You are on page 1of 84

Carnegie Melon

Machine-Level Programming III: Procedures


Computer Organization and Architecture
7th Lecture

Instructor:
Xiaofei Nan
Carnegie Mellon

Toda
y
⬛Procedures
▪Stack Structure
▪Calling Conventions
▪Passing control
▪Passing data
▪Managing local data
▪Illustration of Recursion
Carnegie Mellon

Mechanisms in Procedures
P(…)
P(…) {{
••
⬛Passing control ••
▪To beginning of procedure code yy == Q(x);
Q(x);
▪Back to return point print(y)
print(y)
••
}}
⬛Passing data
▪Procedure arguments
▪Return value int
int Q(int
Q(int i)i)
{{
⬛Memory management int
int tt == 3*i;
3*i;
int
int v[10];
v[10];
▪Allocate during procedure execution ••
▪Deallocate upon return ••
return
return v[t];
v[t];
⬛Mechanisms all implemented with }}
machine instructions
Carnegie Mellon

Mechanisms in Procedures
P(…)
P(…) {{
••
⬛Passing control ••
▪To beginning of procedure code yy == Q(x);
Q(x);
▪Back to return point print(y)
print(y)
••
}}
⬛Passing data
▪Procedure arguments
▪Return value int
int Q(int
Q(int i)i)
{{
⬛Memory management int
int tt == 3*i;
3*i;
int
int v[10];
v[10];
▪Allocate during procedure execution ••
▪Deallocate upon return ••
return
return v[t];
v[t];
⬛Mechanisms all implemented with }}
machine instructions
Carnegie Mellon

Mechanisms in Procedures
P(…)
P(…) {{
••
⬛Passing control ••
▪To beginning of procedure code yy == Q(x);
Q(x);
▪Back to return point print(y)
print(y)
••
}}
⬛Passing data
▪Procedure arguments
▪Return value int
int Q(int
Q(int i)i)
{{
⬛Memory management int
int tt == 3*i;
3*i;
int
int v[10];
v[10];
▪Allocate during procedure execution ••
▪Deallocate upon return ••
return
return v[t];
v[t];
⬛Mechanisms all implemented with }}
machine instructions
Carnegie Mellon

Mechanisms in Procedures
P(…)
P(…) {{
••
⬛Passing control ••
▪To beginning of procedure code yy == Q(x);
Q(x);
▪Back to return point print(y)
print(y)
••
}}
⬛Passing data
▪Procedure arguments
▪Return value int
int Q(int
Q(int i)i)
{{
⬛Memory management int
int tt == 3*i;
3*i;
int
intv[10];
v[10];
▪Allocate during procedure execution
••
▪Deallocate upon return ••
return
return v[t];
v[t];
⬛Mechanisms all implemented with }}
machine instructions
Carnegie Mellon

Mechanisms in Procedures P(…) {


P(…) {
◆Passing control ••
▪ Machine instructions implement the
To beginning of procedure code •

yy == Q(x);
Q(x);
Back ▪ mechanisms,
to return point but the choices are print(y)
print(y)
◆Passing data •

determined by designers. These choices
▪Procedure arguments
}}

make up the Application Binary


▪Return value

◆Memory management
Interface (ABI).
int Q(int i)
{
int t = 3*i;
int▪Q(int i) upon
Deallocate return int
intv[10];
v[10];
Allocate
▪ during procedure execution ••
⬛Mechanisms
{ all implemented with ••
machine instructions int t = 3*i; return
return v[t];
v[t];
}}
Carnegie Mellon

Toda
y
⬛Procedures
▪Stack Structure
▪Calling Conventions
▪Passing control
▪Passing data
▪Managing local data
▪Illustration of Recursion
Carnegie Mellon

x86-64 Stack
⬛Region of memory managed
with stack discipline stack
▪Memory viewed as array of
bytes.
▪Different regions have different
purposes.
▪(Like ABI, a policy decision)

code
Carnegie Mellon

x86-64 Stack
Stack “Bottom”
⬛Region of memory managed
with stack discipline
stack

Stack Pointer: %rsp


code

Stack “Top”
Carnegie Mellon

x86-64 Stack
Stack “Bottom”
⬛Region of memory managed
with stack discipline Increasing

⬛Grows toward lower Addresses


addresses
⬛Register %rspcontains
lowest stack address
▪address of “top” element Stack
Grows
Down
Stack Pointer: %rsp

Stack “Top”
Carnegie Mellon

x86-64 Stack: Push


Stack “Bottom”
⬛ pushq Src
▪Fetch operand at Src val
Increasing
▪Decrement %rspby 8
▪Write operand at address given by %rsp Addresses

Stack
Grows
Down
Stack Pointer:
%rsp

Stack “Top”
Carnegie Mellon

x86-64 Stack: Push


Stack “Bottom”
⬛ pushq Src
▪Fetch operand at Src val
Increasing
▪Decrement %rspby 8
▪Write operand at address given by %rsp Addresses

Stack
Grows
Down
Stack Pointer:
-8
%rsp

Stack “Top”
Carnegie
CarnegieMellon
Mell

x86-64 Stack: Pop


Stack “Bottom”
⬛ popq Dest
▪Read value at address given by %rsp Increasing
▪Increment %rspby 8
▪Store value at Dest (usually a register) Addresses

Stack
Grows
Down
Stack Pointer: val
%rsp
Stack “Top”
Carnegie Mellon

x86-64 Stack: Pop


Stack “Bottom”
⬛ popq Dest
▪Read value at address given by %rsp Increasing
▪Increment %rspby 8
▪Store value at Dest (usually a register) Addresses

val

Stack
Grows
+8
Down
Stack Pointer:
%rsp
Stack “Top”
Carnegie Mellon

x86-64 Stack: Pop


Stack “Bottom”
⬛ popq Dest
▪Read value at address given by %rsp Increasing
▪Increment %rspby 8
▪Store value at Dest (usually a register) Addresses

Stack
Grows
Stack Pointer: Down
%rsp val

(The memory doesn’t change, Stack “Top”


only the value of %rsp)
Carnegie Mellon

Toda
y
⬛Procedures
▪Stack Structure
▪Calling Conventions
▪Passing control
▪Passing data
▪Managing local data
▪Illustration of Recursion
Carnegie Mellon

void
void returnOne(void)
returnOne(void)
Code Examples
{{
return
return abs(-1);
abs(-1);
}}
00000000000016e9
00000000000016e9 <returnOne>:
<returnOne>:
16e9:
16e9: movl
movl $0xffffffff, %edi
$0xffffffff,
16ee:
%edi callq
16ee: 0x1240 <abs>
callq 0x1240
16f3:
<abs> retq
16f3: retq

