class07.ppt

15-213
“The course that gives CMU its Zip!”
Machine-Level Programming III:
Procedures
Sept. 17, 2002
Topics



class07.ppt
IA32 stack discipline
Register saving conventions
Creating pointers to local
variables
IA32 Stack



Region of memory managed
with stack discipline
Grows toward lower
addresses
Register %esp indicates
lowest stack address
Stack “Bottom”
Increasing
Addresses
 address of top element
Stack
Pointer
%esp
Stack Grows
Down
Stack “Top”
–2–
15-213, F’02
IA32 Stack Pushing
Stack “Bottom”
Pushing

pushl Src

Fetch operand at Src
Decrement %esp by 4


Increasing
Addresses
Write operand at address
given by %esp
Stack
Pointer
%esp
Stack Grows
Down
-4
Stack “Top”
–3–
15-213, F’02
IA32 Stack Popping
Stack “Bottom”
Popping

popl Dest


Read operand at address
given by %esp
Increment %esp by 4

Write to Dest
Increasing
Addresses
Stack
Pointer
%esp
Stack Grows
Down
+4
Stack “Top”
–4–
15-213, F’02
Stack Operation Examples
pushl %eax
popl %edx
0x110
0x110
0x110
0x10c
0x10c
0x10c
0x108
–5–
123
0x108
123
0x108
123
0x104
213
0x104
213
%eax
213
%eax
213
%eax
213
%edx
555
%edx
555
%edx
555
213
%esp
0x108
%esp
0x108
0x104
%esp
0x104
0x108
15-213, F’02
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 value


Address of instruction beyond call
Example from disassembly
804854e: e8 3d 06 00 00
8048553: 50
call
pushl
8048b90 <main>
%eax
 Return address = 0x8048553
Procedure return:

–6–
ret
Pop address from stack; Jump to address
15-213, F’02
Procedure Call Example
804854e:
8048553:
e8 3d 06 00 00
50
call
0x110
0x110
0x10c
0x10c
0x108
123
0x108
call
pushl
8048b90 <main>
%eax
8048b90
123
0x104 0x8048553
%esp
0x108
%esp
%eip 0x804854e
0x108
0x104
%eip 0x8048b90
0x804854e
%eip is program counter
–7–
15-213, F’02
Procedure Return Example
8048591:
c3
ret
ret
0x110
0x110
0x10c
0x10c
0x108
123
0x108
0x104 0x8048553
%esp
0x104
%eip 0x8048591
123
0x8048553
%esp
0x104
0x108
%eip 0x8048553
0x8048591
%eip is program counter
–8–
15-213, F’02
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

–9–
state for single procedure instantiation
15-213, F’02
Call Chain Example
Code Structure
yoo(…)
{
•
•
who();
•
•
}

– 10 –
Call Chain
yoo
who(…)
{
• • •
amI();
• • •
amI();
• • •
}
Procedure amI
recursive
who
amI
amI(…)
{
•
•
amI();
•
•
}
amI
amI
amI
15-213, F’02
Stack Frames
Contents



Local variables
Return information
Temporary space
yoo
who
amI
Management

Space allocated when enter
procedure
 “Set-up” code

Deallocated when return
 “Finish” code
Pointers


