Tom Kelliher, CS 220
None.
Study factorial.spim.
Definitions:
Example. Suppose main calls factorial, using an on-stack
parameter ( n) pass.
factorial uses $s0
and has a local
variable, temp:
Example code snippets:
lw $s0, 4($fp) sw $s0, -12($fp) sw $s0, 0($sp) sub $sp, $sp, 4
$sp
vs. $fp
.
Convention:
$v[0-1]
--- function results.
$a[0-3]
--- function arguments.
$t[0-9]
--- caller save registers. (Except for two global
pointers, ignore these registers.)
$s[0-7]
--- callee save registers.
$sp
--- top of stack pointer, pointing to first free location
on execution stack.
$fp
--- frame pointer, pointing to base of current frame.
$ra
--- return address.
$ra
(among others) and executes
jr $ra
.
Use this sequence. Assume caller is calling callee.
Caller:
jal callee
Callee:
$sp
.
Number of words needed:
$fp
and $ra
.
$sx
register used.
$sp
as base register.
$fp
by adding frame size to $sp
and storing.
$fp
as
base register.
$ax
registers.
$sp
as base register.
$sp
.
jr $ra
Caller:
Consider the following C++ code which recursively computes the factorial:
#include <iostream.h> int getnum(void); int factorial(int n); int main() { int value; cout << "Enter 0 to exit.\n"; value = getnum(); while (value != 0) { cout << "Factorial: " << factorial(value) << endl; value = getnum(); } return 0; } int getnum(void) { int num; cout << "Number: "; cin >> num; return num; } int factorial(int n) { if (n <= 1) return 1; return n * factorial(n - 1); }
Here is the corresponding SPIM program:
# factorial.spim --- A recursive SPIM program. Demonstrates function # call and return. .data prompt: .asciiz "Number: " nl: .asciiz "\n" instr: .asciiz "Enter 0 to exit.\n" response: .asciiz "Factorial: " ###################################################################### # main ###################################################################### .text .globl main main: sub $sp, $sp, 16 # Push frame & save registers. sw $fp, 16($sp) sw $ra, 12($sp) sw $s0, 8($sp) add $fp, $sp, 16 li $v0, 4 # Print instruction. la $a0, instr syscall jal getnum # Get a number from keyboard. sw $v0, -12($fp) # Store locally. move $s0, $v0 while1: beqz $s0, endwhile1 # Compute until 0 entered. li $v0, 4 # Print response prompt. la $a0, response syscall move $a0, $s0 # Pass argument jal factorial # Call move $a0, $v0 # Copy return value to print it li $v0, 1 syscall li $v0, 4 # Prepare to read next number. la $a0, nl syscall jal getnum sw $v0, -12($fp) # Store number just read. move $s0, $v0 b while1 endwhile1: lw $s0, 8($sp) # Restore registers and pop frame. lw $ra, 12($sp) lw $fp, 16($sp) add $sp, $sp, 16 li $v0, 0 jr $ra # Exit. ###################################################################### # getnum --- returns integer read from keyboard through $v0. ###################################################################### .text getnum: sub $sp, $sp, 12 # push frame & save registers. sw $fp, 12($sp) sw $ra, 8($sp) add $fp, $sp, 12 li $v0, 4 la $a0, prompt syscall li $v0, 5 syscall # Value read left in $v0. sw $v0, -8($fp) lw $ra, 8($sp) # restore registers & pop frame. lw $fp, 12($sp) add $sp, $sp, 12 jr $ra ###################################################################### # factorial --- compute factorial of $a0 and return result through # $v0 ###################################################################### .text factorial: sub $sp, $sp, 16 sw $fp, 16($sp) sw $ra, 12($sp) sw $s0, 8($sp) add $fp, $sp, 16 sw $a0, -12($fp) # Our value n. move $s0, $a0 bgt $s0, 1, recurse # Base case. Return 1 li $v0, 1 lw $s0, 8($sp) lw $ra, 12($sp) lw $fp, 16($sp) add $sp, $sp, 16 jr $ra recurse: sub $a0, $a0, 1 # Recursive call. Compute (n-1)! jal factorial mul $v0, $v0, $s0 # n * (n-1)! lw $s0, 8($sp) lw $ra, 12($sp) lw $fp, 16($sp) add $sp, $sp, 16 jr $ra