ARMv7架构下能否使用寄存器值实现带链接跳转(BL操作)?
ARMv7 基于寄存器值的带链接跳转实现说明
为什么bl r0会触发报错
编写bl r0时出现的编译报错,本质是ARMv7的BL指令本身的编码规则限制:BL仅支持PC相对偏移的直接跳转(即跳转目标是和当前PC位置绑定的固定标签,由汇编器自动计算偏移量),操作数不支持通用寄存器形式,并非“带链接的寄存器跳转”这个功能完全无法实现。
对应的原生实现方式
ARMv7架构原生提供了 BLX
- 执行逻辑:将
BLX指令的下一条指令地址自动写入链接寄存器(LR/R14),同时将PC的值设置为目标通用寄存器中存储的跳转地址 - 额外特性:会根据目标寄存器值的最低位自动切换指令集状态(最低位为1时跳转进入Thumb状态,为0时进入ARM状态),无需手动修改程序状态寄存器。
这就是想要的类bl寄存器跳转的实现,只是助记符不是bl而已。
对补充示例代码的修正说明
贴出的示例代码存在两处逻辑层面的常见问题,并非blx指令本身的缺陷:
- 提前压栈LR的操作并非必须
BLX <Rm>本身会自动将当前指令的下一行地址(即示例中后续编写的mov r5, 0的地址)写入LR,目标函数只要最后通过bx lr返回,就会准确回到这个位置。这个过程会覆盖原有LR值,只有当当前代码块本身已经是一个带上层返回地址的子函数、需要嵌套调用其他函数时,才需要提前压栈保存旧的LR值,避免被BLX覆盖。 - 代码块排布问题导致的重复执行
示例中把example_label的代码放在pop pc的下方,如果example_label内没有通过bx lr正常返回,程序的顺序执行流就会直接落入example_label的代码块,造成重复执行的问题,这和跳转指令的功能无关。
无嵌套返回需求的常规写法示例
ldr r0, =example_label blx r0 @ 跳转到r0存储的地址,自动保存返回地址到LR mov r5, 0 @ 目标函数返回后会自动执行到这里 @ 目标函数独立排布在代码段末尾,避免顺序执行落入 example_label: mov r5, 111 @ 函数业务逻辑 bx lr @ 将LR中的返回地址载入PC,完成返回
带嵌套返回场景的写法示例
@ 场景:当前代码本身为子函数,调用目标函数后需要直接返回最上层调用者 push {lr} @ 保存当前子函数的上层返回地址 ldr r0, =example_label blx r0 @ 跳转调用目标函数,LR被更新为当前返回点 mov r5, 0 pop {pc} @ 弹出栈上保存的上层返回地址到PC,直接返回上层
常见误区澄清
- 不存在“完全无法实现寄存器值带链接跳转”的限制,只是汇编助记符的语法匹配问题,ARMv7的原生指令集已经完全覆盖了这个功能
- 不推荐手动模拟实现跳转(比如手写
mov lr, pc; bx r0):这种写法不会自动处理ARM/Thumb状态的切换,遇到Thumb目标地址时会出现状态异常,可靠性远低于原生BLX指令
内容的提问来源于stack exchange,提问作者Kookie
相关产品推荐
相关产品推荐

