0% found this document useful (0 votes)
8 views76 pages

06 Procedures

The document discusses how procedures and call stacks work in computer systems. It explains how arguments are passed to procedures and return values are received. It also describes where local variables are stored and how functions know where to return using the call stack and stack pointer register.

Uploaded by

oreh2345
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
8 views76 pages

06 Procedures

The document discusses how procedures and call stacks work in computer systems. It explains how arguments are passed to procedures and return values are received. It also describes where local variables are stored and how functions know where to return using the call stack and stack pointer register.

Uploaded by

oreh2345
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 76

University of Washington

Roadmap Memory & data


Integers & floats
Machine code & C
C: Java:
x86 assembly
car *c = malloc(sizeof(car)); Car c = new Car(); Procedures & stacks
c->miles = 100; c.setMiles(100);
Arrays & structs
c->gals = 17; c.setGals(17);
float mpg = get_mpg(c); float mpg =
Memory & caches
free(c); c.getMPG(); Processes
Virtual memory
Assembly get_mpg: Memory allocation
language: pushq %rbp Java vs. C
movq %rsp, %rbp
...
popq %rbp
ret
OS:
Machine 0111010000011000
100011010000010000000010
code: 1000100111000010
110000011111101000011111

Computer
system:

Autumn 2013 Procedures and Stacks 1


University of Washington

Procedures and Call Stacks


¢ How do I pass arguments to a procedure?
¢ How do I get a return value from a procedure?
¢ Where do I put local variables?
¢ When a function returns, how does it know where to return?

¢ To answer these questions, we need a call stack …

Autumn 2013 Procedures and Stacks 2


University of Washington

Memory Layout
2N-1
local variables;
Stack procedure context

Dynamic Data variables allocated with


new or malloc
(Heap)
static variables
Static Data (including global variables (C))

Literals literals (e.g., “example”)

Instructions
0
Autumn 2013 Procedures and Stacks 3
University of Washington

segmentation faults?
Memory Layout

writable; not executable Stack Managed “automatically”


(by compiler)

writable; not executable Dynamic Data


Managed by programmer
(Heap)

writable; not executable Static Data Initialized when process starts

read-only; not executable Literals Initialized when process starts

read-only; executable Instructions Initialized when process starts

Autumn 2013 Procedures and Stacks 4


University of Washington

IA32 Call Stack


¢ Region of memory managed Stack “Bottom”
with a stack “discipline”
¢ Grows toward lower addresses
Increasing
¢ Customarily shown “upside-down” Addresses

¢ Register %esp contains


lowest stack address
= address of “top” element
Stack Grows
Down
Stack Pointer: %esp

Stack “Top”
Autumn 2013 Procedures and Stacks 5
University of Washington

IA32 Call Stack: Push


Stack “Bottom”
¢ pushl Src

Increasing
Addresses

Stack Grows
Down
Stack Pointer: %esp

Stack “Top”

Autumn 2013 Procedures and Stacks 6


University of Washington

IA32 Call Stack: Push


Stack “Bottom”
¢ pushl Src
§ Fetch value from Src
§ Decrement %esp by 4 (why 4?) Increasing
Addresses
§ Store value at address
given by %esp

Stack Grows
Down

-4
Stack Pointer: %esp

Stack “Top”
Autumn 2013 Procedures and Stacks 7
University of Washington

IA32 Call Stack: Pop


Stack “Bottom”
¢ popl Dest

Increasing
Addresses

Stack Grows
Down
Stack Pointer: %esp

Stack “Top”
Autumn 2013 Procedures and Stacks 8
University of Washington

IA32 Call Stack: Pop


Stack “Bottom”
¢ popl Dest
§ Load value from address %esp
§ Write value to Dest Increasing
Addresses
§ Increment %esp by 4

Stack Grows
Stack Pointer: %esp Down
+4

Stack “Top”

Autumn 2013 Procedures and Stacks 9


University of Washington

IA32 Call Stack: Pop


Stack “Bottom”
¢ popl Dest
§ Load value from address %esp
§ Write value to Dest Increasing
Addresses
§ Increment %esp by 4

Stack Grows
Stack Pointer: %esp Down
+4

