简体   繁体   English

递归Fibonacci汇编MIPS代码

[英]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. 该代码存在各种问题。

  1. you should be decrementing $sp before you write to ($sp) (although this is only by convention) 你应该写入($sp) 之前递减$sp (虽然这只是按惯例)
  2. you should be saving $fp before you modify it (this is by common sense ;)) 你应该修改它之前保存$fp (这是常识;))
  3. MIPS typically uses registers to pass arguments (but you can of course make up your own convention) MIPS通常使用寄存器来传递参数(但您当然可以构成自己的约定)
  4. your stack handling is horribly overcomplicated, and at least in main it's unbalanced 你的堆栈处理非常复杂,至少在main它是不平衡的
  5. it's recommended to return from 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM