Programmation Assembleur/x86/La pile

Un livre de Wikilivres.
Sauter à la navigation Sauter à la recherche
Programmation Assembleur x86

Modifier ce modèle


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.

Fonctionnement[modifier | modifier le wikicode]

Une 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[modifier | modifier le wikicode]

Deux 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.

Les instructions[modifier | modifier le wikicode]

Empiler[modifier | modifier le wikicode]

L'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 partage 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 : [xxxxxx        xxxxxxxxxxxx]
                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 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.

Dépiler[modifier | modifier le wikicode]

L'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 n'a pas d'argument 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 sauvegardés auparavant par l'instruction PUSHA.