为何使用jr $ra会导致MIPS汇编程序陷入无限循环?
问题分析与修复方案
核心问题拆解
无限循环的根源
你定义的exit标签被两个分支共享:main中的错误处理分支,以及product函数的结束分支。当main触发错误处理(比如last < first)时,跳去exit执行jr $ra,但main是程序入口,此时$ra的初始值不确定,执行jr $ra会跳回非法地址,导致无限循环。另外,如果你把main末尾的li $v0,10换成jr $ra,main本身没有上级调用,同样会因为$ra无效引发循环。$v0值始终为10的问题
你在调用product后执行了li $v0,10,这行代码直接把$v0设为10,覆盖了原本要存储的乘积结果,随后的syscall是退出程序指令,所以最终$v0固定为10。错误处理逻辑颠倒
需求是last大于first时$v1设为1,但你用了slt $v1, $t1, $t0——这行代码是当last < first时$v1=1,完全搞反了判断条件。乘积未存入$v0
你把乘积存在$t3里,但最后没有将$t3的值转移到要求的$v0寄存器中。
修正后的代码
.data array: .word 7 4 3 8 5 0 9 10 6 2 1 # 数组 first: .word 2 # 起始索引 last: .word 4 # 结束索引 .text main: la $a0, array # 加载数组基地址到$a0 lw $t0, first # 加载first到$t0 lw $t1, last # 加载last到$t1 # 错误处理:last > first时$v1=1,否则0 slt $v1, $t0, $t1 # 当first < last(即last > first)时,$v1=1 # 若需要在last>first时直接退出,可添加:bne $v1, $zero, exit_main li $t3, 1 # 初始化乘积为1 jal product # 调用乘积计算函数 move $v0, $t3 # 将乘积结果从$t3移到$v0 exit_main: # 单独的程序退出入口 li $v0, 10 syscall # 退出程序 product: bgt $t0, $t1, product_exit # 如果当前索引超过last,退出函数 mul $t4, $t0, 4 # 计算数组元素的字节偏移(每个word占4字节) add $t4, $a0, $t4 # 得到元素的内存地址 lw $t5, 0($t4) # 加载数组元素 mul $t3, $t3, $t5 # 更新乘积 addi $t0, $t0, 1 # 索引自增 j product # 循环处理下一个元素 product_exit: jr $ra # 返回main函数
关键修复点说明
- 拆分了
exit标签:新增exit_main作为程序退出的唯一入口,product_exit作为函数返回的入口,避免$ra被误用导致的无限循环。 - 修正了错误处理的判断条件:用
slt $v1, $t0, $t1实现“last>first时$v1=1”的逻辑。 - 将乘积结果从
$t3转移到$v0,满足作业要求。 - 明确了函数调用和返回的流程:product函数执行完后通过
jr $ra回到main中jal product的下一行,正确返回结果。
内容的提问来源于stack exchange,提问作者James
相关产品推荐
相关产品推荐

