Programmation Assembleur/x86/La pile
La pile est une zone de mémoire permettant de stocker et retrouver rapidement des valeurs pour :
- Placer des variables locales dans un sous-programme,
- Sauvegarder l'adresse de retour (fait par les instructions
CALL
,INT
), - Transmettre les arguments à un sous-programme.
Programmation Assembleur/x86 |
Modifier ce modèle |
Fonctionnement
modifierUne pile fonctionne à la manière d'une pile d'objets réels :
- Il est possible d'ajouter une valeur au sommet de la pile (empiler),
- Il est possible de retirer la valeur située au sommet de la pile (dépiler).
Exemple : soit une pile initialement vide
Empiler A : Pile A Sommet = 1 ^ Index : 1 2 3 4 Empiler B : Pile A B Sommet = 2 ^ Index : 1 2 3 4 Empiler A : Pile A B A Sommet = 3 ^ Index : 1 2 3 4 Dépiler (on obtient A) : Pile A B Sommet = 2 ^ Index : 1 2 3 4
Les registres
modifierDeux registres sont utilisés pour gérer la pile : SS
et SP
.
Ces deux registres forment le pointeur de pile qui pointe le sommet de la pile en mémoire.
- SS (Stack Segment)
- Donne le segment mémoire 16K utilisée par la pile.
- SP (Stack Pointer)
- Donne l'offset dans le segment de la pile du sommet.
Les instructions
modifierEmpiler
modifierL'instruction PUSH
permet d'empiler la valeur fournie en argument sur la pile. Plus précisément, cette instruction réalise les opérations suivantes :
- décrémenter SP du nombre d'octets occupés par la valeur spécifiée,
- copier la valeur spécifiée à l'emplacement mémoire pointé par
SS:SP
.
Exemple :
-- SP vaut FFEE PUSH AX -- SP vaut FFEC (- 2 octets occupés par AX)
La décrémentation peut paraître surprenante au premier abord. Ce mode de fonctionnement vient du fait que dans le modèle mémoire initial (utilisé par les premiers BIOS et MS-DOS) le tas et la pile se partagent le même segment : le tas partant des adresses basses, et la pile des adresses hautes. Ceci permet d'éviter une limite de tas ou de pile, tout en ayant une limite pour le tas + la pile.
Zone mémoire : [------ ------------] TAS → ← PILE
Le tas est la zone ou sont allouées les variables dynamiques. Dans ce modèle de mémoire, il faut donc faire un compromis entre la pile et le tas : ne pas allouer trop de mémoire sous peine de limiter la pile (récurrence des appels de sous-routines et variables dans la pile), ni allouer trop d'espace dans la pile si beaucoup d'espace mémoire est alloué.
L'instruction spéciale PUSHF
(Push Flags) n'a pas d'argument et empile la valeur du registre des indicateurs (EFLAGS
).
Il existe également l'instruction PUSHA
pour empiler la valeur de tous les registres (Push All).
Dépiler
modifierL'instruction POP est l'instruction utilisée pour dépiler une valeur dans le registre ou l'adresse mémoire spécifiée en argument. Cette instruction réalise les opérations suivantes :
- copier depuis l'emplacement mémoire pointé par
SS:SP
vers le registre spécifié un nombre d'octets égal à sa taille, - incrémenter SP du nombre d'octets copiés.
Exemple :
-- SP vaut FFEC POP BX -- SP vaut FFEE
L'instruction spéciale POPF
(Pop Flags) n'a pas d'argument explicite et dépile la valeur de la pile vers le registre des indicateurs (EFLAGS
).
Il existe également l'instruction POPA
pour dépiler la valeur de tous les registres (Pop All) sauvegardés auparavant par l'instruction PUSHA
(Push All).