Сборка х86 - Инструкция по "уходу"

Говорят, что инструкция "отпуск" похожа на:

movl %ebp, %esp
popl %ebp

Я понимаю movl %ebp, %esp часть, и что это действует, чтобы выпустить сохраненную память (как обсуждено в этом вопросе).

Но какова цель popl %ebp код?

2 ответа

LEAVE является аналогом ENTER, ENTER инструкция устанавливает кадр стека, сначала нажав EBP в стек, а затем копирует ESP в EBP, так LEAVE должен сделать наоборот, т.е. EBP в ESP а затем восстановить старое EBP из стека.

Если вы хотите узнать больше о том, как это сделать, обратитесь к разделу " ПРОЦЕДУРА ВЫЗЫВАЕТ БЛОКСТРУКТУРИРОВАННЫЕ ЯЗЫКИ" в Руководстве разработчика программного обеспечения Intel, том 1. ENTER а также LEAVE Работа.


enter n,0 в точности эквивалентно (и должно быть заменено на)

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 в точности эквивалентно

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

enter очень медленно и компиляторы не используют его, но leave Это хорошо. ( http://agner.org/optimize). Компиляторы используют leave если они вообще создают кадр стека (по крайней мере, это делает gcc). Но если esp уже равен ebp наиболее эффективно просто pop ebp,

popl инструкция восстанавливает базовый указатель, а movl Инструкция восстанавливает указатель стека. Базовый указатель является нижней частью стека, а указатель стека является верхней. Перед инструкцией выхода стек выглядит так:

----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)

После movl %ebp %esp, который освобождает стек вызываемого, стек выглядит так:

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

После popl %ebp, который восстанавливает стек вызывающей стороны, стек выглядит так:

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

enter Инструкция сохраняет нижнюю часть стека вызывающего и устанавливает базовый указатель, чтобы вызываемый мог выделить свой стек.

Также обратите внимание, что, хотя большинство компиляторов C выделяют стек таким образом (по крайней мере, с выключенной оптимизацией), если вы пишете функцию на языке ассемблера, вы можете просто использовать тот же самый кадр стека, если хотите, но вы должны обязательно pop все из стека, что вы push на этом или вы будете переходить на нежелательный адрес, когда вы вернетесь (это потому, что call <somewhere> средства push <ret address>[или же push %eip], jmp <somewhere>, а также ret означает переход на адрес в верхней части стека [или pop %eip]. %eip регистр, который содержит адрес текущей инструкции).

Другие вопросы по тегам