#----------------------------------------------------------------------------# # example11.a # # Joe Schmoe # Purpose: show how procedures work, version 2 # (uses activation stack) # Input: none # Output: 5+(10-1) = 14 #----------------------------------------------------------------------------# .data hello: .asciiz "\nProcedure example\n\n" ansis: .asciiz "Sum is: " endl: .asciiz "\n" #----------------------------------------------------------------------------# # first 4 arguments to a function = $a0..$a3 # $t0..$t9 are local # $s0..$s7 are global # $fp = frame pointer -> points to "bottom" of activation record # $sp = stack pointer -> points to first free location on stack # jal == return, stores address in $ra # $v0 holds return value if procedure returns a value .text .globl main main: li $v0, 4 la $a0, hello syscall # Set up actual arguments li $a0, 5 li $a1, 10 # Here is the procedure call (adder) jal adder # Print out answer move $t0, $v0 # store result temporarily ("result") li $v0, 4 # because $v0 is needed for output la $a0, ansis syscall move $a0, $t0 li $v0, 1 syscall # Print out endl (twice) li $v0, 4 la $a0, endl syscall la $a0, endl syscall done: li $v0, 10 syscall #----------------------------------------------------------------------------# # Procedure adder # The difference this time is that we need to store our local information; # that is, the two arguments and the return address of main(). Otherwise, # we can't get back to the calling function (main()). .data inpro: .asciiz "In procedure\n" .text adder: # Allocate storage for frame subu $sp, $sp, 32 # size as we computed # Save return address sw $ra, 20($sp) # Save frame pointer sw $fp, 16($sp) # Reset frame pointer addu $fp, $sp, 28 # Save arguments sw $a0, -4($fp) # save argument (5); same as 24($sp) sw $a1, 0($fp) # save argument (10) # The value in a1 must be passed to the next function as a0 (first argument) move $a0, $a1 # Call subone, which will return result in $v0 jal subone # Load up previous value for "one" lw $t0, -4($fp) # Return value is in $v0 add $v0, $t0, $v0 # Reload registers (i.e., undo what we did at beginning of procedure) lw $ra, 20($sp) lw $fp, 16($sp) addu $sp, $sp, 32 j $ra # jump back to main's address #----------------------------------------------------------------------------# # Procedure subone .data .text subone: sub $v0, $a0, 1 j $ra