先引一段权威描述:

引用:
ENTER指令是一条非常复杂的指令,它实际上完成了相当多条指令的工作。在内部,ENTER指令是用相当冗长的一段微码(microcode)实现的,这样会导致一些执行效率的问题。为此,大多数编译器好像都在避免使用ENTER指令,尽管它们都支持C和C++等
语言中使用嵌套代码。这些编译器在为例程安排局部堆栈布局时就简单地忽视代码块的存在,而将所有的局部变量存放在一个独立的内存区域中。
LEAVE是与ENTER指令配合使用的指令。LEAVE指令只是恢复ESP和EBP寄存器之前存储的值。因为LEAVE指令相对比较简单,许多编译器好像常在函数的尾声中使用该指令(尽管在函数的序言中不一定使用ENTER指令)。
以上是《Reversing:逆向工程揭密》一书的解释,有点拗口,我觉得,对于这对指令,可以结合一段C编译的程序看
这是一个空的main函数在debug模式编译的结果:
代码:
00401010  |> \55            push    ebp
00401011  |.  8BEC          mov     ebp, esp
00401013  |.  83EC 40       sub     esp, 40
00401016  |.  53            push    ebx
00401017  |.  56            push    esi
00401018  |.  57            push    edi
00401019  |.  8D7D C0       lea     edi, dword ptr [ebp-40]
0040101C  |.  B9 10000000   mov     ecx, 10
00401021  |.  B8 CCCCCCCC   mov     eax, CCCCCCCC
00401026  |.  F3:AB         rep     stos dword ptr es:[edi]
00401028  |.  5F            pop     edi
00401029  |.  5E            pop     esi
0040102A  |.  5B            pop     ebx
0040102B  |.  8BE5          mov     esp, ebp
0040102D  |.  5D            pop     ebp
0040102E  \.  C3            retn
可以看到,在retn返回前,函数做了mov esp,ebp pop ebp操作,虽然操作的是栈顶指针寄存器,但目的却是恢复进入函数体之前的esp与ebp的值
leave起的正是这个作用
引用:
leave指令的作用等同于
mov esp,ebp
pop ebp 
但效率较后者高
有一点很关键,是作用等同于,不是等于
以上代码就可以压缩为
代码:
00401010  |> \55            push    ebp
00401011  |.  8BEC          mov     ebp, esp
00401013  |.  83EC 40       sub     esp, 40
00401016  |.  53            push    ebx
00401017  |.  56            push    esi
00401018  |.  57            push    edi
00401019  |.  8D7D C0       lea     edi, dword ptr [ebp-40]
0040101C  |.  B9 10000000   mov     ecx, 10
00401021  |.  B8 CCCCCCCC   mov     eax, CCCCCCCC
00401026  |.  F3:AB         rep     stos dword ptr es:[edi]
00401028  |.  5F            pop     edi
00401029  |.  5E            pop     esi
0040102A  |.  5B            pop     ebx
                                       leave
0040102E  \.  C3            retn
enter是leave的对应操作(恩,好像反过来了,其实应该是先有enter的操作,再用leave对应),也是对应着esp与ebp的操作
mov esp,ebp pop ebp是用来恢复esp与ebp,而esp与ebp被改变的地方在
push    ebp mov     ebp, esp
代码:
00401010  |> \55            push    ebp
00401011  |.  8BEC          mov     ebp, esp
00401013  |.  83EC 40       sub     esp, 40
对应的enter则是enter 40,0,比leave多了一个对esp的sub操作
归纳为
引用:
enter X,0功能等同于
push    ebp
mov     ebp, esp
sub     esp, X
上述代码可进一步压缩为
代码:
                                      enter 40,0
00401016  |.  53            push    ebx
00401017  |.  56            push    esi
00401018  |.  57            push    edi
00401019  |.  8D7D C0       lea     edi, dword ptr [ebp-40]
0040101C  |.  B9 10000000   mov     ecx, 10
00401021  |.  B8 CCCCCCCC   mov     eax, CCCCCCCC
00401026  |.  F3:AB         rep     stos dword ptr es:[edi]
00401028  |.  5F            pop     edi
00401029  |.  5E            pop     esi
0040102A  |.  5B            pop     ebx
                                       leave
0040102E  \.  C3            retn
由上可见,用enter和leave可以更方便更高效率建立与释放函数栈

以上便是一些不成熟的心得,但似乎enter见得很少,leave+retn在某些高级语言编译的程序倒是常见