Stack “Top”
Those bits are still there;
we’re just not using them.
Autumn 2013 Procedures and Stacks 10
University of Washington

Procedure Call Overview


Caller procedures

<set up args> Callee
call <create local vars>
<clean up args> …
<find return val> <set up return val>
… <destroy local vars>
return

¢ Callee must know where to find args


¢ Callee must know where to find “return address”
¢ Caller must know where to find return val
¢ Caller and Callee run on same CPU → use the same registers
¢ So how do we deal with register reuse?

Autumn 2013 Procedures and Stacks 11


University of Washington

Procedure Call Overview


Caller

<save regs>
<set up args>
Callee
call <save regs>
<clean up args> <create local vars>
<restore regs> …
<find return val> <set up return val>
… <destroy local vars>
<restore regs>
return

¢ The convention of where to leave/find things is called the


calling convention (or procedure call linkage).
§ Details vary between systems
§ We will see the convention for IA32/Linux in detail
§ What could happen if our program didn’t follow these conventions?
Autumn 2013 Procedures and Stacks 12
University of Washington

Procedure Control Flow


¢ Use stack to support procedure call and return
¢ Procedure call: call label
§ Push return address on stack (why?, and which exact address?)
§ Jump to label

Autumn 2013 Procedures and Stacks 13


University of Washington

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 instruction after call
§ Example from disassembly:
804854e: e8 3d 06 00 00 call 8048b90 <main>
8048553: 50 pushl %eax
§ Return address = 0x8048553
¢ Procedure return: ret
next instruction
§ Pop return address from stack just happens to be a push
§ Jump to address could be anything

Autumn 2013 Procedures and Stacks 14


University of Washington

Procedure Call Example


804854e: e8 3d 06 00 00 call 8048b90 <main>
8048553: 50 pushl %eax

call 8048b90

0x110
0x10c
0x108 123

%esp 0x108

%eip 0x804854e

%eip: program counter


Autumn 2013 Procedures and Stacks 15
University of Washington

Procedure Call Example


804854e: e8 3d 06 00 00 call 8048b90 <main>
8048553: 50 pushl %eax

call 8048b90

0x110 0x110
0x10c 0x10c
0x108 123 0x108 123
0x104 0x8048553

%esp 0x108 %esp 0x108


0x104

%eip 0x804854e %eip 0x804854e


0x8048553

%eip: program counter


Autumn 2013 Procedures and Stacks 16
University of Washington

Procedure Call Example


804854e: e8 3d 06 00 00 call 8048b90 <main>
8048553: 50 pushl %eax

call 8048b90

0x110 0x110
0x10c 0x10c
0x108 123 0x108 123
0x104 0x8048553

%esp 0x108 %esp 0x108


0x104

relative address
%eip 0x804854e %eip 0x8048553
just like jumps…
+ 0x000063d (chosen by compiler;
there’s also an absolute call)
0x8048b90
%eip: program counter
Autumn 2013 Procedures and Stacks 17
University of Washington

Procedure Return Example


8048591: c3 ret

ret

0x110
0x10c
0x108 123
0x104 0x8048553

%esp 0x104

%eip 0x8048591

%eip: program counter


Autumn 2013 Procedures and Stacks 18
University of Washington

Procedure Return Example


8048591: c3 ret

ret

0x110 0x110
0x10c 0x10c
0x108 123 0x108 123
0x104 0x8048553 0x8048553

%esp 0x104 %esp 0x104

%eip 0x8048591 %eip 0x8048591

%eip: program counter


Autumn 2013 Procedures and Stacks 19
University of Washington

Procedure Return Example


8048591: c3 ret

ret

0x110 0x110
0x10c 0x10c
0x108 123 0x108 123
0x104 0x8048553 0x8048553

%esp 0x104 %esp 0x104

%eip 0x8048591 %eip 0x8048553


0x8048591

%eip: program counter


Autumn 2013 Procedures and Stacks 20
University of Washington

Procedure Return Example


8048591: c3 ret

ret

0x110 0x110
0x10c 0x10c
0x108 123 0x108 123
0x104 0x8048553 0x8048553

%esp 0x104 %esp 0x104


0x108

%eip 0x8048591 %eip 0x8048553


0x8048591

