CSC 84: Computer Systems Using the Stack for Function Calls Lecture Goals Challenges of supporting functions! Providing information for the called function Function arguments and local variables! Allowing the calling function to continue where it left off Return address and contents of registers Stack: last-in-first-out data structure! Stack frame: args, local vars, return address, registers! Stack pointer: pointing to the current top of the stack Calling functions! CALL and instructions! PUSH into and POP from the stack frame! Using the base pointer EBP as a reference point 1
Function Calls main calls add! Push arguments on the stack! Push return address on stack! Jump to add! Allocate local variables on stack, etc. Returning to main! Clear the stack frame for add! Pop return address from stack int add(int a, int b, int c) { int d; } d = a + b + c; return d; int main() { int sum, avg; } sum = add(, 4, 5); avg = sum / ; return avg Stack Frame for add Return Address 4 5 Stack Frames Use stack for all temporary data related to each active function invocation! Input parameters! Return address! Local variables of function! Saving registers across invocations Stack Frame Stack has one Stack Frame per active function invocation 2
High-Level Picture main begins executing main calls P (Extended Stack Pointer) Always points to the top element of the stack Bottom main s Stack Frame High-Level Picture main begins executing main calls P P calls Q Bottom P s Stack Frame main s Stack Frame
High-Level Picture main begins executing main calls P P calls Q Q returns Bottom Q s Stack Frame P s Stack Frame main s Stack Frame High-Level Picture main begins executing main calls P P calls Q Q returns P returns Bottom P s Stack Frame main s Stack Frame 4
High-Level Picture main begins executing main calls P P calls Q Q returns P returns main returns Bottom main s Stack Frame High-Level Picture main begins executing main calls P P calls Q Q returns P returns main returns Bottom 5
Function Call Details Call and Return instructions! call: push EIP on the stack, and jump to function! ret: pop the stack into the EIP to go back Argument passing between procedures! Calling function pushes arguments on to the stack! Called function reads/writes on the stack Local variables! Called function creates and manipulates on the stack Register saving conventions! Either calling or called function saves all of the registers before use Call and Return Instructions Instruction Effective Operations PUSH Src SUB, 4 POP Dest CALL Addr MOV [], Src MOV Dest, [] ADD, 4 PUSH EIP JMP Addr POP EIP before CALL Note: can t really access EIP directly, but this is implicitly what call and ret are doing. 6
Call and Return Instructions Instruction Effective Operations PUSH Src SUB, 4 POP Dest CALL Addr MOV [], Src MOV Dest, [] ADD, 4 PUSH EIP JMP Addr POP EIP after CALL Old EIP Call and Return Instructions Instruction Effective Operations PUSH Src SUB, 4 POP Dest CALL Addr MOV [], Src MOV Dest, [] ADD, 4 PUSH EIP JMP Addr POP EIP before Old EIP Return instruction assumes that the return address is at the top of the stack 7
Call and Return Instructions Instruction Effective Operations PUSH Src SUB, 4 POP Dest CALL Addr MOV [], Src MOV Dest, [] ADD, 4 PUSH EIP JMP Addr POP EIP after Input Arguments Caller pushes input arguments before executing the CALL Parameters are pushed in the reverse order! Push N th argument first! Push 1 st argument last! So that first argument is at the top of the stack at the time of the Call before pushing arguments 8
Input Arguments Caller pushes input parameters before executing the CALL Parameters are pushed in the reverse order! Push N th argument first! Push 1 st argument last! So that first argument is at top of the stack at the time of the CALL before CALL Arg 1 Arg Arg N CALL Called function can address arguments relative to : Arg 1 as [+4] before CALL Arg 1 Arg Arg N after CALL Old EIP Arg 1 Arg Arg N 9
: Returning to Caller before Old EIP Arg 1 Arg Arg N after Arg 1 Arg Arg N Base Pointer: EBP As Callee executes, may change! E.g., preparing to call another function Use EBP as fixed reference point! E.g., to access arguments and other local variables Need to save old value of EBP! Before overwriting EBP register Callee begins by executing prolog MOV EBP, after CALL Old EIP Arg 1 Arg Arg N EBP 1
Base Pointer: EBP As Callee executes, may change! E.g., preparing to call another function Use EBP as fixed reference point! E.g., to access arguments and other local variables Need to save old value of EBP! Before overwriting EBP register Callee begins by executing prolog MOV EBP,, EBP Old EBP Old EIP Arg 1 Arg Arg N Regardless of, Callee can address Arg 1 as [EBP+8] Base Pointer: EBP Before returning, Callee must restore EBP to its old value Executes MOV, EBP EBP Old EBP Old EIP Arg 1 Arg Arg N 11
Base Pointer: EBP Before returning, Callee must restore EBP to its old value Executes MOV, EBP, EBP Old EBP Old EIP Arg 1 Arg Arg N Base Pointer: EBP Before returning, Callee must restore EBP to its old value Executes MOV, EBP Old EIP Arg 1 Arg Arg N EBP 12
Base Pointer: EBP Before returning, Callee must restore EBP to its old value Executes MOV, EBP Arg 1 Arg Arg N EBP Allocation for Local Variables Local variables of the Callee are also allocated on the stack Allocation done by moving the stack pointer Example: allocate two integers! SUB, 4! SUB, 4! (or equivalently, SUB, 8) Reference local variables using the base pointer! [EBP-4]! [EBP-8] EBP Var 2 Var 1 Old EBP Old EIP Arg 1 Arg Arg N 1
Use of Registers Problem: Callee may use a register that the caller is also using! When callee returns control to caller, old register contents may be lost! Caller cannot continue where it left off Solution: save the registers on the stack! Callee must push register contents before altering! Callee must pop register contents before returning A Simple Example int sum(int x, int y) { return x+y; } int main () { int result; } result = sum(1, 2); printf("%d\n", result); return ; Compile: gcc masm=intel sum.c Debug: gdb./a.out disas main 14
Example.LC MOV EBP, SUB, 16 MOV DWORD PTR [+4],2 MOV DWORD PTR [],1 MOV DWORD PTR [+4],EAX MOV DWORD PTR [], OFFSET:.LC MOV EAX, ADD, 16 Recall that:! The stack grows from high addresses towards low addresses EBP Example.LC MOV EBP, SUB, 16 MOV DWORD PTR [+4],2 MOV DWORD PTR [],1 MOV DWORD PTR [+4],EAX MOV DWORD PTR [], OFFSET:.LC MOV EAX, ADD, 16 Recall that:! The stack grows from high addresses towards low addresses EBP 15
Example.LC MOV EBP, SUB, 16 MOV DWORD PTR [+4],2 MOV DWORD PTR [],1 MOV DWORD PTR [+4],EAX MOV DWORD PTR [], OFFSET:.LC MOV EAX, ADD, 16 Example.LC MOV EBP, SUB, 16 MOV DWORD PTR [+4],2 MOV DWORD PTR [],1 MOV DWORD PTR [+4],EAX MOV DWORD PTR [], OFFSET:.LC MOV EAX, ADD, 16 16
Example.LC MOV EBP, SUB, 16 MOV DWORD PTR [+4],2 MOV DWORD PTR [],1 MOV DWORD PTR [+4],EAX MOV DWORD PTR [], OFFSET:.LC MOV EAX, ADD, 16 2 Example.LC MOV EBP, SUB, 16 MOV DWORD PTR [+4],2 MOV DWORD PTR [],1 MOV DWORD PTR [+4],EAX MOV DWORD PTR [], OFFSET:.LC MOV EAX, ADD, 16 1 2 <sum>: MOV EBP, MOV EAX, DWORD PTR [EBP+12] ADD EAX, DWORD PTR [EBP+8] 17
Example.LC MOV EBP, SUB, 16 MOV DWORD PTR [+4],2 MOV DWORD PTR [],1 MOV DWORD PTR [+4],EAX MOV DWORD PTR [], OFFSET:.LC MOV EAX, ADD, 16 RA(main) 1 2 <sum>: MOV EBP, MOV EAX, DWORD PTR [EBP+12] ADD EAX, DWORD PTR [EBP+8] Example.LC MOV EBP, SUB, 16 MOV DWORD PTR [+4],2 MOV DWORD PTR [],1 MOV DWORD PTR [+4],EAX MOV DWORD PTR [], OFFSET:.LC MOV EAX, ADD, 16 RA(main) 1 2 <sum>: MOV EBP, MOV EAX, DWORD PTR [EBP+12] ADD EAX, DWORD PTR [EBP+8] 18
Example.LC MOV EBP, SUB, 16 MOV DWORD PTR [+4],2 MOV DWORD PTR [],1 MOV DWORD PTR [+4],EAX MOV DWORD PTR [], OFFSET:.LC MOV EAX, ADD, 16 RA(main) 1 2 EBP(sum) <sum>: MOV EBP, MOV EAX, DWORD PTR [EBP+12] ADD EAX, DWORD PTR [EBP+8] Example.LC MOV EBP, SUB, 16 MOV DWORD PTR [+4],2 MOV DWORD PTR [],1 MOV DWORD PTR [+4],EAX MOV DWORD PTR [], OFFSET:.LC MOV EAX, ADD, 16 RA(main) 1 2 EBP(sum) <sum>: MOV EBP, MOV EAX, DWORD PTR [EBP+12] ADD EAX, DWORD PTR [EBP+8] EAX 2 19
Example.LC MOV EBP, SUB, 16 MOV DWORD PTR [+4],2 MOV DWORD PTR [],1 MOV DWORD PTR [+4],EAX MOV DWORD PTR [], OFFSET:.LC MOV EAX, ADD, 16 RA(main) 1 2 EBP(sum) <sum>: MOV EBP, MOV EAX, DWORD PTR [EBP+12] ADD EAX, DWORD PTR [EBP+8] EAX Example.LC MOV EBP, SUB, 16 MOV DWORD PTR [+4],2 MOV DWORD PTR [],1 MOV DWORD PTR [+4],EAX MOV DWORD PTR [], OFFSET:.LC MOV EAX, ADD, 16 RA(main) 1 2 <sum>: MOV EBP, MOV EAX, DWORD PTR [EBP+12] ADD EAX, DWORD PTR [EBP+8] EAX 2
Example.LC MOV EBP, SUB, 16 MOV DWORD PTR [+4],2 MOV DWORD PTR [],1 MOV DWORD PTR [+4],EAX MOV DWORD PTR [], OFFSET:.LC MOV EAX, ADD, 16 1 2 EAX Example.LC MOV EBP, SUB, 16 MOV DWORD PTR [+4],2 MOV DWORD PTR [],1 MOV DWORD PTR [+4],EAX MOV DWORD PTR [], OFFSET:.LC MOV EAX, ADD, 16 1 2 EAX 21
Example.section.data.LC STRING "%d\n".lc MOV EBP, SUB, 16 MOV DWORD PTR [+4],2 MOV DWORD PTR [],1 MOV DWORD PTR [+4],EAX MOV DWORD PTR [], OFFSET:.LC MOV EAX, ADD, 16 1 Example.section.data.LC STRING "%d\n".lc MOV EBP, SUB, 16 MOV DWORD PTR [+4],2 MOV DWORD PTR [],1 MOV DWORD PTR [+4],EAX MOV DWORD PTR [], OFFSET:.LC MOV EAX, ADD, 16 Address of % Skipping the details of 22
Example.LC MOV EBP, SUB, 16 MOV DWORD PTR [+4],2 MOV DWORD PTR [],1 MOV DWORD PTR [+4],EAX MOV DWORD PTR [], OFFSET:.LC MOV EAX, ADD, 16 Address of % Example.LC MOV EBP, SUB, 16 MOV DWORD PTR [+4],2 MOV DWORD PTR [],1 MOV DWORD PTR [+4],EAX MOV DWORD PTR [], OFFSET:.LC MOV EAX, ADD, 16 Address of % Prepare to: leave EAX 2
Example.LC MOV EBP, SUB, 16 MOV DWORD PTR [+4],2 MOV DWORD PTR [],1 MOV DWORD PTR [+4],EAX MOV DWORD PTR [], OFFSET:.LC MOV EAX, ADD, 16 EAX Example.LC MOV EBP, SUB, 16 MOV DWORD PTR [+4],2 MOV DWORD PTR [],1 MOV DWORD PTR [+4],EAX MOV DWORD PTR [], OFFSET:.LC MOV EAX, ADD, 16 EAX 24
Summary Invoking a function! CALL: call the function! : return from the instruction Stack Frame for a function call includes! Function arguments! Return address! Local variables! Saved registers Base pointer EBP! Fixed reference point in the Stack Frame! Useful for referencing arguments and local variables 25