На самом деле, это именно то, что делает инструкция leave
, и она была введена для поддержки языков высокого уровня.Тем не менее, он используется не очень часто;большинство компиляторов просто делают явную последовательность mov esp, ebp; pop ebp
.См. Также этот вопрос .
Однако иногда вы можете выполнить оптимизацию «опустить указатель кадра».Это освобождает EBP для использования в качестве регистра общего назначения, но вы (или компилятор) должны отслеживать изменения ESP в течение всей функции и использовать возможные изменения смещения для адресации локальных переменных или входящих аргументов.Если вы сделаете это, вам придется использовать pops или явное добавление, чтобы восстановить ESP до его первоначального значения перед возвратом.
Обратите внимание, что вышесказанное касается всей функции (то есть prolog / epilog);когда вам нужно вызвать определенную функцию __cdecl
в середине функции, вы не можете просто восстановить ESP до значения EBP, потому что это значение действительно только в самом начале функции, до любогоместо выделено для локальных переменных.Здесь есть два подхода:
1) push-аргументы, восстановить ESP после вызова:
push offset msg
call _printf
pop ecx ; clobbers ECX but shorter than add esp, 4
2) переместить аргументы в зарезервированные слоты стека;вам не нужно восстанавливать ESP в этом случае:
mov dword ptr [esp+0], offset msg
call _printf
; no need to change ESP
Если вы выберете второй вариант, вам нужно убедиться, что вы не храните локальные переменные в этих слотах.Кроме того, такие mov
инструкции обычно намного длиннее, чем нажатия, поэтому вам может потребоваться учитывать это, если размер кода является проблемой.