%eip: program counter


Autumn 2013 Procedures and Stacks 21
University of Washington

Stack-Based Languages
¢ Languages that support recursion
§ e.g., C, Java, most modern languages
§ Code must be re-entrant
Multiple simultaneous instantiations of single procedure
§
§ Need some place to store state of each instantiation
§ Arguments
§ Local variables
§ Return pointer

¢ Stack discipline
§ State for a given procedure needed for a limited time
§ Starting from when it is called to when it returns
§ Callee always returns before caller does
¢ Stack allocated in frames
§ State for a single procedure instantiation

Autumn 2013 Procedures and Stacks 22


University of Washington

Call Chain Example


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

} amI();
• amI

}

Procedure amI is recursive


(calls itself)

Autumn 2013 Procedures and Stacks 23


University of Washington

Stack Frames
Previous
¢ Contents Frame
§ Local variables
§ Function arguments Frame Pointer: %ebp
§ Return information Frame
§ Temporary space for
current
proc
Stack Pointer: %esp
¢ Management
§ Space allocated when procedure is entered Stack “Top”
“Set-up” code
§
§ Space deallocated upon return
§ “Finish” code

Autumn 2013 Procedures and Stacks 24


University of Washington

Stack
Example
yoo(…) yoo
%ebp
{
• yoo
who
• %esp
who();
• amI amI

}
amI

amI

Autumn 2013 Procedures and Stacks 25


University of Washington

Stack
Example
who(…) yoo
{
• • • yoo
who
amI();
• • • %ebp
amI(); amI amI who
• • •
%esp
}
amI

amI

Autumn 2013 Procedures and Stacks 26


University of Washington

Stack
Example
amI(…) yoo
{
• yoo
who

amI();
• amI amI who

} %ebp
amI
amI
%esp
amI

Autumn 2013 Procedures and Stacks 27


University of Washington

Stack
Example
amI(…) yoo
{
• yoo
who

amI();
• amI amI who

}
amI
amI

amI %ebp
amI
%esp

Autumn 2013 Procedures and Stacks 28


University of Washington

Stack
Example
amI(…) yoo
{
• yoo
who

amI();
• amI amI who

}
amI
amI

amI
amI

%ebp
amI
%esp

Autumn 2013 Procedures and Stacks 29


University of Washington

Stack
Example
amI(…) yoo
{
• yoo
who

amI();
• amI amI who

}
amI
amI

amI %ebp
amI
%esp

Autumn 2013 Procedures and Stacks 30


University of Washington

Stack
Example
amI(…) yoo
{
• yoo
who

amI();
• amI amI who

} %ebp
amI
amI
%esp
amI

Autumn 2013 Procedures and Stacks 31


University of Washington

Stack
Example
who(…) yoo
{
• • • yoo
who
amI();
• • • %ebp
amI(); amI amI who
• • •
%esp
}
amI

amI

Autumn 2013 Procedures and Stacks 32


University of Washington

Stack
Example
amI(…) yoo
{
• yoo
who


• amI amI who

} %ebp
amI
amI
%esp
amI

Autumn 2013 Procedures and Stacks 33


University of Washington

Stack
Example
who(…) yoo
{
• • • yoo
who
amI();
• • • %ebp
amI(); amI amI who
• • •
%esp
}
amI

amI

Autumn 2013 Procedures and Stacks 34


University of Washington

Stack
Example
yoo(…) yoo
%ebp
{
• yoo
who
• %esp
who();
• amI amI

}
amI

amI

How did we remember where to point %ebp when returning?


Autumn 2013 Procedures and Stacks 35
University of Washington

IA32/Linux Stack Frame


¢ Current Stack Frame (“Top” to Bottom)
§ “Argument build” area
(parameters for function Caller
about to be called) Frame
§ Local variables Arguments
(if can’t be kept in registers)
§ Saved register context Frame pointer Return Addr
(when reusing registers) %ebp Old %ebp
§ Old frame pointer (for caller)
Saved
Registers
+
¢ Caller’s Stack Frame Local
§ Return address Variables
§ Pushed by call instruction
§ Arguments for this call Argument
Stack pointer
Build
%esp
Autumn 2013 Procedures and Stacks 36
University of Washington

