RISC-V汇编斐波那契函数无输出问题求助
你的RISC-V斐波那契代码问题解析
你的代码核心问题出在**jal指令的使用和返回地址的处理**上,以下是具体错误和修正方案:
主要错误点
jal指令的目标寄存器错误
RISC-V中jal rd, label的rd是用来存储返回地址的寄存器,标准约定里用x1(ra)保存返回地址。你写成jal x10, fib,会把返回地址覆盖到x10里——而x10既是传入的参数,也是存放返回值的寄存器,直接导致参数丢失、返回地址错误。返回指令
jr使用错误
函数返回时应该跳转到ra(x1)中保存的返回地址,你用了jr x10,会跳到x10值对应的地址,而非调用者的位置,导致程序执行混乱,无法正常返回主函数打印结果。递归调用时未保存返回地址
每次递归调用fib时,jal会覆盖ra的值,如果不把ra保存到栈里,后续递归会丢失上一层的返回地址,无法正确回溯。
修正后的代码
main: addi x10, zero, 7 # 传入参数7到a0(x10) jal x1, fib # 调用fib,返回地址存在ra(x1) # 打印结果(x10已经是fib的返回值) li x17, 1 # 系统调用号:打印整数 ecall # 退出程序 li x17, 93 # 系统调用号:程序退出 li x10, 0 # 退出状态码0 ecall fib: bne x10, zero, elif # 如果x10≠0,跳转到elif addi x10, zero, 0 # fib(0)=0,存在x10 jr x1 # 返回主调用者(跳转到ra保存的地址) elif: addi x28, zero, 1 # 加载1到临时寄存器x28 bne x10, x28, else # 如果x10≠1,跳转到else addi x10, zero, 1 # fib(1)=1,存在x10 jr x1 # 返回主调用者 else: addi sp, sp, -16 # 栈指针预留16字节:保存ra和x10(每个8字节) sd x1, 8(sp) # 保存返回地址ra到栈 sd x10, 0(sp) # 保存当前参数x10到栈 addi x10, x10, -2 # 计算n-2,作为新参数传入fib jal x1, fib # 递归调用fib(n-2) mv x29, x10 # 保存fib(n-2)的结果到x29 ld x10, 0(sp) # 恢复原参数n addi x10, x10, -1 # 计算n-1,作为新参数传入fib jal x1, fib # 递归调用fib(n-1) mv x30, x10 # 保存fib(n-1)的结果到x30 add x10, x29, x30 # 计算fib(n-2)+fib(n-1),存在x10作为返回值 ld x1, 8(sp) # 恢复返回地址ra addi sp, sp, 16 # 恢复栈指针 jr x1 # 返回主调用者
额外说明
- RISC-V寄存器约定:
x10(a0)用来传递第一个参数和返回值,x1(ra)专门保存返回地址,遵守这个约定能避免很多基础错误。 - 递归场景下必须保存
ra到栈,否则每次jal都会覆盖ra,导致上层调用的返回地址丢失。
内容的提问来源于stack exchange,提问作者asdadada
相关产品推荐
相关产品推荐

