Leaf and NonLeaf Procedures Recursion in MIPS 1

  • Slides: 10
Download presentation
Leaf and Non-Leaf Procedures Recursion in MIPS 1 A leaf procedure is one that

Leaf and Non-Leaf Procedures Recursion in MIPS 1 A leaf procedure is one that doesn't all any other procedures. A non-leaf procedure is one that does call another procedure. Non-leaf procedures pose an additional, but simple, challenge; we make procedure calls by executing a jump-and-link instruction: jal procedure_0 # puts PC+4 into $ra for return But, if procedure_0 also makes a call, say jal procedure_1 # puts PC+4 into $ra for return the original return address just got overwritten… the effect is fascinating… CS@VT August 2009 Computer Organization I © 2006 -09 Mc. Quain, Feng & Ribbens

Preserving the Return Address Recursion in MIPS 2 Non-leaf procedures must back up the

Preserving the Return Address Recursion in MIPS 2 Non-leaf procedures must back up the value of their return address before making a call to another procedure: addi sw $sp, -4 $ra, 0($sp) # make room on stack # save return address And they must restore the return address before they attempt to return: lw addi $ra, 0($sp) $sp, 4 # retrieve return address # pop it off the stack Failure to do this will almost certainly lead to a catastrophic runtime failure. The safest way to do this is to back up the address immediately when the procedure is entered, and to restore it immediately before the return is executed. Of course, you must keep careful track of the stack pointer during all of this… CS@VT August 2009 Computer Organization I © 2006 -09 Mc. Quain, Feng & Ribbens

Factorial: First Version Recursion in MIPS 3 ################################## Returns factorial of parameter. # Unfortunately,

Factorial: First Version Recursion in MIPS 3 ################################## Returns factorial of parameter. # Unfortunately, fac 1 falls into # Pre: an infinite loop when it's # $a 0 stores N called with any value larger # Post: than 1 for $a 0. # $v 0 stores N! # # Modifies: $t 0, $t 1, $v 0, $a 0 # fac 1: li $t 0, 1 # check for base case bgt $a 0, $t 0, recurse li $v 0, 1 # if so, set $v 0 jr $ra # and return recurse: move addi jal mul jr CS@VT August 2009 $t 1, $a 0, -1 fac 1 $v 0, $t 1 # # $ra # Computer Organization I save N calc N-1 for recursive call calc (N-1)! multiply that by N and return © 2006 -09 Mc. Quain, Feng & Ribbens

What went wrong? Recursion in MIPS 4 fac 1: li bgt li jr recurse:

What went wrong? Recursion in MIPS 4 fac 1: li bgt li jr recurse: move addi jal mul jr $t 0, 1 $a 0, $t 0, recurse $v 0, 1 $ra # check for base case $t 1, $a 0, -1 fac 1 $v 0, $t 1 # # $ra # # if so, set $v 0 # and return save N calc N-1 for recursive call calc (N-1)! multiply that by N and return Making the recursive call overwrites the original return address with the address of what? And the effect of that is…. ? An infinite loop in a pgm with no loops. And the moral of that is…. ? Back up $ra before a call in a non-leaf proc. CS@VT August 2009 Computer Organization I © 2006 -09 Mc. Quain, Feng & Ribbens

Factorial: Second Version Recursion in MIPS 5 fac 2: li bgt li jr recurse:

Factorial: Second Version Recursion in MIPS 5 fac 2: li bgt li jr recurse: move addi sw jal mul lw addi jr $t 0, 1 $a 0, $t 0, recurse $v 0, 1 $ra # check for base case $t 1, $a 0, $sp, $ra, fac 2 $v 0, # save N # calc N-1 for recursive call # save return address on stack $a 0, -1 $sp, -4 ($sp) $v 0, $t 1 $ra, ($sp) $sp, 4 $ra # if so, set return value # and return # calc (N-1)! # multiply that by N # restore return address # and return Unfortunately, fac 2 returns 32 when called with $a 0 == 6. CS@VT August 2009 Computer Organization I © 2006 -09 Mc. Quain, Feng & Ribbens

