MIPS数组最值函数异常:始终返回默认值问题求助
MIPS数组最值函数返回默认值的问题排查与修复
核心问题梳理
你的代码返回默认最值,主要是以下几个错误导致的:
- 最值初始化逻辑错误:直接用固定值
0(max)和23456(min)初始化,若数组所有元素都小于0或大于23456,最值永远不会更新。 - 循环内比较逻辑完全反转:最大值和最小值的更新条件写反,导致永远不会触发最值更新。
- 打印时寄存器引用错误:输出最大值时误用了寄存器别名
$2,而非保存最大值的$t2。 - 未遵循MIPS调用约定:使用
$s系列寄存器但未做栈保存,可能破坏主程序的寄存器状态。
修正后的完整代码
.data en: .asciiz "Enter N" val: .asciiz "enter the values: " min: .asciiz "the min is: " max: .asciiz "the max is: " .text li $v0 4 la $a0 en syscall li $v0 5 syscall blez $v0 End move $t0 $v0 #t0 存储N li $v0 9 mul $a0 $t0 4 syscall move $t1 $v0 #t1 存储数组首地址 li $v0 4 la $a0 val syscall li $t2 1 # 填充数组 Fill: bgt $t2 $t0 endFill li $v0 5 syscall sw $v0 ($t1) addi $t2 $t2 1 addi $t1 $t1 4 j Fill endFill: mul $t3 $t0 4 sub $t1 $t1 $t3 move $a0 $t0 move $a1 $t1 jal minmax move $t2 $v0 #max move $t3 $v1 #min # 打印最小值和最大值 li $v0 4 la $a0 min syscall li $v0 1 move $a0 $t3 syscall li $v0 4 la $a0 max syscall li $v0 1 move $a0 $t2 # 修正:原$2改为$t2 syscall j End minmax: # 遵循MIPS调用约定,保存$s寄存器到栈 addi $sp $sp -24 sw $s0 0($sp) sw $s1 4($sp) sw $s2 8($sp) sw $s3 12($sp) sw $s4 16($sp) sw $s5 20($sp) move $s0 $a0 #s0 存储N move $s1 $a1 #s1 存储数组首地址 li $s2 1 # 从第二个元素开始遍历(第一个元素已初始化最值) lw $s3 ($s1) # 用数组第一个元素初始化max lw $s4 ($s1) # 用数组第一个元素初始化min # 处理N=1的边界情况,直接返回 beq $s0 1 EndLoop Loop: bge $s2 $s0 EndLoop addi $s1 $s1 4 # 移动到下一个元素 lw $s5 ($s1) #s5 存储当前数组元素 # 修正最大值更新逻辑:当前元素大于max时更新 bgt $s5 $s3 updateMax j checkMin updateMax: move $s3 $s5 checkMin: # 修正最小值更新逻辑:当前元素小于min时更新 blt $s5 $s4 updateMin j goagain updateMin: move $s4 $s5 goagain: addi $s2 $s2 1 j Loop EndLoop: move $v0 $s3 move $v1 $s4 # 恢复$s寄存器 lw $s0 0($sp) lw $s1 4($sp) lw $s2 8($sp) lw $s3 12($sp) lw $s4 16($sp) lw $s5 20($sp) addi $sp $sp 24 jr $ra End: li $v0 10 syscall
关键修正说明
- 最值初始化:改用数组第一个元素初始化max和min,适配所有数值范围的数组。
- 比较逻辑修正:反转最大值、最小值的判断条件,确保符合“更大则更新max,更小则更新min”的需求。
- 寄存器引用修复:打印最大值时使用正确的
$t2寄存器。 - 调用约定遵守:添加栈操作保存和恢复
$s系列寄存器,避免干扰主程序的寄存器状态。 - 边界处理:新增N=1的判断,避免无意义的循环。
内容的提问来源于stack exchange,提问作者LK.
相关产品推荐
相关产品推荐