– 11 –
Stack pointer %esp indicates
stack top
Frame pointer %ebp indicates
start of current frame
Frame
Pointer
%ebp
proc
Stack
Pointer
%esp
Stack
“Top”
15-213, F’02
Stack Operation
yoo(…)
{
•
•
who();
•
•
}
– 12 –
Call Chain
yoo
Frame
Pointer
%ebp
•
•
•
yoo
Stack
Pointer
%esp
15-213, F’02
•
•
•
Stack Operation
who(…)
{
• • •
amI();
• • •
amI();
• • •
}
– 13 –
Call Chain
yoo
Frame
Pointer
%ebp
yoo
who
who
Stack
Pointer
%esp
15-213, F’02
•
•
•
Stack Operation
amI(…)
{
•
•
amI();
•
•
}
– 14 –
Call Chain
yoo
yoo
who
Frame
Pointer
%ebp
who
amI
amI
Stack
Pointer
%esp
15-213, F’02
•
•
•
Stack Operation
amI(…)
{
•
•
amI();
•
•
}
Call Chain
yoo
yoo
who
who
amI
amI
Frame
Pointer
%ebp
amI
amI
Stack
Pointer
%esp
– 15 –
15-213, F’02
•
•
•
Stack Operation
amI(…)
{
•
•
amI();
•
•
}
Call Chain
yoo
yoo
who
who
amI
amI
amI
amI
Frame
Pointer
%ebp
amI
amI
Stack
Pointer
%esp
– 16 –
15-213, F’02
•
•
•
Stack Operation
amI(…)
{
•
•
amI();
•
•
}
Call Chain
yoo
who
who
amI
amI
amI
– 17 –
yoo
Frame
Pointer
%ebp
amI
amI
Stack
Pointer
%esp
15-213, F’02
•
•
•
Stack Operation
amI(…)
{
•
•
amI();
•
•
}
Call Chain
yoo
yoo
who
Frame
Pointer
%ebp
amI
amI
amI
who
Stack
Pointer
%esp
amI
– 18 –
15-213, F’02
•
•
•
Stack Operation
who(…)
{
• • •
amI();
• • •
amI();
• • •
}
Call Chain
yoo
Frame
Pointer
%ebp
yoo
who
who
amI
Stack
Pointer
%esp
amI
amI
– 19 –
15-213, F’02
•
•
•
Stack Operation
amI(…)
{
•
•
•
•
}
Call Chain
yoo
yoo
Frame
Pointer
%ebp
who
amI
amI
who
amI
amI
Stack
Pointer
%esp
amI
– 20 –
15-213, F’02
•
•
•
Stack Operation
who(…)
{
• • •
amI();
• • •
amI();
• • •
}
Call Chain
Frame
Pointer
%ebp
yoo
yoo
who
who
amI
amI
Stack
Pointer
%esp
amI
amI
– 21 –
15-213, F’02
Stack Operation
yoo(…)
{
•
•
who();
•
•
}
Call Chain
Frame
Pointer
%ebp
•
•
•
yoo
Stack
Pointer
%esp
yoo
who
amI
amI
amI
amI
– 22 –
15-213, F’02
IA32/Linux Stack Frame
Current Stack Frame (“Top”
to Bottom)

Parameters for function
about to call
Caller
Frame
 “Argument build”

Local variables
 If can’t keep in registers


Arguments
Frame Pointer
(%ebp)
Saved register context
Old frame pointer
Saved
Registers
+
Local
Variables
Caller Stack Frame

Return Addr
Old %ebp
Return address
 Pushed by call instruction

– 23 –
Arguments for this call
Stack Pointer
(%esp)
Argument
Build
15-213, F’02
Revisiting swap
Calling swap from call_swap
int zip1 = 15213;
int zip2 = 91125;
void call_swap()
{
swap(&zip1, &zip2);
}
void swap(int *xp, int *yp)
{
int t0 = *xp;
int t1 = *yp;
*xp = t1;
*yp = t0;
}
– 24 –
call_swap:
• • •
pushl $zip2
pushl $zip1
call swap
• • •
•
•
•
# Global Var
# Global Var
Resulting
Stack
&zip2
&zip1
Rtn adr
%esp
15-213, F’02
Revisiting swap
void swap(int *xp, int *yp)
{
int t0 = *xp;
int t1 = *yp;
*xp = t1;
*yp = t0;
}
swap:
pushl %ebp
movl %esp,%ebp
pushl %ebx
movl
movl
movl
movl
movl
movl
Set
Up
12(%ebp),%ecx
8(%ebp),%edx
(%ecx),%eax
(%edx),%ebx
%eax,(%edx)
%ebx,(%ecx)
movl -4(%ebp),%ebx
movl %ebp,%esp
popl %ebp
ret
– 25 –
Body
Finish
15-213, F’02
swap Setup #1
Resulting
Stack
Entering
Stack
%ebp
%ebp
•
•
•
•
•
•
&zip2
yp
&zip1
xp
Rtn adr
%esp
Rtn adr
Old %ebp
%esp
swap:
pushl %ebp
movl %esp,%ebp
pushl %ebx
– 26 –
15-213, F’02
swap Setup #2
Resulting
Stack
Entering
Stack
%ebp
•
•
•
•
•
•
&zip2
yp
&zip1
xp
Rtn adr
%esp
Rtn adr
Old %ebp
%ebp
%esp
swap:
pushl %ebp
movl %esp,%ebp
pushl %ebx
– 27 –
15-213, F’02
swap Setup #3
Resulting
Stack
Entering
Stack
%ebp
•
•
•
•
•
•
&zip2
yp
&zip1
xp
Rtn adr
%esp
Rtn adr
Old %ebp
%ebp
Old %ebx
%esp
swap:
pushl %ebp
movl %esp,%ebp
pushl %ebx
– 28 –
15-213, F’02
Effect of swap Setup
Entering
Stack
Resulting
Stack
%ebp
•
•
•
Offset
(relative to %ebp)
&zip2
12
yp
&zip1
8
xp
4
Rtn adr
Rtn adr
%esp
movl 12(%ebp),%ecx # get yp
movl 8(%ebp),%edx # get xp
. . .
– 29 –
•
•
•
0 Old %ebp
%ebp
Old %ebx
%esp
Body
15-213, F’02
swap Finish #1
swap’s
Stack
Offset
•
•
•
Offset
12
yp
12
yp
8
xp
8
xp
4
Rtn adr
4
Rtn adr
0 Old %ebp
%ebp
0 Old %ebp
%ebp
-4 Old %ebx
%esp
-4 Old %ebx
%esp
Observation

