Computer Architecture Week 06 Instruction Set Architectures (4) College of Information Science and Engineering Ritsumeikan University
subroutines functions, procedures remember the next instruction s address call (jump to the start of) the subroutine perform some computation return control to the remembered address in MIPS the instruction that calls a subroutine is jal, jump and link the address of the next instruction is placed in register $ra (the return address) the program counter is loaded with the address of the subroutine s first instruction the instruction that returns from a subroutine is jr, jump to register the value in a register is moved to the program counter e.g., register $ra execution continues from that address 2
doubling a number in Python def double(n): return n + n print double(21) subroutines doubling a number in MIPS machine language address of next instruction (move) saved in register $ra main: li $a0, 21 jal double move $a0, $v0 li $v0, 1 syscall li $v0, 10 syscall # double the number in a0 # return the result in v0 double: add $v0, $a0, $a0 jr $ra $ra moved to program counter, execution returns to the move instruction following the call main calls the subroutine double main is the caller, and double is the callee 3
only one level of subroutine can be called subroutines li $a0, 20 jal add1dbl # $ra = address of move, jump to add1dbl move $a0, $v0... add1dbl: jal add1 # $ra = address of next instruction jal double # $ra = address of next instruction jr $ra # infinite loop! add1: add $a0, $a0, 1 jr $ra calling add 1dbl saves a return address in $ra the call to add 1 immediately destroys the value saved in $ra the call to add1 will work correctly, but returning from add 1dbl is now impossible 4
subroutines to fix this problem, each function can allocate some memory to store its own local variables save $ra in that local memory perform some computation (including calling more functions) restore $ra from the value saved in local memory deallocate the memory return to the caller where to get some memory to store local variables? 5
subroutines every process (i.e., running program) has a stack for storing temporary values in last-in first-out order which is just what we need the stack grows downward pushing things onto the stack extends it towards lower memory addresses 6
subroutines the register $sp contains the address of the top of the stack to allocate memory on the stack, subtract the amount you need from $sp higher addresses end of stack allocated allocated allocated allocated lower addresses unallocated $sp points to the most recent data pushed on the stack 8 bytes of local memory unallocated subtract 8 $sp the program can now use 0($sp)... 7($sp) for local values to deallocate (free) the memory, add the same value back to $sp 7
at function entry and exit: subroutines func: addi $sp, $sp, -12 # space for 3 words sw $ra, 8($sp) # save return address...... # subroutine can use 0($sp) and 4($sp)... # to store local variables... lw $ra, 8($sp) # restore return address addi $sp, $sp, 12 # deallocate 3 words jr $ra # return $sp + 8 $sp + 4 $sp + 0 saved $ra local variable local variable saved $ra local variable local variable saved $ra local variable local variable function call function call $sp def factorial(n): if n < 2: return 1 return n * factorial(n-1) factorial: addi $sp, $sp, -8 # allocate two words sw $ra, 4($sp) # save return address addi $v0, $a0, -1 bgtz $v0, ok # n > 1 li $v0, 1 # return 1 j return ok: sw $a0, 0($sp) # save n addi $a0, $a0, -1 # n-1 jal factorial # v0 = factorial(n-1) lw $a0, 0($sp) # restore a0 mul $v0, $a0, $v0 # v0 = n*fact(n-1) return: lw $ra, 4($sp) # restore ret addr addi $sp, $sp, 8 # deallocate jr $ra # return 8
register conventions registers $s0... $s7 are callee-saved if you use them in a subroutine, you must save them in the stack and restore their original values before returning i.e., you (the callee) saves them during function calls the other registers ($an, $tn, $vn) are caller-saved their values can be destroyed during function calls (and your code should assume they always will be) if you need their values preserved during function call, save them before calling the function and restore them after the call i.e., you (the caller) saves them during function calls 9
practice 10
glossary allocate reserve some memory for a specific use. call a generic name for an instruction that calls a subroutine, e.g., jal in MIPS machine code. callee a generic name for an instruction that calls a subroutine, e.g., jal in MIPS machine code. callee-saved a register that must be preserved by the subroutine during its execution. callee the subroutine that is being called. caller the program or routine that calls a subroutine. caller-saved a register that can be destroyed by a subroutine, and must be preserved by the caller if necessary. deallocate release some memory that was earlier allocated, freeing it for reuse. function the high-level language idea of a subroutine that returns a value. procedure the high-level language idea of a subroutine that does not return any value. stack a last-in first-out data structure on which values can be pushed, and later popped (or pulled) to recover those same values in the opposite order. 11
subroutine a sequence of instructions that can be called out-of-line in a program, performing some task before returning to the instruction after the call. 12