FUNCTION CALLS IN ASSEMBLY MIPS R 3000 LANGUAGE
FUNCTION CALLS IN ASSEMBLY MIPS R 3000 LANGUAGE (EXTENSIVE USEUpdated OF 7/11/2013 STACK)
FUNCTION CALL STACK � High-level languages hide the behind-thescenes details of stack allocations for function calls int ans = max(5, 17); int max(int x, int y) { if(x >= y) return x; else return y; } // Function call. max x = 5, y = 17 MAIN ans =
DYNAMIC MEMORY ALLOCATION � Space for objects created using “new” are allocated from a pool of memory called the heap. String messg = new String(“Java”); int[] A = new int[4]; messg “Java” A { 0, 0, 0, 0 }
MIPS MEMORY ALLOCATION � Text segment: holds the program instructions � Data segment: holds static and dynamically allocated program data � Stack segment: data, parameters, and local variables allocated for function calls
MIPS MEMORY MAP Stack Segment calls: find. Max(x, y); Dynamic Data malloc(sizeof(My. Struct)); Static Data Text Segment Reserved A: . word 1, 2, 3, 4, 5 MIPS program code
MIPS MEMORY MAP Stack Segment Stack grows downwards Dynamic Data Dynamic data grows upwards Static Data Text Segment Reserved
USING THE STACK � In general the assembly programmer should use space on the stack to store information relevant to a function or procedure call. � Parameters � Local variables declared inside the function � Save copy of registers whose contents are changed as result of being used as local variables � Save $ra on stack for recursive functions
THE MIPS STACK � Stack pointer register $sp holds the address of the topmost data element on the stack. � On MIPS the stack grows downwards in memory Address of next byte pushed on top has an address 1 less than current $sp. � Address of next word pushed on top has an address 4 less than current $sp. �
PUSH A BYTE ON “TOP” OF STACK # Assume $t 0 contains value of 8 -bit variable C. # Push low-order byte in $t 0 onto top of stack. addiu $sp, -1 sb $t 0, ($sp) $sp 0 x 7 FFF A 0 x 7 FFE B 0 x 7 FFD C 0 x 7 FFD $sp 0 x 7 FFC . . . BEFORE: $sp points to B the topmost value AFTER: $sp points to C the topmost value
POP BYTE FROM “TOP” OF STACK # Pop byte from top of stack into $t 0. lb $t 0, ($sp) addiu $sp, 1 $sp 0 x 7 FFF A 0 x 7 FFE B 0 x 7 FFD C $sp 0 x 7 FFF A 0 x 7 FFE B 0 x 7 FFD 0 x 7 FFC . . . BEFORE: $sp points to C the topmost value AFTER: $sp points to B the topmost value
PUSH A WORD ON “TOP” OF STACK # Assume $t 0 contains value of variable C. # Push word in $t 0 onto top of stack. addiu $sp, -4 sw $t 0, ($sp) $sp 0 x 7 FFF A 0 x 7 FFB B 0 x 7 FF 7 C 0 x 7 FF 7 $sp 0 x 7 FF 3 . . . BEFORE: $sp points to B the topmost value AFTER: $sp points to C the topmost value
POP WORD FROM “TOP” OF STACK # Pop word from top of stack into $t 0. lw $t 0, ($sp) addiu $sp, 4 $sp 0 x 7 FFF A 0 x 7 FFB B 0 x 7 FF 7 C $sp 0 x 7 FFF A 0 x 7 FFB B 0 x 7 FF 7 0 x 7 FF 3 . . . BEFORE: $sp points to C the topmost value AFTER: $sp points to B the topmost value
EVALUATION OF ARITHMETIC EXPRESSIONS � Given the infix expression: 10 + 4 * 5 � Convert � Use to postfix: 10 4 5 * + a stack algorithm to evaluate the postfix expression. What was that algorithm?
EVALUATE POSTFIX WITH A STACK � Given postfix: 10 4 5 * + � Loop through tokens from left to right. � If token is an operand push it on stack. � If token is an operator then � Pop its operands from stack � Evaluate that operator � Push result on stack
WRITE CODE TO EVALUATE THIS POSTFIX � See Stack. Post. Fix. asm source code file
ALLOCATING LOCAL VARIABLES � Suppose a function declares and initializes the following local variables. public static void f() { int a = 0, b = 1; char c = ‘A’; // ASCII code is 65 }
LOCAL VARIABLE MEMORY MAP � Suppose that we “carve” out stack space corresponding to pushing each local variable in order of its declaration. BOTTOM a (4 bytes) b (4 bytes) c (1 byte) TOP • How many bytes to deduct from $sp to allocate the space? • Where does $sp point to? • What are the offsets from $sp for each local variable?
LOCAL VARIABLE MEMORY MAP � Suppose that we “carve” out stack space corresponding to pushing each local variable in order of its declaration. BOTTOM +5 a (4 bytes) +1 b (4 bytes) +0 c (1 byte) $sp TOP • How many bytes to deduct from $sp to allocate the space? 9 • Where does $sp point to? C • What are the offsets from $sp for each local variable?
ALLOCATE & DE-ALLOCATE IN “BULK” # Decrement stack pointer to allocate space for # ALL three variables in one shot. # Two 32 -bit words + One byte = 9 bytes addiu $sp, -9 sw $zero, 5($sp) # a = 0 li $t 0, 1 # b = 1 sw $t 0, 1($sp) li $t 0, 65 # c = ‘A’ sbu $t 0, 0($sp) … # Deallocate 9 bytes from stack when function exits addiu $sp, 9
ARRAY SUM Allocate local variables on the stack in order of their declarations. All reads/writes to local variables must be done through the stack. { int[] A = { 1, 3, 5, 7 }; // Allocate on stack int sum = 0, i = 0; while(i < 4) { sum = sum + A[i]; i++; } }
WRITE CODE TO PERFORM ARRAYSUM � See Array. Sum 1. asm source code file �. . MIPS codeArray. Sum. Stack. asm
FUNCTION CALLS EXAMPLE P 1 main: # Call the function named print. It jal print. It # MUST EXIT PROGRAM TO AVOID FUNCTION CODE li $v 0, 10 syscall
FUNCTION CALLS EXAMPLE P 2 print. It: # system call code for print_int li $v 0, 1 # integer to print li $a 0, 5 # print it syscall # Return to caller. # $ra holds the return address jr $ra
CALLING A FUNCTION � MIPS instruction “jump and link” # Jump to first instruction at given label. # Automatically saves return address– # address of next instruction, in register $ra jal Function. Label << “Instruction for return address” >>
PASSING PARAMETERS � In general the caller will push the parameters onto the stack. � The callee (function) assumes that it receives the parameters filled into specific offsets from the $sp (top of stack pointer).
PASSING PARAMETERS EXAMPLE P 1 # Push a single 4 -byte integer parameter value on the stack. addiu $sp, -4 li $t 0, 7 sw $t 0, ($sp) jal print. It addiu li sw jal $sp, -4 $t 0, 3 $t 0, ($sp) print. It # MUST EXIT PROGRAM li $v 0, 10 syscall
PASSING PARAMETERS EXAMPLE P 2 # Assumes one 4 -byte integer parameter is given # on the stack print. It: # system call code for print_int li $v 0, 1 # Load integer to print into $a 0 from top of stack. lw $a 0, ($sp) # print it syscall # Release memory allocated for parameters. addiu $sp, 4 jr $ra
EXERCISE Write the equivalent MIPS code: main { print. Max(5, 10); } void print. Max(int x, int y) { if(x >= y) System. out. println(x); else System. out. println(y); }
ARRAY TYPE PARAMETERS � How should we pass an array parameter to a function? � What information should be pushed on the stack?
ARRAY TYPE PARAMETERS � It’s more efficient to pass only the base address as a 32 -bit value rather than copying all of the array data. � Must also pass an integer giving the length of the array. � By passing the base address, we can also make changes to the contents of the array.
EXERCISE Write the equivalent MIPS code: main { int[] X = { 4, 8, 12 }; print. Sum(X, 3); } void print. Sum(int[] A, int length) { int sum = 0, i = 0; while(i < length) { sum = sum + A[i]; i++; } System. out. println(sum); }
SINGLE RETURN VALUE � In MIPS, a function that returns a single value “returns” the value by leaving it in the $v 0 register. � The last instruction of a function is its exit via the “jump register” instruction jr $ra
WRITE MIPS CODE FOR… main() { $v 0 = max(17, 5); System. out. println( $v 0 ) } int max(int x, int y) { int bigger = x; // Let $v 0 hold bigger. if(x < y) bigger = y; return bigger; }
EXAMPLE: CALLER CODE addiu li sw $sp, $t 0, jal max $sp, -8 17 ($sp) 5 4($sp) move $a 0, $v 0 li $v 0, 1 syscall # integer to print into $a 0 # print integer system call code # Do exit syscall for a clean end of program. li $v 0, 10 # Prevents main from running syscall # into following max function Continued. . .
EXAMPLE: FUNCTION MAX # This code follows the previous slide of main. # Assume first parameter is at ($sp)+4 # Assume second parameters is at ($sp)+0 # Returns larger of two values in register $v 0 max: # suppose first parameter is the larger. lw $v 0, 4($sp) # load second parameter lw $v 1, ($sp) bge $v 0, $v 1, MAX_END_IF move $v 0, $v 1 # second param is larger MAX_END_IF: # Pop off two 32 -bit parameters addiu $sp, 8 # Return address automatically saved in $ra jr $ra
EXAMPLE: FUNCTION ARRAY SUM � Compute sum of given array of N integers. int array. Sum(int[] A, int length) { int sum = 0; for(int i = 0; i < length; i++) sum = sum + A[i]; return sum; }
EXAMPLE: FUNCTION SUM � Compute sum of given array of integers. int array. Sum(int[] A, int length) � Push base address of array onto stack � Push length of array as a word onto stack � Return sum in register $v 0
EXAMPLE: CALLER CODE. data A: . word. text main: la addiu sw li addiu sw jal # Data declaration section 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 $s 0, A $sp, -4 $s 0, ($sp) $s 1, 10 $sp, -4 $s 1, ($sp) Array. Sum li $v 0, 1 syscall li syscall # # # # Base address of A allocate space for address push that element on the stack Number of elements in A allocate space on the stack push that on the stack Call function Array. Sum # system call code for print_int # print it $v 0, 10
EXAMPLE: FUNCTION ARRAY SUM # Receives base address on stack ($sp)+4 # Receives length of array on stack ($sp) # Returns sum of array elements in $v 0 # Uses registers $t 0, $s 0 and $s 1 as local variables Array. Sum: li $a 0, 0 # Sum = 0 lw lw $s 0, 4($sp) $s 1, 0($sp) # Get base address # Get length LOOP: beqz $s 1, END_LOOP lw $t 0, ($s 0) add $a 0, $t 0 addi $s 0, 4 addi $s 1, -1 # Increment A address # Decrement count b LOOP END_LOOP: # Pop parameters off stack addiu $sp, 8 jr $ra
EXAMPLE: LOCAL VARIABLES # Swaps values in $a 0 and $a 1. swap: # Use $t 0 as the local variable temporary. # temp = $a 0 move $t 0, $a 0 # $a 0 = $a 1 move $a 0, $a 1 # $a 1 = temp move $a 1, $t 0 # return to caller. jr $ra
LOCAL VARIABLES SIDE EFFECTS! # Code in “main” # Let $t 0 hold current array base address. lw lw jal # Swap two array elements. $a 0, 0($t 0) $a 1, 4($t 0) swap lw lw jal # Swap two more array elements. $a 0, 8($t 0) $a 1, 12($t 0) swap
LOCAL VARIABLES FOR FUNCTIONS � How can we use registers for local variables in functions but restore their contents to the values they had before the function call? � Solution: � Allocate space on the stack for local variables or to backup registers
EXERCISE � Revisit � Does � If your Array. Sum function. it produce unwanted side effects? so what registers are affected? � Update your code to save and restore local variable registers using the stack.
SIDE-EFFECT FREE ARRAY SUM. data A: . word. text main: la addiu sw li addiu sw jal # Data declaration section 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 $s 0, A # Base address of A $sp, -4 $s 0, ($sp) $s 1, 10 # Number of elements in A $sp, -4 $s 0, ($sp) Array. Sum # Call function Array. Sum # return value is in $v 0
# Receives base address on stack ($sp)+4 # Receives length of array on stack ($sp) # Returns sum of array elements in $v 0 # Uses registers $t 0, $s 0 and $s 1 as local variables Array. Sum: li $v 0, 0 # Sum = 0 # Push contents of $t 0, $s 0, and $s 1 lw lw $s 0, 16($sp) $s 1, 12($sp) # Get base address # Get length LOOP: bnez $s 1, END_LOOP lw $t 0, ($s 0) add $v 0, $t 0 addi $s 0, 4 addi $s 1, -1 b # Increment A address # Decrement count LOOP # Restore saved contents of $t 0, $s 0, and $s 1 # Pop parameters off stack addiu $sp, -20 jr $ra
SWAP FUNCTION – CALLER CODE data: A: B: . word. text 10 20 main: # Main uses $a 0, $a 1, $t 0, $t 1 for some other purpose. li $a 0, 1 li $a 1, 2 li $t 0, 3 li $t 1, 4 # push address of two variables on stack la $s 0, A addiu $sp, -4 sw $s 0, ($sp) la $s 0, B addiu $sp, -4 sw $s 0, ($sp) jal swap li $v 0, 10 syscall # exits program
SIDE-EFFECT FREE SWAP FUNCTION swap: # Push original contents of $t 0, $t 1, $a 0, $a 1 addiu sw $sp, -4 $t 0, ($sp) $sp, -4 $t 1, ($sp) $sp, -4 $a 0, ($sp) $sp, -4 $a 1, ($sp) # Get address of first argument into $a 0 lw $a 0, 20($sp) # Get address of second argument into $a 1 lw $a 1, 16($sp) lw lw sw sw $t 0, ($a 0) $t 1, ($a 1) $t 0, ($a 1) $t 1, ($a 0) # $t 0 = value of variable A # $t 1 = value of variable B #A=B #B=A # Restore preserved $a 1, $a 0, $t 1, $t 0 from the stack. lw $a 1, ($sp) addiu $sp, 4 lw addiu $a 0, ($sp) $sp, 4 lw addiu $t 1, ($sp) $sp, 4 lw addiu $t 0, ($sp) $sp, 4 # Pop off two 32 -bit address arguments addiu $sp, 8 # return to caller. jr $ra
RE-ENTRANT FUNCTIONS � If a function calls itself then program control re-enters a function that is already active. � Such code is known as re-entrant code. � Example: recursive functions.
RE-ENTRANT FUNCTIONS � Re-entrant function must maintain separate copies of all values for each active call. Allocate stack space. � Why? Later calls to the same function will overwrite information from previous calls.
EXAMPLE RECURSIVE FUNCTION /** * Factorial(n) = n*(n-1)*(n-2)*. . . *1 */ int factorial(int n) { if(n <= 1) return 1; else return n * factorial(n-1); }
RECURSIVE STACK TRACE factorial(5) n=5 Each procedure invocation pushes a new stack frame.
RECURSIVE STACK TRACE factorial(5) n=5 n=4 factorial(4) Each procedure invocation pushes a new stack frame.
RECURSIVE STACK TRACE factorial(5) n=5 n=4 n=3 factorial(3) Each procedure invocation pushes a new stack frame.
RECURSIVE STACK TRACE factorial(5) n=5 n=4 n=3 n=2 factorial(2) Each procedure invocation pushes a new stack frame.
RECURSIVE STACK TRACE factorial(5) n=5 n=4 n=3 n=2 n=1 factorial(1) Each procedure invocation pushes a new stack frame.
RECURSIVE STACK TRACE factorial(5) n=5 n=4 n=3 n=2 n=1 1 1
RECURSIVE STACK TRACE factorial(5) n=5 n=4 n=3 2 n=1 2*1 1 Each procedure return pops off its stack frame. 1
RECURSIVE STACK TRACE factorial(5) n=5 n=4 n=3 n=2 n=1 3*2 2*1 1 2 Each procedure return pops off its stack frame. 1
RECURSIVE STACK TRACE factorial(5) n=5 n=4 n=3 n=2 n=1 4*6 3*2 2*1 1 6 2 Each procedure return pops off its stack frame. 1
RECURSIVE STACK TRACE factorial(5) = 120 n=5 n=4 n=3 n=2 n=1 5 * 24 4*6 3*2 2*1 1 24 6 2 5! returns 120 Each procedure return pops off its stack frame. 1
RECURSIVE STACK TRACE factorial(5) = 120 n=5 n=4 n=3 n=2 n=1 5 * 24 4*6 3*2 2*1 1 24 6 2 1 5! returns 120 Stack returns to its original state prior to call to factorial(5) since all procedure stack frames have been popped off.
WHAT TO STORE ON THE STACK � Allocate a stack frame to store the following information used by a recursive function invocation: � Parameter value(s) � Local variables including saved copies of ALL registers read/written by the function � Return address in $ra register
RECURSIVE FACTORIAL � See factorial. asm � See factorial-sef. asm
FYI PASS PARAMETERS IN REGISTERS � For functions that take 4 or fewer 32 -bit arguments you can pass the parameters in registers $a 0, $a 1, $a 2, and $a 3 � The syscall mechanism works this way
EXERCISE � Write calling code in main that assigns values of your choice to $a 0 -$a 3 and calls function sum 4. � Write a function sum 4 that receives 4 integer parameters in $a 0 -$a 3 and returns their sum in $v 0.
SOLUTION: CALLER CODE main: # Assign some values to argument registers li $a 0, 5 li $a 1, 17 li $a 2, 7 li $a 3, 40 # Jump to the function with label “sum 4” jal sum 4 # Do exit syscall for a clean end of program. li $v 0, 10 # Prevents main from running syscall # into following sum 4 function Continued. . .
SOLUTION: FUNCTION SUM 4 # This code follows the previous slide of main. # # Assume four integer arguments $a 0 -$a 3. # Returns sum of integers in register $v 0. sum 4: add $v 0, $a 1 add $v 0, $a 2 add $v 0, $a 3 # Return address automatically saved in $ra jr $ra
- Slides: 67