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

M68K汇编递归阶乘栈使用异常:函数无法正常返回排查

M68K递归阶乘返回问题分析与修正

问题根源

你的代码核心问题是LINK/UNLK指令的错误使用以及栈帧结构的破坏,导致返回地址被覆盖或栈不平衡,最终引发循环返回:

  1. LINK指令参数错误:LINK A6,#8会在栈上分配8字节局部空间,但你并未使用这些空间,反而直接从修改后的SP(A7)弹出参数,破坏了栈帧中返回地址的位置。
  2. 参数访问方式错误:进入函数后,参数应该通过栈帧基址A6的偏移访问,而非直接操作SP。直接弹出参数会导致UNLK恢复SP后,返回地址的位置错位,RTS无法取到正确的返回地址。
  3. 递归调用后未清理参数栈:每次递归前压入的字参数,在调用返回后没有从栈中移除,导致栈持续累积垃圾数据,最终引发栈溢出或返回错误。

修正后的代码

ORG $1000
            MOVE.L #STACK_TOP, A7  ; 初始化栈顶指针
STACK_TOP   EQU $8000
N           DC.W 3                 ; 计算3的阶乘
           
START:      
            MOVE #1,D0             ; 阶乘结果初始化为1
            MOVE.W N,-(A7)         ; 压入参数(注意:为保持双字对齐,可压入LONG)
            BSR FACT               ; 调用阶乘函数
            ADDQ #2,A7             ; 清理栈上的参数(2字节)
            BRA DONE
            
FACT:
            LINK A6,#0             ; 创建栈帧,无局部变量(A6=SP,旧A6压栈)
            MOVE.W 8(A6),D1        ; 从栈帧取参数(A6+8: 调用者压入的字参数)
            
            CMP #1,D1
            BEQ FACT_DONE
            
            MULU D1,D0             ; 累积阶乘结果
            SUBQ #1,D1
            MOVE.W D1,-(A7)        ; 压入递归参数
            BSR FACT
            ADDQ #2,A7             ; 清理递归调用的参数栈
            
FACT_DONE:
            UNLK A6                ; 恢复栈帧和A6寄存器
            RTS

DONE:
            SIMHALT
            END START

关键修正点说明

  1. 正确使用栈帧访问参数:LINK A6,#0建立最小栈帧,参数位于8(A6)(栈帧结构:A6+0=旧A6值,A6+4=返回地址,A6+8=调用者压入的字参数)。
  2. 调用后清理参数栈:每次调用FACT后,用ADDQ #2,A7移除栈上的2字节参数,保证栈始终平衡。
  3. 避免直接操作SP访问参数:通过A6基址访问参数,确保栈帧结构稳定,UNLK和RTS能正确恢复执行流。

不良实践改进建议

  • 注释规范:M68K汇编通常使用;作为注释符,而非*,统一风格更易读:
    ; 初始化栈顶指针
    MOVE.L #STACK_TOP, A7
    
  • 栈对齐:M68K的栈指针最好保持双字(4字节)对齐,压入参数时可以用MOVE.L N,-(A7)(即使N是字,零扩展为长字),避免栈指针处于奇数地址,提升执行效率。
  • 变量命名清晰度:STACK_END改为STACK_TOP更符合语义(栈从高地址向低地址增长,$8000是栈的起始顶部)。
  • 避免冗余操作:原代码中LINK分配的8字节空间未使用,改为LINK A6,#0更简洁,减少栈空间浪费。
  • 递归逻辑优化:可以将D0作为返回值传递,而非依赖全局累加,更符合函数调用规范(比如递归返回时将D1乘到D0,而非在调用前乘)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 20:42:45