What went wrong? Recursion in MIPS 6 fac 2: . . . recurse: move

What went wrong? Recursion in MIPS 6 fac 2: . . . recurse: move addi sw jal mul lw addi jr $t 1, $a 0, $sp, $ra, fac 2 $v 0, $a 0, -1 $sp, -4 ($sp) $v 0, $t 1 $ra, ($sp) $sp, 4 $ra # save N # calc N-1 for recursive call # save return address on stack # calc (N-1)! # multiply that by N # restore return address # and return During the recursive call, the previous contents of $t 1 and $a 0 are overwritten. Moral: before making a call, back up your registers as necessary. CS@VT August 2009 Computer Organization I © 2006 -09 Mc. Quain, Feng & Ribbens

What went wrong: Details Recursion in MIPS 7 Let's say we call this with

What went wrong: Details Recursion in MIPS 7 Let's say we call this with $a 0 set to 3: fac 2: . . . recurse: move addi sw jal mul lw addi jr $t 1, $a 0, $sp, $ra, fac 2 $v 0, $a 0, -1 $sp, -4 ($sp) $v 0, $t 1 $ra, ($sp) $sp, 4 $ra In the first (nonrecursive) call, fac 2: - puts 3 into $t 1 - sets $a 0 to 2 fac 2: - mult $t 1 and $v 0 - returns 4 In the second call, fac 2: - puts 2 into $t 1 fac 2: - sets $a 0 to 1 - mult $t 1 and $v 0 - returns 2 In the third call, fac 2: - puts 1 into $v 0 - returns Moral: before making a call, back up your registers as necessary. CS@VT August 2009 Computer Organization I © 2006 -09 Mc. Quain, Feng & Ribbens

Factorial: Stack Organization Recursion in MIPS 8 In order to fix the execution of

Factorial: Stack Organization Recursion in MIPS 8 In order to fix the execution of the recursive factorial procedure, we need to use the stack to save values that would otherwise be overwritten when a recursive call takes place. Here's one idea for organizing the stack: | | old $sp | | 0 x 7 FFFEFFC +-------------+ | saved return address | +-------------+ new $sp | saved N | 0 x 7 FFFEFF 4 +-------------+ CS@VT August 2009 Computer Organization I on entry to proc after saving return address and N © 2006 -09 Mc. Quain, Feng & Ribbens

Factorial: Third Version Recursion in MIPS 9 fac 3: li bgt li jr $t

Factorial: Third Version Recursion in MIPS 9 fac 3: li bgt li jr $t 0, 1 $a 0, $t 0, recurse $v 0, 1 $ra # check for base case addi sw sw $sp, -8 $ra, 4($sp) $a 0, 0($sp) # make room on stack for # return address, and # N addi jal $a 0, -1 fac 3 # calc N-1 for recursive call # calc (N-1)! lw mul $t 1, 0($sp) $v 0, $t 1 # restore N from stack # multiply (N-1)! by N lw $ra, 4($sp) addi jr $sp, 8 $ra # restore return address from # stack # and restore stack pointer # and return # if so, set return value # and return recurse: CS@VT August 2009 Computer Organization I © 2006 -09 Mc. Quain, Feng & Ribbens

Factorial: Stack Trace Recursion in MIPS 10 Say we call factorial(3): | | old

Factorial: Stack Trace Recursion in MIPS 10 Say we call factorial(3): | | old $sp | | 0 x 7 FFFEFFC +-------------+ | saved $ra to main | +-------------+ $sp | saved 3 | 0 x 7 FFFEFF 4 +-------------+ | saved $ra to 1 st call | +-------------+ new $sp | saved 2 | 0 x 7 FFFEFEC +-------------+ on first call (not recursive) on second call (recursive) Third call triggers base case and returns with $v 0 == 1 Saved value of N (2) is retrieved from stack and multiplied to $v 0; 2*1 is returned to from second call. Saved value of N (3) is retrieved from stack and multipled to $v 0; 3*2*1 is returned from first call. CS@VT August 2009 Computer Organization I © 2006 -09 Mc. Quain, Feng & Ribbens