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

MIPS汇编如何实现寄存器值传入传出 函数调用后值丢失怎么解决

问题原因与修复方案

1. 核心错误:循环变量被意外覆盖

你当前用$s6作为遍历数值范围的循环变量,但是在第一次调用isFactor获取到待检查数的真因数和$s3后,直接执行了move $s6, $s3,把循环变量直接修改为了因数和,这直接打乱了原有的遍历逻辑,是导致无限循环的主要原因。
正确的做法是:调用isFactor计算第二个数的因数和时,仅临时把参数传给isFactor的入参寄存器,不要修改循环变量$s6的值。

2. 寄存器使用不符合MIPS调用约定

MIPS架构中,$s0~$s7属于被调用者保存寄存器:如果子函数(比如你这里的isFactor)要使用这类寄存器,必须先在栈上保存寄存器的原始值,函数返回前再恢复原值,否则父函数存在这些寄存器里的数据会被意外覆盖。
你当前isFactor函数里直接修改了$s2、$s4,没有做栈保存/恢复操作,会导致父函数的相关寄存器值丢失。
建议优化:子函数的临时变量优先使用$t0~$t9这类调用者保存寄存器,不需要额外保存,用完即丢,更适合子函数内部的临时计算。

3. 函数传参逻辑不规范

你当前通过$s6给isFactor传递待计算的参数,既容易误改循环变量,也不符合MIPS的传参约定。MIPS默认用$a0~$a3传递函数入参,用$v0~$v1传递返回值,遵循这个约定可以避免很多变量覆盖问题。


修改后的代码参考
isAmicable:
li $s5, 0 # 亲和数对计数器
add $s6, $s0, $zero # 循环变量,遍历[s0, s1]区间

amicableLoop:
bge $s6, $s1, final_output
# 第一次调用:计算当前数$s6的真因数和
move $a0, $s6 # 用$a0传参
jal isFactor
move $s3, $v0 # 用$v0拿返回值,存到$s3
# 第二次调用:计算$s3的真因数和,不要修改$s6
move $a0, $s3 # 把$s3作为参数传给isFactor
jal isFactor
move $s4, $v0 # 拿到$s3的真因数和
# 亲和数判断逻辑
bne $s6, $s4, increment # a的因数和是b,b的因数和不是a,跳过
bge $s6, $s3, increment # 避免重复计数,只保留a<b的对
bge $s3, $s1, increment # 超出范围,跳过
# 是亲和数对的处理逻辑
addi $s5, $s5, 1
# 此处可自行添加存储亲和数对的逻辑

increment:
addi $s6, $s6, 1
j amicableLoop
    
# isFactor函数:计算$a0的所有真因数和,返回值存在$v0
isFactor:
li $v0, 0           # 真因数和,用返回值寄存器存储
li $t0 , 1          # 除数,用临时寄存器存储,不需要额外保存

sumLoop:
bge $t0, $a0, return_sum # 除数大于等于待计算数,结束循环
rem $t1, $a0, $t0   # 求余
bne $t1, $0, while
addu $v0, $v0, $t0  # 能整除,加到和里

while:
addi $t0, $t0, 1
j sumLoop                 

return_sum:
jr $ra          

内容的提问来源于stack exchange,提问作者Greedy-Boogster

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 02:45:06