#This program demonstrates procedures (also known as subroutines). #author: Hornick #CS2710 - 12/16/12 .text #.text directive (default) just tells the assembler that the following instructions are for the .text segment of memory main: #this label is assigned the value of the address of the next instruction jal proc1 # call the procedure (subroutine) at proc1 # Note that the address of the next instruction following jal is automatically stored in $ra # IMPORTANT: Before calling a procedure - by convention/contract - the calling code is required # to save the value of any $t, $v, or $a register it is using, since the procedure might modify modify those registers. # Saving is typically done by pushing those values onto the stack. After a procedure returns, the calling # code must restore those register values by popping them from the stack. The calling code does not have # to worry about saving/restoring any $s registers - that is the responsibility of the procedure (see below). addi $a0, $zero, 1 # prepare the arguments for the call to addFiveNumbers addi $a1, $zero, 2 addi $a2, $zero, 3 addi $a3, $zero, 4 addi $t0, $zero, 5 sw $t0, ($sp) # push arg5 onto the stack addi $sp, $sp, -4 # decrement $sp jal addFiveNumbers # call the procedure; note that $v0 will contain the return value after the call! # In this code, we used the $t0 register and set it to 5. But addFiveNumbers modified $t0, so we # might want to restore the value here. addi $sp, $sp, 4 # increment $sp, restoring its initial value lw $t0, ($sp) # pop the t0 value from the stack continue: j main # repeat this instruction forever ################################################################################################## # This is procedure proc1. Minimally, every procedure should push the return address (stored in $ra) # onto the stack at the very beginning, and pop the return address from the stack back into $ra # before returning. IN ADDITION, the procedure - by convention/contract - pushes the values of any $s # registers (that it will modify) onto the stack at the beginning, and pop those values off the stack and # back into the $s registers at the end (thus restoring their initial values). This is why the $s # registers are called "saved registers" - because procedures save their values. Note that a procedure # is free to modify any $t, $v, or $a registers without needing to worry about saving/restoring them - that # is the responsibility of the CALLER. proc1: sw $ra, ($sp) # push the return address onto the stack addi $sp, $sp, -4 # decrement $sp (by 4 bytes) to point at the next available stack location addi $sp, $sp, 4 # increment $sp (by 4 bytes) to point to the return address lw $ra, ($sp) # pop the return address from the stack jr $ra # return to the instruction referenced by $ra (return address register) # end procedure proc1 ################################################################################################## ################################################################################################## # This is procedure proc2 proc2: sw $ra, ($sp) # push the return address onto the stack addi $sp, $sp, -4 # decrement $sp to point at the next available stack location addi $sp, $sp, 4 # increment $sp to point to the return address lw $ra, ($sp) # pop the return address from the stack jr $ra # return to the instruction referenced by $ra (return address register) # end procedure proc2 ################################################################################################## ################################################################################################## # This is procedure addFiveNumbers; it addes 5 values passed as arguments. The first four arguments # are passed via registers $a0-$a3. The 5th value is passed on the stack. The sum of the 5 values is # returned via register $v0. addFiveNumbers: sw $ra, ($sp) # push the return address onto the stack addi $sp, $sp, -4 # decrement $sp to point at the next available stack location addi $t0, $zero, 0 # set t0=0 add $v0, $zero, $t0 # initialize the sum: v0=0 add $v0, $v0, $a0 # v0 += a0 add $v0, $v0, $a1 # v0 += a1 add $v0, $v0, $a2 # v0 += a2 add $v0, $v0, $a3 # v0 += a3 lw $t1, 8($sp) # get the 5th arg from the stack # Note we need an offset of 8 since $sp has been decremented at start of the procedure! add $v0, $v0, $t1 # v0 += t1 addi $sp, $sp, 4 # increment $sp to point to the return address lw $ra, ($sp) # pop the return address from the stack jr $ra # return to the instruction referenced by $ra (return address register) # end procedure addFiveNumbers ##################################################################################################