assembly RISC V中的Fibonacci函数

sczxawaw  于 2023-05-23  发布在  其他
关注(0)|答案(2)|浏览(185)

使用RISC-V实现斐波那契函数,使得f(0)= 0,f(1)= 1,...,直到f(47)。我的输出匹配到46的所有内容。但是当我尝试计算f(47)时,我得到:-1323752223.
下面是输出:Output from Code below with n=47
是否有某种溢出,因为我得到一个负整数值?我应该在哪里查看并修复错误?

.data
    n:  .word 47
.text
.globl main

main:

            li x2, 0                # Used to determine if n (x7) equals 0
            li x3, 1                # Used to determine if n (x7) equals 1
            li x5, 0                # First number
            li x6, 1                # Second number
            lw x7, n                # Limit
            li x8, 1                # Counter
            beq x7, x2, DO          # If n == 0 then jump to DO (Which shoud print 0). Implements f(0) = 0
            beq x7, x3, WRITE       # if n == 1 then jump to WRITE (Which should print 1). Implements f(1) = 1  

    LOOP:   beq x8, x7, EXIT        # Comparse the counter x8 which starts with 1 to n (limit). If x8 == x7 jump to EXIT
            add x4, x5, x6          # Add x5 to x6 and store in x4          
            ori x5, x6, 0           # Assign the second number to my first number
            ori x6, x4, 0           # Assign the sum of x5 and x6 to my second number
            addi x8, x8, 1          # Add 1 to my counter
            j LOOP                  # Jump to loop

    EXIT:   
            li x17, 1               # Load constant 1 to x17
            add x10,x4,x0           # Add x4 (which contains the result after the above coe) to x10
            ecall                   # Issue an SystemCall which prints an integer (Because of the 1 in x17)
            li x17, 5                                   
            ecall
            li x17, 10      
            ecall                   # Reads an int from input console (Because of the 10 in x17)
    DO:   
            li x4, 0                # load 0 in x10 (x10 will be used by the SysCall to print) and print            
            add x10,x4,x0       
            li x17, 1
            ecall   
            li x17, 5
            ecall
            li x17, 10
            ecall    

    WRITE:  li x4, 1                # load 1 in x10 and print
            add x10,x4,x0
            li x17,1
            ecall
            li x17, 5
            ecall
            li x17, 10
            ecall
fnx2tebb

fnx2tebb1#

是的,您已经找到了有符号32位整数可以容纳的范围。

  • fib(47) = 2971215073不适合有符号的32位整数,但适合无符号的-然而,RARS没有“unsigned int”打印函数。
  • fib(48) = 4807526976不适合32位格式,即使是无符号格式。

斐波那契数列列表:https://www.math.net/list-of-fibonacci-numbers
如果你想表示更大的数字,你需要一个策略。

  • 如果精度不重要,你可以切换到浮点,在浮点中,如此大的数字的结果将是不精确的。
  • 使用两个整数一起进行64位算术-你会很好地达到fib(92) = 7540113804746346429。
  • 使用可变长度整数,精度仅受计算机内存和计算时间的限制
  • 上述因素的复杂组合

最后,您可以检测并发出所选算术数据类型溢出的错误。RISC V上的溢出检测有点简单,但并不明显。
从技术上讲,将2个任意的32位数字相加会得到一个33位的答案,但不会超过33位,因此我们可以使用数学知识来检测溢出。
首先,在32位数中,最高位是符号位(当有符号数据类型时)或幅度位(当无符号数据类型时)。
如果您添加两个正数(就像fib的情况一样)并且设置了符号位,那么您就有符号溢出-但如果解释为无符号,则是正确的位模式。但是,使用ecall #1将无法正确打印数字,因为它会将数字打印为有符号并解释为负数。你可以自己写无符号数字打印;您也可以查找这种情况,并简单地停止打印程序,并发出一个错误。
除此之外,您还可以通过查看结果值是否小于输入操作数之一来检查32位无符号加法是否溢出。
最后一种方法也用于多字加法,以进行从低位字到高位字的进位。

nr7wwzry

nr7wwzry2#

下面是在RISC-V汇编中计算Fibonacci的简单代码:

.data

ask1: .string "Please enter a number to compute its Fibonacci value:   "
msg: .string "The result is:   \n"

.text

la a0, ask1
li a7, 4
ecall

li a7, 5
ecall

addi t0, x0, 1
add s0, x0, x0

jal ra, Fibonacci
j print

Fibonacci:
bge t0, a0, BaseCase
addi sp, sp, -8
sw ra, 0(sp)
sw a0, 4(sp)
addi a0, a0, -1
jal ra, Fibonacci

lw a1, 4(sp)
sw a0, 4(sp)
addi a0, a1, -2
jal ra, Fibonacci
lw a1, 4(sp)
add a0, a0, a1
lw ra, 0(sp)
addi sp, sp, 8 

BaseCase:
jr ra

print:

add s0, x0, a0
la a0, msg
li a7, 4
ecall
add a0, x0, s0
addi a7, x0, 1
ecall

相关问题