【问题标题】:An issue with an ARM assembly function?ARM 汇编函数有问题吗?
【发布时间】:2026-01-12 05:50:02
【问题描述】:

我有一个用 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 是一个在 Linux 上使用 svc 指令调用 write 系统调用的函数。

【问题讨论】:

    标签: linux assembly arm


    【解决方案1】:

    问题是你没有保存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 进行字节存储。

    【讨论】:

      【解决方案2】:

      此函数将 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 情况,您的堆栈中可能会出现垃圾。

      【讨论】:

      • strs 替换为strbs。还是同样的问题。