如何退出 ARM 汇编中的主子程序?

How can I exit main subroutine in ARM assembly?

如何完成程序,因为下面的代码在 __mainCode 和 funcOne 子例程之间不断循环?

__mainCode  PROC 
            MOV R0, 5                       ;0x0800 0008
            LDR R1, =0xA                    ;0x0800 000C
            BL funcOne                      ;0x0800 0010
            POP {R3}                        ;0x0800 0014
            ENDP ; end of function

            
funcOne     PROC
            MOV R2, #11                     ;0x0800 0018
            PUSH {R2}                       ;0x0800 001c
            BX LR                           ;0x0800 001e
            ENDP

            ALIGN ; fill rest of bytes with 0s
            END

裸机代码没有任何“退出”例程,因为它没有任何东西可以将控制传递给。

当您从 main 函数 return 编写“普通”C 程序时,启动代码只是禁用中断并进入无限循环。

下面是 STMCube 生成的启动代码片段(他们甚至不关心中断)

/* Call the application's entry point.*/
    bl  main

LoopForever:
    b LoopForever

你的代码在做什么?

  1. 执行完BX LR后跳转到POP {R3}继续执行
  2. 它再次到达 BX LR(LR 未被修改)并循环重复。

当你按下 R2 和下一个 pop R3 时,堆栈指针保持不变并且永远不会到达不合法的地址,这可能会引发 BusError 并可能打破这个死循环。

但是如果去掉pop指令最终uC会访问非法地址,说明你没有设置中断向量。它会尝试跳转到 0xffffffff 地址(flash 默认用 0xff 值填充),这个地址也是非法的。它将再次引发 BusFault,您的程序将最终进入死异常引发循环。

如果你不完全了解架构并且不熟练地为ARM uC编写C代码,IMO学习ARM汇编是没有意义的。汇编很少使用(我个人在 10 年前写了 50 行代码,当时我正在编写自己的 RTOS,并且需要很少的指令来交换堆栈指针值和访问一些系统寄存器)——而编程(主要是 ARM)uC 是我的白天工作。