[英]Recursive Fibonacci Assembly MIPS code
I have created a code generator for my coursework in a module compilers. 我在模块编译器中为我的课程创建了一个代码生成器。 It generates code in MIPS assembly code and seems to be working ok (ive tested very simple programs and expressions). 它在MIPS汇编代码中生成代码,似乎工作正常(我测试过非常简单的程序和表达式)。 I tested the recursive Fibonacci program and it currently loops forever. 我测试了递归的Fibonacci程序,它目前永远循环。 The base cases, 0 and 1, work ok. 基本情况0和1正常工作。 But when I try fib(2) or more it keeps looping. 但是当我尝试使用fib(2)或更多时,它会保持循环。 Not sure what the problem is, can anyone help me find it? 不确定是什么问题,任何人都可以帮我找到它吗?
Here is the code: 这是代码:
main:
move $fp $sp
sw $ra 0($sp)
addiu $sp $sp -4
sw $fp 0($sp)
addiu $sp $sp -4
li $a0 2 #testing comment
sw $a0 0($sp)
addiu $sp $sp -4
jal fib_entry
lw $ra 4($sp)
addiu $sp $sp 8
lw $fp 0($sp)
li $v0, 10
syscall
fib_entry:
move $fp $sp
sw $ra 0($sp)
addiu $sp $sp -4
lw $a0 4($fp)
sw $a0 0($sp)
addiu $sp $sp -4
li $a0 0
lw $t1 4($sp)
addiu $sp $sp 4
beq $a0 $t1 thenBranch1
elseBranch1:
lw $a0 4($fp)
sw $a0 0($sp)
addiu $sp $sp -4
li $a0 1
lw $t1 4($sp)
addiu $sp $sp 4
beq $a0 $t1 thenBranch2
elseBranch2:
sw $fp 0($sp)
addiu $sp $sp -4
lw $a0 4($fp)
sw $a0 0($sp)
addiu $sp $sp -4
li $a0 1
lw $t1 4($sp)
sub $a0 $t1 $a0
addiu $sp $sp 4
sw $a0 0($sp)
addiu $sp $sp -4
jal fib_entry
sw $a0 0($sp)
addiu $sp $sp -4
sw $fp 0($sp)
addiu $sp $sp -4
lw $a0 4($fp)
sw $a0 0($sp)
addiu $sp $sp -4
li $a0 2
lw $t1 4($sp)
sub $a0 $t1 $a0
addiu $sp $sp 4
sw $a0 0($sp)
addiu $sp $sp -4
jal fib_entry
lw $t1 4($sp)
add $a0 $a0 $t1
addiu $sp $sp 4
b endIf2
thenBranch2:
li $a0 1
endIf2:
b endIf1
thenBranch1:
li $a0 0
endIf1:
lw $ra 4($sp)
addiu $sp $sp 12
lw $fp 0($sp)
jr $ra
Various problems with that code. 该代码存在各种问题。
$sp
before you write to ($sp)
(although this is only by convention) 你应该在写入($sp)
之前递减$sp
(虽然这只是按惯例) $fp
before you modify it (this is by common sense ;)) 你应该在修改它之前保存$fp
(这是常识;)) main
it's unbalanced 你的堆栈处理非常复杂,至少在main
它是不平衡的 main
and not use exit
syscall 建议从main
返回,而不是使用exit
syscall You should of course be able to write and debug asm code before you try to generate some. 在尝试生成某些代码之前,您当然应该能够编写和调试asm代码。
Given an input structured something like this C implementation: 给定输入结构类似于此C实现:
unsigned fib_entry(unsigned n) {
unsigned ret;
unsigned n1;
unsigned f1;
unsigned n2;
unsigned f2;
if (n <= 1) goto fib_small;
n1 = n - 1;
f1 = fib_entry(n1);
n2 = n - 2;
f2 = fib_entry(n2);
ret = f1 + f2;
goto fib_done;
fib_small:
ret = n;
fib_done:
return ret;
}
I would expect a not-too-clever compiler to produce code like this: 我希望有一个不太聪明的编译器来生成这样的代码:
fib_entry:
addiu $sp $sp -28 # we need room for $ra, n, ret, n1, n2, f1, f2
sw $ra, 24($sp) # store $ra since not leaf function
sw $a0, 20($sp) # store n
lw $t0, 20($sp) # load n
ble $t0 1 fib_small
lw $t0, 20($sp) # load n
addi $t0 $t0 -1 # n - 1
sw $t0, 12($sp) # store as n1
lw $a0, 12($sp) # pass n1 as argument
jal fib_entry
sw $v0 4($sp) # store into f1
lw $t0, 20($sp) # load n
addi $t0 $t0 -2 # n - 2
sw $t0, 8($sp) # store as n2
lw $a0, 8($sp) # pass n2 as argument
jal fib_entry
sw $v0 ($sp) # store into f2
lw $t0 4($sp) # f1
lw $t1 ($sp) # f2
addu $t0 $t0 $t1 # f1 + f2
sw $t0 16($sp) # store into ret
b fib_done
fib_small:
lw $t0, 20($sp) # load n
sw $t0 16($sp) # store into ret
fib_done:
lw $v0 16($sp) # load return value
lw $ra 24($sp) # restore $ra
addiu $sp $sp 28 # restore stack
jr $ra # return
Note I have deliberately left it unoptimized. 注意我故意不加优化。 This kind of code should be simple enough to generate. 这种代码应该足够简单以生成。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.