【问题标题】:Recursive Fibonacci Assembly MIPS code递归斐波那契汇编 MIPS 代码
【发布时间】:2012-11-19 09:21:27
【问题描述】:

我在模块编译器中为我的课程创建了一个代码生成器。它以 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 

【问题讨论】:

    标签: assembly recursion mips fibonacci


    【解决方案1】:

    该代码存在各种问题。

    1. 你应该减少$sp你写信给($sp)(虽然这只是按照惯例)
    2. 你应该保存$fp 你修改它(这是常识;))
    3. MIPS 通常使用寄存器来传递参数(但您可以 当然,你自己的约定)
    4. 您的堆栈处理非常复杂,至少在 main 中它是不平衡的
    5. 建议从main返回,不要使用exit系统调用

    在尝试生成一些 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
    

    注意我故意让它未优化。这种代码应该很容易生成。

    【讨论】:

    • 非常感谢您的回复,我会在您的帮助下修复我的代码^^
    猜你喜欢
    • 2020-08-11
    • 2012-11-06
    • 2013-10-13
    • 2011-08-02
    • 2015-12-21
    • 2021-07-18
    • 2014-06-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多