## LSU EE 4720 # ## Recursion example. # # Factorial procedure written recursively. (Inefficient, but easy to # understand.) # # Presented in class 1 October 2004 # Linkage (register usage) Rules for this Example: # # Caller Save: $tX, $fX, $aX (if caller will need values after return). # Callee Save: $ra, $sX .data ONE: .double 1.0 MSG: .asciiz "%/s0/d! = %/f0/.0f\n" .text .globl __start __start: addi $s0, $0, 0 MAINLOOP: mtc1 $s0, $f2 jal fact cvt.d.w $f2, $f2 la $a0, MSG addi $v0, $0, 11 syscall slti $t0, $s0, 20 bne $t0, $0, MAINLOOP addi $s0, $s0, 1 addi $v0, $0, 10 syscall ################################################################################ ## fact: Factorial # # Load constant 1.0 into register f4 and call fact1, which computes factorial. # fact: ## Register Usage # # CALL VALUE: $f2/$f2 Number, n, double. # RETURN VALUE: $f0/$f1 n! (0! = 1! = 1), double. # Save $ra on the stack. # sw $ra, -4($sp) addi $sp, $sp, -4 # Move stack pointer above saved registers. la $t0, ONE jal fact1 ldc1 $f4, 0($t0) # Restore $ra from stack and restore stack pointer. # addi $sp, $sp, 4 lw $ra, -4($sp) jr $ra nop ################################################################################ ## fact1: Factorial # # Return $f2! in $f0. # fact1: ## Register Usage # # CALL VALUE: $f2/$f3 Number, n, double. # CALL VALUE: $f4/$f5 1.0, double. (Used as a constant.) # RETURN VALUE: $f0/$f1 n! (0! = 1! = 1) # # Save $ra and $f2 on stack. # # $f4 is not saved because we know the called routine (this one) # won't modify it. # sdc1 $f2, -8($sp) sw $ra, -12($sp) addi $sp, $sp, -12 # # If n <= 1 return a 1. (Assume n is 0 or 1.) # c.le.d $f2, $f4 bc1t F1DONE mov.d $f0, $f4 # # Recursive call and factorial computation. # jal fact1 sub.d $f2, $f2, $f4 # n_for_called_routine = n - 1 ldc1 $f2, 4($sp) # Get "our" value of n from stack. mul.d $f0, $f0, $f2 F1DONE: # # Restore $ra and $sp. # # (Register $f2 was restored above, where needed.) # addi $sp, $sp, 12 lw $ra, -12($sp) jr $ra nop