2016-05-18 15 views
0

この再帰関数をMIPSにコーディングしようとしています。 私の問題は、どのように再帰的なステップを行うことができるか分かりません。
私は残りの部分が正しいと確信しています。MIPS Help:再帰関数

int recur(int n) { 
    if(n == 1 || n == 2) { 
      return 2; 
    } else { 
      return (n-4)+n*recur(n-2); 
    } 
} 
.data 

promptMessage: .asciiz "Enter a number that is greater than or equal to 0: " 
resultMessage: .asciiz "\nThe answer is: " 
input: .word 0 
answer: .word 0 

.text 
.globl main 

main: 
#Read the number from the user 
li $v0, 4   
la $a0, promptMessage  
syscall 

li $v0, 5   
syscall   

sw $v0, input   

#Call the function 
lw $a0, input   
jal recur   
sw $v0, answer  

#Display result 
li $v0, 4 
la $a0, resultMessage  
syscall 

li $v0, 1   
lw $a0, answer   
syscall 

.globl recur 

recur: 
addi $sp, $sp, -8  
sw $a0, 0($sp)   
sw $ra, 4($sp)   

#Base Case if(n == 0 || n == 1) return 2; 
li $v0, 2 
beq $a0, $zero, DONE 
beq $a0, 1, DONE 

#RECURSIVE STEP 
addi $a0, $a0, -2  
jal recur   
+0

を、あなたはあなたの質問が壊れフォーマットで出てくる見た場合にそれを修正してくださいあなた自身。次回はプレビューを使用してください。コードに関しては、再帰が正しいことがわかりました。残っているのは、式を評価して関数から戻ることだけです。 – Jester

+0

Andrew、関数が "再帰的"であるとき、それが何を意味するかあなた自身の言葉で教えてください。 –

+0

n <= 0の場合、関数はスタック領域を使い果たすまで繰り返します。 if(n <= 2)が2を返してCの例を開始した方が良いかもしれません。 – rcgldr

答えて

0

あなたは素晴らしい仕事をしました。最初にCコードを作成する。あなたはとても近くにいた。

計算ステップと関数エピログコードを追加する必要がありました。

また、メインプリント後に番号がで、のシステムコール10(終了)があったため、コードが無限に流れて無限に再帰するバグがありました。

CIPSを少し修正したので、MIPSコードと互換性があります。

楽しいと簡単なテストのために、私はループをメインに変更し、負の数になるまで再起動しました。

私は[無償スタイルのクリーンアップをご容赦ください]クリーンアップとコードをテストし、注釈を追加しました:他人への礼儀として

.data 

# NOTE: these should appear first to maintain alignment to a 4 byte boundary 
# (or the .align 4 will do it) otherwise, the lw/sw ops can fail on an 
# alignment exception 
    .align 4 
input:  .word  0 
answer:  .word  0 

promptMessage: .asciiz "Enter a number that is greater than or equal to 0 (-1 to stop): " 
resultMessage: .asciiz "\nThe answer is: " 
nl:   .asciiz "\n" 

    .text .globl 

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

    # Read the number from the user 
    li  $v0,5 
    syscall 
    sw  $v0,input 

    # negative value means stop 
    # NOTE: added this 
    bltz $v0,main_exit 

    # Call the function 
    lw  $a0,input 
    jal  recur 
    sw  $v0,answer 

    # Display result message 
    li  $v0,4 
    la  $a0,resultMessage 
    syscall 

    # display number 
    li  $v0,1 
    lw  $a0,answer 
    syscall 

    # output newline 
    li  $v0,4 
    la  $a0,nl 
    syscall 

    # NOTE: this was added to allow multiple tries, but without it, there was 
    # the bug below 
    j  main 

    # BUG: syscall to exit here was _missing_ so got fallthrough into "recur" 
    # causing the stack to overflow 
main_exit: 
    li  $v0,10 
    syscall 

    .globl recur 

# recur -- recursion 
# 
# arguments: 
# a0 -- the "n" value 
# 
# pseudo code: 
# * int 
# * recur(int n) 
# * { 
# *  int r; 
# * 
# *  if (n == 1 || n == 2) { 
# *   return 2; 
# *  } 
# * 
# *  r = recur(n - 2); 
# * 
# *  return (n - 4) + (n * r); 
# * } 
recur: 
    addi $sp,$sp,-8 
    sw  $a0,0($sp) 
    sw  $ra,4($sp) 

    # Base Case if(n == 0 || n == 1) return 2; 
    li  $v0,2 
    beq  $a0,$zero,recur_done 
    beq  $a0,1,recur_done 

    # RECURSIVE STEP 
    addi $a0,$a0,-2   # n -= 2 
    jal  recur 
    lw  $a0,0($sp)   # we need "n" back (not (n - 2)) 

    # NOTE: this calculation was missing 
    mul  $v0,$v0,$a0   # r *= n (i.e. (n * r)) 
    addi $a0,$a0,-4   # n -= 4 (i.e. (n - 4)) 
    add  $v0,$v0,$a0   # sum them 

    # NOTE: this is the standard reversal for this function's stack prolog 
recur_done: 
    lw  $a0,0($sp) 
    lw  $ra,4($sp) 
    addi $sp,$sp,8 
    jr  $ra