92 votes

Comment fonctionne la pile en langage assembleur ?

J'essaie actuellement de comprendre le fonctionnement de la pile, j'ai donc décidé d'apprendre par moi-même quelques langage assembleur j'utilise ce livre :

http://savannah.nongnu.org/projects/pgubook/

J'utilise Gaz et je fais mon développement sur Linux Mint .

Je suis un peu confus par quelque chose :

Pour autant que je sache, une pile est simplement une structure de données. J'ai donc supposé que si je codais en assembleur, je devais implémenter la pile moi-même. Cependant, cela ne semble pas être le cas, car il existe des commandes telles que

pushl
popl

Ainsi, lors du codage en assembleur pour le x86 et en utilisant la syntaxe Gas : la pile est-elle simplement une structure de données déjà implémentée ? Ou est-elle réellement implémentée au niveau du matériel ? Ou bien est-ce quelque chose d'autre ? De plus, la plupart des langages d'assemblage pour d'autres jeux de puces ont-ils déjà implémenté la pile ?

Je sais que c'est une question un peu stupide, mais je suis en fait assez confus à ce sujet.

3 votes

La plupart de ces réponses parlent de la pile telle qu'elle est utilisée par les langages, en particulier ils parlent de passer des arguments sur la pile. Dans de nombreux processeurs, cela ne sert qu'à faciliter l'implémentation des langages. Si vous codiez manuellement en assembleur, vous passiez généralement les paramètres aux fonctions dans des registres (du moins avant que le processeur ne soit optimisé pour les opérations sur la pile, car les langages l'utilisaient beaucoup). La pile sert principalement à maintenir l'ordre des appels/retours, de même qu'une interruption (qui doit sauvegarder l'état du processeur) pousse les valeurs existantes dans les registres qu'elle utilisera et les retire avant de revenir.

92voto

PintSizedCat Points 4221

Je pense principalement que vous confondez entre une program's stack et any old stack .

A Stack

Est une structure de données abstraite qui consiste en des informations dans un système de type "Last In First Out". Vous placez des objets arbitraires sur la pile et vous les enlevez ensuite, un peu comme un plateau d'entrée/sortie, l'élément du haut est toujours celui qui est enlevé et vous mettez toujours l'élément du haut.

Une pile de programmes

Une pile, c'est une section de la mémoire qui est utilisée pendant l'exécution, elle a généralement une taille statique par programme et est fréquemment utilisée pour stocker les paramètres des fonctions. Vous poussez les paramètres sur la pile lorsque vous appelez une fonction et la fonction adresse directement la pile ou extrait les variables de la pile.

Une pile de programmes n'est généralement pas matérielle (bien qu'elle soit conservée en mémoire et qu'elle puisse donc être considérée comme telle), mais le pointeur de pile qui indique une zone actuelle de la pile est généralement un registre du CPU. Cela la rend un peu plus flexible qu'une pile LIFO car vous pouvez changer le point auquel la pile s'adresse.

Vous devez lire et vous assurer que vous comprenez le wikipedia car il donne une bonne description de la pile matérielle, qui est ce à quoi vous avez affaire.

Il existe également ce tutoriel qui explique la pile en termes d'anciens registres à 16 bits, mais qui pourrait être utile et un autre spécifiquement sur la pile.

De Nils Pipenbrinck :

Il convient de noter que certains processeurs n'implémentent pas toutes les instructions d'accès et de manipulation de la pile (push, pop, pointeur de pile, etc.), mais le x86 le fait en raison de sa fréquence d'utilisation. Dans ces situations, si vous voulez une pile, vous devez l'implémenter vous-même (certains processeurs MIPS et ARM sont créés sans pile).

Par exemple, dans les MIPs, une instruction de poussée serait mise en œuvre comme suit :

addi $sp, $sp, -4  # Decrement stack pointer by 4  
sw   $t0, ($sp)   # Save $t0 to stack  

et une instruction Pop ressemblerait à :

lw   $t0, ($sp)   # Copy from stack to $t0  
addi $sp, $sp, 4   # Increment stack pointer by 4

3 votes

Entre-temps, le x86 dispose de ces instructions de pile spéciales parce que pousser et sortir des choses de la pile se produit si souvent que c'était une bonne idée d'utiliser un opcode court pour cela (moins d'espace de code). Les architectures telles que MIPS et ARM ne disposent pas de ces instructions, vous devez donc implémenter la pile vous-même.

4 votes

N'oubliez pas que votre tout nouveau processeur est, dans une certaine mesure, binairement compatible avec le 8086, qui était source-compatible avec le 8080, un développement du 8008, le premier microprocesseur. Certaines de ces décisions remontent à loin.

5 votes

En ARM, il existe des instructions uniques pour manipuler la pile, elles ne sont simplement pas si évidentes car elles sont appelées STMDB SP ! (pour PUSH) et LDMIA SP ! (pour POP).

7voto

Leaf Garland Points 2648

Pour ce qui est de savoir si la pile est implémentée dans le matériel, ceci Article de Wikipedia pourrait aider.

Certaines familles de processeurs, comme le x86, ont des instructions spéciales pour manipuler la pile de la du thread en cours d'exécution. D'autres familles de processeurs, dont le PowerPC et MIPS, n'ont pas de support explicite de la pile. mais s'appuient plutôt sur convention et la pile déléguée à l'interface binaire d'application (ABI) du système d'exploitation. l'interface binaire d'application (ABI) du système d'exploitation.

Cet article et les autres vers lesquels il renvoie peuvent être utiles pour se faire une idée de l'utilisation des piles dans les processeurs.

4voto

sharptooth Points 93379

Vous confondez une pile abstraite et la pile implémentée au niveau matériel. Cette dernière est déjà implémentée.

3voto

Mr. Shickadance Points 1660

Je pense que la réponse principale que vous cherchez a déjà été évoquée.

Lorsqu'un ordinateur x86 démarre, la pile n'est pas configurée. Le programmeur doit la configurer explicitement au moment du démarrage. Cependant, si vous êtes déjà dans un système d'exploitation, cela a été pris en charge. Vous trouverez ci-dessous un exemple de code d'un programme de démarrage simple.

Tout d'abord, les registres de segment de données et de pile sont définis, puis le pointeur de pile est défini 0x4000 au-delà.

    movw    $BOOT_SEGMENT, %ax
    movw    %ax, %ds
    movw    %ax, %ss
    movw    $0x4000, %ax
    movw    %ax, %sp

Après ce code, la pile peut être utilisée. Maintenant, je suis sûr que cela peut être fait de plusieurs façons différentes, mais je pense que cela devrait illustrer l'idée.

3voto

Alexander Points 1851

La pile n'est qu'une façon dont les programmes et les fonctions utilisent la mémoire.

La pile m'a toujours dérouté, alors j'ai fait une illustration :

The stack is like stalactites

( version svg ici )

  • Une poussée "attache une nouvelle stalactite au plafond".
  • Un pop "fait sauter une stalactite".

J'espère que c'est plus utile que déroutant.

N'hésitez pas à utiliser l'image SVG (sous licence CC0).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X