Revisiting swap
int zip1 = 15213;
int zip2 = 98195;

void call_swap()
{
swap(&zip1, &zip2);
}

void swap(int *xp, int *yp)


{
int t0 = *xp;
int t1 = *yp;
*xp = t1;
*yp = t0;
}

Autumn 2013 Procedures and Stacks 37


University of Washington

Revisiting swap
Calling swap from call_swap
int zip1 = 15213; call_swap:
int zip2 = 98195; • • •
pushl $zip2 # Global Var
void call_swap() pushl $zip1 # Global Var
{ call swap
swap(&zip1, &zip2); • • •
}
not Global War!
we know the address

void swap(int *xp, int *yp)


{
int t0 = *xp;
int t1 = *yp;
*xp = t1;
*yp = t0;
}

Autumn 2013 Procedures and Stacks 38


University of Washington

Revisiting swap
Calling swap from call_swap
int zip1 = 15213; call_swap:
int zip2 = 98195; • • •
pushl $zip2 # Global Var
void call_swap() pushl $zip1 # Global Var
{ call swap
swap(&zip1, &zip2); • • •
}

Resulting
• Stack
void swap(int *xp, int *yp) •
{ •
int t0 = *xp;
int t1 = *yp; &zip2
*xp = t1;
&zip1
*yp = t0;
} Rtn adr %esp

Autumn 2013 Procedures and Stacks 39


University of Washington

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 12(%ebp),%ecx
*xp = t1; movl 8(%ebp),%edx
*yp = t0; movl (%ecx),%eax
} Body
movl (%edx),%ebx
movl %eax,(%edx)
movl %ebx,(%ecx)

movl -4(%ebp),%ebx
movl %ebp,%esp Finish
popl %ebp
ret

Autumn 2013 Procedures and Stacks 40


University of Washington

swap Setup #1
Entering Stack Resulting Stack?
%ebp


&zip2
&zip1
Rtn adr %esp

swap:
pushl %ebp
movl %esp,%ebp Set
pushl %ebx Up

Autumn 2013 Procedures and Stacks 41


University of Washington

swap Setup #1
Entering Stack Resulting Stack
%ebp %ebp
• •
• •
• •

&zip2 yp
&zip1 xp
Rtn adr %esp Rtn adr
Old %ebp %esp

swap:
pushl %ebp
movl %esp,%ebp Set
pushl %ebx Up

Autumn 2013 Procedures and Stacks 42


University of Washington

swap Setup #2
Entering Stack Resulting Stack
%ebp
• •
• •
• •

&zip2 yp
&zip1 xp
Rtn adr %esp Rtn adr
Old %ebp %ebp
%esp

swap:
pushl %ebp
movl %esp,%ebp Set
pushl %ebx Up

Autumn 2013 Procedures and Stacks 43


University of Washington

swap Setup #3
Entering Stack Resulting Stack
%ebp
• •
• •
• •

&zip2 yp
&zip1 xp
Rtn adr %esp Rtn adr
Old %ebp %ebp
Old %ebx %esp
swap:
pushl %ebp
movl %esp,%ebp Set
pushl %ebx Up

Autumn 2013 Procedures and Stacks 44


University of Washington

swap Body
Entering Stack Resulting Stack
%ebp
• •
• •
• Offset relative •
to new %ebp
&zip2 12 yp
&zip1 8 xp
Rtn adr %esp 4 Rtn adr
Old %ebp %ebp
Old %ebx %esp

movl 12(%ebp),%ecx # get yp


movl 8(%ebp),%edx # get xp
. . .
Body
Autumn 2013 Procedures and Stacks 45
University of Washington

swap Finish #1
Finishing Stack Resulting Stack?



yp
xp
Rtn adr
Old %ebp %ebp
Old %ebx %esp

movl -4(%ebp),%ebx
movl %ebp,%esp
Finish
popl %ebp
ret
Autumn 2013 Procedures and Stacks 46
University of Washington

swap Finish #1
Finishing Stack Resulting Stack

• •
• •
• •

yp yp
xp xp
Rtn adr Rtn adr
Old %ebp %ebp Old %ebp %ebp
Old %ebx %esp Old %ebx %esp

