如何在RISC-V中实现阶乘功能

时间:2019-09-23 18:54:44

标签: factorial riscv

    C-code  :

int factorial(int n) 
{
if (n<1) return 1;
 else return n * factorial (n-1);
}

我已经尝试实现它,但是并没有做很多事情。所以这是我的尝试:

     goto:

 factorial:
 int factorial(int n) {
 if (n<1) goto Lthen;

 Lelse:
 tmp=factorial(n-1);
 return n*tmp;
 goto Lend;

 Lthen: return 1;
 Lend;
 }



 RISC V:
.factorial
 addi sp, sp,  -16
 sw ra, (sp)
 sw s0, 4(sp) //n
 sw s1, 8(sp) //tmp
 mv s0, a0               //a--->s0
 addi t1, zero,1 
 blt s0, t1, Lthen

   .Lelse
   mv t0, s0          // copy of n to t0
   addi s0, s0, -1   // n-1
   mv a0, s0;        // n-1--->a0
   jal factorial // factorial(a0)
   mv s1, a0         // s1=factorial(a0) //tmp
   mul a0,t0,s1        //  n*tmp ----> a0 
   ret
   j LEND



Lthen: li a0,1
ret
LEND jr ra, 0 

有人可以告诉我吗,因为我不知道如何测试。 而且我不确定例如返回1 /或其他任何值/表达式,是否可以将其放在a0中并说ret ..

谢谢您的时间!

2 个答案:

答案 0 :(得分:0)

您应使用$s0作为保留值,而不要使用$t0

在递归调用之前从$s0复制后,您应该从$ a0中减去1。

然后乘法将在$a0返回值和$s0保留值之间进行。

$s0可以工作但$t0不能(保留原始的$a0输入)的原因是,您正在(正确的)努力来保存{{1 }}注册。

但是,您不会恢复函数结尾中保存的值,也不会减少堆栈,也不会重新加载s ...

答案 1 :(得分:0)

这是我的RV32I assembly programmer's quick reference中的RISC-V中的递归阶乘函数:(欢迎评论!)

.text  # recursive implementation of factorial
.globl __start
fact:       # arg: n in a0, returns n! in a1
    addi  sp, sp, -8    # reserve our stack area
    sw ra, 0(sp)    # save the return address
    li t0, 2
    blt a0, t0, ret_one # 0! and 1! == 1
    sw a0, 4(sp)    # save our n
    addi a0, a0, -1
    jal fact        # call fact (n-1)
                    # a1 <- fact(n-1)
    lw t0, 4(sp)    # t0 <- n
    mul a1, t0, a1  # a1 <- n * fact(n-1)
    j done
ret_one:
    li a1, 1
done:
    lw ra, 0(sp)    # restore return address from stack
    addi sp, sp, 8  # free our stack frame
    jr ra           # and return

__start:
    li a0, 5        # compute 5!
    jal fact
    li a0, 1        # print it
    ecall
    li a0, 17
    ecall       # and exit

要进行测试,我最喜欢的轻量级RISC-V模拟器是VenusJupiter