int
int abs(int
abs(int num)
num) Branches are expensive…
{{
…but the compiler is a datalab-level hacker!
return
return num
num >=
>= 00 ?? num
num :: -num;
-num;
}}
0000000000001240
0000000000001240 <abs>:
<abs>:
1240:
1240: movl
movl %edi,
%edi, %edx
%edx
1242:
1242: sarl
sarl $0x1f,
$0x1f, %edx
%edx ## either
either 00 or or -1-1
1245:
1245:movl
movl%edi,
%edi,%eax
%eax
1247:
1247: xorl %edx, %eax ## num
xorl %edx, %eax num or or -num-1
-num-1
1249:
1249: subl
subl %edx,
%edx, %eax
%eax ## ANS-0
ANS-0 or or ANS-(-1)
ANS-(-
124b: retq retq
1) 124b:
Carnegie Mellon

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:
▪Address of the next instruction right after call
▪Example from disassembly

⬛Procedure return: ret


▪Pop address from stack
▪Jump to address
Carnegie Mellon

Control Flow Example #0 •


0x130 •
00000000000016e9
00000000000016e9 <returnOne>:
<returnOne>: 0x128 •
16e9:
16e9: movl$0xffffffff,
movl %edi
$0xffffffff, 0x120
16ee:
%edi callq
16ee: 0x1240 <abs>
callq 0x1240
16f3:
<abs> retq
16f3: retq

%rsp 0 x120

%rip 0x16e9
0000000000001240
0000000000001240 <abs>:
<abs>:
1240:
1240: movl
movl %edi,
%edi, %edx
%edx
••
••
124b:
124b: retq
retq
Carnegie Mellon

Control Flow Example #1 •


0x130 •
00000000000016e9
00000000000016e9 <returnOne>:
<returnOne>: 0x128 •
16e9:
16e9: movl$0xffffffff,
movl %edi
$0xffffffff, 0x120
16ee:
%edi callq
16ee: 0x1240 <abs>
callq 0x1240
16f3:
<abs> retq
16f3: retq

%rsp 0 x120

%rip 0x16ee
0000000000001240
0000000000001240 <abs>:
<abs>:
1240:
1240: movl
movl %edi,
%edi, %edx
%edx
••
••
124b:
124b: retq
retq
Carnegie Mellon

Control Flow Example #2 •


0x130 •
00000000000016e9
00000000000016e9 <returnOne>:
<returnOne>: 0x128 •
16e9:
16e9: movl$0xffffffff,
movl %edi
$0xffffffff, 0x120
16ee:
%edi callq
16ee: 0x1240 <abs>
callq 0x1240
16f3: 0x118 0x16f3
<abs> retq
16f3: retq

%rsp 0 x118

%rip 0x1240
0000000000001240
0000000000001240 <abs>:
<abs>:
1240:
1240: movl
movl %edi,
%edi, %edx
%edx
••
••
124b:
124b: retq
retq
Carnegie Mellon

Control Flow Example #3 •


0x130 •
00000000000016e9
00000000000016e9 <returnOne>:
<returnOne>: 0x128 •
16e9:
16e9: movl$0xffffffff,
movl %edi
$0xffffffff, 0x120
16ee:
%edi callq
16ee: 0x1240 <abs>
callq 0x1240
16f3: 0x118 0x16f3
<abs> retq
16f3: retq

%rsp 0 x118

%rip 0x124b
0000000000001240
0000000000001240 <abs>:
<abs>:
1240:
1240: movl
movl %edi,
%edi, %edx
%edx
••
••
124b:
124b: retq
retq
Carnegie Mellon

Control Flow Example #4 •


0x130 •
00000000000016e9
00000000000016e9 <returnOne>:
<returnOne>: 0x128 •
16e9:
16e9: movl$0xffffffff,
movl %edi
$0xffffffff, 0x120
16ee:
%edi callq
16ee: 0x1240 <abs>
callq 0x1240
16f3:
<abs> retq
16f3: retq

%rsp 0 x120

%rip 0x16f3
0000000000001240
0000000000001240 <abs>:
<abs>:
1240:
1240: movl
movl %edi,
%edi, %edx
%edx
••
••
124b:
124b: retq
retq
Carnegie Mellon

Tail-Call Optimization
00000000000016e9
00000000000016e9 <returnOne>:
<returnOne>:
16e9:
16e9: movl
movl $0xffffffff, %edi
$0xffffffff,
16ee:
%edi callq
16ee: 0x1240 <abs>
callq 0x1240
16f3:
<abs> retq
16f3: retq

00000000000016e9
00000000000016e9 <returnOne>:
<returnOne>:
16e9:
16e9: movl$0xffffffff,
movl %edi
$0xffffffff,
16ee:
%edi jmpq0x1240 <abs>
16ee: jmpq 0x1240 <abs>
Carnegie Mellon

Toda
y
⬛Procedures
▪Stack Structure
▪Calling Conventions
▪Passing control
▪Passing data
▪Managing local data
▪Illustrations of Recursion & Pointers
Carnegie Mellon

Procedure Data Flow

Registers Stack
⬛First 6 arguments
%rdi • ••
%rsi Arg n
%rdx
%rcx • ••
%r8 Arg 8
%r9 Arg 7

⬛Return value
%rax
⬛Only allocate stack space
when needed
Carnegie Mellon

Data Flow Example


void
void seeMoreArgs(void)
seeMoreArgs(void) {{
printf(“%d
printf(“%d %d
%d %d
%d %d
%d %d
%d %d
%d %d
%d %d”,
%d”, 2,
2, 3,
3, 4,
4, 5,
5, 6,
6, 7,
7, 8);
8);
}}

000000000000118a
000000000000118a <seeMoreArgs>:
<seeMoreArgs>:
118a
118a <+0>:
<+0>: sub sub $0x8,%rsp
118e <+4>: 118e pushq
$0x8,%rsp <+4>: $0x8pushq
1190
$0x8 <+6>: pushq $0x7
1192
1190 <+8>:
<+6>: mov pushq
$0x6,%r9d
$0x7
1198
1192 <+14>:
<+8>: mov mov $0x5,%r8d
119e <+20>:
$0x6,%r9d mov $0x4,%ecx
11a3
1198 <+25>:
<+14>: movmov $0x3,%edx
$0x5,%r8d 119e
11a8 <+30>:
<+20>: mov
mov $0x4,%ecx $0x2,%esi
11a3
11ad <+35>:
<+25>: lea
mov $0x3,%edx 0xe50(%rip),%rdi
11a8
11b4 <+42>:mov
<+30>: mov $0x0,%eax
$0x2,%esi
11b9
11ad <+47>:
<+35>: callq
lea 0x1050 <printf@plt>
0xe50(%rip),
11be
%rdi <+52>: addmov $0x18,%rsp
11b4 <+42>: $0x0,%eax
11c2
11b9 <+56>:
<+47>: retqcallq 0x1050
<printf@plt> 11be <+52>:add
$0x18,%rsp
Carnegie Mellon

