Recursion RISC-V汇编中的递归程序

Recursion RISC-V汇编中的递归程序,recursion,assembly,stack,riscv,Recursion,Assembly,Stack,Riscv,我试图在RISC-V中创建一个递归程序,但我无法得到正确的结果。看起来它自己的名字是max的两倍,但我试着在纸上运行它,一切似乎都是正确的: addi x31, x0, 4 addi x30, x0, 2 addi x2, x0, 1600 //initialize the stack to 1600, x2= stackpointer ecall x5, x0, 5 //read the input to x5 jal x1, re

我试图在RISC-V中创建一个递归程序,但我无法得到正确的结果。看起来它自己的名字是max的两倍,但我试着在纸上运行它,一切似乎都是正确的:

addi x31, x0, 4
addi x30, x0, 2

addi x2, x0, 1600               //initialize the stack to 1600, x2= stackpointer
ecall x5, x0, 5                 //read the input to x5
jal x1, rec_func
ecall x0, x10, 2                //print the result
beq x0, x0, end

rec_func:
addi x2, x2, -16               //make room in stack
sd x1, 0(x2)                   //store pointer and result in stack
sd x10, 8(x2)
bge x5, x31, true             // if i > 3, then go to true branch
addi x10, x0, 1              // if i <= 3, then return 1
addi x2, x2, 16              // reset stack point
jalr x0, 0(x1)

true:
addi x5, x5, -2                // compute i-2
jal x1, rec_func                // call recursive func for i-2
ld x1, 0(x2)                    // load the return address
ld x10, 8(x2)                  // load result from last function call
addi x2, x2, 16                // reset stack point
mul x10, x10, x30               // multiply by 2
addi x10, x10, 1               // add 1
jalr x0, 0(x1)                 // return

end:
addi x31,x0,4
addi x30,x0,2
addi x2,x0,1600//将堆栈初始化为1600,x2=堆栈指针
ecall x5,x0,5//读取x5的输入
日本航空x1,记录功能
ecall x0、x10、2//打印结果
beq x0,x0,结束
记录功能:
addi x2,x2,-16//在堆栈中腾出空间
sd x1,0(x2)//在堆栈中存储指针和结果
sd x10,8(x2)
bge x5,x31,true//如果i>3,则转到true分支

addi x10,x0,1//如果我没有足够的声誉来添加评论,但是您是否尝试过使用调试器来运行它而不是在纸上运行?这应该显示寄存器中的实际内容,以及为什么它没有像您预期的那样分支。我对这些指令(学习x86汇编)还不太熟悉,目前还没有弄清楚它的源代码。

我现在就知道了。我所做的更改如下:

  • 在返回1的部分,我没有加载返回调用的堆栈指针
  • 我将x10的存储移到内存中,因为@Michael指出我正在返回它,我不需要它
最后的代码如下所示:

addi x31, x0, 4
addi x30, x0, 2

addi x2, x0, 1600               // initialize the stack to 1600, x2= stackpointer
ecall x5, x0, 5                 // read the input to x5
jal x1, rec_func
ecall x0, x10, 2                // print the result
beq x0, x0, end

rec_func:
    addi x2, x2, -8                 // make room in stack
    sd x1, 0(x2)                    // store pointer and result in stack
    bge x5, x31, true               // if i > 3, then go to true branch
    ld x1, 0(x2)
    addi x10, x0, 1                 // if i <= 3, then return 1
    addi x2, x2, 8                  // reset stack point
    jalr x0, 0(x1)

true:
    addi x5, x5, -2                 // compute i-2
    jal x1, rec_func                // call recursive func for i-2
    ld x1, 0(x2)                    // load the return address
    addi x2, x2, 8                  // reset stack point
    mul x10, x10, x30               // multiply by 2
    addi x10, x10, 1                // add 1
    jalr x0, 0(x1)                  // return

end:
addi x31,x0,4
addi x30,x0,2
addi x2,x0,1600//将堆栈初始化为1600,x2=堆栈指针
ecall x5,x0,5//读取x5的输入
日本航空x1,记录功能
ecall x0、x10、2//打印结果
beq x0,x0,结束
记录功能:
addi x2,x2,-8//在堆栈中腾出空间
sd x1,0(x2)//在堆栈中存储指针和结果
bge x5,x31,true//如果i>3,则转到true分支
ld-x1,0(x2)

addi x10,x0,1//i
addi x5,x0,-2
顺便说一句,RISC-V具有
slli
,因此无需使用
mul
@Michael感谢您指出,我复制了错误的版本,但没有很好地修复它,您在堆栈上保存并恢复
x10
似乎也很奇怪。这就是你的回报值,不是吗?所以你想让它改变。谢谢你给我指点调试器,我会用那个调试器试试。我不知道调试器
addi x31, x0, 4
addi x30, x0, 2

addi x2, x0, 1600               // initialize the stack to 1600, x2= stackpointer
ecall x5, x0, 5                 // read the input to x5
jal x1, rec_func
ecall x0, x10, 2                // print the result
beq x0, x0, end

rec_func:
    addi x2, x2, -8                 // make room in stack
    sd x1, 0(x2)                    // store pointer and result in stack
    bge x5, x31, true               // if i > 3, then go to true branch
    ld x1, 0(x2)
    addi x10, x0, 1                 // if i <= 3, then return 1
    addi x2, x2, 8                  // reset stack point
    jalr x0, 0(x1)

true:
    addi x5, x5, -2                 // compute i-2
    jal x1, rec_func                // call recursive func for i-2
    ld x1, 0(x2)                    // load the return address
    addi x2, x2, 8                  // reset stack point
    mul x10, x10, x30               // multiply by 2
    addi x10, x10, 1                // add 1
    jalr x0, 0(x1)                  // return

end: