RISC-V递归实现斐波那契数列错误排查:n=7输出异常
RISC-V递归斐波那契代码错误分析与修复
你的代码存在多处逻辑错误,导致输出始终为2,具体问题及修复方案如下:
错误点梳理
- 终止条件返回值逻辑错误:斐波那契数列定义为
fib(0)=0、fib(1)=1,但你的done块直接执行add x10, x10, x5,此时x5未针对终止场景做正确初始化(比如n=1时x5为1,x10为1,相加后得到2,这是输出2的直接原因)。 - 栈操作完全混乱:
- 第一次递归返回后,你用
ld x5,0(sp)取出原n值,随即把当前x10(fib(n-1)的结果)存到栈的0(sp)位置,直接覆盖了原n值,后续无法正确获取原n来计算n-2。 - 调用
fib(n-2)后,ld x5,8(sp)取出的是ra寄存器的值,而非之前保存的fib(n-1)结果,导致相加逻辑完全错误。 - 栈的恢复操作(
ld ra,0(sp)、addi sp,sp,16)放在done块内,会导致递归未完成就提前恢复栈并触发退出。
- 第一次递归返回后,你用
- 系统调用位置错误:在
done块内执行打印和退出系统调用,会让递归过程中就触发打印和退出,无法完成完整的递归计算流程。
修改后的代码
# 初始化n=7到x10(若运行环境x10初始非0,可改为li x10,7) addi x10, x0, 7 jal x1, fib # 调用递归斐波那契函数 li a7, 1 # 触发打印系统调用 ecall li a7, 10 # 触发程序退出系统调用 ecall # 递归斐波那契函数,输入x10为n,返回x10为fib(n) fib: # 终止条件:fib(0)=0 beq x10, x0, fib0 # 终止条件:fib(1)=1 addi x5, x0, 1 beq x10, x5, fib1 # 栈空间分配:保存ra、原n值、fib(n-1)结果,共24字节 addi sp, sp, -24 sd ra, 16(sp) sd x10, 8(sp) # 计算fib(n-1) addi x10, x10, -1 jal x1, fib sd x10, 0(sp) # 将fib(n-1)结果存入栈 # 计算fib(n-2) ld x10, 8(sp) # 恢复原n值 addi x10, x10, -2 jal x1, fib # 计算fib(n) = fib(n-1) + fib(n-2) ld x5, 0(sp) # 取出fib(n-1)结果 add x10, x10, x5 # 恢复栈与返回地址,返回上层调用 ld ra, 16(sp) addi sp, sp, 24 jalr x0, x1, 0 # fib(0)返回0 fib0: li x10, 0 jalr x0, x1, 0 # fib(1)返回1 fib1: li x10, 1 jalr x0, x1, 0
修改说明
- 拆分主程序与递归函数:将递归逻辑独立为
fib函数,主程序仅负责初始化参数、调用函数、打印结果和退出,避免递归过程中触发系统调用打断流程。 - 明确终止条件返回:为
fib(0)和fib(1)设置独立的返回分支,直接返回对应数值,符合斐波那契数列定义。 - 规范栈操作流程:栈中依次保存返回地址、原n值、
fib(n-1)的结果,确保递归调用过程中数据不被覆盖,计算完成后正确恢复上下文再返回。 - 修正递归计算逻辑:先计算并保存
fib(n-1)的结果,再恢复原n值计算fib(n-2),最后将两者相加得到fib(n)的结果返回。
内容的提问来源于stack exchange,提问作者randy
相关产品推荐
相关产品推荐

