Question

J'ai créé ce code d'assemblage simple et inutile (Y86) pour voir si je comprends tout ce qui se passe dans la pile lorsque les instructions call, pushl, popl et ret sont utilisées.

Comme je l'ai dit, ce code est inutile, il sert uniquement à des fins de test / d'apprentissage. Bien que toutes les adresses de la mémoire aient été correctement calculées (espoir) et ne sont pas aléatoires.

Le code d'assemblage est le suivant:

     | .pos 0
0x00 |   irmovl Stack, %esp
0x06 |   rrmovl %esp, %ebp
0x08 |   irmovl $5, %eax
0x0E |   call func
0x13 |   halt
0x14 | func:
0x14 |   pushl %ebp
0x16 |   rrmovl %esp, %ebp
0x18 |   pushl %eax
0x1A |   popl %eax
0x1C |   popl %ebp
0x1E |   ret
     | .pos 50
0x32 | Stack: .long 0

Ce qui suit est préférable pour dessiner une pile et expliquer ce que chaque étape (instruction) fait de la pile. Veuillez noter que j’ai utilisé SP et BP pour désigner respectivement% esp et% ebp, car ils sont beaucoup utilisés et facilitent la lecture.

Ce que je veux savoir, c’est si j’ai tout bien compris ou si j’ai manqué quelque chose. N'hésitez pas à copier / coller ce que vous voulez et à corriger certaines étapes de votre réponse.

Notez également que ma compréhension de ce point est très importante. J'ai un examen lundi pour lequel je dois être préparé et j'aimerais connaître la meilleure réponse que vous puissiez me donner. En fonction de vos réponses, je pourrais (ou non) poser des questions connexes que nous examinerons dans la section des commentaires.

- INSTRUCTION: irmovl Stack, %esp
- INSTRUCTION: rrmovl %esp, %ebp
  1) Point %esp (SP) and %ebp (BP) to Stack

     |  ...  |
0x2E |-------|
     |       |
0x32 |-------| <--- SP & BP

- INSTRUCTION: irmovl $5, %eax
  1) Sets %eax = 5

- INSTRUCTION: call func
  1) Decrements SP by 4 (0x32 -> 0x2E)
  2) Saves return address (0x13) in memory location pointed by SP (0x2E)
  3) Jumps to "func" memory address (0x14)

     |  ...  |
0x2A |-------|
     | 0x13  |
0x2E |-------| <--- SP
     |       |
0x32 |-------| <--- BP

- INSTRUCTION: pushl %ebp
  1) Decrements SP by 4 (0x2E -> 0x2A)
  2) Saves BP value (0x32) in memory location pointed by SP (0x2A)

     |  ...  |
0x26 |-------|
     | 0x32  |
0x2A |-------| <--- SP
     | 0x13  |
0x2E |-------|
     |       |
0x32 |-------| <--- BP

- INSTRUCTION: rrmovl %esp, %ebp
  1) Sets BP = SP (0x32 -> 0x2A)

     |  ...  |
0x26 |-------|
     | 0x32  |
0x2A |-------| <--- SP & BP
     | 0x13  |
0x2E |-------|
     |       |
0x32 |-------|

- INSTRUCTION: pushl %eax
  1) Decrements SP by 4 (0x2A -> 0x26)
  2) Saves %eax value (5) in memory location pointed by SP (0x26)

     |  ...  |
0x22 |-------|
     |   5   |
0x26 |-------| <--- SP
     | 0x32  |
0x2A |-------| <--- BP
     | 0x13  |
0x2E |-------|
     |       |
0x32 |-------|

- INSTRUCTION: popl %eax
  1) Saves value (5) in memory location pointed by SP (0x26) in %eax
  2) Increments SP by 4 (0x26 -> 0x2A)

     |  ...  |
0x22 |-------|
     |   5   |
0x26 |-------|
     | 0x32  |
0x2A |-------| <--- SP & BP
     | 0x13  |
0x2E |-------|
     |       |
0x32 |-------|

- INSTRUCTION: popl %ebp
  1) Saves value (0x32) in memory location pointed by SP (0x2A) in %ebp
  2) Increments SP by 4 (0x2A -> 0x2E)

     |  ...  |
0x22 |-------|
     |   5   |
0x26 |-------|
     | 0x32  |
0x2A |-------|
     | 0x13  |
0x2E |-------| <--- SP
     |       |
0x32 |-------| <--- BP

- INSTRUCTION: ret
  1) Jumps to memory address (0x13) in memory location pointed by SP (0x2E)
  2) Increments SP by 4 (0x2E -> 0x32)
Était-ce utile?

La solution

Autant que je sache, tout va bien.

Un point mineur que je peux dire, c'est qu'il est probablement plus intuitif d'écrire les adresses au-dessus de la valeur à ces adresses. C'est-à-dire:

0x2E |-------|
     | 0x13  |
0x32 |-------|

La raison en est que la plage d'adresses couvrant la valeur ( 0x2E , 0x2F , 0x30 , 0x31 ) va vers la prochaine adresse 0x32 .

Bien sûr, vous pouvez utiliser la notation attendue par votre enseignant lors de l'examen.

Autres conseils

Vous avez raison.

Vous exercez un appel de fonction à l'aide de conventions standard d'appelant, en créant un cadre pour l'appelé. Vous effectuez ensuite une simple pression sur un registre avant de revenir à l'appelant. C'est tout à fait correct et votre compréhension est correcte (voir http: //y86tutoring.wordpress .com / 2012/10/31 / Fonctionnement-piles / pour plus de détails)

Tout va bien. La seule suggestion est qu'il n'est pas nécessaire de définir un mot 0x0000 sur la pile. Définir simplement l'étiquette de pile l'aurait fait.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top