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

MIPS递归幂函数代码输出全为0,请求问题排查

递归幂函数输出全0的问题排查

核心问题分析与修复

1. 参数传递不符合约定

你明确要求参数n传入$a1,但在main循环中却把指数加载到了$a2,这不仅违反约定,还会导致递归逻辑中参数引用混乱:

# 原错误代码
lw $a2 0($s2)

# 修正为
lw $a1 0($s2)

2. 栈帧操作错误(覆盖返回地址)

在power函数中,你先将$ra保存到8($sp),紧接着又用s.d指令把$f14写入同一位置——sw是4字节存储,s.d是8字节存储,这会直接覆盖$ra的内容,导致递归返回时跳转到错误地址,彻底打乱程序逻辑。

需要重新规划栈帧空间,给每个寄存器分配独立存储位置:

# 原错误栈操作
power: 
    andi $sp 0xfffffff8 
    addi $sp $sp -16
    s.d $f20 ($sp)  
    sw $ra 8($sp)
    s.d $f14, 8($sp)

# 修正后栈操作
power: 
    andi $sp 0xfffffff8  # 栈对齐到8字节边界
    addi $sp $sp -24     # 分配24字节栈帧:$f20(8)、$ra(4)、$f14(8),预留4字节对齐
    s.d $f20 0($sp)      # 保存$f20到栈底
    sw $ra 8($sp)        # 保存返回地址到8-11字节
    s.d $f14 16($sp)     # 保存参数x到16-23字节

3. 递归结果被错误覆盖

在done标签处,你递归计算完成后,又将栈中最初保存的旧$f20加载回来,直接覆盖了刚计算出的幂结果:

# 原错误恢复逻辑
done:
    lw $ra 8($sp)
    l.d $f14, 8($sp)
    l.d $f20 ($sp)  # 这行把递归前的初始值重新加载,覆盖计算结果

# 修正后恢复逻辑
done:
    lw $ra 8($sp)        # 先恢复返回地址
    l.d $f14 16($sp)     # 恢复参数x
    l.d $f20 0($sp)      # 恢复$f20(不影响结果寄存器)
    addi $sp $sp 24      # 释放栈帧
    jr $ra

4. 返回寄存器未按约定使用

你要求结果返回至$f0-$f2,但原代码用$f20存储结果,且打印时直接读取$f20,修正为用$f0作为返回寄存器,符合MIPS调用约定。

修正后的完整代码

.data
array1: .double 2.0 2.0 3.0 3.0 4.2 5.0 2.0 0.0 0.0
array2: .word 5 4 2 1 0 2 3 0 10
array_size: .word 9 
newLine: .asciiz "\n"
one: .double 1.0
.text

main:
    la $s1 array1
    la $s2 array2
    lw $s3 array_size # s3 = 9
    
    li $s4, 0
loop: 
    beq $s4 $s3 exit 

    l.d $f14 0($s1)
    lw $a1 0($s2)  # 按约定将n传入$a1
    
    jal power
    
    li $v0, 3           
    mov.d $f12, $f0     # 从约定的$f0读取返回结果
    syscall             

    # 打印换行分隔结果
    li $v0, 4
    la $a0, newLine
    syscall

    addi $s1 $s1 8  
    addi $s2 $s2 4  
    
    addi $s4, $s4, 1 # 索引自增
    j loop

power: 
    andi $sp 0xfffffff8  # 栈对齐到8字节
    addi $sp $sp -24     # 分配24字节栈帧
    s.d $f20 0($sp)      # 保存$f20
    sw $ra 8($sp)        # 保存返回地址
    s.d $f14 16($sp)     # 保存参数x
    
    l.d $f0, one         # 初始化结果为1.0(n=0时直接返回)
    beq $a1, $zero, done # 终止条件:n=0
    
    addi $a1, $a1, -1    # n = n-1
    jal power            # 递归调用power(x, n-1)
    
    mul.d $f0, $f14, $f0 # 计算x * power(x, n-1)
    
done:
    lw $ra 8($sp)        # 恢复返回地址
    l.d $f14 16($sp)     # 恢复参数x
    l.d $f20 0($sp)      # 恢复$f20
    addi $sp $sp 24      # 释放栈帧
    jr $ra  
exit: 
    li $v0, 10         
    syscall

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 22:20:28