Stack and Procedures

Download Report

Transcript Stack and Procedures

Devoir surveillé
Vendredi 22 février 14h-15h20
Amphi Turing
Programme

Tous les sujets traités en TD
jusqu’au mercredi 20 inclus
Sans document
Adaptation par J.Bétréma
Machine-Level Programming :
Stack and Procedures
Topics



IA32 stack discipline
Procedure calls
Register saving conventions
Randal E. Bryant & David R. O'Hallaron
Carnegie Mellon University
http://csapp.cs.cmu.edu
class07.ppt
Y86 Program Stack

Code


Increasing
Addresses
Region of memory holding
program data
Used in Y86 (and IA32) for
supporting procedure calls
Stack top indicated by %esp
(Stack Pointer)
 Address of top stack element
Stack “Top”

%esp
Stack
“Bottom”
–3–
Stack grows toward lower
addresses
 Top element is at highest
address in the stack
 When pushing, must first
decrement stack pointer
 When popping, increment stack
pointer
Pile et procédures
Stack Operations
pushl rA

Decrement %esp by 4
Store word from rA to memory at %esp

Like IA32

popl rA
–4–
a 0 rA 8
b 0 rA 8

Read word from memory at %esp


Save in rA
Increment %esp by 4

Like IA32
Pile et procédures
IA32 Stack Pushing
Pushing

pushl Src

Fetch operand at Src
Decrement %esp by 4


Stack
Pointer
%esp
-4
%eax
Write operand at address
given by %esp
Y86


–5–
Src = registre
Exemple : pushl %eax
empile le contenu du registre %eax
Pile et procédures
IA32 Stack Popping
Popping

popl Dest


Read operand at address
given by %esp
Increment %esp by 4

Write to Dest
Stack
Pointer + 4
%esp
Y86


–6–
Dest = registre
Exemple : popl %edx
dépile dans %edx le mot
en sommet de pile
Pile et procédures
Stack Operation Examples
pushl %eax
0x108
123
popl %edx
0x104
213
0x104
213
0x108
123
0x108
123
0x10c
0x10c
0x10c
0x110
0x110
0x110
%eax
213
%eax
213
%eax
213
%edx
555
%edx
555
%edx
555
213
%esp
0x108
%esp
0x104
0x108
%esp
0x104
0x108
–7–
Pile et procédures
Call Chain Example
Code Structure
f(…)
{
•
•
g();
•
•
}
–8–
Call Chain
Vocabulaire : fonction C
= procédure = subroutine
g(…)
{
• • •
h();
• • •
h();
• • •
}
f
g
Profondeur
de l’arbre
des appels
non bornée
h
h
...
...
Pile et procédures
Adresse de retour
Procédure appelée
Procédure appelante
f(…)
{
•
•
g();
•
•
}
jmp g
jmp ???
g(…)
{
• • •
h();
• • •
h();
• • •
}
Solution : la procédure appelante sauve
l’adresse de retour avant l’appel.
–9–
La procédure
appelée ignore
l’adresse de
retour, car elle
ignore qui l’a
appelée.
Où ? sur la pile !
Pile et procédures
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: 8b 45 0c
call
mov
8048b90
0xc(%ebp),%eax
 Return address = 0x8048553
Procedure return:

– 10 –
ret
Pop address from stack; Jump to address
Pile et procédures
Subroutine Call and Return
call Dest



ret



– 11 –
8 0
Dest
Push address of next instruction onto stack
Start executing instructions at Dest
Like IA32
9 0
Pop value from stack
Use as address for next instruction
Like IA32
Pile et procédures
Stack-Based Languages
Languages that Support Recursion

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

– 12 –
state for single procedure instantiation
Pile et procédures
Stack Frames
Contents



Local variables
Return information
Temporary space
f
g
h
Management

Space allocated when enter
procedure
 “Set-up” code

Deallocated when return
proc
 “Finish” code
Pointers


– 13 –
Stack pointer %esp
indicates stack top
Frame pointer %ebp indicates
start of current frame
Stack
“Top”
Stack
Pointer
%esp
%ebp
Frame
Pointer
Pile et procédures
Stack Operation
f(…)
{
•
•
g();
•
•
}
Call Chain
f
Stack
Pointer
%esp
f
%ebp
Frame
Pointer
– 14 –
•
•
•
Pile et procédures
Stack Operation
g(…)
{
• • •
h();
• • •
h();
• • •
}
Call Chain
f
g
Stack
Pointer
%esp
g
%ebp
Frame
Pointer
f
•
•
•
– 15 –
Pile et procédures
Stack Operation
h(…)
{
•
•
•
•
}
Call Chain
f
g
h
Stack
Pointer
%esp
h
%ebp
Frame
Pointer
g
f
•
•
•
– 16 –
Pile et procédures
Stack Operation
g(…)
{
• • •
h();
• • •
h();
• • •
}
Call Chain
f
g
Stack
Pointer
%esp
g
h
%ebp
Frame
Pointer
f
•
•
•
– 17 –
Pile et procédures
Stack Operation
h(…)
{
•
•
•
•
}
Call Chain
Stack
Pointer
%esp
f
h
g
h
h
%ebp
Frame
Pointer
g
f
•
•
•
– 18 –
Pile et procédures
Stack Operation
g(…)
{
• • •
h();
• • •
h();
• • •
}
Call Chain
f
Stack
Pointer
%esp
g
h
g
h
%ebp
Frame
Pointer
f
•
•
•
– 19 –
Pile et procédures
Stack Operation
f(…)
{
•
•
g();
•
•
}
Call Chain
f
g
h
h
Stack
Pointer
%esp
f
%ebp
Frame
Pointer
– 20 –
•
•
•
Pile et procédures
IA32/Linux Stack Frame
Current Stack Frame (“Top”
to Bottom)

