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

MIPS汇编中何时需要重置栈指针?亲和数代码栈操作问题排查

栈操作核心错误

  • IsAmicable循环中addi $a1, $a1, 1后连续写栈的逻辑错误:sw $a2, 0($sp)会直接覆盖栈中存储的循环起始值,导致迭代逻辑完全失效。
  • 作为全局循环结束值的$a2存入4($sp)后,代码中多处出现sw $a2, 4($sp)的写操作,直接修改了你要全程保留的结束值,这是你$a2值无法保持不变的直接原因。
  • 20字节的栈空间没有明确的偏移使用规划,IsFactor、IsFactor2的写栈操作经常意外覆盖其他位置的有效数据。
  • IsFactor中的跳转逻辑错误:bne $a1, $a3, continue会直接跳出求和流程回到上层函数,无法完成真因数累加。

修复方案

  1. 删去IsAmicable内addi $a1, $a1, 1后的sw $a2, 0($sp)语句,仅保留sw $a1, 0($sp)更新当前迭代值即可。
  2. 删去所有IsFactor、IsFactor2、continue段中的sw $a2, 4($sp)语句,4($sp)位置仅用于存储固定不变的循环结束值,全程禁止写入。
  3. 调整IsFactor内的跳转逻辑,将bne $a1, $a3, continue改为bge $a3, $a1, continue,仅当除数超过当前数值时再退出求和返回上层。
  4. 你当前栈恢复指令放在Endif中的位置是正确的,退出IsAmicable函数前执行addi $sp, $sp, 20回收栈空间即可。如果需要支持函数正常返回主程序,调用jal IsAmicable前需要额外将$ra返回地址存入栈的空闲偏移位,函数退出前再读取恢复。
  5. 更稳妥的$a2保存方案:进入IsAmicable读取到$a2的初始值后,直接存入s系列寄存器,使用前先将s寄存器的原值压栈保存,函数退出前恢复即可,比反复读写栈更不容易出现值被意外覆盖的问题。
.data 
sent1: .asciiz "Input the start of the range: "
sent2: .asciiz "Input the end of the range: "
sent4: .asciiz "IN ELSE "
sent5: .asciiz " ," 

userInput: .word 20
userInput2: .word 20
number: .space 20
number2: .space 20

.text
main:
    # Add space on the stack for two words
li $v0, 4            # Loads immediate for a sentace to be printed
la $a0, sent1        # Loads the address of the sentance to print 
syscall              # System calls and prints out sentance

li $v0, 5
syscall
move $t1, $v0

li $v0, 4
la $a0, sent2
syscall

li $v0, 5
syscall 
move $t2, $v0

move $a1, $t1
move $a2, $t2

slt $s0, $a2, $a1
bne  $s0, $zero, Else
addi $sp, $sp, -20
sw $a1, 0($sp)
sw $a2, 4($sp)
jal IsAmicable

Else:
move $a3, $a1
move $a1, $a2
move $a2, $a3
addi $sp, $sp, -20
sw $a1, 0($sp)
sw $a2, 4($sp)
jal IsAmicable

IsAmicable:
lw $a1, 0($sp)
lw $a2, 4($sp)
loop:
#lw $a2, 4($sp)
li $v0, 1
move $a3, $a2
syscall
beq $a1, $a2, Endif    # Setup for loop from value in a1 to value in a2

addi $a1, $a1, 1           # Adds 1 to a1 to iterate
sw $a1, 0($sp) 
                      # loads value in a1 to address in a0 to pass to isFactor
jal IsFactor

continue:
lw $a0, 12($sp)
lw $a2, 4($sp)
move $a3, $a0
sw $a3, 12($sp)
sw $a0, 0($sp)

jal IsFactor2

continue2:
lw $t2, 0($sp)
lw $a3, 12($sp)
lw $a2, 4($sp)
bne $t2, $a3, loop
li $v0, 1
move $a0, $a2
syscall

j loop

IsFactor:
lw $a1, 0($sp)
lw $a2, 4($sp)
move $a3, $0
li $a3, 0

loop2:
move $t4, $zero
addi $a3, $a3, 1
bge $a3, $a1, continue  
rem $t4, $a1, $a3
bne $t4, 0,loop2
add $a0, $a0, $a3
sw $a0, 12($sp)
j loop2

Endif:
add $sp, $sp, 20
li $v0, 10
syscall

IsFactor2:
lw $a0, 0($sp)
lw $a2, 4($sp)
move $a3, $0
li $a3, 0

loop3:
move $t3, $zero
bgt $a3, $a0, continue2 
addi $a3, $a3, 1 
rem $t3, $a0, $a3
bne $t3, 0,loop3
add $t2, $t2, $a3
sw $t2, 0($sp)
j loop3

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 18:36:02