Data Flow Example


int
int seeMoreArgs(void)
seeMoreArgs(void) {{
return
return printf(“%d
printf(“%d %d
%d %d
%d %d
%d %d
%d %d
%d %d
%d %d”,
%d”, 2,
2, 3,
3, 4,
4, 5,
5, 6,
6, 7,
7, 8);
8);
}}

000000000000118a
000000000000118a <seeMoreArgs>:
<seeMoreArgs>:
118a
118a <+0>:
<+0>: sub sub $0x8,%rsp
118e <+4>: 118e pushq
$0x8,%rsp <+4>: $0x8pushq
1190
$0x8 <+6>: pushq $0x7
1192
1190 <+8>:
<+6>: mov pushq
$0x6,%r9d
$0x7
1198
1192 <+14>:
<+8>: mov mov $0x5,%r8d
119e <+20>:
$0x6,%r9d mov $0x4,%ecx
11a3
1198 <+25>:
<+14>: movmov $0x3,%edx
$0x5,%r8d 119e
11a8 <+30>:
<+20>: mov
mov $0x4,%ecx $0x2,%esi
11a3
11ad <+35>:
<+25>: lea
mov $0x3,%edx 0xe50(%rip),%rdi
11a8
11b4 <+42>:mov
<+30>: mov $0x0,%eax
$0x2,%esi
11b9
11ad <+47>:
<+35>: callq
lea 0x1050 <printf@plt>
0xe50(%rip),
11be
%rdi <+52>: addmov $0x18,%rsp
11b4 <+42>: $0x0,%eax
11c2
11b9 <+56>:
<+47>: retqcallq 0x1050
<printf@plt> 11be <+52>:add
$0x18,%rsp
Carnegie Mellon

Toda
y
⬛Procedures
▪Stack Structure
▪Calling Conventions
▪Passing control
▪Passing data
▪Managing local data
▪Illustration of Recursion
Carnegie Mellon

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


Carnegie Mellon

Call Chain Example


Example
yoo(…) Call Chain
yoo(…)
{{
•• yoo
•• who(…)
who(…)
who();
who(); {{ who
•• •• •• ••
•• amI();
amI(); amI(…)
amI(…) a m I amI
}} •• •• •• {{
amI();
amI(); ••
•• •• •• amI
••
}} amI();
amI();
•• amI
••
}}

Procedure a m I ( ) i s recursive
Carnegie Mellon

Stack Frames Previous


Frame
⬛Contents
▪Return information Frame Pointer: %rbp
▪Local storage (if needed) (Optional)
Frame for
▪Temporary space (if needed)
proc

Stack Pointer: %rsp

⬛Management
▪Space allocated when enter procedure Stack “Top”
▪“Set-up” code
▪Includes push by call instruction
▪Deallocated when return
▪“Finish” code
▪Includes pop by ret instruction
Carnegie Mellon

Stack
Example
yoo(…)
yoo(…) yoo
%rbp
{{ yoo
•• yoo
who %rsp
••
who();
who();
•• amI amI
••
}}
amI

amI
Carnegie Mellon

Stack
Example
yoo(…) yoo
yoo(…)
{{ who(…)
who(…) yoo
•{ yoo
•{ who
• • •
•• • • • %rbp
amI();
ho();
who(); who
w• •amI();
• • amI amI
amI(); %rsp
•• • • •
}} • • •
amI
•} amI();
• • •
} amI
Carnegie Mellon

Stack
Example
yoo(…) yoo
yoo(…)
{{ who(…)
who(…) yoo
•{ yoo
•{ amI(…) who
• •amI(…)
• •
• { •mI();
• •
ho();
{
who();
a • who
w• •amI();
•• • amI amI

mI();
•• • amI( %rbp
}} • ••• •• );
a

amI(); amI amI
•} amI();

•• • • %rsp
}
}• amI
}
Carnegie Mellon

Stack
Example
yoo(…) yoo
yoo(…)
{{ who(…)
who(…) yoo
•{ yoo
•{ amI(…) who
• •amI(…)
• •
• { •mI();
• •
ho();
{
a • amI
who(); (…)
amI(…) who
w• •amI();
••{• amI amI
•{
mI();
•• • • ••
mI();

}} a •
• • ••
aamI();• amI amI
•} amI(); amI();
• amI();
•• • • •
} • %rbp
} • •• amI amI
} }
} %rsp
Carnegie Mellon

Stack
Example
yoo(…) yoo
yoo(…)
{{ who(…)
who(…) yoo
•{ yoo
•{ amI(…) who
• •amI(…)
• •
• { •mI();
• •
ho();
{
a • amI
who(); (…
amI(…) who
w• •amI();
••{• ) amI amI
• { amI(…)
mI();
•• • • •• amI(…)
mI();

}} a •
• • • • {{
aamI();•
•• amI amI
•} amI(); amI();
• amI();
•• • • • ••
} •
} • •• amI();
amI(); amI amI
} } ••
}
••
}} %rbp
amI
%rsp
Carnegie Mellon

Stack
Example
yoo(…) yoo
yoo(…)
{{ who(…)
who(…) yoo
•{ yoo
•{ amI(…) who
• •amI(…)
• •
• { •mI();
• •
ho();
{
a • amI
who(); (…)
amI(…) who
w• •amI();
••{• amI amI
•{
mI();
•• • • ••
mI();

}} a •
• • ••
aamI();• amI amI
•} amI(); amI();
• amI();
•• • • •
} • %rbp
} • •• amI amI
} }
} %rsp
Carnegie Mellon

Stack
Example
yoo(…) yoo
yoo(…)
{{ who(…)
who(…) yoo
•{ yoo
•{ amI(…) who
• •amI(…)
• •
• { •mI();
• •
ho();
{
who();
a • who
w• •amI();
•• • amI amI

mI();
•• • amI( %rbp
}} • ••• •• );
a

amI(); amI amI
•} amI();

•• • • %rsp
}
}• amI
}
Carnegie Mellon

Stack
Example
yoo(…) yoo
yoo(…)
{{ who(…)
who(…) yoo
•{ yoo
•{ who
• • •
•• • • • %rbp
amI();
ho();
who(); who
w• •amI();
• • amI amI
amI(); %rsp
•• • • •
}} • • •
amI
•} amI();
• • •
} amI
Carnegie Mellon

