Проблема с функцией сборки ARM?

У меня есть простая функция, написанная на ассемблере ARM. При первом запуске все работает как надо (выводит BOOT\n). Однако при втором выполнении функции ничего не печатается.

.globl __printTest
.text
.align 2

__printTest:
 sub sp, #64 /* yes, I know this is too much */

 mov r0, #66
 str r0, [sp]
 mov r0, #79
 str r0, [sp, #1]
 mov r0, #79
 str r0, [sp, #2]
 mov r0, #84
 str r0, [sp, #3]
 mov r0, #10
 str r0, [sp, #4]

 mov r0, #0
 mov r1, sp
 mov r2, #5

 bl _write
 add sp, #64

 bx lr

В чем может быть проблема? Я подозреваю, что это каким-то образом портит буфер, и он больше не работает. Write — это функция, которая вызывает системный вызов write в Linux с помощью инструкции svc.


person Kristina Brooks    schedule 18.04.2012    source источник


Ответы (2)


Проблема в том, что вы не сохраняете lr.

     bl _write
     add sp, #64
     bx lr

bl _write перезапишет lr, который затем указывает на add sp, #64, поэтому ваш bx lr просто приведет к бесконечному циклу на последних двух инструкциях.

Это должно работать, если вы измените свой код следующим образом:

__printTest:
 push {lr}
 sub sp, #64 /* yes, I know this is too much */
 ....
 bl _write
 add sp, #64
 pop {pc}

Как уже говорилось в другом ответе, вы также должны использовать strb вместо str для байтовых хранилищ.

person Nico Erfurth    schedule 18.04.2012

Эта функция помещает 32-битные значения в невыровненные адреса указателя стека. Он должен использовать strb для записи отдельных байтов. Для невыровненного str в Справочном руководстве по архитектуре ARM говорится:

if UnalignedSupport() || address<1:0> == ‘00’ then
    MemU[address,4] = R[t];
else // Can only occur before ARMv7
    MemU[address,4] = bits(32) UNKNOWN;

Таким образом, в зависимости от вашей конфигурации вы можете получить мусор в своем стеке, если столкнетесь с случаем UNKNOWN.

person Variable Length Coder    schedule 18.04.2012
comment
Заменены strs на strbs. Все та же проблема. - person Kristina Brooks; 18.04.2012