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

MIPS指令load word未加载字至寄存器及数组交换程序技术问询

排查MIPS load word加载失败与数组交换程序问题

我来帮你一步步捋清楚这个问题,先从你提到的lw指令加载失败和未完成的数组程序入手:

先说说lw加载失败的常见坑

你已经用.align 4确保了数组的字对齐,这一点做得很好,但还有几个容易踩的点会导致lw加载异常:

  • 地址计算错误:MIPS的每个字占4字节,如果你直接用索引作为字节偏移(而不是索引×4),会访问到非对齐地址或者错误的元素位置,lw要求地址必须是4字节对齐,非对齐访问会直接触发异常。
  • 基址寄存器没正确初始化:如果没把数组起始地址(list)加载到基址寄存器(比如$s0),后续计算元素地址时用了错误的基址,自然加载不到正确的数据。
  • 索引越界:你的数组是6个元素,有效索引是0-5,如果用户输入的索引超出这个范围,lw会访问数组外的内存(比如后面的字符串区域),加载的是无效数据,看起来就像加载失败。

补全并修正你的程序

你给出的代码里msg4字符串没写完,我帮你补全并完善了整个程序的逻辑,同时规避了lw的常见问题:

.globl main
.data
list: .align 4
.word 5, 17, 43, 22, 120, 3  # 6个元素,有效索引0-5
endList:
space: .asciiz " "
newLine: .asciiz "\n"
msg1: .asciiz "Array is: "
msg2: .asciiz "Enter first index to swap: "
msg3: .asciiz "Enter second index to swap: "
msg4: .asciiz "Array after swap is: "

.text
main:
    # 打印初始数组提示
    li $v0, 4
    la $a0, msg1
    syscall

    # 打印初始数组
    la $s0, list               # 把数组起始地址存入$s0作为基址
    li $t0, 0                  # 循环计数器i=0
    li $t1, 6                  # 数组长度为6
print_loop:
    bge $t0, $t1, end_print    # i>=6时跳出打印循环
    sll $t2, $t0, 2            # 计算字节偏移:i × 4(左移2位等价于乘4,效率更高)
    add $t3, $s0, $t2          # 得到当前元素的绝对地址
    lw $a0, 0($t3)             # 正确加载数组元素到$a0
    li $v0, 1                  # 调用打印整数的系统调用
    syscall

    # 打印分隔空格
    li $v0, 4
    la $a0, space
    syscall

    addi $t0, $t0, 1           # i++
    j print_loop
end_print:
    # 打印换行
    li $v0, 4
    la $a0, newLine
    syscall

    # 获取第一个交换索引
    li $v0, 4
    la $a0, msg2
    syscall
    li $v0, 5
    syscall
    move $s1, $v0              # 保存第一个索引到$s1

    # 获取第二个交换索引
    li $v0, 4
    la $a0, msg3
    syscall
    li $v0, 5
    syscall
    move $s2, $v0              # 保存第二个索引到$s2

    # 检查索引合法性,避免越界访问
    blt $s1, $zero, exit       # 索引小于0则直接退出
    bge $s1, $t1, exit
    blt $s2, $zero, exit
    bge $s2, $t1, exit

    # 加载两个需要交换的元素
    sll $t2, $s1, 2
    add $t3, $s0, $t2
    lw $t4, 0($t3)             # 第一个索引对应的元素存入$t4

    sll $t2, $s2, 2
    add $t3, $s0, $t2
    lw $t5, 0($t3)             # 第二个索引对应的元素存入$t5

    # 执行交换操作
    sll $t2, $s1, 2
    add $t3, $s0, $t2
    sw $t5, 0($t3)             # 把第二个元素写入第一个索引的位置

    sll $t2, $s2, 2
    add $t3, $s0, $t2
    sw $t4, 0($t3)             # 把第一个元素写入第二个索引的位置

    # 打印交换后的数组
    li $v0, 4
    la $a0, msg4
    syscall

    li $t0, 0
print_loop_after:
    bge $t0, $t1, end_program
    sll $t2, $t0, 2
    add $t3, $s0, $t2
    lw $a0, 0($t3)
    li $v0, 1
    syscall

    li $v0, 4
    la $a0, space
    syscall

    addi $t0, $t0, 1
    j print_loop_after

end_program:
    li $v0, 4
    la $a0, newLine
    syscall
exit:
    li $v0, 10                 # 调用退出程序的系统调用
    syscall

关键修正点说明

  1. 正确计算元素地址:用sll $t2, $t0, 2将索引转换为字节偏移,确保lw访问的是4字节对齐的地址,这是解决加载失败的核心。
  2. 索引合法性检查:新增了索引范围判断,避免越界访问导致的无效加载或内存异常。
  3. 寄存器规范使用:用s寄存器保存数组基址和用户输入的索引,避免被临时寄存器覆盖(虽然这个程序没有子函数,但这是MIPS编程的好习惯)。
  4. 补全缺失的字符串:完善了msg4的内容,保证提示信息完整。

排查lw问题的通用步骤

如果以后再遇到lw加载失败的情况,可以按这个顺序排查:

  • 检查目标地址的最低两位是否为00:MIPS要求字访问地址必须4字节对齐,非对齐地址会触发异常。
  • 确认基址寄存器的值是否正确:比如用模拟器查看$s0是否等于list的起始地址。
  • 验证偏移计算是否正确:确保是“索引×4”而不是直接用索引作为字节偏移。
  • 检查索引是否在有效范围内:避免访问数组外的内存区域。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:39:18