# # simple example demonstrating a procedure call # (adapted from example by former colleague M. Eggen) # # this program is an approximate translation of the following C code: # # int main(void) { # int a, b, c, x; # a = 5; b = 6; c = 7; # x = addproc(a, b, c); # return 0; # } # int addproc(int a, int b, int c) { # return a + b + c; # } .globl main main: # opening linkage (save return address) addi $sp, $sp, -4 sw $ra, 0($sp) # # register usage: # a $s0 # b $s1 # c $s2 # x $s3 # # initialize variables addi $s0, $zero, 5 addi $s1, $zero, 6 addi $s2, $zero, 7 # set up parameters for call add $a0, $zero, $s0 add $a1, $zero, $s1 add $a2, $zero, $s2 # call addproc jal addproc # use returned value add $s3, $v0, $zero # set return value of 0 from main add $v0, $zero, $zero # closing linkage (get return address and restore stack pointer) lw $ra, 0($sp) addi $sp, $sp, 4 jr $ra # # addproc procedure # addproc: # opening linkage (save return address and registers) # we save all registers even though we aren't using them -- "good practice" addi $sp, $sp, -4 sw $ra, 0($sp) # here we could continue pushing things onto the stack by repeatedly # decrementing the stack pointer, but it's quicker to do one decrement .... addi $sp, $sp, -32 sw $s0, 0($sp) sw $s1, 4($sp) sw $s2, 8($sp) sw $s3, 12($sp) sw $s4, 16($sp) sw $s5, 20($sp) sw $s6, 24($sp) sw $s7, 28($sp) # do computation and set return value add $v0, $a0, $a1 add $v0, $v0, $a2 # closing linkage # "unwind the stack" # (restore registers, get return address, restore stack pointer) lw $s7, 28($sp) lw $s6, 24($sp) lw $s5, 20($sp) lw $s4, 16($sp) lw $s3, 12($sp) lw $s2, 8($sp) lw $s1, 4($sp) lw $s0, 0($sp) addi $sp, $sp, 32 lw $ra, 0($sp) addi $sp, $sp, 4 # return to caller jr $ra .end main