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

RISC-V汇编递归函数栈:如何用非保留寄存器替换n为n-1?

解决RISC-V递归函数累加逻辑错误的问题

你的递归函数目标是实现 a0 = (n-1) + factorial(n-1) 的累加逻辑,但当前代码在递归返回后用了入栈前的原始n进行计算,导致结果不符合预期:输入7得到0x0000001c而非预期的0x00000015,输入5预期1+2+3+4=10(0x0000000a)也出错。

问题根源

看else分支的执行流程:

  1. 你先把a0减1得到n-1,然后调用递归
  2. 但入栈的是减1之前的原始n(function开头的sw a0, 4(sp))
  3. 递归返回后,从栈里取出的t1是原始n,所以add a0, t1, a0实际执行的是原始n + factorial(n-1),和需求的(n-1) + factorial(n-1)相差1。

两种可行修改方案

方案1:累加前将原始n减1

直接在取出t1后,把它调整为n-1再进行累加:

else:
addi a0, a0, -1 # n = n − 1
jal function # 递归调用
lw t1, 4(sp) # 取出原始n
lw ra, 0(sp)
addi sp, sp, 8
addi t1, t1, -1 # 将原始n转为n-1
add a0, t1, a0 # 执行a0 = (n-1) + factorial(n-1)
jr ra

方案2:入栈时直接存储n-1

提前计算n-1并存入栈,避免后续二次计算:

function:
addi sp, sp, -8 # 分配栈空间
sw ra, 0(sp) # 先存返回地址
addi t0, zero, 1 # 临时变量=1
bgt a0, t0, else # n>1则跳转到else
addi a0, zero, 1 # n<=1时返回1
addi sp, sp, 8 # 回收栈空间
jr ra # 返回

else:
addi t1, a0, -1 # 计算n-1并存入t1
sw t1, 4(sp) # 将n-1存入栈(替换原来的原始n)
addi a0, a0, -1 # a0改为n-1用于递归调用
jal function # 递归调用
lw t1, 4(sp) # 直接取出预存的n-1
lw ra, 0(sp)
addi sp, sp, 8
add a0, t1, a0 # 执行累加
jr ra # 返回

关于你之前尝试的问题

你提到用其他寄存器存储n-1却出错,大概率是存储时机不对:如果在递归调用之后才去计算n-1,此时原始n已经被递归调用覆盖;或者用了临时寄存器(如t0-t6),这类寄存器在递归函数中可能被修改,导致数值丢失。正确的做法是在递归调用前就把n-1存入栈(或保存到s0-s11这类被调用者保存寄存器),确保递归返回后数值还在。

验证结果

修改后:

  • 输入5时,计算1+2+3+4=10,对应0x0000000a,符合预期
  • 输入7时,计算1+2+3+4+5+6=21,对应0x00000015,结果正确

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 18:00:29