movl -4(%ebp),%ebx
movl %ebp,%esp
Finish Observation: Saved and restored
popl %ebp
ret register %ebx
Autumn 2013 Procedures and Stacks 47
University of Washington

swap Finish #2
Finishing Stack Resulting Stack

• •
• •
• •

yp yp
xp xp
Rtn adr Rtn adr
Old %ebp %ebp Old %ebp %ebp
%esp
Old %ebx %esp

movl -4(%ebp),%ebx
movl %ebp,%esp
Finish
popl %ebp
ret
Autumn 2013 Procedures and Stacks 48
University of Washington

swap Finish #3
Finishing Stack Resulting Stack

%ebp
• •
• •
• •

yp yp
xp xp
Rtn adr Rtn adr %esp
Old %ebp %ebp
Old %ebx %esp

movl -4(%ebp),%ebx
movl %ebp,%esp
Finish
popl %ebp
ret
Autumn 2013 Procedures and Stacks 49
University of Washington

swap Finish #4
Finishing Stack Resulting Stack

%ebp
• •
• •
• •

yp yp
xp xp %esp
Rtn adr
Old %ebp %ebp
Old %ebx %esp

movl -4(%ebp),%ebx
movl %ebp,%esp
Finish
popl %ebp
ret
Autumn 2013 Procedures and Stacks 50
University of Washington

Disassembled swap
080483a4 <swap>:
80483a4: 55 push %ebp
80483a5: 89 e5 mov %esp,%ebp
80483a7: 53 push %ebx
80483a8: 8b 55 08 mov 0x8(%ebp),%edx
80483ab: 8b 4d 0c mov 0xc(%ebp),%ecx
80483ae: 8b 1a mov (%edx),%ebx
80483b0: 8b 01 mov (%ecx),%eax
80483b2: 89 02 mov %eax,(%edx)
80483b4: 89 19 mov %ebx,(%ecx)
80483b6: 5b pop %ebx mov %ebp,%esp
80483b7: c9 leave pop %ebp
80483b8: c3 ret

Calling Code
8048409: e8 96 ff ff ff call 80483a4 <swap>
804840e: 8b 45 f8 mov 0xfffffff8(%ebp),%eax

Autumn 2013 relative addressProcedures


(littleandendian)
Stacks 51
University of Washington

swap Finish #4
Finishing Stack Resulting Stack

%ebp
• •
• •
• •

yp yp
xp xp %esp
Rtn adr
Old %ebp %ebp
Old %ebx %esp
¢ Observation
movl -4(%ebp),%ebx § Saved & restored register %ebx
movl %ebp,%esp
Finish § but not %eax, %ecx, or %edx
popl %ebp
ret
Autumn 2013 Procedures and Stacks 52
University of Washington

Register Saving Conventions


¢ When procedure yoo calls who:
§ yoo is the caller
§ who is the callee

¢ Can a register be used for temporary storage?


yoo: who:
• • • • • •
movl $12345, %edx movl 8(%ebp), %edx
call who ? addl $98195, %edx
addl %edx, %eax • • •
• • • ret
ret

§ Contents of register %edx overwritten by who

Autumn 2013 Procedures and Stacks 53


University of Washington

Register Saving Conventions


¢ When procedure yoo calls who:
§ yoo is the caller
§ who is the callee

¢ Can a register be used for temporary storage?


¢ Conventions
§ “Caller Save”
§Caller saves temporary values in its frame before calling
§ “Callee Save”
§ Callee saves temporary values in its frame before using

Autumn 2013 Procedures and Stacks 54


University of Washington

IA32/Linux Register Usage


¢ %eax, %edx, %ecx
§ Caller saves prior to call if %eax
values are used later Caller-Save
Temporaries %edx
¢ %eax %ecx
§ also used to return %ebx
integer value Callee-Save
Temporaries %esi
¢ %ebx, %esi, %edi %edi
§ Callee saves if wants to %esp
Special
use them %ebp
¢ %esp, %ebp
§ special form of callee save – restored to original values upon exit from
procedure
Autumn 2013 Procedures and Stacks 55
University of Washington

Example: Pointers to Local Variables


