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
© Copyright 2025 Paperzz