I have written a code for calculating nth fibonacci number in RISC-V assembly language. It has two parts- fib.s
and runtest.s
, which loads the value of n
into a0
and calls fib
, which calculates the nth fibonacci number (without recursion), loads the result into a0
itself and returns. Here is my code:
.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
And here is my testbench (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
Everytime I run this code I'm only getting a return value of 1. Can someone point out the error in this? Also if there's a better way to implement the same logic, please let me know of that as well.
I was able to get all of your testbench cases to pass in a RISC-V simulator with 3 changes:
(1) Your second test case has the wrong expected result. I'm assuming you're using 0-indexed Fibonacci numbers, since that's what most of your test cases do (e.g. test case 1 says Fibonacci number 1 is 1, test case 3 says Fibonacci number 7 is 13). In that case, Fibonacci number 3 should be 2, not 3.
(2) To get the correct number of iterations, in your loop, your "i" variable / register a4 should begin set to 1, not 2.
(3) You generally don't use ECALL to return from a function in RISC-V. As per the RISC-V spec, "the ECALL instruction is used to make a service request to the execution environment." It causes a precise trap and is used (for example) when implementing syscalls. Instead, there is the pseudoinstruction ret to return from a function call (similar notation to x86). ret is equivalent to jalr x0 0(ra). (That being said, maybe you've defined ecall behavior such that when a7 is 93, the equivalent of a ret is executed.)