Top-Level Call Recursive Procedure
int sfact(int x) void s_helper
{ (int x, int *accum)
int val = 1; {
s_helper(x, &val); if (x <= 1)
return val; return;
} else {
int z = *accum * x;
*accum = z;
s_helper (x-1,accum);
}
sfact(3) }

Pass pointer to update location

Autumn 2013 Procedures and Stacks 56


University of Washington

Example: Pointers to Local Variables


Top-Level Call Recursive Procedure
int sfact(int x) void s_helper
{ (int x, int *accum)
int val = 1; {
s_helper(x, &val); if (x <= 1)
return val; return;
} else {
int z = *accum * x;
*accum = z;
s_helper (x-1,accum);
}
sfact(3) val = 1 }
s_helper(3, &val)

Pass pointer to update location

Autumn 2013 Procedures and Stacks 57


University of Washington

Example: Pointers to Local Variables


Top-Level Call Recursive Procedure
int sfact(int x) void s_helper
{ (int x, int *accum)
int val = 1; {
s_helper(x, &val); if (x <= 1)
return val; return;
} else {
int z = *accum * x;
*accum = z;
s_helper (x-1,accum);
}
sfact(3) val = 1 }
s_helper(3, &val) val = 3
s_helper(2, &val)

Pass pointer to update location

Autumn 2013 Procedures and Stacks 58


University of Washington

Example: Pointers to Local Variables


Top-Level Call Recursive Procedure
int sfact(int x) void s_helper
{ (int x, int *accum)
int val = 1; {
s_helper(x, &val); if (x <= 1)
return val; return;
} else {
int z = *accum * x;
*accum = z;
s_helper (x-1,accum);
}
sfact(3) val = 1 }
s_helper(3, &val) val = 3
s_helper(2, &val) val = 6
s_helper(1, &val) .
Pass pointer to update location

Autumn 2013 Procedures and Stacks 59


University of Washington

Creating & Initializing Pointer


int sfact(int x) ¢ Variable val must be stored on stack
{ § Because: Need to create pointer to it
int val = 1;
¢ Compute pointer as -4(%ebp)
s_helper(x, &val);
return val; ¢ Push on stack as second argument
}

8 x
4 Rtn adr %esp
Initial part of sfact
0 Old %ebp %ebp
_sfact:
pushl %ebp # Save %ebp -4 val = 1 %esp
movl %esp,%ebp # Set %ebp -8 Temp.
subl $16,%esp # Add 16 bytes
-12 Space
Unused
movl 8(%ebp),%edx # edx = x
movl $1,-4(%ebp) # val = 1 -16 %esp

Autumn 2013 Procedures and Stacks 60


University of Washington

Passing Pointer
¢ Variable val must be stored on stack
int sfact(int x)
§ Because: Need to create pointer to it
{
int val = 1; ¢ Compute pointer as -4(%ebp)
s_helper(x, &val); ¢ Push on stack as second argument
return val;
}
Stack at time of call: 8 x
4 Rtn adr
0 Old %ebp %ebp
Calling s_helper from sfact -4 val
val=x!
= 1
leal -4(%ebp),%eax # Compute &val -8
pushl %eax # Push on stack -12 Unused
pushl %edx # Push x
call s_helper # call -16
%esp
movl -4(%ebp),%eax # Return val &val
• • • # Finish
x

Autumn 2013 Procedures and Stacks 61


University of Washington

IA 32 Procedure Summary
¢ Important points:
§ IA32 procedures are a combination of instructions
and conventions Caller
§ Conventions prevent functions from Frame
disrupting each other Arguments
§ Stack is the right data structure for procedure
Return Addr
call / return
%ebp Old %ebp
§ If P calls Q, then Q returns before P
Saved
¢ Recursion handled by normal calling Registers
conventions +
§ Can safely store values in local stack frame and in Local
callee-saved registers Variables
§ Put function arguments at top of stack
Argument
§ Result returned in %eax Build
%esp
Autumn 2013 Procedures and Stacks 62
University of Washington

x86-64 Procedure Calling Convention


¢ Doubling of registers makes us less dependent on stack
§ Store argument in registers
§ Store temporary variables in registers

¢ What do we do if we have too many arguments or too many


temporary variables?

Autumn 2013 Procedures and Stacks 63