Stack
Example
yoo(…) yoo
yoo(…)
{{ who(…)
who(…) yoo
•{ yoo
•{ amI(…) who
• •amI(…)
• •
• { •mI();
• •
ho();
{
who();
a • who
w• •amI();
•• • amI amI

mI();
•• • amI( %rbp
}} • ••• •• );
a

amI(); amI amI
•} amI();

•• • • %rsp
}
}• amI
}
Carnegie Mellon

Stack
Example
yoo(…) yoo
yoo(…)
{{ who(…)
who(…) yoo
•{ yoo
•{ who
• • •
•• • • • %rbp
amI();
ho();
who(); who
w• •amI();
• • amI amI
amI(); %rsp
•• • • •
}} • • •
amI
•} amI();
• • •
} amI
Carnegie Mellon

Stack
Example
yoo
yoo(…) %rbp
yoo(…) yoo
{{ yoo
•• who %rsp
••
who();
who(); amI amI
••
••
}} amI

amI
Carnegie Mellon

x86-64/Linux Stack Frame


⬛Current Stack Frame (“Top” to Bottom)
▪“Argument build:” Caller
Parameters for function about to call Arguments
7+
▪Local variables Frame
Return Addr
If can’t keep in registers
▪Saved register context Frame pointer Old %rbp
▪Old frame pointer (optional) %rbp Saved
(Optional) Register
s
+
⬛Caller Stack Frame Local
Variable
▪Return address s

▪Pushed by callinstructi on Argument


▪Arguments for this call Build
(Optional)
Stack pointer
Carnegie Mellon

Example: i n c r
long
long incr(long
incr(long *p,*p, long
long val)
val) {{
long xx == *p;
long *p;
long long
y = xy += val;
x + val;
*p = *p
y; = y;
return
return x;x;
}}

incr:
incr: Register Use(s)
movq
movq (%rdi), %rax
(%rdi), %rdi Argument p
%rax %rax, %rsi
addq %rsi, (%rdi) %rsi Argument val, y
addq %rax, %rsi
movq %rsi, %rax x, Return value
movq
(%rdi) ret
ret
Carnegie Mellon

Example: Calling i n c r # 1
Initial Stack
long
long call_incr()
call_incr() { Structure
{long
long
v1 v1 =
= 15213;
15213;
long v2 = incr(&v1, 3000); ...
long v2 = incr(&v1,
return v1+v2; 3000);
} return v1+v2; Rtn address %rsp
}

call_incr:
call_incr:
subq
subq $16,
$16, %rsp
%rsp Resulting Stack
movq
movq $15213,
$15213, Str cture
8(%rsp)
8(%rsp) movl
movl$3000,
$3000, u
%esi
%esi leaq 8(%rsp), %rdi
leaq8(%rsp), ...
%rdi
call call incr
incr
addq
addq 8(%rsp),
8(%rsp), Rtn address
%rax
%rax addq $16, %rsp
addq$16, %rsp 1 5213 %rsp+8
ret
ret
Unused %rsp
Carnegie Mellon

Example: Calling i n c r # 2
Stack
long
long call_incr()
call_incr() { Structure
{long
long
v1 v1 =
= 15213;
15213;
long v2 = incr(&v1, 3000); ...
long v2 = incr(&v1,
return v1+v2; 3000);
} return v1+v2; Rtn address
}
1 5213 %rsp+8
Unused %rsp
call_incr:
call_incr:
subq
subq $16,
$16, %rsp
%rsp
movq $15213, Register Use(s)
movq $15213,
8(%rsp)
8(%rsp) movl
movl$3000,
$3000, %rdi &v1
%esi
%esi leaq 8(%rsp), %rdi
leaq8(%rsp), %rsi 3000
%rdi
call call incr
incr
addq
addq 8(%rsp),
8(%rsp),
%rax
%rax addq $16, %rsp
addq$16, %rsp
ret
ret
Carnegie Mellon

Example: Calling i n c r # 2
Stack
long
long call_incr()
call_incr() { Structure
{long
long
v1 v1 =
= 15213;
15213;
long v2 = incr(&v1, 3000); ...
long v2 = incr(&v1,
return v1+v2; 3000);
} return v1+v2;
Rtn address
}
152 13 %rsp+8
Aside 1: movl $3000, Unused%esi %rsp
• Remember, movl -> %exx zeros out high order 32 bits.
all_incr:
ccall_incr:
subq
• Why use$16,
subq $16,%rsp
movl %rsp of movq? 1 byte short er.
instead
movq
movq $15213,8(%rsp)
$15213, Register Use(s)
movl
8(%rsp) $3000, %esi
movl $3000, %rdi &v1
8(%rsp), %rdi
%esi leaq8(%rsp), %rdi %rsi 3000
leaq
call incr
incr
addq 8(%rsp),
8(%rsp),%rax
call $16, %rsp
%rax addq$16, %rsp
ret
addq
Carnegie Mellon

Example: Calling i n c r # 2
Stack
long
long call_incr()
call_incr() { Structure
{long
long
v1 v1 =
= 15213;
15213;
long v2 = incr(&v1, 3000); ...
long v2 = incr(&v1,
return v1+v2; 3000);
} return v1+v2;
Rtn address
}
1 5213 %rsp+8
Unused %rsp
ca Aside 2: leaq 8(%rsp), %rdi
ll_incr:
call_incr:
ubq
subq $16,
$16,%rsp
%rsp
s• Computes %rsp+8 se(s)
movq
ovq $15213,8(%rsp)
$15213, Register
m
m8(%rsp)
• Actuallymovl
used$3000,
for what it is meant! v1
leaq U
8(%rsp), %rdi
%esi leaq8(%rsp), %rdi %rsi 3000
call incr
incr
ovl $3000, %esi %rdi
call
addq 8(%rsp),
8(%rsp),%rax
$16,
&
%rax addq$16, %rsp
%rsp
addq
ret

addq
Carnegie Mellon

Example: Calling i n c r # 2
Stack
long
long call_incr()
call_incr() { Structure
{long
long
v1 v1 =
= 15213;
15213;
long v2 = incr(&v1, 3000); ...
long v2 = incr(&v1,
return v1+v2; 3000);
} return v1+v2; Rtn address
}
1 5213 %rsp+8
Unused %rsp
call_incr:
call_incr:
subq
subq $16,
$16, %rsp
%rsp
movq $15213, Register Use(s)
movq $15213,
8(%rsp)
8(%rsp) movl
movl$3000,
$3000, %rdi &v1
%esi
%esi leaq 8(%rsp), %rdi
leaq8(%rsp), %rsi 3000
%rdi
call call incr
incr
addq
addq 8(%rsp),
8(%rsp),
%rax
%rax addq $16, %rsp
addq$16, %rsp
ret
ret
Carnegie Mellon

