Date post: | 13-Mar-2016 |
Category: |
Documents |
Upload: | samantha-mason |
View: | 30 times |
Download: | 0 times |
Machine-Level Programming III:Procedures
TopicsTopics IA32 stack discipline Register-saving conventions Creating pointers to local variables
CS 105“Tour of the Black Holes of Computing”
– 2 – CS 105
IA32 Stack Region of memory managed
with stack discipline Grows toward lower
addresses Register %esp indicates
numerically lowest stack address
Address of top element
StackPointer%esp
Stack GrowsDown
IncreasingAddresses
Stack “Top”
Stack “Bottom”
– 3 – CS 105
IA32 Stack PushingPushingPushing
pushl Src Fetch operand at Src Decrement %esp by 4 Write operand at address
given by %esp
Stack GrowsDown
IncreasingAddresses
Stack “Top”
Stack “Bottom”
StackPointer%esp -4
– 4 – CS 105
IA32 Stack PoppingPoppingPopping
popl Dest Read operand at address
given by %esp Increment %esp by 4 Write to Dest
StackPointer%esp
Stack GrowsDown
IncreasingAddresses
Stack “Top”
Stack “Bottom”
+4
– 5 – CS 105
%esp
%eax%edx
%esp
%eax%edx
%esp
%eax%edx
0x104
5550x108
0x1080x10c0x110
0x104
555213
213123
Stack Operation Examples
0x1080x10c0x110
555213
123
0x108 0x104
pushl %eax
0x1080x10c0x110
213
123
0x104213
popl %edx
0x108
213
– 6 – CS 105
Procedure Control Flow Use stack to support procedure call and return
Procedure call:Procedure call:call label Push return address on stack; jump to label
Return address valueReturn address value 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:Procedure return: ret Pop address from stack; jump to address
– 7 – CS 105
%esp
%eip
%esp
%eip 0x804854e
0x108
0x1080x10c0x110
0x104
0x804854e
0x8048553123
Procedure Call Example
0x1080x10c0x110
123
0x108
804854e: e8 3d 06 00 00 call 8048b90 <main>8048553: 50 pushl %eax
0x104
%eip is program counter
call 8048b90
0x80485530x8048b90
– 8 – CS 105
0x80485920x8048553
%esp
%eip
0x104
%esp
%eip0x8048591
0x1040x104
0x1080x10c0x110
0x8048553123
Procedure Return Example
0x1080x10c0x110
123
ret
8048591: c3 ret
0x108
%eip is program counter
0x8048553
– 9 – CS 105
Stack-Based LanguagesLanguages That Support RecursionLanguages 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
ArgumentsLocal variablesReturn pointer
Stack DisciplineStack Discipline State for given procedure needed for limited time
From when called to when return Callee returns before caller does
Stack Allocated in Stack Allocated in FramesFrames State for single procedure instantiation
– 10 – CS 105
Call Chain ExampleCode StructureCode Structureyoo(…){
••who();••
}
who(…){
• • •amI();• • •amI();• • •
}
amI(…){
••amI();••
}
yoo
who
amI
amI
amI
Call Chain
Procedure amI recursive
amI
– 11 – CS 105
StackPointer%esp
yoo
who
proc
FramePointer%ebp
Stack“Top”
Stack FramesContentsContents
Local variables Return information Temporary space
ManagementManagement Space allocated when entering
procedure“Set-up” code (prologue)
Deallocated when returning“Finish” code (epilogue)
PointersPointers Stack pointer %esp indicates stack top Frame pointer %ebp indicates start of
current frame
amI
– 12 – CS 105
StackPointer%esp
yoo
•••
FramePointer%ebp
Stack Operation
yoo
Call Chainyoo(…){
••who();••
}
– 13 – CS 105
StackPointer%esp
yoo
who
•••
FramePointer%ebp
Stack Operation
yoo
who
Call Chainwho(…){
• • •amI();• • •amI();• • •
}
– 14 – CS 105
StackPointer%esp
yoo
who
amI
•••
FramePointer%ebp
Stack Operation
yoo
who
amI
Call ChainamI(…){
••amI();••
}
– 15 – CS 105
StackPointer%esp
yoo
who
amI
•••
FramePointer%ebp
Stack Operation
yoo
who
amI
Call ChainamI(…){
••amI();••
}
amIamI
– 16 – CS 105
StackPointer%esp
yoo
who
amI
•••
FramePointer%ebp
Stack Operation
yoo
who
amI
Call ChainamI(…){
••amI();••
}
amI
amI
– 17 – CS 105
StackPointer%esp
yoo
who
•••
FramePointer%ebp
Stack Operation
yoo
who
Call Chainwho(…){
• • •amI();• • •amI();• • •
} amI
amI
amI
– 18 – CS 105
StackPointer%esp
yoo
who
•••
FramePointer%ebp
Stack Operation
yoo
who
Call Chainwho(…){
• • •amI();• • •amI();• • •
} amI
amI
amI
amI
– 19 – CS 105
yoo(…){
••who();••
}
StackPointer%esp
yoo
•••
FramePointer%ebp
Stack Operation
yoo
who
Call Chain
amI
amI
amI
amI
– 20 – CS 105
IA32/Linux Stack FrameCurrent Stack Frame, “Top” Current Stack Frame, “Top”
(Low Addrs) to “Bottom”(Low Addrs) to “Bottom” Parameters for function
about to be called“Argument build”
Local variables If can’t keep in registers
Saved register context Old frame pointer
Caller Stack FrameCaller Stack Frame Return address
Pushed by call instruction Arguments for this call Stack Pointer
(%esp)
Frame Pointer(%ebp)
Return Addr
SavedRegisters
+Local
Variables
ArgumentBuild
Old %ebp
Arguments
CallerFrame
– 21 – CS 105
Revisiting swap
void swap(int *xp, int *yp) { int t0 = *xp; int t1 = *yp; *xp = t1; *yp = t0;}
int zip1 = 15213;int zip2 = 91711;
void call_swap(){ swap(&zip1, &zip2);}
call_swap:• • •pushl $zip2 # Global Varpushl $zip1 # Global Varcall swap• • •
&zip2&zip1Rtn adr %esp
ResultingStack
•••
Calling swap from call_swap
– 22 – CS 105
Revisiting swap
void swap(int *xp, int *yp) { int t0 = *xp; int t1 = *yp; *xp = t1; *yp = t0;}
swap:pushl %ebpmovl %esp,%ebppushl %ebx
movl 12(%ebp),%ecxmovl 8(%ebp),%edxmovl (%ecx),%eaxmovl (%edx),%ebxmovl %eax,(%edx)movl %ebx,(%ecx)
movl -4(%ebp),%ebxmovl %ebp,%esppopl %ebpret
Body
SetUp
Finish
– 23 – CS 105
swap Setup #1
swap:pushl %ebpmovl %esp,%ebppushl %ebx
ResultingStack
&zip2&zip1Rtn adr %esp
Stack atEntry
•••
%ebp
ypxp
Rtn adrOld %ebp
%ebp•••
%esp
– 24 – CS 105
swap Setup #2
swap:pushl %ebpmovl %esp,%ebppushl %ebx
ypxp
Rtn adrOld %ebp %ebp
ResultingStack
•••
&zip2&zip1Rtn adr %esp
Stack atEntry
•••
%ebp
%esp
– 25 – CS 105
swap Setup #3
swap:pushl %ebpmovl %esp,%ebppushl %ebx
ypxp
Rtn adrOld %ebp %ebp
ResultingStack
•••
&zip2&zip1Rtn adr %esp
Stack atEntry
•••
%ebp
Old %ebx %esp
– 26 – CS 105
Effect of swap Setup
ypxp
Rtn adrOld %ebp %ebp 0
4 8 12
Offset(relative to %ebp)
•••
&zip2&zip1Rtn adr %esp
Stack atEntry
•••
%ebp
Old %ebx %esp
movl 12(%ebp),%ecx # get ypmovl 8(%ebp),%edx # get xp. . .
Body
Stack afterSetup
– 27 – CS 105
swap Finish #1
movl -4(%ebp),%ebxmovl %ebp,%esppopl %ebpret
ypxp
Rtn adrOld %ebp %ebp 0
4 8 12
Offset
swap’sStack •
••
Old %ebx %esp-4
ObservationObservation Saved & restored register %ebx
ypxp
Rtn adrOld %ebp %ebp 0
4 8 12
Offset
•••
Old %ebx %esp-4
– 28 – CS 105
swap Finish #2
movl -4(%ebp),%ebxmovl %ebp,%esppopl %ebpret
ypxp
Rtn adrOld %ebp %ebp 0
4 8 12
Offset
swap’sStack •
••
Old %ebx %esp-4
ypxp
Rtn adrOld %ebp %ebp 0
4 8 12
Offset
swap’sStack •
••
%esp
– 29 – CS 105
swap Finish #3
movl -4(%ebp),%ebxmovl %ebp,%esppopl %ebpret
ypxp
Rtn adr
%ebp
0 4 8
Offset
swap’sStack •
••
ypxp
Rtn adrOld %ebp %ebp 0
4 8 12
Offset
swap’sStack •
••
%esp
%esp
{Also knownas leave
– 30 – CS 105
swap Finish #4
movl -4(%ebp),%ebxmovl %ebp,%esppopl %ebpret
&zip2&zip1 %esp
Stackafter ret
•••
%ebp
ObservationObservation Saved & restored register %ebx Didn’t do so for %eax, %ecx, or %edx
ypxp
Rtn adr
%ebp
4 8 12
Offset
swap’sStack •
••
%esp
– 31 – CS 105
Register Saving ConventionsWhen procedure When procedure yooyoo calls calls whowho::
yoo is the caller, who is the callee
Can Register be Used for Temporary Storage?Can Register be Used for Temporary Storage?
Contents of register %edx overwritten by who
yoo:• • •movl $15213, %edxcall whoaddl %edx, %eax• • •ret
who:• • •movl 8(%ebp), %edxaddl $91711, %edx• • •ret
– 32 – CS 105
Register Saving ConventionsWhen procedure When procedure yooyoo calls calls whowho::
yoo is the caller, who is the callee
Can Register be Used for Temporary Storage?Can Register be Used for Temporary Storage?
ConventionsConventions “Caller Save”
Caller saves temporary in its frame before calling “Callee Save”
Callee saves temporary in its frame before using
– 33 – CS 105
IA32/Linux Register Usage
Integer RegistersInteger Registers Two have special uses
%ebp, %esp Three managed as
callee-save%ebx, %esi, %ediOld values saved on
stack prior to using Three managed as
caller-save%eax, %edx, %ecxDo what you please,
but expect any callee to do so, as well
Register %eax also holds returned value
%eax
%edx
%ecx
%ebx
%esi
%edi
%esp
%ebp
Caller-SaveTemporaries
Callee-SaveTemporaries
Special
– 34 – CS 105
int rfact(int x){ int rval; if (x <= 1) return 1; rval = rfact(x-1); return rval * x;}
.globl rfact.type
rfact,@functionrfact:
pushl %ebpmovl %esp,%ebppushl %ebxmovl 8(%ebp),%ebxcmpl $1,%ebxjle .L78leal -1(%ebx),%eaxpushl %eaxcall rfactimull %ebx,%eaxjmp .L79.align 4
.L78:movl $1,%eax
.L79:movl -4(%ebp),%ebxmovl %ebp,%esppopl %ebpret
Recursive Factorial
RegistersRegisters %eax used without first saving %ebx used, but save at
beginning & restore at end
– 35 – CS 105
rfact:pushl %ebpmovl %esp,%ebppushl %ebx
rfact:pushl %ebpmovl %esp,%ebppushl %ebx
Rfact Stack Setup
Entering Stack
xRtn adr 4
8
Caller
%ebp 0 %espOld %ebx-4
Callee
xRtn adr
Caller
%esp
%ebppre %ebppre %ebx
pre %ebppre %ebx
Old %ebp
rfact:pushl %ebpmovl %esp,%ebppushl %ebx
– 36 – CS 105
Rfact Body
RegistersRegisters%ebx Value of x as passed in%eax
Temporary value of x-1Returned value from rfact(x-1)Returned value from this call
movl 8(%ebp),%ebx # ebx = xcmpl $1,%ebx # Compare x : 1jle .L78 # If <= goto Termleal -1(%ebx),%eax # eax = x-1pushl %eax # Push x-1call rfact # rfact(x-1)imull %ebx,%eax # rval * xjmp .L79 # Goto done
.L78: # Term:movl $1,%eax # return val = 1
.L79: # Done:
int rfact(int x){ int rval; if (x <= 1) return 1; rval = rfact(x-1) ; return rval * x;}
Recursion
– 37 – CS 105
Rfact Recursion
xRtn adr
Old %ebp %ebp
Old %ebx
pushl %eax
%espx-1
x-1%eaxx%ebx
xRtn adr
Old %ebp %ebp
Old %ebx %esp
%eaxx%ebx
x-1
leal -1(%ebx),%eax
xRtn adr
Old %ebp %ebp
Old %ebxx-1
x-1%eaxx%ebx
%espRtn adr
call rfact
– 38 – CS 105
(x-1)!
Rfact Result
xRtn adr
Old %ebp %ebp
Old %ebx
%espx-1
imull %ebx,%eax
x!%eaxx%ebx
xRtn adr
Old %ebp %ebp
Old %ebx
%espx-1
(x-1)!%eaxx%ebx
Return from Call
(x-1)!
Assume that rfact(x-1) returns (x-1)! in register %eax
– 39 – CS 105
Rfact Completion movl -4(%ebp),%ebxmovl %ebp,%esppopl %ebpret
xRtn adr
Old %ebp %ebp 0 4 8
Old %ebx%esp
-4
x!%eaxx%ebx
x-1-8
pre %ebppre %ebx
movl -4(%ebp),%ebxmovl %ebp,%esppopl %ebpret
xRtn adr
Old %ebp %ebp 0 4 8
%esp
x!%eaxOld %ebx%ebx
pre %ebppre %ebx
Old %ebx
movl -4(%ebp),%ebxmovl %ebp,%esppopl %ebpret
xRtn adr
%ebp
%esp
x!%eaxOld %ebx%ebx
pre %ebppre %ebx
– 40 – CS 105
Pointer Code
void s_helper (int x, int *accum){ if (x <= 1) return; else { int z = *accum * x; *accum = z; s_helper (x-1,accum); }}
int sfact(int x){ int val = 1; s_helper(x, &val); return val;}
Top-Level CallRecursive Procedure
Pass pointer to update location
– 41 – CS 105
Temp.Space
%esp
Creating & Initializing Pointer
int sfact(int x){ int val = 1; s_helper(x, &val); return val;}
_sfact:pushl %ebp # Save %ebpmovl %esp,%ebp # Set %ebpsubl $16,%esp # Add 16 bytes movl 8(%ebp),%edx # edx = xmovl $1,-4(%ebp) # val = 1
Using Stack for Local VariableUsing Stack for Local Variable Variable val must be stored on
stackNeed to create pointer to it
Compute pointer as -4(%ebp) Push on stack as second argument
Initial part of sfact
xRtn adr
Old %ebp %ebp 0 4 8
-4 val = 1
Unused-12 -8
-16
_sfact:pushl %ebp # Save %ebpmovl %esp,%ebp # Set %ebpsubl $16,%esp # Add 16 bytes movl 8(%ebp),%edx # edx = xmovl $1,-4(%ebp) # val = 1
_sfact:pushl %ebp # Save %ebpmovl %esp,%ebp # Set %ebpsubl $16,%esp # Add 16 bytes movl 8(%ebp),%edx # edx = xmovl $1,-4(%ebp) # val = 1
_sfact:pushl %ebp # Save %ebpmovl %esp,%ebp # Set %ebpsubl $16,%esp # Add 16 bytes movl 8(%ebp),%edx # edx = xmovl $1,-4(%ebp) # val = 1
– 42 – CS 105
Passing Pointer
int sfact(int x){ int val = 1; s_helper(x, &val); return val;}
leal -4(%ebp),%eax # Compute &valpushl %eax # Push on stackpushl %edx # Push xcall s_helper # callmovl -4(%ebp),%eax # Return val• • • # Finish
Calling s_helper from sfact
xRtn adr
Old %ebp %ebp 0 4 8
val = 1 -4
Unused-12 -8
-16
%espx&val
Stack at time of call
leal -4(%ebp),%eax # Compute &valpushl %eax # Push on stackpushl %edx # Push xcall s_helper # callmovl -4(%ebp),%eax # Return val• • • # Finish
leal -4(%ebp),%eax # Compute &valpushl %eax # Push on stackpushl %edx # Push xcall s_helper # callmovl -4(%ebp),%eax # Return val• • • # Finish
val = x!
– 43 – CS 105
Using Pointer
• • •movl %ecx,%eax # z = ximull (%edx),%eax # z *= *accummovl %eax,(%edx) # *accum = z• • •
void s_helper (int x, int *accum){ • • • int z = *accum * x; *accum = z; • • •}
Register %ecx holds x Register %edx holds pointer to accum
Use access (%edx) to reference memory
%edxaccum
xx%eax
%ecxaccum*x
accum*x
– 44 – CS 105
Summary
The Stack Makes Recursion WorkThe Stack Makes Recursion Work Private storage for each instance of procedure call
Instantiations don’t clobber each otherAddressing of locals + arguments can be relative to stack
positions Can be managed by stack discipline
Procedures return in inverse order of calls
IA32 Procedures Combination of Instructions + IA32 Procedures Combination of Instructions + ConventionsConventions Call / Ret instructions Register usage conventions
Caller / Callee save %ebp and %esp
Stack frame organization conventions