– 30 –
•
•
•
Saved & restored register %ebx
movl -4(%ebp),%ebx
movl %ebp,%esp
popl %ebp
ret
15-213, F’02
swap Finish #2
swap’s
Stack
Offset
swap’s
Stack
•
•
•
Offset
•
•
•
12
yp
12
yp
8
xp
8
xp
4
Rtn adr
4
Rtn adr
0 Old %ebp
%ebp
-4 Old %ebx
%esp
0 Old %ebp
%ebp
%esp
movl -4(%ebp),%ebx
movl %ebp,%esp
popl %ebp
ret
– 31 –
15-213, F’02
swap Finish #3
swap’s
Stack
Offset
%ebp
swap’s
Stack
•
•
•
Offset
•
•
•
12
yp
12
yp
8
xp
8
xp
4
Rtn adr
4
Rtn adr
0 Old %ebp
%ebp
%esp
%esp
movl -4(%ebp),%ebx
movl %ebp,%esp
popl %ebp
ret
– 32 –
15-213, F’02
swap Finish #4
%ebp
swap’s
Stack
%ebp
•
•
•
•
•
•
12
yp
&zip2
8
xp
&zip1
4
Rtn adr
Offset
Exiting
Stack
%esp
%esp
Observation


– 33 –
Saved & restored register %ebx
Didn’t do so for %eax, %ecx, or %edx
movl -4(%ebp),%ebx
movl %ebp,%esp
popl %ebp
ret
15-213, F’02
Register Saving Conventions
When procedure yoo calls who:

yoo is the caller, who is the callee
Can Register be Used for Temporary Storage?
yoo:
• • •
movl $15213, %edx
call who
addl %edx, %eax
• • •
ret

– 34 –
who:
• • •
movl 8(%ebp), %edx
addl $91125, %edx
• • •
ret
Contents of register %edx overwritten by who
15-213, F’02
Register Saving Conventions
When procedure yoo calls who:

yoo is the caller, who 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
– 35 –
15-213, F’02
IA32/Linux Register Usage
Integer Registers

%ebp, %esp

Three managed as
callee-save
%ebx, %esi, %edi
 Old values saved on
stack prior to using

– 36 –
Caller-Save
Temporaries
Register %eax also
stores returned value
%edx
%ecx
%ebx
Callee-Save
Temporaries
%esi
%edi
Three managed as
caller-save
%eax, %edx, %ecx
 Do what you please,
but expect any callee
to do so, as well

%eax
Two have special uses
%esp
Special
%ebp
15-213, F’02
Recursive Factorial
int rfact(int x)
{
int rval;
if (x <= 1)
return 1;
rval = rfact(x-1);
return rval * x;
}
Registers


– 37 –
%eax used without first
saving
%ebx used, but save at
beginning & restore at end
.globl rfact
.type
rfact,@function
rfact:
pushl %ebp
movl %esp,%ebp
pushl %ebx
movl 8(%ebp),%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(%ebp),%ebx
movl %ebp,%esp
popl %ebp
ret
15-213, F’02
Rfact Stack Setup
pre %ebp
%ebp
pre %ebx
Entering Stack
Caller
x
Rtn adr
%esp
rfact:
pushl %ebp
movl %esp,%ebp
pushl %ebx
pre %ebp
Caller
Callee
– 38 –
pre %ebx
8
x
4
Rtn adr
0 Old %ebp
%ebp
-4 Old %ebx
%esp
15-213, F’02
Rfact Body
Recursion
movl 8(%ebp),%ebx
cmpl $1,%ebx
jle .L78
leal -1(%ebx),%eax
pushl %eax
call rfact
imull %ebx,%eax
jmp .L79
.L78:
#
movl $1,%eax
.L79:
#
int rfact(int x)
{
int rval;
if (x <= 1)
return 1;
rval = rfact(x-1) ;
return rval * x;
}
– 39 –
# ebx = x
# Compare x : 1
# If <= goto Term
# eax = x-1
# Push x-1
# rfact(x-1)
# rval * x
# Goto done
Term:
# return val = 1
Done:
Registers
%ebx Stored value of x
%eax
 Temporary value of x-1
 Returned value from rfact(x-1)
 Returned value from this call