Stack Pointer
(%esp)
Parameters for function
about to call
Saved
Registers
+
Local
Variables
 “Argument build”

Local variables
 If can’t keep in registers


Saved register context
Old frame pointer
Frame Pointer
(%ebp)
Caller Stack Frame

Return address
 Pushed by call instruction

– 21 –
Argument
Build
Old %ebp
Return Addr
Arguments
Caller
Frame
Arguments for this call
Pile et procédures
Example: swap
Calling swap from call_swap
int zip1 = 15213;
int zip2 = 91125;
void call_swap()
{ ...
swap(&zip1, &zip2);
...
}
call_swap:
• • •
pushl $zip2
pushl $zip1
call swap
• • •
%esp
# Global Var
# Global Var
Rtn adr
&zip1
void swap(int *xp, int *yp)
{
int t0 = *xp;
int t1 = *yp;
*xp = t1;
*yp = t0;
}
– 22 –
Resulting
Stack
&zip2
•
•
•
Pile et procédures
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
– 23 –
Body
Finish
Pile et procédures
swap Setup
%ebp
%esp
Old %ebx
%esp
%ebp
Old %ebp
%esp
Rtn adr
&zip1
swap:
pushl %ebp
movl %esp,%ebp
pushl %ebx
&zip2
•
•
•
%ebp
– 24 –
Pile et procédures
Effect of swap Setup
movl 12(%ebp),%ecx # get yp
movl 8(%ebp),%edx # get xp
. . .
Entering
Stack
%esp
Rtn adr
&zip1
&zip2
•
•
•
Resulting
Stack
Body
%esp
Offset
(relative to %ebp)
Old %ebx
0
Old %ebp
4
Rtn adr
8
xp
12
yp
%ebp
•
•
•
%ebp
– 25 –
Pile et procédures
swap Finish
%esp
%esp
Old
%ebx
%ebx
%ebp
Old
%ebp
%ebp
%esp
Rtn adr
%esp
xp
Restores %ebx
movl -4(%ebp),%ebx
movl %ebp,%esp
popl %ebp
ret
yp
•
•
•
%ebp
– 26 –
Observation

Saved & restored
register %ebx

Didn’t do so for
%eax, %ecx, or %edx
Pile et procédures
Register Saving Conventions
When procedure f calls g:

f is the caller, g is the callee
Can Register be Used for Temporary Storage?
f:
g:
• • •
movl $15213, %edx
call g
addl %edx, %eax
• • •
ret

– 27 –
• • •
movl 8(%ebp), %edx
addl $91125, %edx
• • •
ret
Contents of register %edx overwritten by g
Pile et procédures
Register Saving Conventions
When procedure f calls g:

f is the caller, g 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
– 28 –
Pile et procédures
IA32/Linux Register Usage
Integer Registers

%ebp, %esp

Three managed as
callee-save
%ebx, %esi, %edi
 Old values saved on
stack prior to using

– 29 –
Caller-Save
Temporaries
Register %eax also
stores returned value
%ecx
%edx
%ebx
Callee-Save
Temporaries
%esi
%edi
Three managed as
caller-save
%eax, %ecx, %edx
 Do what you please,
but expect any callee
to do so, as well

%eax
Two have special uses
%ebp
Special
%esp
Pile et procédures
Procédures récursives
Le protocole précédent ne limite pas la profondeur
de l’arbre des appels.

Pièces bien placées sur l’échiquier = position solide.

Prêt à parer une attaque inattendue :
 Procédure récursive = procédure qui s’appelle elle-même
 Procédure appelante (caller) = procédure appelée (callee)
– 30 –
Pile et procédures
Informatique théorique
Un automate à états finis ne peut pas gérer
correctement les appels de procédures :



Le langage des mots de la forme an bn n’est pas rationnel
Idem pour le langage des parenthèses  mots de la forme
()(()())=abaababb
a = appel (call) b = retour (return)
Pour parcourir un arbre il faut un automate à pile !
– 31 –
Pile et procédures
rfact:
pushl %ebp
movl %esp,%ebp
int rfact (int x)
pushl %ebx
lit l’argument
{
movl 8(%ebp),%ebx
int rval;
cmpl $1,%ebx
if (x <= 1)
jle .L78
return 1;
calcule x-1
leal -1(%ebx),%eax
rval = rfact (x-1);
pushl %eax
return rval * x;
call rfact
}
imull %ebx,%eax
jmp .L79
empile l’argument
.align 4
avant l’appel récursif
.L78:
Registers
movl $1,%eax
 %eax used without first
.L79:
movl -4(%ebp),%ebx
saving
movl %ebp,%esp
 %ebx used, but save at
popl %ebp
beginning & restore at end
ret
Recursive Factorial
– 32 –
Pile et procédures
Summary
The Stack Makes Procedures 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

– 33 –
Stack frame organization conventions
Pile et procédures