Example: Calling i n c r # 3
Stack
long
long call_incr()
call_incr() { Structure
{long
long
v1 v1 =
= 15213;
15213;
long v2 = incr(&v1, 3000); ...
long v2 = incr(&v1,
return v1+v2; 3000);
} return v1+v2; Rtn address
}
1 8213 %rsp+8
Unused %rsp
call_incr:
call_incr:
subq
subq $16,
$16, %rsp
%rsp
movq $15213, Register Use(s)
movq $15213,
8(%rsp)
8(%rsp) movl
movl$3000,
$3000, %rdi &v1
%esi
%esi leaq 8(%rsp), %rdi
leaq8(%rsp), %rsi 3000
%rdi
call call incr
incr
addq
addq 8(%rsp),
8(%rsp),
%rax
%rax addq $16, %rsp
addq$16, %rsp
ret
ret
Carnegie Mellon

Example: Calling i n c r # 4 Stack


Structure
long
long call_incr()
call_incr() { ...
{long
long
v1 v1 =
= 15213;
15213;
long v2 = incr(&v1, 3000);
long v2 = incr(&v1,
return v1+v2; 3000); Rtn address
} return v1+v2; 1 8213 %rsp+8
}
Unused %rsp

call_incr:
call_incr: Register Use(s)
subq
subq $16,
$16, %rsp
%rsp %rax Return value
movq
movq $15213,
$15213,
8(%rsp)
8(%rsp) movl
movl$3000,
$3000,
%esi
%esi leaq 8(%rsp), %rdi
leaq8(%rsp),
%rdi
call call incr
incr
addq
addq 8(%rsp),
8(%rsp),
%rax
%rax addq $16, %rsp
addq$16, %rsp
ret
ret
Carnegie Mellon

Example: Calling i n c r # 5 a Stack


Structure
long
long call_incr()
call_incr() { ...
{long
long
v1 v1 =
= 15213;
15213;
long v2 = incr(&v1, 3000);
long v2 = incr(&v1,
return v1+v2; 3000); Rtn address
} return v1+v2; 1 8213 %rsp+8
}
Unused %rsp

call_incr:
call_incr: Register Use(s)
subq
subq $16,
$16, %rsp
%rsp %rax Return value
movq
movq $15213,
$15213,
8(%rsp)
8(%rsp) movl
movl$3000,
$3000,
%esi
%esi leaq 8(%rsp), %rdi
leaq8(%rsp), Updated Stack
%rdi
call call incr
incr Str cture
addq
addq 8(%rsp),
8(%rsp), u
%rax
%rax addq $16, %rsp
addq$16, %rsp ...
ret
ret
Rtn address %rsp
Carnegie Mellon

Example: Calling i n c r # 5 b
Updated Stack
long
long call_incr()
call_incr() {
{long
long Stru cture
v1 v1 =
= 15213;
15213;
long v2 = incr(&v1, 3000); ...
long v2 = incr(&v1,
return v1+v2; 3000);
} return v1+v2;
} Rtn address %rsp

call_incr:
call_incr: Register Use(s)
subq
subq $16,
$16, %rsp
%rsp %rax Return value
movq
movq $15213,
$15213,
8(%rsp)
8(%rsp) movl
movl$3000,
$3000,
%esi
%esi leaq 8(%rsp), %rdi
leaq8(%rsp), Final Stack
%rdi
call call incr
incr Structure
addq
addq 8(%rsp),
8(%rsp),
%rax
%rax addq $16, %rsp
addq$16, %rsp ...
ret
ret %rsp
Carnegie Mellon

Register Saving Conventions


⬛When procedure yoocalls who:
▪yoois the caller
▪whois the callee

⬛Can register be used for temporary


yoo:
storage?
who:
yoo: who:
•• •• •• •• •• ••
movq
movq $15213,
$15213, %rdx
%rdx subq
subq $18213,
$18213, %rdx
%rdx
call
call who
who •• •• ••
addq
addq %rdx,
%rdx, %rax
%rax ret
ret
•• •• ••
ret
ret

▪Contents of register %rdx overwritten by who


▪This could be trouble ➙ something should be done!
▪Need some coordination
Carnegie Mellon

Register Saving Conventions


⬛When procedure yoocalls who:
▪yoois the caller
▪whois the callee

⬛Can register be used for temporary storage?

⬛Conventions
▪“Caller Saved”
▪Caller saves temporary values in its frame before the call
▪“Callee Saved”
▪Callee saves temporary values in its frame before using
▪Callee restores them before returning to caller
Carnegie Mellon

x86-64 Linux Register Usage #1


⬛%rax Return %rax
value
▪Return value %rdi
▪Also caller-saved
%rsi
▪Can be modified by procedure
%rdx
Argument
⬛%rdi, ..., %r9 s %rcx
▪Arguments
%r8
▪Also caller-saved
▪Can be modified by procedure %r9
%r10
⬛%r10, %r11 Caller-
saved %r11
▪Caller-saved temporaries
▪Can be modified by procedure
Carnegie Mellon

x86-64 Linux Register Usage #2


%rbx
⬛%rbx, %r12, %r13, %r14
▪Callee-saved
Callee- %r12
▪Callee must save & restore saved %r13
Temporarie
⬛%rbp s %r14
▪Callee-saved %rbp
Special
▪Callee must save & restore
%rsp
▪May be used as frame pointer
▪Can mix & match

⬛%rsp
▪Special form of callee save
▪Restored to original value upon
exit from procedure
Carnegie Mellon

Callee-Saved Registers Example


void
void mult4(int
mult4(int a,
a, int
int b,
b, int
int c,
c, int
int d)
d) {{ return
return (a*b)*(c*d);
(a*b)*(c*d); }
}
0000000000001428
0000000000001428 <mult4>:
<mult4>:
1428
1428 <+0>:
<+0>: pushpush%rbx
1429 <+1>: push%rbx%r12
142b
1429 <+3>:
<+1>: pushpush%r13
142d <+5>: mov %r12%edx,%r12d
1430
142b <+8>:
<+3>: mov push%ecx,%r13d
1433 <+11>: callq
%r130x1422 <mult2>
1438
142d <+16>:
<+5>: mov mov %r12d,%edi
%edx,
143b
%r12d<+19>: mov mov %r13d,%esi
1430 <+8>: %ecx,
143e
%r13d<+22>: mov %eax,%ebx
1440
1433 <+24>:
<+11>: callq 0x1422
callq <mult2>
0x1422
1445 <+29>:
<mult2> mov %eax,%edi
1447
1438 <+31>:
<+16>: mov mov %ebx,%esi
%r12d,
1449
%edi <+33>: callq
143b <+19>: mov 0x1422 <mult2>
%r13d,
144e
%esi <+38>: pop mov %r13%eax,
143e <+22>:
1450
%ebx <+40>: pop callq
1440 <+24>: %r120x1422
1452 <+42>:
<mult2> pop %rbx
1453
1445 <+43>:
<+29>: retqmov %eax,
%edi
Carnegie Mellon

