[英]Recursive Fibonacci Assembly MIPS code
我在模塊編譯器中為我的課程創建了一個代碼生成器。 它在MIPS匯編代碼中生成代碼,似乎工作正常(我測試過非常簡單的程序和表達式)。 我測試了遞歸的Fibonacci程序,它目前永遠循環。 基本情況0和1正常工作。 但是當我嘗試使用fib(2)或更多時,它會保持循環。 不確定是什么問題,任何人都可以幫我找到它嗎?
這是代碼:
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
該代碼存在各種問題。
($sp)
之前遞減$sp
(雖然這只是按慣例) $fp
(這是常識;)) main
它是不平衡的 main
返回,而不是使用exit
syscall 在嘗試生成某些代碼之前,您當然應該能夠編寫和調試asm代碼。
給定輸入結構類似於此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;
}
我希望有一個不太聰明的編譯器來生成這樣的代碼:
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
注意我故意不加優化。 這種代碼應該足夠簡單以生成。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.