0

我用RISC-V汇编语言编写了一个计算第n个斐波那契数的代码。它有两个部分 -fib.sruntest.s,分别加载ninto的值a0和调用fib,计算第 n 个斐波那契数(没有递归),将结果加载到a0自身并返回。这是我的代码:

.global fib              # the runtest.s will give an a0 value as input n and call fib 
fib:
    li a1, 0             # This is a
    li a2, 1             # This is b
    li a3, 0             # This is c 
    li a4, 2             # This is i
   
    li a6, 2             # dummy, just to check a0 with
    ble a0, a6, cond1    # check if a0 <= 2
    bgt a0, a6, head     # if a0 > 2, proceed to loop

head:                    # start of loop
    add a3, a1, a2       # Here I'm implementing the space optimized version of fibonacci series without recursion:
    mv a1, a2            # for i in range(2, n+1): c = a + b; a = b; b = c; return b
    mv a2, a3            
    addi a4, a4, 1
    blt a4, a0, head
    bge a4, a0, end      # iterates n-1 times and goes to end

cond1:
    li a0, 1             # if n==1 or n==2 return 1
    li a7, 93
    ecall

end:
    mv a0, a2            # copying the value of a2 (which is b) to a0, since the testbench
    li a7, 93            # runtest.s is setup that way.
    ecall

这是我的测试台(runtest.s):

.global _start
_start:
    # Load 'n' into a0 and call fib
    # Test 1
    li      a0,1  # Check n'th Fib number
    call    fib
    li      a5,1  # Expected result
    bne     a0,a5,.FINISH
    # Test 2
    li      a0,3  
    call    fib
    li      a5,3  
    bne     a0,a5,.FINISH
    # Test 3
    li      a0,7  
    call    fib
    li      a5,13  
    bne     a0,a5,.FINISH
    # Test 4
    li      a0,9 
    call    fib
    li      a5,34
    bne     a0,a5,.FINISH
    # Test 5
    li      a0,20 
    call    fib
    li      a5,6765 
    bne     a0,a5,.FINISH
    # Test 6
    li      a0,30
    call    fib
    li      a5,832040 
    bne     a0,a5,.FINISH
    # Finished tests
    li      a5,0  # All passed
.FINISH:
    mv      a0, a5
    li      a7, 93
    ecall

每次我运行这段代码时,我只得到一个返回值 1。有人能指出其中的错误吗?另外,如果有更好的方法来实现相同的逻辑,也请告诉我。

4

1 回答 1

4

通过 3 处更改,我能够让您的所有测试台案例通过 RISC-V 模拟器:

(1) 你的第二个测试用例有错误的预期结果。我假设您使用的是 0 索引的斐波那契数,因为这是您的大多数测试用例所做的(例如,测试用例 1 说斐波那契数 1 是 1,测试用例 3 说斐波那契数 7 是 13)。在这种情况下,斐波那契数 3 应该是 2,而不是 3。

(2) 要获得正确的迭代次数,在您的循环中,您的“i”变量/寄存器 a4 应该开始设置为 1,而不是 2。

(3) 你一般不使用 ECALL 从 RISC-V 中的函数返回。根据 RISC-V 规范,“ECALL 指令用于向执行环境发出服务请求。” 它会导致精确的陷阱,并在(例如)实现系统调用时使用。取而代之的是从函数调用返回的伪指令 ret(类似于 x86 的表示法)。ret 等价于 jalr x0 0(ra)。(话虽如此,也许您已经定义了 ecall 行为,使得当 a7 为 93 时,执行相当于 ret 的行为。)

于 2020-09-09T05:08:46.437 回答