MIPS实现带数组存取的for循环时,输出全为33333的修正方法
MIPS代码错误梳理与修正方案
现存错误点
- 循环逻辑顺序错误:C语言for循环的执行顺序是「初始化i → 判断i<j → 执行循环体 → i自增 → 重复判断」,你写的代码是判断后立刻让i自增,导致循环体使用的i值比预期大1,循环次数错位。
- 数组元素读取逻辑错误:
- 读取A[i]的代码
lw $t3, ($s6)固定读取数组A的首元素5,没有绑定i的偏移量,导致每次取值都是固定值。 - 读取A[i+1]的代码
lw $t4, 4($10)未初始化$10寄存器,且没有关联i的偏移量,实际运行时刚好读到A[1]的固定值8,因此差值永远是8-5=3,输出自然全是3。
- 读取A[i]的代码
- 空间分配不足:
arrayB: .space 4只分配了1个4字节字的空间,j=5的情况下需要存储5个元素,共20字节,原空间会导致内存越界。 - 循环判断逻辑不严谨:仅用
beq $s0, $s1, Exit判断退出,只有i完全等于j时才会退出,不符合C代码中「i>=j就退出」的逻辑,极端情况会出现死循环。 - 数组越界风险:当前A数组只有5个元素(下标0-4),j=5时i最大为4,此时A[i+1]为A[5],属于越界访问,建议将j的初始值设为4,或给A数组多分配1个元素。
修正后的完整代码
严格遵循作业要求的寄存器分配规则:$s0存i、$s1存j、$s6存A基地址、$s7存B基地址
.data arrayA: .word 5, 8, 12, 13, 28 # 原有A数组 arrayB: .space 20 # 分配5个4字节字的空间存储B的结果 i_init: .word 0 # i的初始值 j_init: .word 4 # 调整j为4,避免A数组越界(若要保留j=5可在A数组末尾加一个字元素) .text main: la $s6, arrayA # 加载A的基地址到$s6 la $s7, arrayB # 加载B的基地址到$s7 lw $s0, i_init # 加载i的初始值0到$s0 lw $s1, j_init # 加载j的初始值到$s1 Loop: # 实现i<j的判断:i<j则继续循环,否则退出 slt $t0, $s0, $s1 # 若$s0 < $s1,$t0=1;否则$t0=0 beq $t0, $zero, Exit # $t0=0说明i>=j,跳转到退出流程 sll $t1, $s0, 2 # 计算i的字偏移量:左移2位等价于乘4,适配4字节字的寻址 add $t2, $s6, $t1 # 得到A[i]的实际地址 add $t3, $t2, 4 # 得到A[i+1]的实际地址(相邻字的地址差4字节) add $t4, $s7, $t1 # 得到B[i]的实际地址 lw $t5, 0($t2) # 读取A[i]的值 lw $t6, 0($t3) # 读取A[i+1]的值 sub $t5, $t6, $t5 # 计算A[i+1] - A[i]的差值 sw $t5, 0($t4) # 将差值存入B[i]的对应位置 # 输出当前计算结果(和你原有需求一致) add $a0, $zero, $t5 li $v0, 1 syscall addi $s0, $s0, 1 # 循环末尾执行i自增,符合C代码逻辑 j Loop # 跳回循环入口重新判断 Exit: li $v0, 10 syscall # 触发程序退出的系统调用
修正后运行效果
调整j为4后,i从0到3依次计算,输出结果为3 4 1 15,和C代码的逻辑完全一致。
内容的提问来源于stack exchange,提问作者SCORE00
相关产品推荐
相关产品推荐

