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

MIPS汇编time2string子程序地址越界及寄存器保存问题求助

MIPS汇编time2string子程序错误排查与修正

核心错误分析

1. 非法内存访问(地址越界)

主函数已将mytime的数值(如0x5957)加载到$a1作为参数传入,但你在time2string第一行写了lw $a1, 0($a1)——这会把$a1的值当作内存地址去加载数据,而0x5957不是合法内存地址,直接触发地址越界错误。

2. 数据存储方式错误

  • 作业要求用sb(存储字节)保存ASCII字符,但你全程用sw(存储字,4字节),会一次性覆盖4个字节的内存,导致内存破坏。
  • 地址偏移错误:字符串每个字符占1字节,存储后应执行addi $a0, $a0, 1,而非addi $a0, $a0, 4。

3. 寄存器使用错误

  • 错误引用$t0:time2string中直接用$t0提取时间字段,但$t0是调用者保存寄存器,主函数已用它加载mytime地址,子程序未保存就修改会破坏主函数上下文;且应使用传入的参数$a1(时间值),而非$t0。
  • 移位指令写错:srl $t3, $3, 8中的$3是无效寄存器,正确写法为srl $t3, $t3, 8。

4. 逻辑错误

  • 冒号处理错误:直接将ASCII冒号(0x3A)加载到$v0后调用hexasc,但hexasc是将低4位转换为ASCII,0x3A的低4位是0xA,会被转成'A',完全不符合需求——直接用sb存储冒号即可,无需调用hexasc。
  • 缺少空终止符:生成的字符串末尾未添加\0(0x00),不符合C风格字符串要求。

修正后的time2string子程序

time2string:
    PUSH($ra)        # 保存返回地址,因要调用hexasc
    PUSH($s0)        # 保存被调用者保存寄存器$s0,存储原始输出地址
    PUSH($s1)        # 保存$s1,存储传入的时间值

    move $s0, $a0    # 把原始输出地址存到$s0(被调用者保存寄存器,不会被破坏)
    move $s1, $a1    # 把时间值存到$s1

    # 提取分钟高位(NBCD的第15-12位)
    andi $a0, $s1, 0xF000
    srl $a0, $a0, 12
    jal hexasc
    sb $v0, 0($s0)   # 存储分钟高位ASCII
    addi $s0, $s0, 1

    # 提取分钟低位(NBCD的第11-8位)
    andi $a0, $s1, 0x0F00
    srl $a0, $a0, 8
    jal hexasc
    sb $v0, 0($s0)
    addi $s0, $s0, 1

    # 存储冒号':'
    li $t0, 0x3A
    sb $t0, 0($s0)
    addi $s0, $s0, 1

    # 提取秒高位(NBCD的第7-4位)
    andi $a0, $s1, 0x00F0
    srl $a0, $a0, 4
    jal hexasc
    sb $v0, 0($s0)
    addi $s0, $s0, 1

    # 提取秒低位(NBCD的第3-0位)
    andi $a0, $s1, 0x000F
    jal hexasc
    sb $v0, 0($s0)
    addi $s0, $s0, 1

    # 添加空终止符
    li $t0, 0x00
    sb $t0, 0($s0)

    POP($s1)         # 恢复寄存器
    POP($s0)
    POP($ra)

    jr $ra
    nop

寄存器保存的正确用法(MIPS规范)

MIPS寄存器分为两类,需严格遵守调用约定:

  1. 调用者保存寄存器($t0-$t9, $a0-$a3, $v0-$v1):
    • 子程序可直接修改,无需保存;若主函数需保留这些值,由主函数负责保存。
  2. 被调用者保存寄存器($s0-$s7, $ra, $fp):
    • 子程序若要修改这些寄存器,必须先用PUSH保存到栈中,执行完逻辑后用POP恢复,否则会破坏调用者上下文。

在你的场景中:

  • 必须保存$ra:因为time2string要调用hexasc,jal会覆盖$ra的值,所以必须先保存。
  • 使用$s0-$s1存储输出地址和时间值:这两个值需要在多次调用hexasc后保持不变,而hexasc可能修改$a0等调用者保存寄存器,用被调用者保存寄存器更安全,且需要保存/恢复。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 04:50:24