MIPS汇编模拟中代码无法终止运行问题求助
MIPS汇编程序陷入无限循环超时的问题修复
核心问题分析
你的程序超时并非end处的无限循环本身,而是代码执行流程出现异常,导致程序根本没走到end就提前进入死循环,或是栈/寄存器管理错误引发的执行混乱:
addAtStart未恢复栈帧和寄存器就返回:在addNode中你为s0-s2和$ra分配了栈空间并保存,但addAtStart直接通过jr $ra返回,没有恢复栈指针和保存的寄存器。这会导致栈指针错位、返回地址错误,程序大概率跳转到非法地址或进入无限循环。findNode未正确设置返回值$v0:你注释说明findNode要返回目标节点的地址到$v0,但代码全程没有将$t0(当前节点)赋值给$v0,导致addNode后续操作使用未定义的$v0值,引发内存访问错误或执行流程混乱。findNode循环计数逻辑错误:要插入到位置n(n>0)时,需要找到第n-1个节点挂载新节点,但当前循环从0开始计数,第一次递增后就判断是否等于n,会错误返回第0个节点而非目标节点。
修复后的完整代码
main: jal addNode # 调用addNode插入新节点 move $s3, $v0 # 将返回值存入$s3 j end # 跳转到end终止程序 addNode: addi $sp, $sp, -16 # 分配栈空间保存寄存器 sw $ra, 12($sp) # 保存返回地址$ra sw $s0, 8($sp) # 保存头节点head sw $s1, 4($sp) # 保存新节点newNode sw $s2, 0($sp) # 保存插入位置n beq $s2, $zero, addAtStart # 如果n=0,跳转到头部插入逻辑 # 准备调用findNode move $a0, $s0 # 传入头节点作为参数 move $a1, $s2 # 传入插入位置n作为参数 jal findNode # 调用findNode # 在找到的节点后插入新节点 lw $t0, 4($v0) # 加载当前节点的下一个节点地址 sw $t0, 4($s1) # 设置新节点的next为当前节点的下一个节点 sw $s1, 4($v0) # 设置当前节点的next为新节点 # 加载新节点的值作为返回值 lw $v0, 0($s1) # 恢复寄存器并返回 lw $s2, 0($sp) lw $s1, 4($sp) lw $s0, 8($sp) lw $ra, 12($sp) addi $sp, $sp, 16 jr $ra addAtStart: sw $s0, 4($s1) # 设置新节点的next为当前头节点 move $s0, $s1 # 更新头节点为新节点 lw $v0, 0($s1) # 加载新节点的值作为返回值 # 恢复寄存器和栈帧,和addNode的返回逻辑一致 lw $s2, 0($sp) lw $s1, 4($sp) lw $s0, 8($sp) lw $ra, 12($sp) addi $sp, $sp, 16 jr $ra # 返回至main findNode: ori $t2, $zero, 0 # 初始化循环计数器为0 move $t0, $a0 # $t0指向当前节点,初始为头节点 beq $a1, $zero, findNode_exit # 如果n=0,直接退出(外部已处理头部插入) loop_findNode: # 先移动到下一个节点,再递增计数器 lw $t0, 4($t0) # 移动到下一个节点 beq $t0, $zero, findNode_exit # 如果到达链表末尾,退出循环 addi $t2, $t2, 1 # 递增计数器 bne $t2, $a1, loop_findNode # 未到达目标位置,继续循环 findNode_exit: move $v0, $t0 # 将目标节点地址存入$v0作为返回值 jr $ra # 返回至调用者 end: j end # 无限循环终止程序
关键修复点说明
- 修复
addAtStart的栈帧恢复:在addAtStart末尾添加和addNode相同的寄存器恢复和栈指针调整代码,确保返回时栈状态正确、返回地址有效。 - 修复
findNode的返回值:在findNode_exit处将$t0(目标节点地址)赋值给$v0,保证调用者能拿到正确的节点地址。 - 调整
findNode的循环逻辑:先移动节点再递增计数器,确保当n=1时能找到第0个节点的下一个节点,匹配插入逻辑的需求。
内容的提问来源于stack exchange,提问作者asimn
相关产品推荐
相关产品推荐