Callee-Saved Registers Example


void
void mult4(int
mult4(int a,
a, int
int b,
b, int
int c,
c, int
int d)
d) {{ return
return (a*b)*(c*d);
(a*b)*(c*d); }
}
0000000000001428
0000000000001428 <mult4>:
<mult4>:
1428
1428 <+0>:
<+0>: pushpush%rbx
1429 <+1>: push%rbx%r12
142b
1429 <+3>:
<+1>: pushpush%r13
142d <+5>: mov %r12%edx,%r12d
1430
142b <+8>:
<+3>: mov push%ecx,%r13d
1433 <+11>: callq
%r130x1422 <mult2>
1438
142d <+16>:
<+5>: mov mov %r12d,%edi
%edx,
143b
%r12d<+19>: mov mov %r13d,%esi
1430 <+8>: %ecx,
143e
%r13d<+22>: mov %eax,%ebx
1440
1433 <+24>:
<+11>: callq 0x1422
callq <mult2>
0x1422
1445 <+29>:
<mult2> mov %eax,%edi
1447
1438 <+31>:
<+16>: mov mov %ebx,%esi
%r12d,
1449
%edi <+33>: callq
143b <+19>: mov 0x1422 <mult2>
%r13d,
144e
%esi <+38>: pop mov %r13%eax,
143e <+22>:
1450
%ebx <+40>: pop callq
1440 <+24>: %r120x1422
1452 <+42>:
<mult2> pop %rbx
1453
1445 <+43>:
<+29>: retqmov %eax,
%edi
Carnegie Mellon

Small Exercise
long
long add5(long
add5(long b0,
b0, long
long b1,
b1, long
long b2,
b2, long
long b3,
b3, long
long b4)
b4) {{
return b0+b1+b2+b3+b4;
return b0+b1+b2+b3+b4;
}}

long
long add10(long
add10(long a0,
a0, long
long a1,
a1, long
long a2,
a2, long
long a3,
a3, long
long a4,
a4, long
long a5,
a5,
long a6, long a7, long a8, long
long a6, long a7, long a8, long a9) {a9) {
return
return add5(a0,
add5(a0, a1,
a1, a2,
a2, a3,
a3, a4)+
a4)+
add5(a5,
add5(a5, a6, a7, a8, a9);
a6, a7, a8, a9);
}}

⬛Where are a0,…, a9 passed?


rdi, rsi, rdx, rcx, r8, r9, stack

⬛Where are b0,…, b4 passed?


rdi, rsi, rdx, rcx, r8

⬛Which registers do we need to save?


