Поделиться через


Вопросы, связанные с написанием кода пролога и эпилога

Блок, относящийся только к системам Майкрософт

Прежде чем писать собственные последовательности кода пролога и эпилога, важно понять, как выложен кадр стека. Также полезно знать, как использовать предопределенную константу __LOCAL_SIZE .

Макет кадра CStack

В данном примере показан стандартный код пролога, который может присутствовать в 32-разрядной функции.

push     ebp                 ; Save ebp
mov      ebp, esp            ; Set stack frame pointer
sub      esp, localbytes     ; Allocate space for locals
push     <registers>         ; Save registers

Переменная localbytes представляет число байтов, которые требуются в стеке для локальных переменных, а переменная registers — это заполнитель, представляющий список сохраняемых в стеке регистров. После проталкивания регистров можно разместить в стеке все другие необходимые данные. Ниже приведен соответствующий код эпилога.

pop      <registers>         ; Restore registers
mov      esp, ebp            ; Restore stack pointer
pop      ebp                 ; Restore ebp
ret                          ; Return from function

Стек всегда расширяется в направлении вниз (от старших адресов памяти к младшим). Указатель базы (ebp) указывает на помещенное в стек значение ebp. Область локальных переменных начинается с ebp-2. Для доступа к локальным переменным необходимо вычислить смещение от ebp путем вычитания соответствующего значения из ebp.

Константа __LOCAL_SIZE

Компилятор предоставляет константу __LOCAL_SIZE, которую можно использовать использования во встроенном ассемблерном блоке кода пролога функции. Она служит для выделения пространства локальным переменным в кадре стека пользовательского кода пролога.

Значение константы __LOCAL_SIZE определяется компилятором. Это значение представляет общее количество байтов всех определяемых пользователем локальных переменных и временных переменных, создаваемых компилятором. Константу __LOCAL_SIZE можно использовать только в качестве непосредственного операнда, но не в выражениях. Значение этой константы не следует изменять и переопределять. Например:

mov      eax, __LOCAL_SIZE           ;Immediate operand--Okay
mov      eax, [ebp - __LOCAL_SIZE]   ;Error

В следующем примере функции naked с пользовательскими последовательностями пролога и эпилога константа __LOCAL_SIZE используется в последовательности пролога.

__declspec ( naked ) func()
{
   int i;
   int j;

   __asm      /* prolog */
      {
      push   ebp
      mov      ebp, esp
      sub      esp, __LOCAL_SIZE
      }

   /* Function body */

   __asm      /* epilog */
      {
      mov      esp, ebp
      pop      ebp
      ret
      }
}

Завершение блока, относящегося только к системам Майкрософт

См. также

Функции naked