IA32 Stack
15-213
“The course that gives CMU its Zip!”
Machine-Level Programming III:
Procedures
Sept. 17, 2002
!
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
Topics
!
IA32 stack discipline
!
Register saving conventions
!
Creating pointers to local
variables
Stack Grows
Down
Stack
Pointer
%esp
Stack “Top”
15-213, F’02
–2–
class07.ppt
IA32 Stack Pushing
IA32 Stack Popping
Pushing
Stack “Bottom”
Popping
!
pushl Src
!
popl Dest
!
Fetch operand at Src
Decrement %esp by 4
!
Read operand at address
given by %esp
!
Increment %esp by 4
!
Write to Dest
!
!
Increasing
Addresses
Write operand at address
given by %esp
Stack
Pointer
%esp
Stack “Bottom”
Increasing
Addresses
Stack
Pointer
%esp
Stack Grows
Down
Stack Grows
Down
+4
-4
Stack “Top”
Stack “Top”
–3–
15-213, F’02
–4–
15-213, F’02
Procedure Control Flow
Stack Operation Examples
pushl %eax
!
popl %edx
Use stack to support procedure call and return
Procedure call:
call label
0x110
0x110
0x110
0x10c
0x10c
0x10c
0x108
0x108
123
0x104
%eax
213
%eax
%edx
555
%esp
0x108
0x108
123
0x104
213
Return address value
!
123
!
213
213
%eax
%edx
555
%edx
555
213
%esp
0x108
0x104
%esp
0x104
0x108
e8 3d 06 00 00
50
call
0x110
!
0x108
8048b90 <main>
%eax
%esp
0x108
%eip 0x804854e
ret
Pop address from stack; Jump to address
15-213, F’02
c3
ret
8048b90
ret
0x110
0x110
0x10c
0x108
123
0x10c
123
0x108
0x104 0x8048553
%esp
0x108
0x104
%eip 0x8048b90
0x804854e
0x104
%eip 0x8048591
%eip is program counter
–7–
%eax
8048591:
0x104 0x8048553
%esp
8048b90 <main>
pushl
Procedure Return Example
0x10c
123
call
8048553: 50
–6–
0x110
0x10c
0x108
call
pushl
Example from disassembly
804854e: e8 3d 06 00 00
Procedure return:
Procedure Call Example
804854e:
8048553:
Address of instruction beyond call
" Return address = 0x8048553
213
15-213, F’02
–5–
Push return address on stack; Jump to label
123
0x8048553
%esp
0x104
0x108
%eip 0x8048553
0x8048591
%eip is program counter
15-213, F’02
–8–
15-213, F’02
Stack-Based Languages
Call Chain Example
Languages that Support Recursion
!
e.g., C, Pascal, Java
!
Code must be “Reentrant”
Code Structure
yoo(…)
{
•
•
who();
•
•
}
" 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
Call Chain
yoo
who(…)
{
• • •
amI();
• • •
amI();
• • •
}
who
amI
amI(…)
{
•
•
amI();
•
•
}
" From when called to when return
!
Callee returns before caller does
!
Stack Allocated in Frames
!
Procedure amI
recursive
state for single procedure instantiation
15-213, F’02
–9–
Stack Frames
Local variables
!
Return information
!
Temporary space
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
yoo(…)
{
•
•
who();
•
•
}
who
Frame
Pointer
%ebp
Stack
Pointer
%esp
amI
15-213, F’02
Stack Operation
yoo
amI
– 10 –
Contents
!
amI
Call Chain
yoo
Frame
Pointer
%ebp
Stack
Pointer
%esp
•
•
•
yoo
proc
Stack
“Top”
15-213, F’02
– 12 –
15-213, F’02
•
•
•
Stack Operation
who(…)
{
• • •
amI();
• • •
amI();
• • •
}
Call Chain
yoo
who
Frame
Pointer
%ebp
Stack
Pointer
%esp
yoo
15-213, F’02
•
•
•
Stack Operation
amI(…)
{
•
•
amI();
•
•
}
amI(…)
{
•
•
amI();
•
•
}
who
– 13 –
Call Chain
who
amI
Frame
Pointer
%ebp
yoo
yoo
who
amI
Frame
Pointer
%ebp
Stack
Pointer
%esp
amI
who
amI
15-213, F’02
– 14 –
amI(…)
{
•
•
amI();
•
•
}
yoo
amI
Call Chain
•
•
•
Stack Operation
yoo
who
•
•
•
Stack Operation
Call Chain
yoo
yoo
who
who
amI
amI
amI
amI
Stack
Pointer
%esp
amI
Frame
Pointer
%ebp
amI
amI
Stack
Pointer
%esp
– 15 –
15-213, F’02
– 16 –
15-213, F’02
•
•
•
Stack Operation
amI(…)
{
•
•
amI();
•
•
}
Call Chain
yoo
amI
amI
amI
who
Frame
Pointer
%ebp
amI
Stack
Pointer
%esp
•
•
•
– 19 –
Call Chain
yoo
who
amI
Frame
Pointer
%ebp
Stack
Pointer
%esp
yoo
yoo
Frame
Pointer
%ebp
who
amI
Stack
Pointer
%esp
who
amI
amI
15-213, F’02
Stack Operation
Call Chain
amI
amI
– 17 –
who(…)
{
• • •
amI();
• • •
amI();
• • •
}
amI(…)
{
•
•
amI();
•
•
}
yoo
who
•
•
•
Stack Operation
15-213, F’02
– 18 –
•
•
•
Stack Operation
yoo
amI(…)
{
•
•
•
•
}
who
Call Chain
yoo
amI
amI
amI
amI
– 20 –
Frame
Pointer
%ebp
who
amI
15-213, F’02
yoo
amI
Stack
Pointer
%esp
who
amI
15-213, F’02
•
•
•
Stack Operation
who(…)
{
• • •
amI();
• • •
amI();
• • •
}
Call Chain
Frame
Pointer
%ebp
yoo
who
amI
amI
Stack
Pointer
%esp
Stack Operation
yoo
yoo(…)
{
•
•
who();
•
•
}
who
amI
!
Saved register context
!
Old frame pointer
Arguments
Frame Pointer
(%ebp)
Return Addr
Old %ebp
Saved
Registers
+
Local
Variables
Caller Stack Frame
!
int zip1 = 15213;
int zip2 = 91125;
Caller
Frame
" “Argument build”
" If can’t keep in registers
Return address
" Pushed by call instruction
!
– 23 –
Arguments for this call
15-213, F’02
– 22 –
Calling swap from call_swap
Current Stack Frame (“
(“Top”
Top”
to Bottom)
Local variables
amI
Revisiting swap
IA32/Linux Stack Frame
!
amI
amI
Parameters for function
about to call
yoo
who
amI
15-213, F’02
Frame
Pointer
%ebp
Stack
Pointer
%esp
yoo
amI
– 21 –
!
Call Chain
•
•
•
Stack Pointer
(%esp)
Argument
Build
15-213, F’02
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 Setup #1
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
%ebp
Body
•
•
•
&zip2
yp
&zip1
xp
%esp
swap:
pushl %ebp
movl %esp,%ebp
pushl %ebx
15-213, F’02
– 26 –
swap Setup #3
Resulting
Stack
Resulting
Stack
Entering
Stack
%ebp
•
•
•
•
•
•
•
•
•
•
•
•
&zip2
yp
&zip2
yp
&zip1
xp
&zip1
xp
Rtn adr
%esp
%esp
Finish
%ebp
Rtn adr
Old %ebp
Rtn adr
%esp
%ebp
%esp
swap:
pushl %ebp
movl %esp,%ebp
pushl %ebx
– 27 –
Rtn adr
Old %ebp
swap Setup #2
Entering
Stack
%ebp
•
•
•
Rtn adr
15-213, F’02
– 25 –
Resulting
Stack
Entering
Stack
Rtn adr
Old %ebp
%ebp
Old %ebx
%esp
swap:
pushl %ebp
movl %esp,%ebp
pushl %ebx
15-213, F’02
– 28 –
15-213, F’02
swap Finish #1
Effect of swap Setup
Entering
Stack
Resulting
Stack
%ebp
•
•
•
swap’s
Stack
Offset
•
•
•
Offset
(relative to %ebp)
•
•
•
Offset
12
yp
12
8
xp
8
xp
Rtn adr
4
Rtn adr
yp
&zip2
12
yp
4
&zip1
8
xp
0 Old %ebp
%ebp
0 Old %ebp
%ebp
4
Rtn adr
-4 Old %ebx
%esp
-4 Old %ebx
%esp
%esp
Rtn adr
movl 12(%ebp),%ecx # get yp
movl 8(%ebp),%edx # get xp
. . .
0 Old %ebp
%ebp
Old %ebx
%esp
!
15-213, F’02
swap Finish #2
swap’s
Stack
Offset
Offset
12
yp
8
xp
4
Rtn adr
12
0 Old %ebp
%ebp
-4 Old %ebx
%esp
Saved & restored register %ebx
15-213, F’02
– 30 –
swap Finish #3
swap’s
Stack
•
•
•
movl -4(%ebp),%ebx
movl %ebp,%esp
popl %ebp
ret
Observation
Body
– 29 –
swap’s
Stack
•
•
•
Offset
yp
12
%ebp
swap’s
Stack
•
•
•
Offset
12
yp
xp
Rtn adr
8
xp
8
xp
4
Rtn adr
4
Rtn adr
4
0 Old %ebp
%ebp
0 Old %ebp
%esp
15-213, F’02
•
•
•
yp
8
%ebp
%esp
%esp
movl -4(%ebp),%ebx
movl %ebp,%esp
popl %ebp
ret
– 31 –
•
•
•
movl -4(%ebp),%ebx
movl %ebp,%esp
popl %ebp
ret
– 32 –
15-213, F’02
swap Finish #4
Register Saving Conventions
%ebp
swap’s
Stack
%ebp
•
•
•
•
•
•
yp
&zip2
8
xp
&zip1
4
Rtn adr
Offset
12
Exiting
Stack
%esp
%esp
Observation
!
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
– 33 –
When procedure yoo calls who:
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
!
who:
• • •
movl 8(%ebp), %edx
addl $91125, %edx
• • •
ret
Contents of register %edx overwritten by who
15-213, F’02
– 34 –
Register Saving Conventions
IA32/Linux Register Usage
When procedure yoo calls who:
who:
Integer Registers
!
!yoo is the caller, who is the callee
!
%ebp, %esp
Can Register be Used for Temporary Storage?
!
Conventions
!
" Caller saves temporary in its frame before calling
!
Three managed as
callee-save
%ebx, %esi, %edi
" Old values saved on
stack prior to using
“Caller Save”
“Callee Save”
!
" Callee saves temporary in its frame before using
!
– 35 –
– 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
15-213, F’02
%eax
Two have special uses
Special
%esp
%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
!
!
%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
– 37 –
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:
#
# 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:
Rfact Stack Setup
Caller
pre %ebp
%ebp
pre %ebx
Entering Stack
x
%esp
Rtn adr
rfact:
pushl %ebp
movl %esp,%ebp
pushl %ebx
pre %ebp
Caller
Callee
pre %ebx
8
x
4
Rtn adr
0 Old %ebp
%ebp
-4 Old %ebx
%esp
15-213, F’02
– 38 –
Rfact Recursion
leal -1(%ebx),%eax
x
pushl %eax
Rtn adr
Old %ebp
Old %ebx
%ebp
x
%esp
Rtn adr
Old %ebp
– 39 –
Registers
%ebx Stored value of x
%eax
x-1
%ebx
x
%eax
" Temporary value of x-1
" Returned value from rfact(x-1)
" Returned value from this call
15-213, F’02
%ebp
Old %ebx
x-1
int rfact(int x)
{
int rval;
if (x <= 1)
return 1;
rval = rfact(x-1) ;
return rval * x;
}
call rfact
– 40 –
x
Rtn adr
%esp
Old %ebp
%ebp
Old %ebx
%eax
x-1
%ebx
x
x-1
Rtn adr
%eax
x-1
%ebx
x
%esp
15-213, F’02
Rfact Result
Rfact Completion
movl -4(%ebp),%ebx
movl %ebp,%esp
popl %ebp
ret
pre %ebp
x
x
Rtn adr
Rtn adr
Old %ebp
%ebp
Old %ebp
Old %ebx
x-1
pre %ebx
imull %ebx,%eax
Return from Call
x-1
x
4
Rtn adr
0 Old %ebp
%ebp
-8
x-1
(x-1)!
%eax
(x-1)!
x!
%ebx
x
%ebx
x
pre %ebx
pre %ebp
8
x
pre %ebx
4
Rtn adr
%ebp
%esp
%esp
0 Old %ebp
%eax
%eax
pre %ebp
-4 Old %ebx
Old %ebx
%esp
8
x!
%ebx Old x
%ebx
%eax
x
%ebp
%esp
%ebx Old %ebx
%eax
15-213, F’02
Pointer Code
!
– 43 –
x!
%ebx Old %ebx
– 41 –
Recursive Procedure
%esp
Rtn adr
x!
Assume that rfact(x-1)
returns (x-1)! in register
%eax
void s_helper
(int x, int *accum)
{
if (x <= 1)
return;
else {
int z = *accum * x;
*accum = z;
s_helper (x-1,accum);
}
}
%ebp
15-213, F’02
– 42 –
Creating & Initializing Pointer
Top-Level Call
Initial part of sfact
int sfact(int x)
{
int val = 1;
s_helper(x, &val);
return val;
}
_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
Pass pointer to update location
15-213, F’02
– 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
Using 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
8
x
4
Rtn adr
%ebp
0 Old %ebp
-4 val =x!
= 1
accum*x
accum
%eax
accum*x
x
%ecx
x
%edx
-8
-12
int sfact(int x)
{
int val = 1;
s_helper(x, &val);
return val;
}
void s_helper
(int x, int *accum)
{
• • •
int z = *accum * x;
*accum = z;
• • •
}
Stack at time of call
• • •
movl %ecx,%eax
# z = x
imull (%edx),%eax # z *= *accum
movl %eax,(%edx) # *accum = z
• • •
Unused
-16
&val
x
%esp
!
Register %ecx holds x
!
Register %edx holds pointer to accum
" Use access (%edx) to reference memory
15-213, F’02
– 45 –
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
– 46 –
15-213, F’02
© Copyright 2025 Paperzz