2016-09-20 130 views
0

所以,我正在MIPS中的斐波那契工作,并且规则是我需要有一个解决问题的递归方法的序言。我的代码目前产生错误的输出,我无法确定哪个部分应该被编辑。MIPS斐波那契使用递归

.text 

main: li $v0, 5 
    syscall 
    move $a0, $v0 
    move $v0, $zero 
    jal fibo 

    move $t2, $v0 
    li $v0, 1 
    move $a0, $t2 
    syscall 

    li $v0, 10 
    syscall 


fibo: ####preamble#### #push from stack 
     subu $sp, $sp, 32 
     sw $ra, 0($sp)  #store return address 
     sw $a0, 4($sp) 
     sw $fp, 8($sp) 
     sw $v0, 12($sp) 
     addu $fp, $sp, 32 
     ####preamble####  

zero: bne $a0, 0, one 
     move $v0, $a0 
     jr $ra 

one: bne $a0, 1, fn1 
     move $v0, $a0 
     jr $ra 

fn1: subi $a0, $a0, 1 #call for fibo(n-1) 
     jal fibo   #recursive 

     lw $a0, 4($sp) 
     addi $a0, $a0, 1 

     subi $a0, $a0, 2 #call for fibo(n-2) 
     jal fibo   

result: lw $ra, 0($sp)  #load ra 
     lw $fp, 8($sp) 
     lw $t0, 12($sp) 
     add $v0, $t0, $v0 
     addu $sp, $sp, 32 
     addu $fp, $fp, 32 
     jr $ra 
+0

SPIM/MARS有一个单步功能,您可以用它逐步执行代码指令。 – Michael

+0

欢迎来到StackOverflow。请阅读并遵守帮助文档中的发布准则。 [最小,完整,可验证的示例](http://stackoverflow.com/help/mcve)适用于此处。在您发布代码并准确描述问题之前,我们无法有效帮助您。具体而言,请提供实际输出,预期输出以及迄今为止尝试追踪它的结果。 – Prune

回答

1

好的,你的基本结构和组件正确,但不幸的是,有一些错误。

我已经创建了两个版本的程序。一个带有详细说明错误的评论。而且,用的东西清理第二个版本,简化,工作


这里的注释版本[请原谅无偿风格清理]:

.text 

main: 
    li  $v0,5 
    syscall 
    move $a0,$v0 

    # NOTE/BUG: doing this is unnecessary/wrong if fibo is correct 
    move $v0,$zero 

    jal  fibo 

    move $t2,$v0 
    li  $v0,1 
    move $a0,$t2 
    syscall 

    li  $v0,10 
    syscall 

####preamble#### #push from stack 
fibo: 
    # NOTE/BUG: for simple functions like this, setting up fp is extra work 
    # NOTE/BUG: we want to have extra space in the frame but we don't need 
    # to push/pop for some 
    subu $sp,$sp,32 
    sw  $ra,0($sp)    # store return address 
    sw  $a0,4($sp) 
    sw  $fp,8($sp) 
    sw  $v0,12($sp) 
    addu $fp,$sp,32 
    ####preamble#### 

    # NOTE/BUG: we must zero out t0 so that the add in result: is valid 

    # NOTE/BUG: a stack frame has already been established -- it must be popped 
    # we can _not_ just do a "jr" here 
zero: 
    bne  $a0,0,one 
    move $v0,$a0 
    jr  $ra 

    # NOTE/BUG: a stack frame has already been established -- it must be popped 
one: 
    bne  $a0,1,fn1 
    move $v0,$a0 
    jr  $ra 

fn1: 
    subi $a0,$a0,1    # call for fibo(n-1) 
    jal  fibo     # recursive 

    # NOTE/BUG: we must save the result for fibo(n-1) in our stack frame 

    # NOTE/BUG: this is incorrect -- by doing it, we [effectively] do fibo(n-1) 
    # again (i.e.) (n+1)-2 --> (n-1) and _not_ (n-2) as we wish 
    # do one of these but _not_ both 
    lw  $a0,4($sp) 
    addi $a0,$a0,1 

    subi $a0,$a0,2    # call for fibo(n-2) 
    jal  fibo 

    # NOTE/BUG: fibo(n-1) must be added to fibo(n-2) 

result: 
    lw  $ra,0($sp)    # load ra 
    lw  $fp,8($sp) 

    # NOTE/BUG: this is misplaced because entering this block should already 
    # have v0 set correctly 
    lw  $t0,12($sp) 
    add  $v0,$t0,$v0 

    # NOTE/BUG: the correct way to restore $fp is using: lw $fp,8($sp) 
    addu $sp,$sp,32 
    addu $fp,$fp,32 
    jr  $ra 

这里的工作版本:

.data 
msg_ask: .asciiz  "Enter n for fibonacci(n) (-1=stop): " 
msg_fibo: .asciiz  "fibonacci(n) is: " 
msg_nl:  .asciiz  "\n" 
    .text 

main: 
    # prompt user 
    la  $a0,msg_ask 
    li  $v0,4 
    syscall 

    # get number from user 
    li  $v0,5 
    syscall 
    move $a0,$v0 
    bltz $a0,main_exit 

    jal  fibo 
    move $t2,$v0     # save the result 

    # print message 
    la  $a0,msg_fibo 
    li  $v0,4 
    syscall 

    # print the result 
    li  $v0,1 
    move $a0,$t2 
    syscall 

    # print message 
    la  $a0,msg_nl 
    li  $v0,4 
    syscall 

    j  main 

main_exit: 
    li  $v0,10 
    syscall 

# fibo -- recursive fibonacci 
# 
# RETURNS: 
# v0 -- fibonacci(n) 
# 
# arguments: 
# a0 -- the "n" for the Nth fibonacci number 
# 
# registers: 
# t0 -- temporary 
fibo: 
    # fibo(0) is 0 and fibo(1) is 1 -- no need to establish a stack frame 
    bgt  $a0,1,fibo_full   # do we need recursion? if yes, fly 
    move $v0,$a0     # no, just set return value 
    jr  $ra      # fast return 

    # establish stack frame 
    # we need an extra cell (to preserve the result of fibo(n-1)) 
fibo_full: 
    # this gives us a temp word at 0($sp) 
    subu $sp,$sp,12    # one more than we need 
    sw  $ra,4($sp) 
    sw  $a0,8($sp) 

    subi $a0,$a0,1    # call for fibo(n-1) 
    jal  fibo     # recursive 
    sw  $v0,0($sp)    # save result in our frame (in extra cell) 

    subi $a0,$a0,1    # call for fibo(n-2) 
    jal  fibo     # recursive 

    lw  $t0,0($sp)    # restore fibo(n-1) from our stack frame 
    add  $v0,$t0,$v0    # result is: fibo(n-1) + fibo(n-2) 

    # restore from stack frame 
    lw  $ra,4($sp) 
    lw  $a0,8($sp) 
    addu $sp,$sp,12 

    jr  $ra      # return