Lecture 5 Machine-Level Programming III: Procedures Topics IA32 stack discipline Register saving conventions Creating pointers to local variables IA32 Region of memory managed with stack discipline Grows toward lower addresses Register indicates lowest stack address address of top element Bottom Increasing Addresses Grows Down Top 2 Datorarkitektur 26 IA32 Pushing IA32 Popping Bottom Bottom Pushing pushl Src Fetch operand at Src Decrement by Write operand at address given by Increasing Addresses Popping popl Dest Read operand at address given by Increment by Write to Dest Increasing Addresses - Grows Down + Grows Down Top Top 3 Datorarkitektur 26 Datorarkitektur 26
Operation Eamples Procedure Control Flow pushl %ea popl %ed Use stack to support procedure call and urn Procedure call: 11 1c 1 3 11 1c 1 3 11 1c 1 3 call label Push urn address on stack; Jump to label Return address value Address of instruction beyond call 1 213 1 213 Eample from disassembly 5e: e 3d 6 call b9 <main> %ea %ed 213 555 1 %ea %ed 213 555 1 1 %ea %ed 213 555 213 1 1 553: 5 pushl %ea Return address = 553 Procedure urn: Pop address from stack; Jump to address 5 Datorarkitektur 26 6 Datorarkitektur 26 Procedure Call Eample 5e: e 3d 6 call b9 <main> 553: 5 pushl %ea call b9 Procedure Return Eample 591: c3 11 11 11 11 1c 1c 1c 1c 1 3 1 3 1 3 1 3 1 553 1 553 553 1 1 1 1 1 1 %eip 5e %eip 5e b9 %eip 591 %eip 591 553 %eip is program counter %eip is program counter 7 Datorarkitektur 26 Datorarkitektur 26
-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 Discipline State for given procedure needed for limited time From when called to when urn Callee urns before caller does Allocated in s state for single procedure instantiation Eample Code Structure ( ) (); ( ) (); (); Procedure recursive ( ) (); 9 Datorarkitektur 26 1 Datorarkitektur 26 s Contents Local variables Return information Temporary space Management Space allocated when enter procedure Set-up code Deallocated when urn Finish code s pointer indicates stack top pointer indicates start of current frame proc Top Operation ( ) (); 11 Datorarkitektur 26 Datorarkitektur 26
Operation Operation ( ) (); (); ( ) (); 13 Datorarkitektur 26 1 Datorarkitektur 26 Operation Operation ( ) (); ( ) (); 15 Datorarkitektur 26 16 Datorarkitektur 26
Operation Operation ( ) (); ( ) (); 17 Datorarkitektur 26 1 Datorarkitektur 26 Operation Operation ( ) (); (); ( ) 19 Datorarkitektur 26 2 Datorarkitektur 26
Operation ( ) (); (); Operation ( ) (); 21 Datorarkitektur 26 22 Datorarkitektur 26 IA32/Linu Revisiting swap Current ( Top to Bottom) Parameters for function about to call Argument build Local variables If can t keep in registers Saved register contet Old frame pointer Caller Return address Pushed by call instruction Arguments for this call Caller () () Arguments Return Addr Old Saved Registers + Local Variables Argument Build int zip1 = 15213; int zip2 = 915; void call_swap() swap(&zip1, &zip2); void swap(int *p, int *) int t = *p; int t1 = *; *p = t1; * = t; Calling swap from call_swap call_swap: pushl $zip2 # Global Var pushl $zip1 # Global Var call swap &zip2 &zip1 Resulting 23 Datorarkitektur 26 2 Datorarkitektur 26
Revisiting swap void swap(int *p, int *) int t = *p; int t1 = *; *p = t1; * = t; swap: pushl movl, pushl %eb movl (),%ec movl (),%ed movl (%ec),%ea movl (%ed),%eb movl %ea,(%ed) movl %eb,(%ec) movl -(),%eb movl, popl Set Up Body Finish swap Setup #1 Entering &zip2 &zip1 swap: pushl movl, pushl %eb Resulting p Old 25 Datorarkitektur 26 26 Datorarkitektur 26 swap Setup #2 Entering Resulting swap Setup #3 Entering Resulting &zip2 &zip1 p &zip2 &zip1 p swap: pushl movl, pushl %eb Old swap: pushl movl, pushl %eb Old Old %eb 27 Datorarkitektur 26 2 Datorarkitektur 26
Effect of swap Setup swap Finish #1 Entering &zip2 &zip1 movl (),%ec # get movl (),%ed # get p... (relative to ) Body p Old Old %eb Resulting swap s - Observation p Old Old %eb Saved & restored register %eb - p Old Old %eb movl -(),%eb movl, popl 29 Datorarkitektur 26 3 Datorarkitektur 26 swap Finish #2 swap Finish #3 swap s - p Old Old %eb swap s p Old swap s p Old swap s p movl -(),%eb movl, popl movl -(),%eb movl, popl 31 Datorarkitektur 26 32 Datorarkitektur 26
swap Finish # swap s Observation p Saved & restored register %eb Didn t do so for %ea, %ec, or %ed &zip2 &zip1 Eiting movl -(),%eb movl, popl Register Saving Conventions When procedure calls : is the caller, is the callee Can Register be Used for Temporary Storage? : movl $15213, %ed call addl %ed, %ea : movl (), %ed addl $915, %ed Contents of register %ed overwritten by 33 Datorarkitektur 26 3 Datorarkitektur 26 Register Saving Conventions IA32/Linu Register Usage When procedure calls : is the caller, is 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 Integer Registers Two have special uses, Three managed as calleesave %eb,%esi, %edi Old values saved on stack prior to using Three managed as callersave %ea, %ed, %ec Do what you please, but epect any callee to do so, as well Register %ea also stores urned value Caller-Save Temporaries Callee-Save Temporaries Special %ea %ed %ec %eb %esi %edi 35 Datorarkitektur 26 36 Datorarkitektur 26
Recursive Factorial int rfact(int ) int rval; if ( <= 1) urn 1; rval = rfact(-1); urn rval * ; Registers %ea used without first saving %eb used, but save at beginning & restore at end.globl rfact.te rfact,@function rfact: pushl movl, pushl %eb movl (),%eb cmpl $1,%eb jle.l7 leal -1(%eb),%ea pushl %ea call rfact imull %eb,%ea jmp.l79.align.l7: movl $1,%ea.L79: movl -(),%eb movl, popl 37 Datorarkitektur 26 Rfact Setup pre pre %eb Caller Entering rfact: pushl movl, pushl %eb pre Caller pre %eb Old Callee - Old %eb 3 Datorarkitektur 26 Rfact Body Recursion int rfact(int ) int rval; if ( <= 1) urn 1; rval = rfact(-1) ; urn rval * ; movl (),%eb # eb = cmpl $1,%eb # Compare : 1 jle.l7 # If <= goto Term leal -1(%eb),%ea # ea = -1 pushl %ea # Push -1 call rfact # rfact(-1) imull %eb,%ea # rval * jmp.l79 # Goto done.l7: # Term: movl $1,%ea # urn val = 1.L79: # Done: Registers %eb Stored value of %ea Temporary value of -1 Returned value from rfact(-1) Returned value from this call Rfact Recursion leal -1(%eb),%ea pushl %ea Old Old %eb Old Old %eb -1 %ea -1 %eb %ea -1 %eb call rfact Old Old %eb -1 %ea -1 %eb 39 Datorarkitektur 26 Datorarkitektur 26
Rfact Result Return from Call Old Old %eb -1 imull %eb,%ea Old Old %eb -1 - - %ea Rfact Completion pre pre %eb Old Old %eb -1! pre pre %eb Old movl -(),%eb movl, popl pre pre %eb %ea (-1)! %ea (-1)!! %eb Old %eb %ea! %eb %eb %eb Old %eb %ea! Assume that rfact(-1) urns (-1)! in register % ea %eb Old %eb 1 Datorarkitektur 26 2 Datorarkitektur 26 Code Recursive Procedure void s_helper (int, int *accum) if ( <= 1) urn; else int z = *accum * ; *accum = z; s_helper (-1,accum); Pass pointer to update location Top-Level Call int sfact(int ) int val = 1; s_helper(, &val); urn val; Creating & Initializing Initial part of sfact _sfact: pushl # Save movl, # Set subl $16, # Add 16 bytes movl (),%ed # ed = movl $1,-() # val = 1 Using for Local Variable Variable val must be stored on stack Need to create pointer to it Compute pointer as -() Push on stack as second argument Temp. Unused Space int sfact(int ) int val = 1; s_helper(, &val); urn val; Old - val = 1 - - -16 3 Datorarkitektur 26 Datorarkitektur 26
Passing Using Calling s_helper from sfact leal -(),%ea # Compute &val pushl %ea # Push on stack pushl %ed # Push call s_helper # call movl -(),%ea # Return val # Finish int sfact(int ) int val = 1; s_helper(, &val); urn val; at time of call Old - val =! 1 - - Unused -16 &val void s_helper (int, int *accum) int z = *accum * ; *accum = z; movl %ec,%ea # z = imull (%ed),%ea # z *= *accum movl %ea,(%ed) # *accum = z Register %ec holds Register %ed holds pointer to accum Use access (%ed) to reference memory %ea %ec accum* accum* %ed 5 Datorarkitektur 26 6 Datorarkitektur 26 Summary The 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 Can be managed by stack discipline Procedures urn in inverse order of calls IA32 Procedures Combination of Instructions + Conventions Call / Ret instructions Register usage conventions Caller / Callee save and frame organization conventions 7 Datorarkitektur 26