RV64I递归Fibonacci函数输出错误求助:输入7得4而非13
RV64I递归斐波那契函数错误排查
我是汇编初学者,正在使用RV64I架构编写递归Fibonacci函数。编译错误已解决,但输入值为7时,函数输出结果为4,正确结果应为13,无法定位错误原因。以下是我的RV64I代码及参考的C++实现:
# main function main: li x10, 7 # Load immediate value 7 into register x10 jal ra, fib # Jump and link to the fib function li x17, 10 # Load immediate value 10 into register x17 ecall # System call (end of program) # fib function fib: addi sp, sp, -16 # Allocate 16 bytes on the stack sd ra, 8(sp) # Save the return address on the stack at offset 8 sd x10, 0(sp) # Save the value of x10 on the stack at offset 0 bnez x10, elif # Branch if x10 is not equal to zero li x10, 0 # Load immediate value 0 into register x10 addi sp, sp, 16 # Deallocate 16 bytes from the stack jr ra # Jump to the return address (end of function) elif: li x28, 1 # Load immediate value 1 into register x28 bne x10, x28, else # Branch if x10 is not equal to x28 li x10, 1 # Load immediate value 1 into register x10 addi sp, sp, 16 # Deallocate 16 bytes from the stack jr ra # Jump to the return address (end of function) else: addi x10, x10, -1 # Subtract 1 from the value of x10 jal fib # Jump and link to the fib function (commented out) mv x29, x10 # Move the value of x10 into register x29 ld x10, 0(sp) # Load the saved value of x10 from the stack addi x10, x10, -2 # Subtract 2 from the value of x10 jal fib # Jump and link to the fib function (commented out) add x10, x29, x10 # Add the value of x29 and x10, and store the result in x10 ld ra, 8(sp) # Load the saved return address from the stack addi sp, sp, 16 # Deallocate 16 bytes from the stack jr ra # Jump to the return address (end of function)
参考的C++实现:
int fib(int n) { if (n==0) return 0; else if (n == 1) return 1; else return fib(n−1) + fib(n−2); }
错误原因
问题出在临时寄存器的使用违反了RV64I调用规范:
你在else分支中用x29保存fib(n-1)的返回结果,但x29属于RV64I的临时寄存器(caller-saved),调用fib(n-2)时,fib函数会修改x29的值,导致之前保存的fib(n-1)结果被覆盖,最终计算结果错误。
修复方案
改用被调用者保存寄存器(callee-saved)(如s0/x8)存储中间结果,这类寄存器会被被调用函数(fib)保存到栈中,调用后原值会恢复。同时需要调整栈空间分配,用于保存新增的寄存器。
修复后的完整代码
# main function main: li x10, 7 # 加载输入值7到x10(参数寄存器) jal ra, fib # 调用fib函数 li x17, 10 # 加载退出系统调用号 ecall # 触发系统调用结束程序 # fib函数:输入x10=n,返回x10=fib(n) fib: addi sp, sp, -24 # 分配24字节栈空间:保存ra(8)、x10(8)、s0(8) sd ra, 16(sp) # 保存返回地址到栈 sd x10, 8(sp) # 保存输入参数n到栈 sd s0, 0(sp) # 保存被调用者保存寄存器s0 bnez x10, elif # n≠0则跳转到elif分支 # base case: n=0,返回0 li x10, 0 ld s0, 0(sp) # 恢复s0 addi sp, sp, 24 # 释放栈空间 jr ra # 返回调用者 elif: li x28, 1 bne x10, x28, else # n≠1则跳转到else分支 # base case: n=1,返回1 li x10, 1 ld s0, 0(sp) # 恢复s0 addi sp, sp, 24 # 释放栈空间 jr ra # 返回调用者 else: # 计算fib(n-1) addi x10, x10, -1 jal ra, fib mv s0, x10 # 用s0保存fib(n-1)的结果(s0是被调用者保存寄存器) # 计算fib(n-2) ld x10, 8(sp) # 从栈中恢复原始n值 addi x10, x10, -2 jal ra, fib # 合并结果:fib(n-1)+fib(n-2) add x10, s0, x10 # 恢复寄存器并释放栈 ld s0, 0(sp) ld ra, 16(sp) addi sp, sp, 24 jr ra
修改后输入7时,函数会正确返回13,符合预期。
内容的提问来源于stack exchange,提问作者asdadada
相关产品推荐
相关产品推荐