Ill-posed question. Need assembly.
rbx, rbp, r9 (during first call to
Carnegie Mellon

Small Exercise
long
long add5(long
add5(long b0,
b0, long
long b1,
b1, long
long b2,
b2, long
long b3,
b3, long
long b4)
b4) {{
return b0+b1+b2+b3+b4;
return b0+b1+b2+b3+b4;
}}

long
long add10(long
add10(long a0,
a0, long
long a1,
a1, long
long a2,
a2, long
long a3,
a3, long
long a4,
a4, long
long a5,
a5,
long a6, long a7, long a8, long
long a6, long a7, long a8, long a9) {a9) {
return
return add5(a0,
add5(a0, a1,
a1, a2,
a2, a3,
a3, a4)+
a4)+
add5(a5,
add5(a5, a6, a7, a8, a9);
a6, a7, a8, a9);
}}

add10:
add10:
pushq
pushq %rbp %rbp
pushq %rbx %rbx
pushq
movq %r9, %rbp%r9,
movq
%rbp add5
call
call %rax, add5
movq
movq %rbx %rax,
movq 48(%rsp),
%rbx movq %r8
movq 40(%rsp),
48(%rsp), %r8 movq %rcx
movq 32(%rsp),
40(%rsp), %rcx movq
movq %rdx
32(%rsp), %rdx movq
movq 24(%rsp), %rsi add5:
add5:
24(%rsp), %rsi movq addq %rsi, %rdi
call %rbp, %rdi
%rbp, %rdi addq %rsi,
addq %rdi %rdi, %rdx
call add5 add5
popq addq
addq %rdx, %rcx
%rdi,
addq %rbx, %rax
%rbx,
popq %rbx %rdx (%rcx,%r8), %rax
%rax addq
ret %rbp addq %rdx,
popq %rbx
%rcx
popq leaq
leaq (%rcx,
ret
%r8), %rax ret
Carnegie Mellon

Callee-Saved Example #1
Initial Stack
long
long call_incr2(long
call_incr2(long x)
x) {{ Structure
long
long v1
v1 == 15213;
15213;
long
long v2
v2 == incr(&v1,
incr(&v1, 3000);
3000); ...
return
return x+v2;
x+v2;
}} Rtn address %rsp

• X comes in register %rdi.


• We need %rdi for the call to incr.
• Where should be put x, so we can use
it after the call to incr?
Carnegie Mellon

Callee-Saved Example #2
Initial Stack
long
long call_incr2(long
call_incr2(long x) x) {{ Structure
long v1
long v1 == 15213;
15213;
long long
v2 = v2
incr(&v1, 3000);
= incr(&v1, 3000); ...
return
returnx+v2;
x+v2;
}} Rtn address %rsp

call_incr2:
call_incr2:
pushq
pushq %rbx
%rbx Resulting Stack
subq
subq $16,
$16,%rsp
%rsp
movq %rdi, %rbx Str cture
movq %rdi, %rbx u
movq
movq $15213,
$15213,8(%rsp) ...
movl
8(%rsp) $3000, %esi
movl $3000,
leaq leaq8(%rsp),
%esi 8(%rsp), %rdi %rdi Rtn address
call
call incr
incr
addq
addq %rbx,
%rbx,%rax
%rax Saved %rbx
%rsp
addq
addq $16,
$16,%rsp
%rsp
popq
popq %rbx
ret ret
%rbx
Carnegie Mellon

Callee-Saved Example #3
Initial Stack
long
long call_incr2(long
call_incr2(long x) x) {{ Structure
long v1
long v1 == 15213;
15213; ...
long long
v2 = v2
incr(&v1, 3000);
= incr(&v1, 3000);
return
returnx+v2;
x+v2;
}} Rtn address
Saved %rbx
%rsp
call_incr2:
call_incr2:
pushq
pushq %rbx
%rbx Resulting Stack
subq
subq $16,
$16,%rsp
%rsp
movq %rdi, %rbx Str cture
movq %rdi, %rbx u
movq
movq $15213,
$15213,8(%rsp) ...
movl
8(%rsp) $3000, %esi
movl $3000,
leaq leaq8(%rsp),
%esi 8(%rsp), %rdi %rdi Rtn address
call
call incr
incr
addq
addq %rbx,
%rbx,%rax
%rax Saved %rbx
addq
addq $16,
$16,%rsp
%rsp %rsp+8
popq
popq %rbx
%rbx ret %rsp
Carnegie Mellon

Callee-Saved Example #4 Stack Structure


long
long call_incr2(long
call_incr2(long x) x) {{
long v1
v1 == 15213;
15213; ...
long
long long
v2 = v2
incr(&v1, 3000);
= incr(&v1, 3000);
return
returnx+v2;
x+v2; Rtn address
}}
Saved %rbx
%rsp+8
call_incr2:
pushq %rbx %rsp
subq $16, %rsp
movq %rdi, %rbx
movq $15213, 8(%rsp)
movl $3000, %esi
leaq 8(%rsp), %rdi • X saved in %rbx.
call incr
addq %rbx, %rax • A callee saved register.
addq $16, %rsp
%rbx
popq
ret
Carnegie Mellon

Callee-Saved Example #5 Stack Structure


long
long call_incr2(long
call_incr2(long x) x) {{
long v1
v1 == 15213;
15213; ...
long
long long
v2 = v2
incr(&v1, 3000);
= incr(&v1, 3000);
return
returnx+v2;
x+v2; Rtn address
}}
Saved %rbx
1 5213 %rsp+8
call_incr2:
pushq %rbx Unused %rsp
subq $16, %rsp
movq %rdi, %rbx
movq $15213, 8(%rsp)
movl $3000, %esi
leaq 8(%rsp), %rdi • X saved in %rbx.
call incr
addq %rbx, %rax • A callee saved register.
addq $16, %rsp
%rbx
popq
ret
Carnegie Mellon

Callee-Saved Example #6 Stack Structure


long
long call_incr2(long
call_incr2(long x) x) {{
long v1
v1 == 15213;
15213; ...
long
long long
v2 = v2
incr(&v1, 3000);
= incr(&v1, 3000);
return
returnx+v2;
x+v2; Rtn address
}}
Saved %rbx
1 8213 %rsp+8
call_incr2:
pushq %rbx Unused %rsp
subq $16, %rsp
movq %rdi, %rbx
movq $15213, 8(%rsp)
movl $3000, %esi
leaq 8(%rsp), %rdi • X Is safe in %rbx
call
addq
incr
%rbx, %rax
• Return result in %rax
addq $16, %rsp
%rbx
popq
ret
Carnegie Mellon

Callee-Saved Example #7 Stack Structure


long
long call_incr2(long
call_incr2(long x) x) {{
long v1
v1 == 15213;
15213; ...
long
long long
v2 = v2
incr(&v1, 3000);
= incr(&v1, 3000);
return
returnx+v2;
x+v2; Rtn address
}}
Saved %rbx
%rsp
1 8213
call_incr2:
pushq %rbx Unused
subq $16, %rsp
movq %rdi, %rbx
movq $15213, 8(%rsp)
movl $3000, %esi
leaq 8(%rsp), %rdi • Return result in %rax
call incr
addq %rbx, %rax
$16, %rsp
addq %rbx

popq
Carnegie Mellon

Callee-Saved Example #8 Initial Stack Structure


long
long call_incr2(long
call_incr2(long x) x) {{
long v1
v1 == 15213;
15213; ...
long
long long
v2 = v2
incr(&v1, 3000);
= incr(&v1, 3000);
return
returnx+v2;
x+v2; Rtn address
}}
Saved %rbx
%rsp
1 8213
call_incr2:
call_incr2:
pushq %rbx Unused
pushq %rbx
subq
subq $16, %rsp
$16, %rsp
movq
movq %rdi, %rbx
%rdi, %rbx final Stack Structure
movq
movq $15213,
$15213,8(%rsp)
movl
8(%rsp) $3000, %esi
movl $3000, ...
leaq leaq8(%rsp),
%esi 8(%rsp), %rdi%rdi
call
call incr
incr Rtn address
addq
addq %rbx, %rax
%rbx, %rax %rsp
addq $16, %rsp
$16, %rsp Saved %rbx
addq
popq %rbx 1 8213
%rbx ret Unused
popq
Carnegie Mellon

Local Array Example


void
void getV(int
getV(int i)
i) {{
int
int x[4];
x[4];
return
return getValue(x,
getValue(x, i);
i);
}}

0000000000001346
0000000000001346 <getV>:
<getV>:
1346
1346 <+0>:
<+0>: sub sub $0x18,%rsp
134a <+4>: 134a
$0x18,%rsp mov<+4>:%edi,%esi
mov
134c <+6>: 134cmov
%edi,%esi <+6>: %rsp,%rdi
mov
134f <+9>:
%rsp,%rdi callq 0x145c <getValue>
1354
134f <+14>:
<+9>: addcallq
$0x18,%rsp
0x145c
1358 <+18>: 1354
<getValue> retq
<+14>: add
$0x18,%rsp
1358 <+18>: retq
Carnegie Mellon

Local Array Example


void
void getV(int
getV(int i)
i) {{
int
int x[4];
x[4];
return
return getValue(x,
getValue(x, i);
i);
}}

0000000000001346
0000000000001346 <getV>:
<getV>:
1346
1346 <+0>:
<+0>: sub sub $0x18,%rsp
134a <+4>: 134a
$0x18,%rsp mov<+4>:%edi,%esi
mov
134c <+6>: 134cmov
%edi,%esi <+6>: %rsp,%rdi
mov
134f <+9>:
%rsp,%rdi callq 0x145c <getValue>
1354
134f <+14>:
<+9>: addcallq
$0x18,%rsp
0x145c
1358 <+18>: 1354
<getValue> retq
<+14>: add
$0x18,%rsp
1358 <+18>: retq
Carnegie Mellon

Toda
y
⬛Procedures
▪Stack Structure
▪Calling Conventions
▪Passing control
▪Passing data
▪Managing local data
▪Illustration of Recursion
Carnegie Mellon

Recursive Function
/*
/* Recursive
Recursive popcount
popcount */
*/ pcount_r:
long
long pcount_r(unsigned
pcount_r(unsigned long
long x)
x) {{ movl $0, %eax
if
if (x(x ==
== 0)
0) testq %rdi, %rdi
return
return 0;0; je .L6
else
else pushq %rbx
return
return movq %rdi, %rbx
(x
(x && 1)
1) andl $1, %ebx
++ shrq %rdi
call pcount_r
pc
pc addq %rbx,
ou
ou popq %rax
nt
nt .L6: %rbx
_r
_r rep; ret
(x
(x
>>
>>
1)
1)
;;
}}
Carnegie Mellon

Recursive Function Terminal Case


/*
/* Recursive
Recursive popcount
popcount */
*/ pcount_r:
long
long pcount_r(unsigned
pcount_r(unsigned long
long x)
x) {{ movl $0, %eax
if
if (x(x ==
== 0)
0) testq %rdi, %rdi
return
return 0;0; je .L6
else
else pushq %rbx
return
return movq %rdi, %rbx
(x
(x && 1)
1) andl $1, %ebx
++ shrq %rdi
call pcount_r
pc
pc addq %rbx,
ou
ou popq %rax
nt
nt .L6: %rbx
Register _r
_r
Use(s) Type rep; ret
(x
%rdi x (x Argument
>>
>>
%rax Return
1) value
1) Return value
;;
}}
Carnegie Mellon

Recursive Function Register Save


/*
/* Recursive
Recursive popcount
popcount */
*/ pcount_r:
long
long pcount_r(unsigned
pcount_r(unsigned longlong x)
x) {{ movl $0, %eax
ifif(x(x====0)0) testq %rdi, %rdi
return 0;
return je .L6
0;
else pushq %rbx
else return movq %rdi, %rbx
return
(x & (x1) & andl $1, %ebx
} 1) + shrq %rdi
+ call pcount_r
pc
pc addq %rbx,
ou
ou popq %rax
nt
nt .L6: %rbx
Register _r
_r
Use(s) Type rep; ret
(x
%rdi x (x Argument
>>
>> ...
1)
1)
;;
Rtn address
}
Saved %rbx %rsp
77
Carnegie Mellon

Recursive Function Call Setup


/*
/* Recursive
Recursive popcount
popcount */
*/ pcount_r:
long
long pcount_r(unsigned
pcount_r(unsigned long
long x)
x) {{ movl $0, %eax
if
if (x(x ==
== 0)
0) testq %rdi, %rdi
return
return 0;0; je .L6
else
else pushq %rbx
return
return movq %rdi, %rbx
(x
(x && 1)
1) andl $1, %ebx
++ shrq %rdi
call pcount_r
pc
pc addq %rbx,
ou
ou popq %rax
nt
nt .L6: %rbx
Register _r
_r
Use(s) Type rep; ret
(x
(x 1
%rdi x >> Rec. argument
>>
>>
%rbx x &1)
1)1 Callee-saved
;;
}}

78
Carnegie Mellon

Recursive Function Call


/*
/* Recursive
Recursive popcount
popcount */
*/ pcount_r:
long
long pcount_r(unsigned
pcount_r(unsigned long
long x)
x) {{ movl $0, %eax
if
if (x(x ==
== 0)
0) testq %rdi, %rdi
return
return 0;0; je .L6
else
else pushq %rbx
return
return movq %rdi, %rbx
(x
(x && 1)
1) andl $1, %ebx
++ shrq %rdi
call pcount_r
pc
pc addq %rbx,
ou
ou popq %rax
nt
nt .L6: %rbx
Register _r
_r
Use(s) Type rep; ret
(x
%rbx x &(x1 Callee-saved
>>
>>
%rax 1)
Recursive
1) call
return
;; value
}}

79
Carnegie Mellon

Recursive Function Result


/*
/* Recursive
Recursive popcount
popcount */
*/ pcount_r:
long
long pcount_r(unsigned
pcount_r(unsigned long
long x)
x) {{ movl $0, %eax
if
if (x(x ==
== 0)
0) testq %rdi, %rdi
return
return 0;0; je .L6
else
else pushq %rbx
return
return movq %rdi, %rbx
(x
(x && 1)
1) andl $1, %ebx
++ shrq %rdi
call pcount_r
pc
pc addq %rbx,
ou
ou popq %rax
nt
nt .L6: %rbx
Register _r
_r
Use(s) Type rep; ret
(x
%rbx x &(x1 Callee-saved
>>
>>
%rax Return
1) value
1)
;;
}}

80
Carnegie Mellon

Recursive Function Completion


/*
/* Recursive
Recursive popcount
popcount */
*/ pcount_r:
long
long pcount_r(unsigned
pcount_r(unsigned longlong x) x) {{ movl $0, %eax
ifif(x(x====0)0) testq %rdi, %rdi
return 0;
return je .L6
0;
else pushq %rbx
else return movq %rdi, %rbx
return
(x & (x1) & andl $1, %ebx
} 1) + shrq %rdi
+ call pcount_r
pc
pc addq %rbx,
ou
ou popq %rax
nt
nt .L6: %rbx
Register _r
_r
Use(s) Type rep; ret
(x
(x value
%rax Return Return value
>>
>>
1) ...
1) %rsp
;;
}

81
Carnegie Mellon

Observations About Recursion


⬛Handled Without Special Consideration
▪Stack frames mean that each function call has private storage
▪Saved registers & local variables
▪Saved return pointer
▪Register saving conventions prevent one function call from corrupting
another’s data
▪Unless the C code explicitly does so (e.g., buffer overflow in
Lecture 9)
▪Stack discipline follows call / return pattern
▪If P calls Q, then Q returns before P
▪Last-In, First-Out

⬛Also works for mutual recursion


▪P calls Q; Q calls P
82
Carnegie Mellon

x86-64 Procedure Summary


⬛Important Points
▪Stack is the right data structure for procedure
Caller
call/return Arguments
7+
▪If P calls Q, then Q returns before P Frame
Return Addr
⬛Recursion (& mutual recursion) handled by Old %rbp
normal calling conventions %rbp Saved
(Optional) Register
callee-saved
▪Can registers
safely store values in local stack frame and in s
▪Put function arguments at top of stack +
▪Result return in % r a x Local
Variable
s
⬛Pointers are addresses of values
▪On stack or global Argument
Build
%rsp
83
Carnegie Mellon

Appendix

84

You might also like