X86 Assembly -Procedure II:1
IA32 Object Code Setup Label.L61 becomes address 0x8048630 Label.L62 becomes address 0x80488dc Assembly Code switch_eg:... ja.l61 # if > goto default jmp *.L62(,%edx,4) # goto JTab[x] Disassembled Object Code 08048610 <switch_eg>:... 8048622: 77 0c ja 8048630 8048624: ff 24 95 dc 88 04 08 jmp *0x80488dc(,%edx,4) II:3
Types of jumps Direct jump Absolute jump je $0x00804000 PC relative jump je $14 je $-14 Indirect jump jmp%eax jmp8(%eax) jmp(%eax, %ebx, 4) II:4
IA32 Stack Region of memory managed with stack discipline Grows toward lower addresses Stack Bottom Increasing Addresses Register contains lowest stack address = address of top element Stack Pointer: Stack Grows Down Stack Top II:5
IA32 Stack: Push pushl Src Fetch operand at Src Decrement by 4 Write operand at address given by Stack Bottom Increasing Addresses Stack Grows Down Stack Pointer: -4 Stack Top II:6
IA32 Stack: Pop popl Dest Read operand at address Increment by 4 Write operand to Dest Stack Bottom Increasing Addresses Stack Pointer: +4 Stack Grows Down Stack Top II:7
Procedure Control Flow Use stack to support procedure call and return Procedure call: call label Push return address on stack Jump to label Return address: Address of instruction beyond call Example from disassembly 804854e: e8 3d 06 00 00 call 8048b90 <main> 8048553: 50 pushl %eax Return address = 0x8048553 Procedure return: ret Pop address from stack Jump to address II:8
Procedure Call Example 804854e: e8 3d 06 00 00 call 8048b90 <main> 8048553: 50 pushl %eax call 8048b90 0x110 0x110 0x10c 0x10c 0x108 123 0x108 123 0x104 0x8048553 0x108 0x108 0x104 %eip 0x804854e %eip 0x804854e 0x8048b90 %eip: program counter II:9
Procedure Return Example 8048591: c3 ret ret 0x110 0x110 0x10c 0x10c 0x108 123 0x108 123 0x104 0x8048553 0x8048553 0x104 0x104 0x108 %eip 0x8048591 %eip 0x8048591 0x8048553 %eip: program counter II:10
Stack-Based Languages Languages that support recursion e.g., C, Pascal, Java Code must be Reentrant Multiple simultaneous instantiations of single procedure Need some place to store state of each instantiation Arguments Local variables Return pointer Stack discipline State for given procedure needed for limited time From when called to when return Callee returns before caller does Stack allocated in Frames State for single procedure instantiation II:11
Call Chain Example yoo( ) { who(); } who( ) { (); (); } ( ) { (); } Example Call Chain yoo who Procedure is recursive II:12
Stack Frames Contents Local variables Return information Temporary space Frame Pointer: Stack Pointer: Previous Frame Frame for proc Management Space allocated when procedure entered Set-up code Deallocated when return Finish code Stack Top II:13
Example Stack yoo( ) { who(); } yoo who yoo II:14
Example Stack who( ) { (); (); } yoo who yoo who II:15
Example Stack ( ) { (); } yoo who yoo who II:16
Example Stack ( ) { (); } yoo who yoo who II:17
Example Stack ( ) { (); } yoo who yoo who II:18
Example Stack ( ) { (); } yoo who yoo who II:19
Example Stack ( ) { (); } yoo who yoo who II:20
Example Stack who( ) { (); (); } yoo who yoo who II:21
Example Stack ( ) { } yoo who yoo who II:22
Example Stack who( ) { (); (); } yoo who yoo who II:23
Example Stack yoo( ) { who(); } yoo who yoo II:24
IA32/Linux Stack Frame Current Stack Frame ( Top to Bottom) Argument build: Parameters for function about to call Local variables If can t keep in registers Saved register context Old frame pointer Caller Stack Frame Return address Pushed by call instruction Arguments for this call Frame pointer Stack pointer Caller Frame Arguments Return Addr Old Saved Registers + Local Variables Argument Build II:25
Revisiting swap int zip1 = 15213; int zip2 = 91125; void call_swap() { swap(&zip1, &zip2); } Calling swap from call_swap call_swap: pushl $zip2 # Global Var pushl $zip1 # Global Var call swap void swap(int *xp, int *yp) { int t0 = *xp; int t1 = *yp; *xp = t1; *yp = t0; } &zip2 &zip1 Rtn adr Resulting Stack II:26
Revisiting swap void swap(int *xp, int *yp) { int t0 = *xp; int t1 = *yp; *xp = t1; *yp = t0; } swap: pushl movl, pushl %ebx movl 12(),%ecx movl 8(),%edx movl (%ecx),%eax movl (%edx),%ebx movl %eax,(%edx) movl %ebx,(%ecx) movl -4(),%ebx movl, popl ret Set Up Body Finish II:27
swapsetup #1 Entering Stack Resulting Stack &zip2 yp &zip1 xp Rtn adr Rtn adr Old swap: pushl movl, pushl %ebx II:28
swapsetup #1 Entering Stack &zip2 yp &zip1 xp Rtn adr Rtn adr Old swap: pushl movl, pushl %ebx II:29
swapsetup #1 Entering Stack Resulting Stack &zip2 &zip1 Rtn adr yp xp Rtn adr Old swap: pushl movl, pushl %ebx II:30
swapsetup #1 Entering Stack &zip2 &zip1 Rtn adr yp xp Rtn adr Old swap: pushl movl, pushl %ebx II:31
swapsetup #1 Entering Stack Resulting Stack &zip2 &zip1 Rtn adr Offset relative to 12 8 4 yp xp Rtn adr Old Old %ebx movl 12(),%ecx # get yp movl 8(),%edx # get xp... II:32
swapfinish #1 swap s Stack Resulting Stack yp yp xp xp Rtn adr Rtn adr Old Old Old %ebx Old %ebx movl -4(),%ebx movl, popl ret Observation: Saved and restored register %ebx II:33
swapfinish #2 swap s Stack yp yp xp xp Rtn adr Rtn adr Old Old Old %ebx Old %ebx movl -4(),%ebx movl, popl ret II:34
swapfinish #2 swap s Stack Resulting Stack yp yp xp xp Rtn adr Rtn adr Old Old %ebx Old movl -4(),%ebx movl, popl ret II:35
swapfinish #2 swap s Stack yp yp xp xp Rtn adr Rtn adr Old Old %ebx Old movl -4(),%ebx movl, popl ret II:36
swapfinish #3 swap s Stack Resulting Stack yp xp Rtn adr Old Old %ebx yp xp Rtn adr movl -4(),%ebx movl, popl ret II:37
swapfinish #4 swap s Stack yp xp Rtn adr Old Old %ebx yp xp Rtn adr movl -4(),%ebx movl, popl ret II:38
swapfinish #4 swap s Stack Resulting Stack yp xp Rtn adr Old Old %ebx yp xp movl -4(),%ebx movl, popl ret Observation Saved & restored register %ebx Didn t do so for %eax, %ecx, or %edx II:39
Register Saving Conventions When procedure yoo calls who: yoois the caller whois the callee Can register be used for temporary storage? yoo: movl $15213, %edx call who addl %edx, %eax ret Contents of register %edx overwritten by who who: movl 8(), %edx addl $91125, %edx ret II:40
Register Saving Conventions When procedure yoo calls who: yoois the caller whois the callee Can register be used for temporary storage? Conventions Caller Save Caller saves temporary in its frame before calling Callee Save Callee saves temporary in its frame before using II:41
Parents leaving for weekend analogy (1/5) Parents (main) leaving for weekend They (caller) give keys to the house to kid (callee) with the rules (calling conventions): You can trash the temporaryroom(s), like the den and basement (registers) if you want, we don t care about it BUTyou d better leave the rooms (registers) that we want to savefor the guests untouched. these rooms better look the same when we return! Who hasn t heard this in their life? II:42
Parents leaving for weekend analogy (2/5) Kid now owns rooms (registers) Kid wants to use the savedrooms for a wild, wild party (computation) What does kid (callee) do? Kid takes what was in these rooms and puts them in the garage (memory) Kid throws the party, trashes everything(except garage, who ever goes in there?) Kid restores the rooms the parents wantedsaved after the partyby replacing the items from the garage (memory) back into those saved rooms II:43
Parents leaving for weekend analogy (3/5) Same scenario, except beforeparents return and kid replaces saved rooms Kid (callee) has left valuable stuff (data) all over. Kid s friend (another callee) wants the house for a party when the kidis away Kid knows that friend might trash the place destroying valuable stuff! Kid remembers rule parents taught and now becomes the parent (caller), instructing friend (callee) on good rules (conventions) of house. II:44
Parents leaving for weekend analogy (4/5) If kid had data in temporary rooms (which were going to be trashed), there are three options: Move items directly to garage (memory) Move items to saved roomswhose contents have already been moved to the garage (memory) Optimize lifestyle (code) so that the amount you ve got to shlepstuff back and forth from garage (memory) is minimized. Mantra: Minimize register footprint Otherwise: Dude, where s my data?! II:45
Parents leaving for weekend analogy (5/5) Friend now owns rooms (registers) Friend wants to use the savedrooms for a wild, wild party (computation) What does friend (callee) do? Friend takes what was in these rooms and puts them in the garage (memory) Friend throws the party, trashes everything (except garage) Friend restores the rooms the kid wantedsaved after the partyby replacing the items from the garage (memory) back into those saved rooms II:46
IA32/Linux Register Usage %eax, %edx, %ecx Caller saves prior to call if values are used later %eax Also used to return integer value %ebx, %esi, %edi Calleesaves if wants to use them Caller-Save Temporaries Callee-Save Temporaries Special %eax %edx %ecx %ebx %esi %edi, Special II:47
Recursive Factorial int rfact(int x) { int rval; if (x <= 1) return 1; rval = rfact(x-1); return rval * x; } Registers %eax used without first saving %ebxused, but saved at beginning & restored at end rfact: pushl movl, pushl %ebx movl 8(),%ebx cmpl $1,%ebx jle.l78 leal -1(%ebx),%eax pushl %eax call rfact imull %ebx,%eax jmp.l79.align 4.L78: movl $1,%eax.L79: movl -4(),%ebx movl, popl ret II:48
Pointer Code Recursive Procedure void s_helper (int x, int *accum) { if (x <= 1) return; else { int z = *accum * x; *accum = z; s_helper(x-1,accum); } } Top-Level Call int sfact(int x) { int val = 1; s_helper(x, &val); return val; } Pass pointer to update location How many copies of val,accumand x? II:49
Creating & Initializing Pointer int sfact(int x) { int val = 1; s_helper(x, &val); return val; } Variable val must be stored on stack Need to create pointer to it Compute pointer as -4() Push on stack as second argument Initial part of sfact _sfact: pushl # Save movl, # Set subl $16, # Add 16 bytes movl 8(),%edx # edx = x movl $1,-4() # val = 1 8 x 4 Rtn adr 0 Old -4 val = 1-8 Temp. -12 Unused Space -16 II:50
Passing Pointer int sfact(int x) { int val = 1; s_helper(x, &val); return val; } Calling s_helper from sfact leal -4(),%eax # Compute &val pushl %eax # Push on stack pushl %edx # Push x call s_helper # call movl -4(),%eax # Return val # Finish Stack at time of call 8 x 4 Rtn adr 0 Old -4 val=x! = 1-8 -12 Unused -16 &val x II:51
IA 32 Procedure Summary The stack makes recursion work Private storage for each instance of procedure call Instantiations don t clobber each other Addressing of locals + arguments can be relative to stack positions Managed by stack discipline Procedures return in inverse order of calls IA32 procedures combination of instructions + conventions Call / Ret instructions Register usage conventions Caller / Calleesave and Stack frame organization conventions Caller Frame Arguments Return Addr Old Saved Registers + Local Variables Argument Build II:52