我在任务上遇到了一些麻烦,并希望得到一些帮助。我不是要求答案,我宁愿把两个和两个放在一起自己解决,但我对MIPS知之甚少,我很难知道从哪里开始。
这是我开始的
.data
.text
main:
addi $sp, $sp, -16 #prepare stack for 4 items
sw $s0, 0($sp)
sw $s1, 4($sp)
sw $s2, 8($sp)
sw $ra, 12($sp)
move $s0, $a0
move $s1, $a1
add $s2, $s0, $s1 #add two previous numbers and store result in $s2
move $v0, $s2 #put answer into $v0
lw $s0, 0($sp)
lw $s1, 4($sp)
lw $s2, 8($sp)
lw $ra, 12($sp)
addi $sp, $sp, 16
jr$ra
基本上我们使用递归函数来计算斐波纳契数,并使用一个循环来打印斐波那契序列的前10个数字。
我查了很多例子,但是他们都使用了我们还没有学到的指令,所以我无法理解它,我只能假设我们不能使用它们。在上面的代码中,我基本上创建了一个堆栈来存储$ ra以及三个值,两个要添加的数字和总和。我的部分问题是了解函数的开始和结束位置以及正在完成的工作的总体情况。
我们还给你打印使用以下
li $v0, 1
move $a0, $s0
syscall
我认为这是打印存储在$ v0中的值吗?
提前致谢
答案 0 :(得分:8)
以下是您的功能代码。我知道你不是在寻找答案,但有时候寻找一个例子以及它是如何工作的,在你明白它是如何工作的时候更容易理解。
.data
msg1: .asciiz "Give a number: "
.text
.globl main
main:
li $v0, 4
la $a0, msg1
syscall # print msg
li $v0, 5
syscall # read an int
add $a0, $v0, $zero # move to $a0
jal fib # call fib
add $a0, $v0, $zero
li $v0, 1
syscall
li $v0, 10
syscall
fib:
# $a0 = y
# if (y == 0) return 0;
# if (y == 1) return 1;
# return fib(y - 1) + fib(y - 2);
#save in stack
addi $sp, $sp, -12
sw $ra, 0($sp)
sw $s0, 4($sp)
sw $s1, 8($sp)
add $s0, $a0, $zero
addi $t1, $zero, 1
beq $s0, $zero, return0
beq $s0, $t1, return1
addi $a0, $s0, -1
jal fib
add $s1, $zero, $v0 # $s1 = fib(y - 1)
addi $a0, $s0, -2
jal fib # $v0 = fib(n - 2)
add $v0, $v0, $s1 # $v0 = fib(n - 2) + $s1
exitfib:
lw $ra, 0($sp) # read registers from stack
lw $s0, 4($sp)
lw $s1, 8($sp)
addi $sp, $sp, 12 # bring back stack pointer
jr $ra
return1:
li $v0,1
j exitfib
return0:
li $v0,0
j exitfib
像古斯布鲁所说的那样,为了在mips中使用递归,你必须做两件事。 jal
(跳转并链接)到函数的名称,但首先总是将返回地址存储到堆栈中:$ra
所以将来如果要返回到开头,您将能够使用jr $ra
。如果您不保存返回地址并尝试通过jr
访问该地址,则很可能会获得invalid program counter error
。希望我能帮助你,并通过MIPS编程获得更好的掌握!
答案 1 :(得分:2)
这里有一些提示:
你必须写一个递归函数,但你根本就没有编写函数。 要在MIPS汇编程序中编写此函数,我建议您先用更高级别的语言(C)编写它。 所以它会是这样的:
int fib(int n)
{
if(n == 0 or n == 1)
return n;
else return fib(n-1) + fib(n-2);
}
第一行检查您是否处于递归的基本情况(n = 0或n = 1)。如果是这种情况,fib(n)返回n。 否则递归步骤将返回fib(n-1)加上fib(n-2)的总和。
所以你必须编写一个函数,定义输入/输出参数(哪个寄存器将保持n,哪个将返回fib(n)。 手动编译C代码。 要启动一个功能,只需添加一个标签
fib:
jal
指令。jr $ra
的函数返回之前,从堆栈中恢复已保存的值。n
的寄存器),然后加载jal fib
。 答案 2 :(得分:0)
这解释了如何在 MIPS 中实现斐波那契函数以及如何将 MIPS 函数转换回等效的 C 代码,非常详细:Fibonacci function in MIPS by illinois.edu
fib:
bgt $a0, 1, recurse
move $v0, $a0
jr $ra
fib:
bgt $a0, 1, recurse
move $v0, $a0
jr $ra
sub $sp, $sp, 12 # We need to store 3 registers to stack
sw $ra, 0($sp) # $ra is the first register
sw $a0, 4($sp) # $a0 is the second register, we cannot assume $a registers will not be overwritten by callee
addi $a0, $a0, -1 # N-1
jal fib
sw $v0, 8($sp) # store $v0, the third register to be stored on the stack so it doesn’t get overwritten by callee
lw $a0, 4($sp) # retrieve original value of N
addi $a0, $a0, -2 #N-2 jal fib