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 位无符号加法是否溢出。
最后一种方法也用于多词加法,从低位词到高位词进行进位。
使用 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 位无符号加法是否溢出。
最后一种方法也用于多词加法,从低位词到高位词进行进位。