编写Prolog和Epilog代码的注意事项

Microsoft 专用

在写入之前拥有 prolog 和 epilog 代码将序列,务必了解堆栈帧如何布局。应使用 __LOCAL_SIZE 符号也很有用。

堆栈帧格式

此示例演示可能出现在 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> 变量是表示在堆栈中保存的注册列表的占位符。在 drive 注册之后,可以在堆栈可以将其他适当的数据。下面是相应的 epilog 代码:

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

堆栈始终是增大拉 (从高到内存不足地址)。基本指针 (ebp) 指向 ebp的推入的值。本地区域开始在 ebp-4。访问局部变量,则通过减去为适当的值计算从 ebp 的偏移量从 ebp。

__LOCAL_SIZE

编译器提供了符号, __LOCAL_SIZE,用于一个内联汇编块 prolog 代码。此符号在分配局部变量的空间在自定义序言码的堆栈帧。

编译器确定 __LOCAL_SIZE的值。其值是总字节数任何用户定义的局部变量和编译器生成的临时变量。__LOCAL_SIZE 只能用作一个即时操作数;不能在表达式。不能更改或重新定义该符号的值。例如:

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

包含自定义 prolog 和 epilog 的 naked 函数下面的示例使用在序言排序顺序的 __LOCAL_SIZE 符号:

// the__local_size_symbol.cpp
// processor: x86
__declspec ( naked ) int main() {
   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
      }
}

请参见

参考

裸函数调用