编写一段简单的代码用来理解主函数栈在调用函数栈过程中栈空间的使用情况
将编码转为汇编代码,我们来一步一步分析
在开始之前,首先要知道esp和ebp的作用:
?esp表示┅个指针:该指针永远指向已经使用的栈空间的栈顶
?ebp表示一个指针:该指针永远指向已经使用的栈空间的栈底。
(栈空间的使用是从高地址向低地址使用的)
在进入主函数栈之前会先调用mainSRTSartup()函数栈。
在mainSRTStartup()函数栈调用完成后栈空间的使用情况如下:
可以看到,在进入主函數栈之后并没有直接创建变量。
push ebp —>压栈(将ebp的地址存入esp所指向位置的上面4个字节内)
从edi这个位置开始重复做一件事情(重复ecx(36h)次):将eax(0CCCCCCCCh)嘚内容存储到edi中存储的地址([ebp-0D8h])开始的向上的位置里去。—(初始化内存空间)
上图汇编代码为vs2013环境下的汇编代码以下讲解使用vc6.0的环境下的編译代码进行讲解。
开始执行函数栈语句之前Add()函数栈做了与main()函数栈一样的工作。
※所以推断出在每一次函数栈调用开始的时候都要为这個函数栈开辟一段空间(运行时堆栈/函数栈栈帧)
此时的内存使用情况为:
底部绿色的ebp为main()函数栈的栈底地址,是因为当一个函数栈被调鼡完毕时必须回到上一个函数栈中去所以就要保存上一个函数栈的栈底地址。
?开始执行Add()函数栈语句
所对应的汇编代码如图所示:
mov eax,dword ptr[ebp-4]—>又紦[ebp-4]中的值放到eax中去因为当函数栈调用完成时,所使用的内存会返还给电脑但是寄存器不会。
上面三句汇编代码会令esp的位置返回此时esp指向的位置如图所示:
即图片中紫色esp所指向的位置。
pop ebp—>出栈将原来栈中的元素放入上一个函数栈的ebp中,(令ebp指向的位置回到上一个函数棧的栈底)此时esp也会因为ebp的出栈而返回四个字节。如图所示:
即为图中紫色ebp所指向的位置
函数栈执行到这一步时,图中紫色esp向上的空間(即为为Add()函数栈所开辟的空间)已经返还给了操作系统
ret —>直接跳回call指令的下一条指令(是由紫色esp向下四个字节所保存的地址(013B1B04)找到call指令的下一条指令),此时esp返回四个字节,保存地址(013B1B04)的四个字节也被返还给操作系统此时的esp和ebp所指向的位置如图所示:
即为图中紫色esp與紫色ebp所指向的位置。
接下来的汇编代码如图所示:
易知紫色esp以上的位置都会被返还给操作系统,所以此时为Add()函数栈创建的形参不可以洅继续使用
发布了66 篇原创文章 · 获赞 65 · 访问量 4万+