You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ARM汇编如何返回分支起始位置?程序跳转后无法回归问题求助

问题分析与解决方案

看起来你遇到的问题是BlinkBoth函数执行完毕后无法回到主循环的分支起始位置,而是直接流入了Wait循环的代码里。这是因为你的BlinkBoth函数缺少返回主调用点的关键指令,同时主循环的闭环逻辑也需要补全。

具体问题拆解:

  • 当你用blne BlinkBoth调用BlinkBoth时,ARM会把当前下一条指令的地址存入lr(链接寄存器),但你的BlinkBoth函数执行完最后一条swi SWI_SETLED后,没有任何指令把lr的值送回pc(程序计数器),导致程序不会返回主循环,而是继续执行后续的Wait标签代码。
  • 主循环没有添加循环跳转指令,程序执行一次按键检查后就会直接结束,无法持续检测按键状态。

修改后的完整代码:

MainLoop:  ; 主循环标签,实现持续检测按键
swi SWI_CheckBlue 
cmp r0, #0 
blne BlinkBoth  ; 调用BlinkBoth,lr保存此处下一条指令地址
b MainLoop  ; 回到主循环开头,持续检测按键

BlinkBoth: 
mov r0,#(LEFT_LED|RIGHT_LED) 
swi SWI_SETLED 
ldr r3,=500 
BL Wait  ; 调用Wait,lr保存mov r0,#0的地址
mov r0,#0 
swi SWI_SETLED
ldr r3,=500  ; 让灭灯状态也持续500时间单位(可按需移除)
BL Wait
mov pc, lr  ; 关键:将lr中的主循环地址加载到pc,返回分支起始位置

Wait: 
stmfd sp!,{r0-r5,lr}  ; 保存寄存器与lr,避免上下文混乱
ldr r4,=0x00007FFF @mask for 15-bit timer 
SWI SWI_GetTicks @Get start time 
and r1,r0,r4 @adjusted time to 15-bit 
Wloop: 
SWI SWI_GetTicks @Get current time 
and r2,r0,r4 @adjusted time to 15-bit 
cmp r2,r1 
blt Roll @rolled above 15 bits 
sub r5,r2,r1 @compute easy elapsed time 
bal CmpLoop 
Roll: 
sub r5,r4,r1 @compute rolled elapsed time 
add r5,r5,r2 
CmpLoop:cmp r5,r3 @is elapsed time < delay? 
blt Wloop @Continue with delay 
ldmfd sp!,{r0-r5,pc}  ; 恢复寄存器,pc=lr,返回Wait的调用点

关键修改说明:

  1. 添加MainLoop标签和b MainLoop指令:让程序持续循环检测按键状态,不会执行一次就结束。
  2. 在BlinkBoth函数末尾添加mov pc, lr:这会把blne BlinkBoth时存入lr的主循环指令地址加载到pc,确保执行完闪烁逻辑后回到主循环的分支位置。
  3. 补充灭灯后的等待逻辑:让LED的亮、灭状态都保持固定时长,闪烁效果更符合预期(不需要的话可以删除对应的ldr r3,=500和BL Wait)。

内容的提问来源于stack exchange,提问作者EmmanoelD97

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:56:44