Linux 手臂装配功能有问题吗?
我有一个用ARM汇编程序编写的简单函数。它第一次运行时,一切都按需要运行(它打印Linux 手臂装配功能有问题吗?,linux,assembly,arm,Linux,Assembly,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
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是一个函数,在Linux上使用
svc
指令调用Write
syscall。此函数将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;
如果UnalignedSupport()| | address==“00”,则
MemU[address,4]=R[t];
else//只能在ARMv7之前出现
MemU[地址,4]=位(32)未知;
因此,根据您的配置,如果遇到未知情况,堆栈中可能会出现垃圾。此函数将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;
如果UnalignedSupport()| | address==“00”,则
MemU[address,4]=R[t];
else//只能在ARMv7之前出现
MemU[地址,4]=位(32)未知;
因此,根据您的配置,如果遇到未知情况,您可能会在堆栈中收到垃圾。问题在于您没有保存
lr
bl _write
add sp, #64
bx lr
bl\u 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来存储字节。问题在于您没有保存
lr
bl _write
add sp, #64
bx lr
bl\u 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来存储字节。将
str
s替换为strb
s。仍然是相同的问题。将str
s替换为strb
s。还是一样的问题。