"
"
ebp--栈底指针
esp--栈顶指针
开始两行代码的意思是先将ebp1压栈,然后将现在的栈顶esp1作为函数调用时的栈底,所以会执行如下语句:
00413701 mov ebp,esp
当函数调用执行结束,我们要执行相反的过程:
00413728 mov esp,ebp
还原栈顶指针
0041372A pop ebp
还原栈底指针
0041372B ret
返回到函数调用前的指令继续执行。
"
参考:http://blog.163.com/yichangjun1989@126/blog/static/131972028201442221956603/
“
首先说明,在堆栈中变量分布是从高地址到低地址分布,EBP是指向栈底的指针,在过程调用中不变,又称为帧指针。ESP指向栈顶,程序执行时移动,ESP减小分配空间,ESP增大释放空间,ESP又称为栈指针。(如“sub esp 0D8h”是否是栈顶指针向低地址移动并分配空间的过程?)
下面来逐步分析函数的调用过程
1.函数main执行,main各个参数从右向左逐步压入栈中,最后压入返回地址
2.执行第15行,3个参数以从左向右的顺序压入堆栈,及从param3到param1,栈内分布如下图:
3.然后是返回地址入栈:此时的栈内分布如下:
4.第3行函数调用时,通过跳转指令进入函数后,函数地址入栈后,EBP入栈(EBP相当于分界线,也是查找参数的基准),然后把当前ESP的值给EBP,对应的汇编指令:
push ebp mov ebp esp
此时栈顶和栈底指向同一位置,栈内分布如下:
5.第5行开始执行, int var1 = param1; int var2 = param2; int var3 = param3;按申明顺序依次存储。对应的汇编:
mov 0x8(%ebp),%eax mov %eax,-0x4(%ebp)
其中将[EBP+0x8]地址里的内容赋给EAX,即把param的值赋给EAX,然后把EAX的中的值放到[EBP-4]这个地址里,即把EAX值赋给var1,完成C代码 int var1 = param1,其他变量雷同。
6.第9行,输出结果,第10行执行 对应的汇编代码:
mov -0x4(%ebp),%eax
最后通过eax寄存器保存函数的返回值;
7.调用执行函数完毕,局部变量var3,var2,var1依次出栈,EBP恢复原值,返回地址出栈,找到原执行地址,param1,param2,param3依次出栈,函数调用执行完毕
"lea 的意思就是 Load Effective Address 读有效地址
比如定义的变量
int nTemp;
用
_asm lea ebx, nTemp
就将nTemp的偏移地址读入了ebx;
_asm xor eax, eax
_asm mov [ebx], eax
ASSERT(nTemp == 0);
dword 是双字节的意思"
"比如你用local在栈上定义了一个局部变量LocalVar,你知道实际的指令是什么么?一般都差不多像下面的样子:
push ebp
mov esp, ebp
sub esp, 4
现在栈上就有了4各字节的空间,这就是你的局部变量。
接下来,你执行mov LocalVar, 4,那么实际的指令又是什么?是这样:
mov dword ptr [ebp-4], 4
于是,这个局部变量的“地址”就是ebp-4——显然,它不是一个固定的地址。现在需要将它的“地址”作为参数传给某个函数,你这样写:
invoke/call SomeFunc, addr LocalVar
实际生成的指令是:
lea eax, [ebp-4]
push eax
call SomeFunc
当然,你也可以写成:
mov eax, ebp
sub eax, 4
push eax
call SomeFunc
看到了,这里多了一条指令。这就是lea的好处。于是,lea又多了一个非常美妙的用途:作简单的算术计算,特别是有了32位指令的增强寻址方式,更是“如虎添翼”:
比如你要算EAX*4+EBX+3,结果放入EDX,怎么办?
mov edx, eax
shl edx, 2
add edx, ebx
add edx, 3
现在用lea一条指令搞定:
lea edx, [ebx+eax*4+3]
lea的英文解释是: Load Effective Address.(加入有效地址,开始迷惑效地址是什么???既然是有效地址与mov ax , [address] 又有什么不同呢?其实他们都是等效的。 后来知道实际上是一个偏移量可以是立即数,也可以是经过四则运算的结果,更省空间,更有效率)"??????????存疑
" 三、地址传送指令
(1) 格式:LEA REG,MEM
功能:将源操作数的有效地址传送到通用寄存器,操作数REG为16位或32位通用寄存器,源操作数为16位或32位存储器操作数。"
参考:http://www.xuebuyuan.com/338873.html