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

MIPS中jal调用后返回地址异常问题及正确保存方法咨询

MIPS汇编中使用jal后正确保存返回地址的方法

问题根源

用jal调用子过程时,指令会自动把当前返回地址写入$ra寄存器。如果你的子过程内部还会用jal调用其他函数(比如选择排序里的交换子程序、递归调用),新的jal会直接覆盖$ra里原来的地址,导致执行jr $ra时找不到最初的调用点unazaKalimit,最终触发内存错误。

正确的保存步骤

在调用子过程前,必须把$ra的当前值存到栈里,子过程执行完再从栈里恢复$ra,具体操作:

  • 先调整栈指针,预留4字节空间(MIPS栈向下增长):subi $sp, $sp, 4
  • 把$ra的值存入栈:sw $ra, 0($sp)
  • 调用子过程:jal 子过程名
  • 子过程执行完毕后,从栈中读回$ra:lw $ra, 0($sp)
  • 恢复栈指针:addi $sp, $sp, 4
  • 最后执行jr $ra就能正确返回原调用地址

代码示例修改

假设你原代码中调用子过程的片段是这样:

unazaKalimit:
    # 前置逻辑代码
    jal sort_subroutine  # 调用子过程,此时原返回地址被覆盖
    # 后续逻辑代码
    jr $ra

修改后正确的代码:

unazaKalimit:
    # 先把当前$ra保存到栈
    subi $sp, $sp, 4
    sw $ra, 0($sp)
    
    jal sort_subroutine  # 调用子过程,即便$ra被覆盖,我们已经存了原地址
    
    # 恢复$ra的值
    lw $ra, 0($sp)
    addi $sp, $sp, 4
    
    jr $ra  # 现在能准确回到原调用点

如果你的子过程内部还有嵌套的jal调用,那子过程里也要做同样的保存操作。比如sort_subroutine里调用swap函数:

sort_subroutine:
    # 保存当前子过程的返回地址
    subi $sp, $sp, 4
    sw $ra, 0($sp)
    
    jal swap  # 调用交换子程序
    
    # 恢复返回地址
    lw $ra, 0($sp)
    addi $sp, $sp, 4
    
    jr $ra

每一层调用都按这个流程保存、恢复$ra,就能保证返回地址不丢失,彻底解决内存错误问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 22:52:25