CSC 2400: Computer Systems Using the Stack for Function Calls
Lecture Goals int add3(int a, int b, int c) { int d; How are function calls d = a + b + c; implemented at the return d; } machine level? int main() { int sum, avg; • Challenges: sum = add3(3, 4, 5); ! Providing info for the called function avg = sum / 3; – Function arguments return avg } – Local variables ! Upon return, resume execution of caller – Return address – Register contents • Solution: use the stack
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 • Solution: use the stack ! Stack frame: args, local vars, return address, registers ! Stack pointer ESP : pointing to the current top of the stack • Calling functions ! CALL and RET instructions ! Using the base pointer EBP as a reference point
int add3(int a, int b, int c) { Function Calls int d; d = a + b + c; return d; • main calls add3 } ! Push arguments on the stack ! Push return address on stack int main() { ! Jump to add3 int sum, avg; ! Allocate local variables on stack, save registers, etc. sum = add3(3, 4, 5); avg = sum / 3; Return return avg Address } • Returning to main Stack Frame for add3 ! Clear the stack frame for add3 ! Pop return address from stack Return Addr. ESP Stack Frame Address 3 for main 4 5
The Stack MEMORY q The stack is a region of your 0 1 executable program used to 2 facilitate function calls . - it stores function arguments, TEXT . DATA . local variables, etc. HEAP q The register ESP always points to (contains the STACK address of) the top stack ESP 7 element 11 5 23 ESP = Extended Stack Pointer Always points to the top element of the stack
Function Calls int add3(int a, int b, int c) { int d; How are function d = a + b + c; calls implemented in return d; assembly? } int main() { int sum, avg; sum = add3(3, 4, 5); avg = sum / 3; return avg }
int main() { Stack Frames int sum = 0,avg = 0; sum = add3(3, 4, 5); q The stack frame , also known as avg = sum / 3; activation record , is the collection return avg of all data on the stack } associated with one function call 0 q The stack frame includes local variables, arguments passed to functions, saved registers, etc. ESP 3 4 Stack Frame 5 for main 0 (avg) 0 (sum) Bottom
Stack Frames – High-Level Picture main begins executing 0 main calls A (Extended Stack Pointer) ESP main’s Stack Frame (Extended Base Pointer) EBP
High-Level Picture main begins executing 0 main calls A A calls B ESP A’s Stack Frame EBP main’s Stack Frame Bottom
High-Level Picture main begins executing 0 main calls A A calls B B returns ESP B’s Stack Frame EBP A’s Stack Frame main’s Stack Frame Bottom
High-Level Picture main begins executing 0 main calls A A calls B A returns B returns ESP A’s Stack Frame EBP main’s Stack Frame Bottom
High-Level Picture main begins executing 0 main calls A A calls B A returns B returns main returns ESP main’s Stack Frame EBP
High-Level Picture main begins executing 0 main calls P P calls Q Q returns P returns main returns Bottom
Function Calls int add3(int a, int b, int c) { int d; How are function d = a + b + c; calls implemented in return d; assembly? } int main() { Let’s look at the int sum, avg; disassembled code sum = add3(3, 4, 5); avg = sum / 3; return avg }
Disassembled code for main : int main() ... { <main+17>: mov DWORD PTR [esp+0x8],0x5 int sum, avg; <main+25>: mov DWORD PTR [esp+0x4],0x4 sum = add3(3, 4, 5); <main+33>: mov DWORD PTR [esp],0x3 avg = sum / 3; <main+40>: call 0x8048394 <add3> return avg <main+45>: mov DWORD PTR [ebp-0xc],eax } ... Stack before • main prepares to call add3 call <add3> ! place arguments on the stack ESP 3 ESP+4 4 ESP+8 5
Disassembled code for main : int main() ... { <main+17>: mov DWORD PTR [esp+0x8],0x5 int sum, avg; <main+25>: mov DWORD PTR [esp+0x4],0x4 sum = add3(3, 4, 5); <main+33>: mov DWORD PTR [esp],0x3 avg = sum / 3; <main+40>: call 0x8048394 <add3> return avg <main+45>: mov DWORD PTR [ebp-0xc],eax } ... Stack after • call <add3> call <add3> ! Push return address on stack Stack Frame ! Jump to add3 for add3 ESP return address (EIP) main+45 3 Stack Frame 4 for main 5
Disassembled code for add3 : <add3+0>: push ebp int add3(int a, int b, int c) { <add3+1>: mov ebp,esp int d; <add3+3>: sub esp,0x10 <add3+6>: mov edx,DWORD PTR [ebp+0xc] d = a + b + c; <add3+9>: mov eax,DWORD PTR [ebp+0x8] return d; <add3+12>: add eax,edx } <add3+14>: add eax,DWORD PTR [ebp+0x10] ... <add3+23>: leave <add3+24>: ret This is how the stack looks like before add3 starts executing ESP ESP EBP ebp (copy) ESP EBP+4 (return address) main+45 main+45 EBP+8 3 (a) 3 (a) EBP+12 4 (b) 4 (b) EBP+16 5 (c) 5 (c)
In general …
CALL instruction 0 0 ESP Return Address after ESP Arg 1 Arg 1 CALL before Arg … Arg … CALL Arg N Arg N EBP EBP Arguments placed onto CALL: push EIP on the the stack before CALL stack and jump to callee
Called Function uses Base Pointer EBP 0 • As called function executes, ESP may change ! e.g., calling another function • How to access arguments? ESP EBP Old EBP ! Use EBP as fixed reference EBP+4 Return Address ! Save old EBP value first EBP+8 Arg 1 • Callee begins by executing Arg … Arg N PUSH EBP MOV EBP, ESP Callee always finds the first argument at address EBP+8 , second argument at address EBP+12 , etc. Old EBP
Allocation for Local Variables • Local variables are also 0 allocated on the stack • Allocation done by moving the EBP-8 Var 2 stack pointer EBP-4 Var 1 EBP • Example: allocate two integers Old EBP ! SUB ESP, 4 Return Address EBP+8 ! SUB ESP, 4 Arg 1 ! (or equivalently SUB ESP, 8 ) Arg … • Reference local variables Arg N using the base pointer ! [EBP-4] ! [EBP-8]
Called function ends by executing LEAVE 0 0 RET ESP EBP Old EBP ESP Return Address Return Address Arg 1 Arg 1 Arg … Arg … Arg N Arg N EBP Stack after LEAVE Stack before LEAVE
Called function ends by executing Return Address copied into EIP 0 0 LEAVE RET ESP Return Address ESP Arg 1 Arg 1 Arg … Arg … Arg N Arg N EBP EBP Stack after RET Stack before RET
A Simple Example int sum(int x, int y) { return x+y; } int main () { int result; result = sum(0x11, 0x22); printf("%d\n", result); return 0; } Compile: gcc sum.c –o xsum Debug: gdb ./xsum set disassembly-flavor intel disas main
Example main: PUSH EBP MOV EBP,ESP ... SUB ESP, 0x14 MOV DWORD PTR [ESP+4], 0x22 MOV DWORD PTR [ESP], 0x11 CALL sum MOV DWORD PTR [EBP-4],EAX ... MOV EAX, 0 ADD ESP, 0x14 POP EBP RET ESP • Recall that: ! The stack grows from high addresses towards low addresses
Example main: PUSH EBP MOV EBP,ESP ... SUB ESP, 0x14 MOV DWORD PTR [ESP+4], 0x22 MOV DWORD PTR [ESP], 0x11 CALL sum MOV DWORD PTR [EBP-4],EAX ... MOV EAX, 0 ADD ESP, 0x14 POP EBP RET ESP EBP(os) • Recall that: ! The stack grows from high addresses towards low addresses
Example main: PUSH EBP MOV EBP,ESP ... SUB ESP, 0x14 MOV DWORD PTR [ESP+4], 0x22 MOV DWORD PTR [ESP], 0x11 CALL sum MOV DWORD PTR [EBP-4],EAX ... MOV EAX, 0 ADD ESP, 0x14 POP EBP RET ESP EBP(main) EBP(os)
Example main: PUSH EBP MOV EBP,ESP ... SUB ESP, 0x14 MOV DWORD PTR [ESP+4], 0x22 MOV DWORD PTR [ESP], 0x11 CALL sum MOV DWORD PTR [EBP-4],EAX ESP ... MOV EAX, 0 ADD ESP, 0x14 POP EBP RET EBP(main) EBP(os)
Example main: PUSH EBP MOV EBP,ESP ... SUB ESP, 0x14 MOV DWORD PTR [ESP+4], 0x22 MOV DWORD PTR [ESP], 0x11 CALL sum MOV DWORD PTR [EBP-4],EAX ESP ... MOV EAX, 0 0x22 ADD ESP, 0x14 POP EBP RET EBP(main) EBP(os)
Example main: PUSH EBP MOV EBP,ESP ... SUB ESP, 0x14 MOV DWORD PTR [ESP+4], 0x22 MOV DWORD PTR [ESP], 0x11 CALL sum MOV DWORD PTR [EBP-4],EAX ESP ... 0x11 MOV EAX, 0 0x22 ADD ESP, 0x14 POP EBP RET <sum>: PUSH EBP EBP(main) EBP(os) MOV EBP, ESP MOV EAX, DWORD PTR [EBP+12] ADD EAX, DWORD PTR [EBP+8] POP EBP RET
Example main: PUSH EBP MOV EBP,ESP ... SUB ESP, 0x14 MOV DWORD PTR [ESP+4], 0x22 MOV DWORD PTR [ESP], 0x11 CALL sum ESP (return address) RA RA MOV DWORD PTR [EBP-4],EAX ... 0x11 MOV EAX, 0 0x22 ADD ESP, 0x14 POP EBP RET <sum>: PUSH EBP EBP(main) EBP(os) MOV EBP, ESP MOV EAX, DWORD PTR [EBP+12] ADD EAX, DWORD PTR [EBP+8] POP EBP RET
Example main: PUSH EBP MOV EBP,ESP ... SUB ESP, 0x14 MOV DWORD PTR [ESP+4], 0x22 ESP MOV DWORD PTR [ESP], 0x11 EBP(main) CALL sum (return address) RA RA MOV DWORD PTR [EBP-4],EAX ... 0x11 MOV EAX, 0 0x22 ADD ESP, 0x14 POP EBP RET <sum>: PUSH EBP EBP(main) EBP(os) MOV EBP, ESP MOV EAX, DWORD PTR [EBP+12] ADD EAX, DWORD PTR [EBP+8] POP EBP RET
Recommend
More recommend