【问题标题】:How can I exit main subroutine in ARM assembly?如何退出 ARM 程序集中的主子程序?
【发布时间】:2022-01-12 18:31:47
【问题描述】:

如何完成程序,如下代码在 __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

【问题讨论】:

  • 您需要某种形式的返回或退出系统调用。请注意,您的 funcOne 会使堆栈不平衡,这不是一个好主意。
  • 不平衡堆栈是什么意思?
  • 您在funcOne 中有PUSH,但在main 中有POP。虽然它在这种情况下有效,但不建议这样做。
  • 是的,我正在从主子程序调用 funcOne。 funcOne 返回值我 PUSH 到堆栈,一旦返回到主函数我 POP 那个返回值。这种方法有问题吗?

标签: assembly arm stm32 keil


【解决方案1】:

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

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

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

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

LoopForever:
    b LoopForever

你的代码在做什么?

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

当您推送 R2 和下一个弹出 R3 时,堆栈指针保持不变,并且永远不会到达可能引发 BusError 的非法地址,从而可能会破坏这个死循环。

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

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

【讨论】:

  • 我不同意最后一段。如果您不了解汇编,则无法编写它。内联汇编对于不映射到像“C”这样的高级语言的架构结构通常很有用。他们可能需要 10 年或更长时间才能找到进入标准的方法。例如。 asm volatile("dmb ish": : :"memory")... 没有办法在“C”中编码。程序员需要能够在汇编程序中制作简单的序列。 他们不需要在汇编程序中完全编写程序。我认为这更符合您的意图?
猜你喜欢
  • 2018-06-23
  • 1970-01-01
  • 1970-01-01
  • 2013-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多