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). I tested the recursive Fibonacci program and it currently loops forever. The base cases, 0 and 1, work ok. But when I try fib(2) or more it keeps looping. 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) $fp
before you modify it (this is by common sense ;)) main
it's unbalanced main
and not use exit
syscall You should of course be able to write and debug asm code before you try to generate some.
Given an input structured something like this C implementation:
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.