В программировании на языке ассемблера пролог функции представляет собой несколько строк кода в начале функции, которые подготавливают стек и регистры для использования внутри функции. Аналогично, эпилог функции появляется в конце функции и восстанавливает стек и регистры в состояние, в котором они находились до вызова функции.
Пролог и эпилог не являются частью самого языка ассемблера; они представляют собой соглашение, используемое программистами на языке ассемблера и компиляторами многих языков более высокого уровня . Они достаточно жесткие и имеют одинаковую форму в каждой функции.
Пролог и эпилог функций также иногда содержат код защиты от переполнения буфера .
Пролог функции обычно выполняет следующие действия, если архитектура имеет базовый указатель (также известный как указатель кадра) и указатель стека:
Можно написать несколько возможных прологов, что приведет к несколько иной конфигурации стека. Эти различия допустимы, если программист или компилятор правильно использует стек внутри функции.
В качестве примера, вот типичный пролог функции языка ассемблера x86 , созданный GCC .
push ebp mov ebp , esp sub esp , N
Непосредственное значение N — это количество байтов, зарезервированных в стеке для локального использования .
Того же результата можно добиться, используя enter
инструкцию:
введите Н , 0
Более сложные прологи можно получить, используя другие значения (кроме 0) для второго операнда инструкции enter
. Эти прологи помещают несколько указателей базы/фрейма, чтобы обеспечить вложенные функции , как того требуют такие языки, как Паскаль . Однако современные версии этих языков не используют эти инструкции, поскольку в некоторых случаях они ограничивают глубину вложенности. [ нужна цитата ]
Эпилог функции отменяет действия пролога функции и возвращает управление вызывающей функции. Обычно он выполняет следующие действия (эта процедура может отличаться от одной архитектуры к другой):
Данный эпилог отменяет эффекты любого из вышеупомянутых прологов (либо полного, либо того, в котором используется enter
). Согласно определенным соглашениям о вызовах, ответственность за очистку аргументов из стека лежит на вызываемом объекте, поэтому эпилог также может включать этап перемещения указателя стека вниз или вверх.
Например, эти три шага можно выполнить на 32-битном языке ассемблера x86 с помощью следующих инструкций:
mov esp , ebp pop ebp ret
Как и пролог, процессор x86 содержит встроенную инструкцию, выполняющую часть эпилога. Следующий код эквивалентен приведенному выше коду:
оставить в отставке
Инструкция leave
выполняет инструкции mov
и pop
, как описано выше.
Функция может содержать несколько эпилогов. Каждая точка выхода из функции должна либо перейти к общему эпилогу в конце, либо содержать собственный эпилог. Поэтому программисты или компиляторы часто используют комбинацию leave
и ret
для выхода из функции в любой момент. (Например, компилятор C заменяет return
оператор последовательностью leave
/ ret
).