University of Washington

x86-64 64-bit Registers: Usage Conventions


%rax Return value %r8 Argument #5

%rbx Callee saved %r9 Argument #6

%rcx Argument #4 %r10 Caller saved

%rdx Argument #3 %r11 Caller Saved

%rsi Argument #2 %r12 Callee saved

%rdi Argument #1 %r13 Callee saved

%rsp Stack pointer %r14 Callee saved

%rbp Callee saved %r15 Callee saved

Autumn 2013 Procedures and Stacks 64


University of Washington

Revisiting swap, IA32 vs. x86-64 versions


swap: swap (64-bit long ints):
pushl %ebp movq (%rdi), %rdx
movl %esp,%ebp Set movq (%rsi), %rax
pushl %ebx Up movq %rax, (%rdi)
movq %rdx, (%rsi)
movl 12(%ebp),%ecx ret
movl 8(%ebp),%edx
movl (%ecx),%eax ¢ Arguments passed in registers
Body
movl (%edx),%ebx § First (xp) in %rdi,
movl %eax,(%edx)
second (yp) in %rsi
movl %ebx,(%ecx)
§ 64-bit pointers
movl -4(%ebp),%ebx ¢ No stack operations
movl %ebp,%esp
popl %ebp
Finish required (except ret)
ret ¢ Avoiding stack
§ Can hold all local information
in registers
Autumn 2013 Procedures and Stacks 65
University of Washington

X86-64 procedure call highlights


¢ Arguments (up to first 6) in registers
§ Faster to get these values from registers than from stack in memory
¢ Local variables also in registers (if there is room)
¢ Registers still designated “caller-saved” or “callee-saved”
¢ callq instruction stores 64-bit return address on stack
§ Address pushed onto stack, decrementing %rsp by 8
¢ No frame pointer
§ All references to stack frame made relative to %rsp; eliminates need to
update %ebp/%rbp, which is now available for general-purpose use
¢ Functions can access memory up to 128 bytes beyond %rsp:
the “red zone”
§ Can store some temps on stack without altering %rsp

Autumn 2013 Procedures and Stacks 66


University of Washington

x86-64 Memory Layout


2N-1
Stack %rsp

128-byte red zone


space lower than the
stack pointer that
Dynamic Data procedures can use for
(Heap) data not needed across
procedure calls
Static Data
optimization to avoid
extra %rsp updates
Literals

Instructions
0
Autumn 2013 Procedures and Stacks 67
University of Washington

x86-64 Stack Frames


¢ Often (ideally), x86-64 functions need no stack frame at all
§ Just a return address is pushed onto the stack when a function call is
made
¢ A function does need a stack frame when it:
§ Has too many local variables to hold in registers
§ Has local variables that are arrays or structs
§ Uses the address-of operator (&) to compute the address of a local
variable
§ Calls another function that takes more than six arguments
§ Needs to save the state of caller-save registers before calling a procedure
§ Needs to save the state of callee-save registers before modifying them

Autumn 2013 Procedures and Stacks 68


University of Washington

Example
long int call_proc() call_proc:
{ subq $32,%rsp
long x1 = 1; movq $1,16(%rsp)
int x2 = 2; movl $2,24(%rsp)
short x3 = 3; movw $3,28(%rsp)
char x4 = 4; movb $4,31(%rsp)
proc(x1, &x1, x2, &x2, • • •
x3, &x3, x4, &x4);
return (x1+x2)*(x3-x4);
}

Return address to caller of call_proc %rsp

NB: Details may vary


depending on compiler.
Autumn 2013 Procedures and Stacks 69
University of Washington

Example
long int call_proc() call_proc:
{ subq $32,%rsp
long x1 = 1; movq $1,16(%rsp)
int x2 = 2; movl $2,24(%rsp)
short x3 = 3; movw $3,28(%rsp)
char x4 = 4; movb $4,31(%rsp)
proc(x1, &x1, x2, &x2, • • •
x3, &x3, x4, &x4);
return (x1+x2)*(x3-x4);
}

Return address to caller of call_proc


x4 x3 x2
x1

%rsp

Autumn 2013 Procedures and Stacks 70


University of Washington

