Assembly 递归斐波那契汇编MIPS码

Assembly 递归斐波那契汇编MIPS码,assembly,recursion,mips,fibonacci,Assembly,Recursion,Mips,Fibonacci,我在模块编译器中为我的课程作业创建了一个代码生成器。它在MIPS汇编代码中生成代码,似乎工作正常(我测试过非常简单的程序和表达式)。 我测试了递归斐波那契程序,现在它永远循环。基本情况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 #testin

我在模块编译器中为我的课程作业创建了一个代码生成器。它在MIPS汇编代码中生成代码,似乎工作正常(我测试过非常简单的程序和表达式)。 我测试了递归斐波那契程序,现在它永远循环。基本情况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
    (这是常识;)
  • MIPS通常使用寄存器传递参数(但您可以 课程(制定自己的惯例)
  • 堆栈处理非常复杂,至少在
    main
    中是不平衡的
  • 建议从
    main
    返回,不要使用
    exit
    syscall
  • 当然,在尝试生成一些asm代码之前,您应该能够编写和调试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