PDA

Voir la version complète : Aidez moi à comprendre la stack



julian
13/09/2007, 22h09
Yop,

Votre mission, si vous l'acceptez, c'est de me faire comprendre le fonctionnement de la stack. J'ai commencé le C il y a peu, et j'aimerais comprendre plus le déroulement du programme, la gestion des routines et tout le bordel. J'ai lu quelques tutos, mais j'avoue ne pas y comprendre grand chose (n'ayant que de vagues notions d'asm).. un coup on me parle d'adresses haute, un autre d'adresse basse... que la pile grandit par le bas.. j'ai entendu parler d'esi, d'esp, d'eip.. J'ai juste compris que l'eip contient l'adresse de la prochaine instruction qui va être executée.. mais c'est tout.

Voilà, expliquez moi la pile comme vous l'expliqueriez à un gamin de 12 ans. Avec des schémas, les descriptions de chaque étape et tout.

D'avance merci, parce que ça va bien me dépanner.

DaP
13/09/2007, 22h59
Bah c'est une zone de données comme une autre, à part qu'on s'en sert pour "entasser" les données (il y a des instructions pour ça). Par exemple tu dois utiliser un registre pour faire un certain truc mais il contient une valeur que tu ne peux pas perdre, alors tu le sauvegardes sur la pile avec l'instruction PUSH et tu le ressors après avec POP.
Le pointeur de pile (registre SP, ESP, ou RSP si c'est un processeur 16, 32 ou 64 bits) est égal à l'adresse de la prochaine instruction qui sera dépilée (avec POP). Au départ elle est maximale, puis elle diminue au fur et à mesure que tu empiles jusqu'à atteindre zéro quand elle est pleine. En tout cas c'est comme ça en mode réel (avant le 286), peut-être qu'en mode protégé c'est plus compliqué.
Les variables locales du C sont stockées sur la pile. C'est pratique parce que ça permet d'utiliser des fonctions récursives (chaque appel à la fonction va entasser des nouvelles données sur la pile, donc chaque fonction aura ses données séparées) et ça facilite la mise en cache des données parce qu'on réutilise souvent le même espace d'adressage.
Après si tu veux savoir plus de détails comme ça il va falloir te remettre à l'assembleur. ;) Lis ça au 6.2 si tu veux plus de détails : http://www.intel.com/design/processor/manuals/253665.pdf

julian
14/09/2007, 07h10
peut-être qu'en mode protégé c'est plus compliqué.Parce que là c'est sensé être simple ? :ninja:

En fait ce que j'aimerais savoir, c'est :

1) que fait chaque élément de la pile (avec un exemple concret et des explications très simples (genre à la siteduzero).

2) savoir si on retrouve toujours ces même éléments dans chaque différente pile

3) est-ce que deux piles (donc de deux programmes différents) peuvent interagir ensemble ?

DaP
14/09/2007, 11h19
2) savoir si on retrouve toujours ces même éléments dans chaque différente pile
Quand on appelle une fonction, on tape les arguments sur la pile, l'adresse de la prochaine instruction, puis on entre dans le code de la fonction. Là on sauvegarde certains registres qui ont une valeur importante, on réserve de la place sur la pile pour les variables locales et on entre dans le code de la fonction proprement dite. Puis on enlève tout ce qu'on avait mis dessus, on retourne au programme appelant grâce à l'adresse qui avait été mise et on enlève les arguments. Il y a aussi moyen de sauvegarder des pointeurs de pile pour faire des fonctions imbriquées mais je ne m'en suis pas encore servi et on ne les utilise jamais en C.
Et à part ça on peut utiliser la pile pour sauvegarder n'importe quel truc.
Il y a aussi des variantes du genre passer les paramètres par les registres si c'est possible et que le compilateur est un peu malin (sinon il faut lui dire à chaque fois qu'il doit le faire).


3) est-ce que deux piles (donc de deux programmes différents) peuvent interagir ensemble ?
En mode réel ça n'a pas se sens puisque c'est monotâche. De toute façon les piles ne servent qu'à contenir des données a priori, si tu t'en sers pour exécuter du code ça doit être pour faire des trucs pas très catholiques (et puis il faut voir si c'est possible, c'est pas gagné d'avance à mon avis). ;)
Tu peux toujours faire communiquer deux de tes programmes avec les méthodes classiques (fichier, message, pipe, ...) pour leur dire de foutre tel machin sur leur pile mais je ne sais pas si il y a quelque chose de plus automatique.
Tu veux t'essayer au hacking, chipoter avec les adresses de retour tout ça ? :ninja:

Daeke
14/09/2007, 11h47
...
J'ai l'impression que tu ne t'imagines pas correctement ce qu'est une pile.

Alors d'abord, muni toi de 3 boîtes d'allumettes, on va construire une pile (ca devrait te faire comprendre le coup des adresses hautes/basses).
D'abord, pose une première boîte. Poser une boîte correspond à l'action "push". Là si tu regardes le dessus de ta pile, tu vois la 1ère boîte d'allumettes.
Maintenant, ajoute une autre boîte par dessus (dans le même sens). Si tu regardes le dessus de ta pile, tu ne vois plus que la 2ème boîte d'allumettes.
Enfin, ajoute la dernière boîte d'allumettes tout en haut. Si tu regardes le sommet de ta pile (le "top"), tu ne vois que la 3ème boîte d'allumettes.
Donc à ce point là, tu as une pile de boîtes d'allumettes. Au sommet tu as la dernière boîte que tu as posé et tout en bas tu as la première boite. Si tu veux voir le haut de la 2ème boîte, tu es obligé d'enlever la boîte qui est au dessus (= action "pop") et si tu veux voir le haut de la 1ère boîte, tu dois enlever les 2 boîtes qui sont au dessus.

Donc voilà, en gros une pile c'est ça. Tu poses des valeurs dessus et si tu ne peux lire que la dernière valeur stockée (celle qui est tout en haut).

jeanba
14/09/2007, 11h50
Faites gaffe, kernel32 il est souvent planqué dans une pile :ninja: