我有一个用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
系统调用的函数。
答案 0 :(得分:4)
问题是您没有保存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来进行字节存储。
答案 1 :(得分:3)
此函数将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案例,您可能会在堆栈中收到垃圾邮件。