15-213, F’02
Rfact Recursion
leal -1(%ebx),%eax
x
pushl %eax
Rtn adr
Old %ebp
%ebp
x
Old %ebx
%esp
Rtn adr
Old %ebp
call rfact
%ebp
Old %ebx
x-1
%eax
x-1
%ebx
x
Rtn adr
%esp
Old %ebp
%ebp
Old %ebx
%eax
%ebx
– 40 –
x
x-1
x-1
Rtn adr
x
%eax
x-1
%ebx
x
%esp
15-213, F’02
Rfact Result
imull %ebx,%eax
Return from Call
x
x
Rtn adr
Rtn adr
Old %ebp
%ebp
Old %ebp
Old %ebx
x-1
%ebp
Old %ebx
x-1
%esp
%eax
(x-1)!
%eax
(x-1)!
x!
%ebx
x
%ebx
x
%esp
Assume that rfact(x-1)
returns (x-1)! in register
%eax
– 41 –
15-213, F’02
Rfact Completion
movl -4(%ebp),%ebx
movl %ebp,%esp
popl %ebp
ret
pre %ebp
pre %ebx
8
x
4
Rtn adr
0 Old %ebp
pre %ebp
-4 Old %ebx
-8
x-1
pre %ebx
pre %ebp
8
x
pre %ebx
4
Rtn adr
x
%ebp
%esp
0 Old %ebp
%eax
x!
%ebx Old x
%ebx
%eax
%ebp
%esp
%ebp
%esp
Rtn adr
x!
%ebx Old %ebx
%eax
x!
%ebx Old %ebx
– 42 –
15-213, F’02
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);
}
}

– 43 –
Top-Level Call
int sfact(int x)
{
int val = 1;
s_helper(x, &val);
return val;
}
Pass pointer to update location
15-213, F’02
Creating & Initializing Pointer
Initial part of sfact
_sfact:
pushl %ebp
movl %esp,%ebp
subl $16,%esp
movl 8(%ebp),%edx
movl $1,-4(%ebp)
#
#
#
#
#
Save %ebp
Set %ebp
Add 16 bytes
edx = x
val = 1
Using Stack for Local
Variable

Variable val must be
stored on stack
 Need to create pointer to it
– 44 –

Compute pointer as 4(%ebp)

Push on stack as second
argument
8
x
4
Rtn adr
%ebp
0 Old %ebp
-4 val = 1
-8
-12
Temp.
Space
Unused
-16
%esp
int sfact(int x)
{
int val = 1;
s_helper(x, &val);
return val;
}
15-213, F’02
Passing Pointer
Calling s_helper from sfact
leal -4(%ebp),%eax
pushl %eax
pushl %edx
call s_helper
movl -4(%ebp),%eax
• • •
#
#
#
#
#
#
Compute &val
Push on stack
Push x
call
Return val
Finish
Stack at time of call
8
x
4
Rtn adr
0 Old %ebp
-4 val =x!
= 1
-8
-12
int sfact(int x)
{
int val = 1;
s_helper(x, &val);
return val;
}
– 45 –
%ebp
Unused
-16
&val
x
%esp
15-213, F’02
Using Pointer
void s_helper
(int x, int *accum)
{
• • •
int z = *accum * x;
*accum = z;
• • •
}
accum*x
accum
%eax
accum*x
x
%ecx
x
%edx
• • •
movl %ecx,%eax
# z = x
imull (%edx),%eax # z *= *accum
movl %eax,(%edx) # *accum = z
• • •


Register %ecx holds x
Register %edx holds pointer to accum
 Use access (%edx) to reference memory
– 46 –
15-213, F’02
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

Can be managed by stack discipline
 Procedures return in inverse order of calls
IA32 Procedures Combination of Instructions +
Conventions


Call / Ret instructions
Register usage conventions
 Caller / Callee save
 %ebp and %esp

– 47 –
Stack frame organization conventions
15-213, F’02