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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 17:32:04