07 Machine Procedures
07 Machine Procedures
Instructors:
Randy Bryant and Dave O’Hallaron
Carnegie Mellon
Today
IA 32 Procedures
▪ Stack Structure
▪ Calling Conventions
▪ Illustrations of Recursion & Pointers
2
Carnegie Mellon
IA32 Stack
Stack “Bottom”
Region of memory managed
with stack discipline
Grows toward lower addresses Increasing
Addresses
Stack “Top”
3
Carnegie Mellon
Stack
Grows
Down
Stack Pointer: %esp
-4
Stack “Top”
4
Carnegie Mellon
Increasing
Addresses
Stack
Grows
+4 Down
Stack Pointer: %esp
Stack “Top”
5
Carnegie Mellon
call 8048b90
0x110 0x110
0x10c 0x10c
0x108 123 0x108 123
0x104 0x8048553
ret
0x110 0x110
0x10c 0x10c
0x108 123 0x108 123
0x104 0x8048553 0x8048553
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
▪ state for single procedure instantiation
9
Carnegie Mellon
10
Carnegie Mellon
Stack Frames
Previous
Contents Frame
▪ Local variables
▪ Return information
Frame Pointer: %ebp
▪ Temporary space
Frame for
proc
Management
▪ Space allocated when enter procedure Stack “Top”
▪ “Set-up” code
▪ Deallocated when return
▪ “Finish” code
11
Carnegie Mellon
Stack
Example
yoo(…) yoo
%ebp
{ yoo
yoo
• who %esp
•
who();
• amI amI
•
} amI
amI
12
Carnegie Mellon
Stack
Example
yoo(…) yoo
{ who(…)
•{ yoo
yoo
who
• • • • %ebp
amI();
who();
• • • • amI amI who
%esp
• amI();
} • • •
} amI
amI
13
Carnegie Mellon
Stack
Example
yoo(…) yoo
{ who(…)
•{ yoo
yoo
amI(…) who
• • • •
{
amI();
who();
• who
• • • • amI amI
•
• amI();
• •amI();
• %ebp
}
} • amI amI
• %esp
}
amI
14
Carnegie Mellon
Stack
Example
yoo(…) yoo
{ who(…)
•{ yoo
yoo
amI(…) who
• • • •
{
amI();
who(); amI(…)
• who
• • • {• amI amI
•
• amI();•
} • •amI();
••
} • amI amI
• amI();
} • %ebp
• amI
}
amI
%esp
15
Carnegie Mellon
Stack
Example
yoo(…) yoo
{ who(…)
•{ yoo
yoo
amI(…) who
• • • •
{
amI();
who(); amI(…)
• who
• • • {• amI amI
•
• amI();• amI(…)
} • •amI();
• •{
} • • amI amI
• amI();
• •
}
• amI(); amI
} • amI
•
} %ebp
amI
%esp
16
Carnegie Mellon
Stack
Example
yoo(…) yoo
{ who(…)
•{ yoo
yoo
amI(…) who
• • • •
{
amI();
who(); amI(…)
• who
• • • {• amI amI
•
• amI();•
} • •amI();
••
} • amI amI
• amI();
} • %ebp
• amI
}
amI
%esp
17
Carnegie Mellon
Stack
Example
yoo(…) yoo
{ who(…)
•{ yoo
yoo
amI(…) who
• • • •
{
amI();
who();
• who
• • • • amI amI
•
• amI();
• •amI();
• %ebp
}
} • amI amI
• %esp
}
amI
18
Carnegie Mellon
Stack
Example
yoo(…) yoo
{ who(…)
•{ yoo
yoo
who
• • • • %ebp
amI();
who();
• • • • amI amI who
%esp
• amI();
} • • •
} amI
amI
19
Carnegie Mellon
Stack
Example
yoo(…) yoo
{ who(…)
•{ yoo
yoo
amI(…) who
• • • •
{
amI();
who();
• who
• • • • amI amI
•
• amI();
• •amI();
• %ebp
}
} • amI amI
• %esp
}
amI
20
Carnegie Mellon
Stack
Example
yoo(…) yoo
{ who(…)
•{ yoo
yoo
who
• • • • %ebp
amI();
who();
• • • • amI amI who
%esp
• amI();
} • • •
} amI
amI
21
Carnegie Mellon
Stack
Example
yoo
yoo(…) %ebp
{ yoo
yoo
• who %esp
•
who(); amI amI
•
•
} amI
amI
22
Carnegie Mellon
Saved
Caller Stack Frame Registers
+
▪ Return address Local
▪Pushed by call instruction Variables
▪ Arguments for this call
Argument
Stack pointer
Build
%esp
23
Carnegie Mellon
Revisiting swap
Calling swap from call_swap
int course1 = 15213; call_swap:
int course2 = 18243; • • •
subl $8, %esp
void call_swap() { movl $course2, 4(%esp)
swap(&course1, &course2); movl $course1, (%esp)
} call swap
• • •
Resulting
void swap(int *xp, int *yp) • Stack
{ •
int t0 = *xp; •
int t1 = *yp; %esp
*xp = t1; &course
*yp = t0; 2 subl
&course
} %esp
1 call
Rtn adr %esp
24
Carnegie Mellon
Revisiting swap
swap:
pushl %ebp
void swap(int *xp, int *yp) movl %esp, %ebp Set
{ pushl %ebx Up
int t0 = *xp;
int t1 = *yp; movl 8(%ebp), %edx
*xp = t1; movl 12(%ebp), %ecx
*yp = t0; movl (%edx), %ebx Body
} movl (%ecx), %eax
movl %eax, (%edx)
movl %ebx, (%ecx)
popl %ebx
popl %ebp Finish
ret
25
Carnegie Mellon
swap Setup #1
Entering Stack Resulting Stack
%ebp %ebp
• •
• •
• •
&course2 yp
&course1 xp
Rtn adr %esp Rtn adr
Old %ebp %esp
swap:
pushl %ebp
movl %esp,%ebp
pushl %ebx
26
Carnegie Mellon
swap Setup #2
Entering Stack Resulting Stack
%ebp
• •
• •
• •
&course2 yp
&course1 xp
Rtn adr %esp Rtn adr
%ebp
Old %ebp %esp
swap:
pushl %ebp
movl %esp,%ebp
pushl %ebx
27
Carnegie Mellon
swap Setup #3
Entering Stack Resulting Stack
%ebp
• •
• •
• •
&course2 yp
&course1 xp
Rtn adr %esp Rtn adr
Old %ebp %ebp
Old %ebx %esp
swap:
pushl %ebp
movl %esp,%ebp
pushl %ebx
28
Carnegie Mellon
swap Body
Entering Stack Resulting Stack
%ebp
• •
• •
• •
Offset relative to %ebp
&course2 12 yp
&course1 8 xp
Rtn adr %esp 4 Rtn adr
Old %ebp %ebp
Old %ebx %esp
29
Carnegie Mellon
swap Finish
Stack Before Finish Resulting Stack
%ebp
• •
• •
popl %ebx
• •
popl %ebp
yp yp
xp xp
Rtn adr Rtn adr %esp
Old %ebp %ebp
Old %ebx %esp Observation
▪ Saved and restored register %ebx
▪ Not so for %eax, %ecx, %edx
30
Carnegie Mellon
Disassembled swap
08048384 <swap>:
8048384: 55 push %ebp
8048385: 89 e5 mov %esp,%ebp
8048387: 53 push %ebx
8048388: 8b 55 08 mov 0x8(%ebp),%edx
804838b: 8b 4d 0c mov 0xc(%ebp),%ecx
804838e: 8b 1a mov (%edx),%ebx
8048390: 8b 01 mov (%ecx),%eax
8048392: 89 02 mov %eax,(%edx)
8048394: 89 19 mov %ebx,(%ecx)
8048396: 5b pop %ebx
8048397: 5d pop %ebp
8048398: c3 ret
Calling Code
80483b4: movl $0x8049658,0x4(%esp) # Copy &course2
80483bc: movl $0x8049654,(%esp) # Copy &course1
80483c3: call 8048384 <swap> # Call swap
80483c8: leave # Prepare to return
80483c9: ret # Return
31
Carnegie Mellon
Today
Switch statements
IA 32 Procedures
▪ Stack Structure
▪ Calling Conventions
▪ Illustrations of Recursion & Pointers
32
Carnegie Mellon
34
Carnegie Mellon
Today
IA 32 Procedures
▪ Stack Structure
▪ Calling Conventions
▪ Illustrations of Recursion & Pointers
36
Carnegie Mellon
pcount_r:
pushl %ebp
Recursive Call #1 movl%esp, %ebp
/* Recursive popcount */ pushl %ebx
int pcount_r(unsigned x) { subl$4, %esp
if (x == 0) movl8(%ebp), %ebx
return 0; • • •
else return
(x & 1) + pcount_r(x >> 1);
}
•
•
•
Actions
▪ Save old value of %ebx on stack x
▪ Allocate space for argument to Rtn adr
recursive call
Old %ebp %ebp
▪ Store x in %ebx
Old %ebx
%ebx x %esp
38
Carnegie Mellon
Recursive Call #2 • • •
movl $0, %eax
/* Recursive popcount */ testl %ebx, %ebx
int pcount_r(unsigned x) { je .L3
if (x == 0) • • •
return 0; .L3:
else return • • •
(x & 1) + pcount_r(x >> 1); ret
}
Actions
▪ If x == 0, return
▪ with %eax set to 0
%ebx x
39
Carnegie Mellon
Recursive Call #3 • • •
movl %ebx, %eax
/* Recursive popcount */ shrl %eax
int pcount_r(unsigned x) { movl %eax, (%esp)
if (x == 0) call pcount_r
return 0; • • •
else return
(x & 1) + pcount_r(x >> 1);
}
Actions •
•
▪ Store x >> 1 on stack •
▪ Make recursive call
Effect Rtn adr
▪ %eax set to function result Old %ebp %ebp
▪ %ebx still has value of x Old %ebx
x >> 1 %esp
%ebx x
40
Carnegie Mellon
Recursive Call #4
/* Recursive popcount */ • • •
int pcount_r(unsigned x) { movl %ebx, %edx
if (x == 0) andl $1, %edx
return 0; leal (%edx,%eax), %eax
else return • • •
(x & 1) + pcount_r(x >> 1);
}
Assume
▪ %eax holds value from recursive call
▪ %ebx holds x %ebx x
Actions
▪ Compute (x & 1) + computed value
Effect
▪ %eax set to function result
41
Carnegie Mellon
Recursive Call #5
/* Recursive popcount */ • • •
int pcount_r(unsigned x) { L3:
if (x == 0) addl$4, %esp
return 0; popl%ebx
else return popl%ebp
(x & 1) + pcount_r(x >> 1); ret
}
%ebp
Actions
• •
▪ Restore • •
values of %ebx • •
and %ebp %esp
▪ Restore %esp Rtn adr
Old %ebp %ebp
%ebx
Old %ebx
%esp Old %ebx
42
Carnegie Mellon
43
Carnegie Mellon
Pointer Code
Generating Pointer
/* Compute x + 3 */
int add3(int x) {
int localx = x;
incrk(&localx, 3);
return localx;
}
Referencing Pointer
/* Increment value by k */
void incrk(int *ip, int k) {
*ip += k;
}
45
Carnegie Mellon
8 x
4 Rtn adr
0 Old %ebp %ebp
Middle part of add3
-4 localx
movl $3, 4(%esp) # 2nd arg = 3
leal -4(%ebp), %eax # &localx -8
movl %eax, (%esp) # 1st arg = &localx -12 Unused
call incrk
-16
-20 3 %esp+4
-24 %esp
46
Carnegie Mellon
8 x
4 Rtn adr
0 Old %ebp %ebp
Final part of add3
-4 localx
movl -4(%ebp), %eax # Return val= localx
leave -8
ret -12 Unused
-16
-20
-24 %esp
47
Carnegie Mellon
IA 32 Procedure Summary
Important Points
▪ Stack is the right data structure for procedure call
/ return Caller
Frame
▪ If P calls Q, then Q returns before P
Arguments
Recursion (& mutual recursion) handled by
normal calling conventions Return Addr
%ebp Old %ebp
▪ Can safely store values in local stack frame and in
callee-saved registers Saved
▪ Put function arguments at top of stack Registers
▪ Result return in %eax +
Local
Pointers are addresses of Variables
values
Argument
▪ On stack or global Build
%esp
48