本文主要介绍stack中的EBP、ESP寄存器以及enterleavecall、和ret这四个指令。
本文多数内容转载自:对寄存器ESP和EBP的一些理解

1. 基本概念

1.1 structure


push时,地址减小;pop时,地址增大。

1.2 Stack-Frame

The stack is typically divided into frames. Each stack frame can then contain local variables, parameters to be passed to another procedure, and procedure linking information.

1.3 EBP and ESP

In x86 architecure, register EBP means base pointer which always pointing to the base address of a stack frame. And register ESP means stack pointer which always pointing to the top of the stack frame. EIP as a program counter, storing the address of next instruction should be executed.

ESP has a special function, which is to act as the stack pointer, and it gets implicitly modified by certain instructions (e.g. push, pop, call).

2. example

下面是caller调用函数test(int p1,int p2)的汇编代码
假设caller前堆栈指针ESP为0xAAAAAAA ;EBP为0xAAAAAB0.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
push   p2    ;参数2入栈,ESP-=4h,ESP=0xAAAAAA6
push   p1    ;参数1入栈,ESP-=4h,ESP=0xAAAAAA2
call test    ;压入caller的EIP,ESP-=4h,ESP=0xAAAAA9E
;//进入函数内
{
push   ebp                        ;保存caller的EBP指针,EBP入栈(即0xAAAAAB0入栈),ESP-=4h,ESP=0xAAAAA9A
mov    ebp, esp                   ;设置EBP指针指向栈顶,EBP=0xAAAAA9A
mov    eax, dword ptr  [ebp+0ch]  ;ebp+0ch为0xAAAAAA6即参数2的位置
mov    ebx, dword ptr  [ebp+08h]  ;ebp+08h为0xAAAAAA2,即参数1的位置
sub    esp, 8                     ;局部变量所占空间ESP-=8h,ESP=0xAAAAA92
...
add    esp, 8                     ;释放局部变量,ESP+=8h,ESP=0xAAAAA9A
pop    ebp                        ;出栈,恢复EBP,ESP+=4h,ESP=0xAAAAA9E,EBP=0xAAAAAB0
ret    8                          ;ret返回,弹出EIP,ESP+=4h,ESP=0xAAAAAA2
add    esp, 8 ;ESP+=8h,ESP=0xAAAAAAA,恢复caller进入test函数前的堆栈.
}

3. enterleavecall、和ret

In AT&T x86 assembly, there’re four instructions: call, ret, enter and leave participated in function call.

call and ret equal to the following logics respectively:

1
2
3
4
5
6
CALL: push %eip		#store the return address on stack frame
mov f, %eip #reset the value of EIP for safety
jmp LABEL #jump to subroutine

RET: pop %eip #restore the return address to EIP
jmp %eip #jump back to where the subroutine call ends

enter and leave equal to the following instructions respectively:

1
2
3
4
5
ENTER: push %ebp	#store the old EBP
mov %esp, %ebp #set new EBP pointing to current ESP

LEAVE: mov %ebp, %esp #set ESP pointing to current EBP (return to the point before function call happened)
pop %ebp #restore the old EBP


参考资料:

  1. sdm vol1 Chapter6
  2. 对寄存器ESP和EBP的一些理解
  3. Function Call with register EBP and ESP in x86