Example
long int call_proc() call_proc:
{ • • •
long x1 = 1; leaq 24(%rsp),%rcx
int x2 = 2; leaq 16(%rsp),%rsi
short x3 = 3; leaq 31(%rsp),%rax
char x4 = 4; movq %rax,8(%rsp)
proc(x1, &x1, x2, &x2, movl $4,(%rsp)
x3, &x3, x4, &x4); leaq 28(%rsp),%r9
return (x1+x2)*(x3-x4); movl $3,%r8d
} movl $2,%edx
movq $1,%rdi
Return address to caller of call_proc call proc
x4 x3 x2 • • •

x1 Arguments passed in (in


Arg 8 order): rdi, rsi, rdx, rcx, r8, r9
Arg 7 %rsp

Autumn 2013 Procedures and Stacks 71


University of Washington

Example
long int call_proc() call_proc:
{ • • •
long x1 = 1; leaq 24(%rsp),%rcx
int x2 = 2; leaq 16(%rsp),%rsi
short x3 = 3; leaq 31(%rsp),%rax
char x4 = 4; movq %rax,8(%rsp)
proc(x1, &x1, x2, &x2, movl $4,(%rsp)
x3, &x3, x4, &x4); leaq 28(%rsp),%r9
return (x1+x2)*(x3-x4); movl $3,%r8d note
} movl $2,%edx sizes
movq $1,%rdi
Return address to caller of call_proc call proc
x4 x3 x2 • • •

x1 Arguments passed in (in


Arg 8 order): rdi, rsi, rdx, rcx, r8, r9
Arg 7 %rsp

Autumn 2013 Procedures and Stacks 72


University of Washington

Example
long int call_proc() call_proc:
{ • • •
long x1 = 1; leaq 24(%rsp),%rcx
int x2 = 2; leaq 16(%rsp),%rsi
short x3 = 3; leaq 31(%rsp),%rax
char x4 = 4; movq %rax,8(%rsp)
proc(x1, &x1, x2, &x2, movl $4,(%rsp)
x3, &x3, x4, &x4); leaq 28(%rsp),%r9
return (x1+x2)*(x3-x4); movl $3,%r8d
} movl $2,%edx
movq $1,%rdi
Return address to caller of call_proc call proc
x4 x3 x2 • • •

x1
Arg 8
Arg 7
Return address to line after call to proc %rsp
Autumn 2013 Procedures and Stacks 73
University of Washington

Example sign extension!


long int call_proc() call_proc:
{ • • •
long x1 = 1; movswl 28(%rsp),%eax
int x2 = 2; movsbl 31(%rsp),%edx
short x3 = 3; subl %edx,%eax
char x4 = 4; cltq
proc(x1, &x1, x2, &x2, movslq 24(%rsp),%rdx
x3, &x3, x4, &x4); addq 16(%rsp),%rdx
return (x1+x2)*(x3-x4); imulq %rdx,%rax
} addq $32,%rsp
ret
Return address to caller of call_proc
x4 x3 x2
x1
Arg 8
Arg 7 %rsp

Autumn 2013 Procedures and Stacks 74


University of Washington

Example
long int call_proc() call_proc:
{ • • •
long x1 = 1; movswl 28(%rsp),%eax
int x2 = 2; movsbl 31(%rsp),%edx
short x3 = 3; subl %edx,%eax
char x4 = 4; cltq
proc(x1, &x1, x2, &x2, movslq 24(%rsp),%rdx
x3, &x3, x4, &x4); addq 16(%rsp),%rdx
return (x1+x2)*(x3-x4); imulq %rdx,%rax
} addq $32,%rsp
ret
Return address to caller of call_proc %rsp

Autumn 2013 Procedures and Stacks 75


University of Washington

x86-64 Procedure Summary


¢ Heavy use of registers (faster than using stack in memory)
§ Parameter passing
§ More temporaries since more registers

¢ Minimal use of stack


§ Sometimes none
§ When needed, allocate/deallocate entire frame at once
§ No more frame pointer: address relative to stack pointer

¢ More room for compiler optimizations


§ Prefer to store data in registers rather than memory
§ Minimize modifications to stack pointer

Autumn 2013 Procedures and Stacks 76

You might also like