Как я могу вызвать putchar из библиотеки C, используя ARM Assembly для Raspberry pi? - PullRequest
0 голосов
/ 11 января 2019

Мне очень трудно пытаться вызвать putchar в цикле, который печатает первый аргумент, отправленный через программу, написанную на ARM Assembly для raspberry pi. например . / Myprog1 hello должен вывести "hello" в консоли при запуске.

Код выглядит следующим образом:

    .text
   .balign 4
   .global main
   main:
       LDR r4, [r1, #4]    @ base address for argv[1] 
       MOV r5, #0          @ counter for loop

   loop:
       LDRB r0, [r4], #1   @ read each char byte in and increment
       CMP r0, #0          @ #0 representing null terminator
       BL putchar
       ADDNE r5, r5, #1
       BNE loop
   end:
       MOV r0, #0
       BX lr

Я знаю, что есть очевидные проблемы, но относительно того, где я не уверен. Например. BL putchar должен вызвать putchar и поместить следующую инструкцию в регистр ссылок, но после возни с этим я получаю только первый символ.

Я обращался к таким ресурсам, как:

https://thinkingeek.com/arm-assembler-raspberry-pi/ и http://bob.cs.sonoma.edu/IntroCompOrg-RPi/intro-co-rpi.html но, похоже, я никак не могу обойти это. Я уверен, что это, вероятно, просто простое решение о перемещении и извлечении регистров в нужном месте или что-то подобное, но я застрял на этом в течение нескольких дней и не смог прогрессировать. Программе даже не нужно выводить аргумент - цикл предназначен для вычисления длины, но я хотел возиться с этим и учиться на вершине этого.

Это, конечно, не домашняя задача, а способ для меня отладить часть гораздо большего задания, которое мне нужно сделать.

Любая помощь будет принята с благодарностью!

1 Ответ

0 голосов
/ 11 января 2019

На самом деле есть несколько проблем с вашим кодом, и все они связаны с тем, что находится и не сохраняется за границей вызова.

Комментарий

@ Jester является точным с точки зрения вашей непосредственной проблемы: PSR (который содержит флаги состояния) не сохраняется за границей вызова, поэтому результат вашего CMP равен забитый BL.

Но также стоит отметить, что lr тоже перекрывается BL, поэтому, когда вы достигнете конца main(), BX lr ответвляется обратно к линии после BL. Ваш комментарий говорит о том, что вы знаете, что r0-r3 засорены. Но r12 и lr тоже, поэтому их нужно сохранять, если вы их используете; main() - это функция, как и любая другая, поэтому она должна соответствовать соглашениям о вызовах, сохраняя r4-r11.

В настоящее время main() является коберберингом r4 и r5, поэтому их необходимо поместить в стек в начале и вытолкнуть в конце вместе с lr (чтобы избежать проблемы lr забитый BL). Для ARM ABI требуется 8-байтовое выравнивание стека по границам вызовов в разных единицах перевода, поэтому вам придется нажать и вытолкнуть еще один регистр, чтобы сделать его четным числом.

Итак, в начале вы захотите

main:
    PUSH {r4-r6,lr}

и в конце

    POP {r4-r6,lr}
    BX lr

или эквивалентно

    POP {r4-r6,pc}

, где суммированное значение lr выталкивается непосредственно в счетчик программы, что вызывает переход.

...