Проблем с функция за сглобяване на 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 syscall на 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