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

MARS运行MIPS坐标转内存地址代码时出现无效程序计数器错误

问题原因分析与修复

你的代码出现invalid program counter value: 0x00000000错误,核心问题出在栈帧的建立与恢复流程不符合MIPS栈规范,具体有两个关键错误:

1. 保存旧帧指针时未正确移动栈指针

MIPS栈是向下增长的(栈指针$sp数值越小,指向栈的越深处),压栈操作必须先将$sp减去对应字节数,再存储数据。你直接执行sw $fp, 0($sp),会覆盖调用者(main函数)栈顶的有效数据,破坏栈结构,导致返回时程序计数器无法获取正确的返回地址。

2. 栈恢复时未正确重置栈指针位置

在函数退出阶段,你恢复完寄存器后,仅将$sp移动到$fp位置并恢复$fp,但没有将$sp调整回调用前的状态,导致栈指针始终停留在错误位置,进一步引发程序执行异常。


修复后的translate_coordinates函数

translate_coordinates:
    # 正确建立栈帧:先分配24字节栈空间(满足8字节对齐要求,适配MARS模拟器)
    subu    $sp, $sp, 24    
    sw      $fp, 20($sp)    # 保存旧帧指针到栈中
    move    $fp, $sp        # 帧指针指向当前栈顶
    sw      $ra, 16($fp)    # 保存返回地址
    sw      $s0, 12($fp)    # 保存需要用到的$s寄存器
    sw      $s1, 8($fp)
    sw      $s2, 4($fp)

    # 原函数逻辑保持不变
    move    $s0, $a0       # $s0 = x coordinate
    move    $s1, $a1       # $s1 = y coordinate
    move    $s2, $a2       # $s2 = width for calculations
    
    sll     $t3, $s1, 5     # y * 32
    add     $t4, $t3, $s0   # (y * 32) + x = 像素索引
    sll     $t5, $t4, 2     # 索引 * 4(每个像素占4字节)
    add     $t6, $gp, $t5   # 计算内存地址:全局指针 + 偏移量
    move    $v0, $t6        # 结果存入返回寄存器$v0
    
    # 恢复寄存器与栈帧
    lw      $s2, 4($fp)
    lw      $s1, 8($fp)
    lw      $s0, 12($fp)
    lw      $ra, 16($fp)
    lw      $fp, 20($fp)    # 恢复旧帧指针
    addi    $sp, $sp, 24    # 释放栈空间,栈指针回到调用前位置
    jr      $ra 

额外说明

  • MIPS栈要求8字节对齐,所以分配栈空间时尽量使用8的倍数(比如这里用24字节,而非你原来的20字节),避免模拟器出现隐性错误。
  • 栈帧操作的核心原则:建立时先分配空间再保存寄存器,退出时先恢复寄存器再释放空间,严格遵循这个流程就能避免多数栈相关问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 22:40:40