web-dev-qa-db-fra.com

Assemblage x86 - Instruction "laisser"

On dit que l'instruction "congé" est similaire à:

movl %ebp, %esp
popl %ebp

Je comprends le movl %ebp, %esp part, et qu'il agit pour libérer de la mémoire stockée (comme discuté dans cette question ).

Mais quel est le but du popl %ebp code?

15
alexswo

LEAVE est l'équivalent de ENTER. L'instruction ENTER configure un cadre de pile en poussant d'abord EBP sur la pile, puis copie ESP dans EBP, donc LEAVE a pour faire le contraire, c'est-à-dire copier EBP vers ESP puis restaurer l'ancien EBP à partir de la pile.

Voir la section nommée APPELS DE PROCÉDURE POUR LES LANGUES STRUCTURÉES EN BLOC dans Manuel du développeur du logiciel Intel Vol 1 si vous voulez en savoir plus sur la façon dont ENTER et LEAVE travail.


enter n,0 est exactement équivalent à (et doit être remplacé par)

Push  %ebp
mov   %esp, %ebp     # ebp = esp,  mov  ebp,esp in Intel syntax
sub   $n, %esp       # allocate space on the stack.  Omit if n=0

leave est exactement équivalent à

mov   %ebp, %esp     # esp = ebp,  mov  esp,ebp in Intel syntax
pop   %ebp

enter est très lent et les compilateurs ne l'utilisent pas, mais leave est très bien. ( http://agner.org/optimize ). Les compilateurs utilisent leave s'ils créent un cadre de pile (du moins gcc le fait). Mais si esp est déjà égal à ebp, il est plus efficace de simplement pop ebp.

31
Michael

L'instruction popl restaure le pointeur de base et l'instruction movl restaure le pointeur de pile. Le pointeur de base est le bas de la pile et le pointeur de la pile est le haut. Avant l'instruction de congé, la pile ressemble à ceci:

----Bottom of Caller's stack----
...
Caller's
Variables
...
Function Parameters
----Top of Caller's Stack/Bottom of Callee's stack----   (%ebp)
...
Callee's
Variables
...
---Bottom of Callee's stack----    (%esp)

Après le movl %ebp %esp, qui désalloue la pile de l'appelé, la pile ressemble à ceci:

----Bottom of Caller's stack----
...
Caller's
Variables
...
Function Parameters
----Top of Caller's Stack/Bottom of Callee's stack----   (%ebp) and (%esp)

Après le popl %ebp, qui restaure la pile de l'appelant, la pile ressemble à ceci:

----Bottom of Caller's stack----    (%ebp)
...
Caller's
Variables
...
Function Parameters
----Top of Caller's Stack----   (%esp)

L'instruction enter enregistre le bas de la pile de l'appelant et définit le pointeur de base afin que l'appelé puisse allouer sa pile.

Notez également que, si la plupart des compilateurs C allouent la pile de cette façon (au moins avec l'optimisation désactivée), si vous écrivez une fonction de langage d'assemblage, vous pouvez simplement utiliser le même cadre de pile si vous le souhaitez, mais vous devez assurez-vous de pop tout ce qui se trouve sur la pile que vous Push dessus, sinon vous passerez à une adresse indésirable à votre retour (c'est parce que call <somewhere> veux dire Push <ret address>[ou Push %eip], jmp <somewhere> et ret signifie sauter à l'adresse en haut de la pile [ou pop %eip]. %eip est le registre qui contient l'adresse de l'instruction en cours).

2
Justin C. B.