编写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
}
}