Vous êtes sur la page 1sur 32

SMI S4

ARCHITECTURE DES ORDINATEURS


CHAPITRE 3 : PILE
La gestion de la pile
REMPLISSAGE

EMPILE : PUSH
PILE

a5
a4
a3
4 1
a2
3 2
2< a1 3
1 a0 4
ESP
ADRESSES
La gestion de la pile
VIDAGE (LIFO:Last In First Out)

DEPILE : POP
PILE

a5
a4
a3
4 1
a2
3 2
2< a1 3
1 a0 4
ESP
ADRESSES
RAPPEL
• La pile est une région de la mémoire principale mais
qui a un fonctionnement spécial.
• On rappelle que, dans le cas de la mémoire
principale, pour avoir accès à une donnée il suffit
d’avoir son adresse et le microprocesseur nous la
donne : c’est un mode d’accès ALEATOIRE (RANDOM
ACCESS MEMORY : RAM).
• Exemple pratique de pile : Une pile de livres est un
ensemble de livres superposés les uns sur les autres.
• Pour atteindre un certain livre, il faut enlever tous les
livres qui se trouvent dessus.
• Eh bien, c’est pareil pour la pile de mémoire qui est
une pile de données. alors pour enlever (dépiler) ou
déposer (empiler) des données dans la pile, le
microprocesseur utilise un de ses registres qui est fait
pour ça, appelé le Stack Pointer SP (pointeur de pile).
• C’est un registre de 16 bits qui contiendra l’adresse
de la dernière donnée dans la pile.
• Pour les processeurs actuels on utilise ESP (Extented
SP dit SP étendu et qui est un registre de 32 bits).
• ESP contient toujours l’adresse de la donnée du
sommet de la pile.
Objectifs
À la fin de cette presentation vous saurez comment
la pile est utilisée pour passer les paramètres aux
sous-programmes, effectuer l'allocation dynamique
des variables locales de ces sous-programmes. Pour y
arriver, vous devrez atteindre les objectifs suivants :
 Comprendre les instructions push et pop.
 Décrire les différents modes de passage des
paramètres
 Décrire un bloc de pile
1) Empilement et dépilement
La plupart des microprocesseurs utilisent abandement la
pile, surtout pour le passage des paramètres aux sous-
programmes. On dispose de deux instructions pour
empiler et dépiler les données :

L'instruction push décrémente le pointeur de pile ESP,


puis écrit l’opérande en mémoire à l’adresse contenue
dans ESP. C'est l'empilement.

L'instruction pop lit l’opérande à l’adresse ESP puis


incrémente ESP . C'est le dépilement.
– La syntaxe de l’instruction push est la suivante :

– push REGISTRE
– Où REGISTRE est un registre de taille 16 ou 32 bits.

– push ADRESSE
– Où ADRESSE est une adresse de taille 16 ou 32 bits.

– push CONSTANTE
– Où CONSTANTE est une valeur quelconque.
– En mode 32 bits, l'instruction push CONSTANTE a l'effet
suivant :
push 61h
Mémoire Mémoire
0 0

ESP
61
00
00
ESP 00

 

– Chaque case mémoire correspond à un octet (4x8=32 bots)


– 61h sur 32 bits est : 00 00 00 61h.
– Le processeur pushe les octets du poids fort au poids faible.
– Le pointeur de pile doit toujours être pair, de sorte qu’on
doit toujours empiler un registre de 16 bits ou un registre de
32 bits.

mov eax,0100h
Mémoire Mémoire
0 push eax 0

ESP
00
01
00
00
ESP

 

– De la même façpn 0100h sur 32 bits est :


– 00 00 01 00h.
– Il en va de même pour les opérandes mémoire.
Ainsi, si x est une donnée de 8 bits, on fera :

Mov ax, byte ptr x


Mémoire
push ax Mémoire
0 0

ESP
03
00
ESP

 

– Mov ax,x n’est pas accépté car x est de 8 bits alors


