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

Apple Silicon ARM64架构下BL指令跳转异常问题排查

ARM64递归斐波那契汇编中BL指令异常问题分析

问题代码

.section __TEXT,__text,regular,pure_instructions

_main:
  mov X0, 5
  bl fib
  bl exit

fib_end:
  mov X0, 0
  b exit

.align 2
fib:
  stp fp, lr, [sp, -16]!
  mov fp, sp
  ; BASE CONDITION
  cmp X0, 1
  b.le fib_base_case
  mov X4, X0
  sub X0, X0, 1
  mov lr, 0
  bl fib
  mov lr, x9
  mov X3, X0 ; result for fib (n-1)
  mov X0, X4
  sub X0, X0, 2
  bl fib
  add X0, X0, X3 ; adding the results 
  ldp fp, lr, [sp], 16
  ret

fib_base_case:
  ldp fp, lr, [sp], 16
  ret
exit: 
    mov X16, #1
    svc 0x80
    ret

问题描述

编写递归实现斐波那契数列的ARM64汇编代码时,标记的bl fib指令执行后,链接寄存器(LR)更新正确,但程序计数器(PC)并未回到函数开头;将其替换为普通分支指令后,跳转功能恢复正常,询问该差异的原因。

原因分析

核心问题是手动修改lr寄存器,彻底破坏了BL指令的返回逻辑:

  • bl指令的本质是跳转+保存返回地址:执行bl fib时,CPU会自动把当前指令的下一条指令地址存入lr,后续通过ret指令(将lr的值加载到PC)就能回到调用点继续执行。
  • 你在第一次bl fib前执行了mov lr, 0,直接覆盖了BL本该保存的返回地址;之后又执行mov lr, x9,但x9是未初始化的垃圾值。这导致递归调用完成后执行ret时,PC会跳转到错误的地址,表现为“没回到函数开头”。
  • 换成普通b fib指令时,它只做单纯跳转,不依赖lr实现返回,所以不受修改lr的影响,跳转功能自然正常。

修正建议

直接删除mov lr, 0和mov lr, x9这两行多余代码即可。递归调用的返回地址会由bl自动存入lr,你已经通过stp fp, lr, [sp, -16]!把lr保存到栈上,后续ldp fp, lr, [sp], 16会恢复正确的返回地址,最后ret就能正常回到调用点。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 05:12:38