IA32/Linux Stack • Memory managed with stack discipline • Register %esp stores the address of top element 0x0 Procedure Calls Instructions Functions pushl src Fetch data at src CS 217 Decrement %esp by 4 movl src, (%esp) popl dest Stack pointer %esp Top Top element movl (%esp), dest Increment %esp by 4 Bottom 1 Procedure Calls Procedure Calls • Calling a procedure involves following actions o o o o o 2 • Requirements o o o o o o o pass arguments save a return address transfer control to callee transfer control back to caller return results int add3(int a, int b, int c) { return a + b + c; } Make a call to an arbitrary address Return back after the call sequence Handle nested procedure calls Save and restore caller’s registers Pass an arbitrary number of arguments Pass and return structures Allocate and deallocate space for local variables • Procedure call and return instruction sequences collaborate to implement these requirements foo(void) { int d; d = add3( 3, 4, 5 ); return d; } 3 4 Procedure Calls Call and Return Instructions • Requirements ¾ ¾ o o o o o • Procedure call Make a call to an arbitrary address Return back after the call sequence Handle nested procedure calls Save and restore caller’s registers Pass an arbitrary number of arguments Pass and return structures Allocate and deallocate space for local variables o Push the return address on the stack o Jump to the procedure location 0 • Procedure return o Pop the return address off the stack o Jump to the return address • Why using a stack? • Procedure call and return instruction sequences collaborate to implement these requirements Instructions Functions call addr pushl %eip jmp addr ret Stack pointer %esp Old eip pop %eip Bottom 5 Nested Procedure Call Procedure Calls • A calls B, which calls C • Requirements o o ¾ ¾ o o o • Must even work when B is A A: C: B: call B 6 call C Make a call to an arbitrary address Return back after the call sequence Handle nested procedure calls Save and restore caller’s registers Pass an arbitrary number of arguments Pass and return structures Allocate and deallocate space for local variables • Procedure call and return sequences collaborate to implement these requirements ret ret ret 7 8 Procedure Stack Structure Stack Frame in Detail • Callee stack frame • Stack frame o Parameters for called functions o Local variables – If can’t keep in registers o Saved register context o Old frame pointer o Each procedure call has a stack frame o Deal with nested procedure calls 0x0 • Stack Pointer • o Register %esp o Point to the top element of the stack Stack pointer Frame Pointer (%esp) o Register %ebp Frame pointer o Start of current stack frame (%ebp) • Caller stack frame o Return address – Pushed by “call” instruction o Arguments for this call Stack frame • Before return, use “leave” instruction, which does Stack frame • Why using a frame pointer? o Pop off the entire frame before the procedure call returns (%esp) Callee frame (%ebp) Arguments Caller frame movl %ebp, %esp popl %ebp Stack frame Local variables Saved registers Old ebp Return addr Local variables Saved registers Old ebp 9 Procedure (Callee) 10 Procedure (Callee) in Action .text .text .globl Foo .globl Foo Foo: Foo: pushl %ebp movl %esp, %ebp . . . leave Callee frame (%ebp) movl %ebp, %esp popl %ebp movl %esp, %ebp . . . leave Local variables Saved registers Old ebp Return addr Arguments Caller frame ret pushl %ebp (%esp) movl %ebp, %esp popl %ebp 11 (%ebp) (%esp) (%ebp) (%esp) (%esp) Local variables Saved registers Old ebp Return addr Arguments Caller frame ret Local variables Saved registers Old ebp (%esp) (%ebp) Local variables Saved registers Old ebp 12 Register Saving Options • Problem: a procedure needs to use registers, but o If you use the registers, their contents will be changed when returning to the caller o If we save registers on the stack, who is responsible? IA32/Linux Register Saving Convention • Special stack registers main: • • • movl $0x123, %edx call Foo addl %edx, %eax • • • ret o %ebp, %esp • Callee-save registers o %ebx, %esi, %edi o Old values saved on stack prior to using • Caller-save registers • Caller Save o Caller saves registers in its frame before calling • “Callee Save” o Callee saves registers in its frame before using %eax Caller-Save registers %ecx %ebx Callee-Save registers o %eax, %edx, %ecx o Save on stack prior to calling Foo: • • • movl 8(%ebp), %edx addl $0x456, %edx • • • ret %edx %esi %edi %esp Stack %ebp 13 Procedure Calls Passing Arguments to Procedure • Requirements o o o o ¾ ¾ ¾ 14 • Arguments are passed on stack in order Set PC to arbitrary address Return PC to instruction after call sequence Handle nested procedure calls Save and restore caller’s registers Pass an arbitrary number of arguments Pass and return structures Allocate and deallocate space for local variables 0x0 o Push N-th argument first o Push 1st argument last • Callee references the argument by o 1st argument: 8(%ebp) o 2nd argument: 12(%ebp) o ... • Procedure call and return sequences collaborate to implement these requirements • Passing result back by %eax o Caller is responsible for saving %eax register 15 (%esp) Callee frame (%ebp) Caller frame Arguments build Local variables Saved registers Old ebp Return addr Arg1 .. . ArgN Local variables Saved registers Old ebp 16 Example: Passing Arguments Allocation for Local Variables .text .globl add3 int d; • Local variables are stored in a stack frame add3: pushl %ebp movl %esp, %ebp movl 12(%ebp), %eax addl 8(%ebp), %eax addl 16(%ebp), %eax leave ret .globl foo int add3(int a, int b, int c) { return a + b + c; } • Allocation is done by moving the stack pointer %esp subl $4, %esp • Reference local variable by using register %ebp foo: foo(void) { d = add3( 3, 4, 5 ); return d; } pushl movl pushl pushl pushl call movl leave ret .comm %ebp %esp, %ebp $5 $4 $3 add3 %eax, d d,4,4 { return a + b + c; } foo(void) { int d; d = add3( 3, 4, 5 ); return d; } .text .globl add3 add3: pushl %ebp movl %esp, %ebp movl 12(%ebp), %eax addl 8(%ebp), %eax addl 16(%ebp), %eax leave ret .globl foo foo: pushl %ebp movl %esp, %ebp subl $4, %esp pushl $5 pushl $4 pushl $3 call add3 movl %eax, -4(ebp) leave ret (%esp) Callee frame (%ebp) e.g. -4(%ebp) Caller frame Arguments build Local variables Saved registers Old ebp Return addr Arg1 .. . ArgN Local variables Saved registers Old ebp 17 Example: Local Variables int add3(int a, int b, int c) 0x0 18 Summary • Issues related to calling conventions o o o o o o Stack frame for caller and callee Use esp and ebp registers Passing arguments on stack Saving registers on stack (caller save and callee save) Local variables on stack Passing result in eax register • Procedure call instructions call, ret, leave 19 20