que ax est de 16 bits.
– On a pris x = 00 03h par exemple.
– L'instruction pop a l'effet contraire :

Mémoire pop bx Mémoire


0 0
[bx] = 5678
ESP
78 78
56 56
ESP
34 34
12 12

 

pop tient compte de la taille de la destination,


mais dépile toujours un nombre pair d’octets.
pop bl serait illégal.
– Les instructions pusha empilent les huit registres dans
l’ordre AX, CX, DX, BX, SP, BP, SI, DI.
– pusha empile toujours les registres de 16 bits donc 16
octets.
– pushad empile les registres de 32 bits, donc 32 octets.
– Les instructions popa restaurent les registres à partir de la
pile dans l ’ordre DI, SI, BP, SP, BX, DX, CX, AX.
– Les instructions pushf et pushfd empilent respectivment le
registre FLAGS ou le registre EFLAGS.
– Les instructions popf et popfd dépilent respectivement le
registre FLAGS ou le registre EFLAGS.
• 2) Sous-programmes (procédures qui sont l’équivalent des
fonctions en langages évolués))

– L'architecture Intel dispose d'instructions pour l'appel de


sous-programmes et pour le retour de sous-programmes.

– L'instruction call pose l’adresse de l’instruction suivante


dans la pile et saute à l’adresse spécifiée par l’opérande. Sa
syntaxe est la suivante :
• call etiquette

– Où etiquette est l’adresse du sous-programme (voir tp procedure).


– L'instruction ret dépile l’adresse de retour
au sommet de la pile, la place dans EIP et
saute à cette adresse. Sa syntaxe est la
suivante : ret

– Passage des paramètres aux sous-programmes
– Passage par valeur
– La valeur numérique du paramètre est passée au sous-
programme.

– Le sous-programme ne peut pas modifier le paramètre


car il n’est pas en mémoire.

– Les données de 8, 16 et 32 bits (64 bits en virgule


flottante) sont passées par valeur.
– Passage des paramètres aux sous-programmes

– Passage par adresse


– C’est l’adresse du paramètre qui est passée au sous-program-me.
– Le sous-programme connaît l’adresse mémoire du paramètre et
peut en principe le modifier.
– Passage des paramètres aux sous-programmes
– Passage par registres
– On dispose des six registres eax, ebx, ecx, edx, edi et
esi pour le passage des paramètres.
– Cette méthode est la plus rapide car elle n’utilise pas la
mémoire.
– exemple : mov ebx, param1
– mov ecx, param2
– call sous-programme
– Le sous-programme se termine simplement par ret.
– Passage des paramètres aux sous-programmes
– Passage par la pile

– Lors d'un passage de parametres par la pile, le


programme appelant empile d'abord les
paramètres. Il exécute ensuite l'instruction call, qui
empile l'adresse de retour. Au moment d'entrer
dans le sous-programme, la pile a donc l'allure
suivante :
– Passage des paramètres aux sous-programmes
– Passage par la pile

ESP après CALL


@_retour
CALL ESP avant CALL
param2
param1
ESP initial


– Passage des paramètres aux sous-programmes (Fonction)
– Passage par la pile
– Soit le sous-programme Fonction(a, b, c). Ce sous-programme
est appelé comme suit :

– push a ESP
– push b APRES CALL @_retour ESP
c APRES RET
– push c b
– call Fonction a

– a, b et c sont les parametres du sous-programme Fonction.


• Passage des paramètres aux sous-programmes
– Passage par la pile
– À l'intérieur du sous-programme, on peut accèder
aux paramètres en utilisant leur position par
rapport à esp. Dans l'exemple ci-dessous, on
accède au paramètre a avec l’instruction :
– mov eax, [esp+4] ; eax = a

esp dans
sous-programme &retour esp avant call
c et après ret
b
a
Explication de esp + 4
• 4 veut dire 4 octets;
• a, b et c ont 1 octet chacun;
• @_retour = 2 octets;
• Pour aller de esp à a on fait :
• esp + 2 (@_retour) + 1 (c) + 1 (b);
• Donc on aura esp + 4.
• 3) Blocs de pile

