Reputation: 16345
I have a simple function written in ARM assembler. The first time it's ran, everything works as desired (it prints BOOT\n
). However, the second time the function is executed, nothing is printed.
.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
What could be the issue? I suspect that this somehow screws up the buffer that it no longer works. Write is a function that calls the write
syscall on Linux using the svc
instruction.
Upvotes: 0
Views: 564
Reputation: 3453
The problem is that you're not saving lr
.
bl _write
add sp, #64
bx lr
bl _write
will overwrite lr
which then points to add sp, #64
, so your bx lr
will just result in an endless loop on the last two instructions.
It should work if you modify your code like this:
__printTest:
push {lr}
sub sp, #64 /* yes, I know this is too much */
....
bl _write
add sp, #64
pop {pc}
As already stated in another answer, you should also use strb instead of str for byte-stores.
Upvotes: 5
Reputation: 8116
This function is pushing 32-bit values into unaligned stack pointer addresses. It should be using strb
to write single bytes. For unaligned str
, the ARM Architecture Reference Manual says:
if UnalignedSupport() || address<1:0> == ‘00’ then
MemU[address,4] = R[t];
else // Can only occur before ARMv7
MemU[address,4] = bits(32) UNKNOWN;
So depending on your configuration, you might be getting junk in your stack if you're hitting the UNKNOWN case.
Upvotes: 2