RISC V 中的斐波那契函数

Fibonacci Function in RISC V

使用 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

是的,你已经找到了有符号 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 位无符号加法是否溢出。

最后一种方法也用于多词加法,从低位词到高位词进行进位。