– La méthode que nous venons de voir consistant à adresser les


paramètres par rapport au pointeur de pile espn’est pas
professionnelle. En effet, le sous-programme doit habituellement
empiler les registres qu'il utilise (procédure propre : voir tp
procédure). On doit donc tenir compte du nombre de registres
sauvegardés dans la pile pour déterminer l'adresse des paramètres.
Si, par la suite, on change ce nombre, il faut changer tous les offsets
des paramètres.

– De plus, on souhaite disposer d’une façon élégante de faire de


l’allocation dynamique pour les variables locales du sous-programme.
– On atteint ces objectifs en créant pour le sous-programme un bloc de pile (stack frame :
cadre de pile).
• Pour cela on utilisera ebp qui contient l’adresse de la base de la pile

• Sous_programmeproc
• push ebp ; sauvegarde de ebp
• mov ebp,esp ; copie esp dans ebp
• push registre_1 ; on empile n registres
• ...
• push registre_n
• sub esp, 4n ; n variables locales
• …
• d’autres instructions du sous-programme
• …
• add esp,4 n ;on libére l’espace des n variables locales

• pop registre_n ; on dépile les n registres


• ...
• pop registre_1
• pop ebp ; on dépile l'ancien ebp
• ret
• Sous_programmeendp
• 3) Blocs de pile

De cette façon, 0
ebp fournit un
ESP après sub esp,4n
point fixe par 4n octets
pour
rapport auquel on variables
peut adresser les locales
esp après push registres
paramètres. On registres
ebp après
adresse les mov ebp, esp ebp
esp après push ebp
esp après call
variables locales @_retour
esp avant call
par rapport au param2
param1
pointeur de pile esp initial

esp (+) ou par 


rapport à ebp (-).
• 3) Blocs de pile
• Accès aux paramètres

• mov ebx,[ebp+8] ; charge param2 0

• mov cx,[ebp+12] ; charge param1 esp


4n octets
• … pour
• Stockage dans une variable locale variables
locales

• mov dword ptr [esp], eax registres

• mov word ptr [esp+4], ax ebp


ebp
@_retour
• ou encore : param2

• mov dword ptr [ebp - 24], eax param1


• 3) Blocs de pile
• Accès aux paramètres

• Notre assembleur permet d’appeler les


0
paramètres par leur nom. Ainsi, dans l’exemple
ci-contre, soit la déclaration de fonction suivante: esp
4n octets
• maFonction proc pour
• x: DWORD variables
locales
• a: WORD
• on peut référer à a et à x comme suit : registres
ebp
ebp
• mov cx, a @_retour
• mov esi, x x
a


• 3) Blocs de pile
• Accès aux variables locales
• Dans la séquence d’instruction suivante, on déclare deux
variables locales i et j. La figure indique où elles sont placées et
le code indique comment on accède à i :

–Procedure proc
– LOCAL i: WORD
esp
– LOCAL j: DWORD i
j
• mov word ptr [ebp-6], 3 ; i = 3 ebp
ebp
• … @_retour
• ...
• Procedure endp
• 3) Blocs de pile
• Accès aux variables locales
• On peut référer à i et j par rapport à esp au lieu de ebp :
–sousProgramme proc
– LOCAL i: WORD
– LOCAL j: DWORD
• mov word ptr [esp], 3 ;i=3 esp
i
• mov dword ptr [esp+2], 4 ; j = 4 j
ebp
• … ebp
@_retour
• ...
• sousProgramme endp
• 3) Blocs de pile
• Accès aux variables locales
• On peut référer à i et j par nom. L’assembleur effectue la
traduction par rapport à ebp ou esp.
–sousProgramme proc
– LOCAL i: WORD
– LOCAL j: DWORD
• mov i, 3 ; i = 3 i
esp

• mov j, 4 ; j = 4 ebp
j

• … ebp
@_retour
• ...
• sousProgramme endp

Vous aimerez peut-être aussi