dw做网站教程,建设部网站监理工程师报名,网站开发费属于什么费用,建外贸网站用什么主机目录
如果你能熟练的掌握函数的栈帧与销毁在面试中是及其亮眼的加分项#xff0c;所以我们来以实例来将解函数是如何实现栈帧与销毁的。
一. 函数栈帧
二.寄存器
三. 用例题讲解创建栈帧的过程
3.1 main 函数的反汇编代码。
第一步#xff1a;给调用main函数的函数分配…目录
如果你能熟练的掌握函数的栈帧与销毁在面试中是及其亮眼的加分项所以我们来以实例来将解函数是如何实现栈帧与销毁的。
一. 函数栈帧
二.寄存器
三. 用例题讲解创建栈帧的过程
3.1 main 函数的反汇编代码。
第一步给调用main函数的函数分配栈帧。
第二步通过将edp压栈将edp赋值给esp再将esp的值减减。这样esp和edp之间的差值就是main函数的栈帧空间。
第三步 将ediesiebx压栈。
第四步初始化 第五步给实参分配空间
第六步将实参拷贝到新地址
第七步 call指令传参
call跳add函数的地址之后在添加call指令的下一条指令的地址。 3.2 add函数的栈帧
第一步为add创建栈帧
第二步将形参相加
3.3 return 的栈帧
第一步
z出了add栈帧被销毁但是值被临时放到eax寄存器里。
第二步
第三步回收空间
第四步pop edp
第五步回来之后执行call指令的下一条指令
第六步
创建的完整过程没带销毁
四.面试问题
4.1 局部变量时怎么创建的
4.2 为什么局部变量的值是随机值
4.3 函数是怎么传参的传参的顺序是什么
4.4 形参和实参的关系是什么
4.5 函数的调用是怎么做的
5.6 函数调用是结束后怎么返回的 如果你能熟练的掌握函数的栈帧与销毁在面试中是及其亮眼的加分项所以我们来以实例来将解函数是如何实现栈帧与销毁的。 一. 函数栈帧 edpesp这两个寄存器存放的是地址这两个地址是用来维护函数栈帧的。 每一个函数调用都要在栈区中创建一个空间。 二.寄存器 1.1 edp栈底指针。 1.2 esp栈顶指针每次push它都会向上低地址挪动push就会--pop就会。 esp和edp中间的 内容才是当前维护的内容esp上方的内容已经销毁的内容。 寄存器寄存器是集成到CPU 上的是独立的存储空间。与硬盘内存都是独立存在的。
三. 用例题讲解创建栈帧的过程 3.1 main 函数的反汇编代码。
main函数也是被调用main函数是被t_main CRTStartup调用。 第一步给调用main函数的函数分配栈帧。 第二步通过将edp压栈将edp赋值给esp再将esp的值减减。这样esp和edp之间的差值就是main函数的栈帧空间。 第三步 将ediesiebx压栈。
lea是load effective address 是加载有效地址的意思。即esp-014H。 第四步初始化 从edi开始向下ecx次即39h次将ecx里dword一个word两个字节doubleword是四个字节个内容初始化为0cccccccch初始化39h39h是十六进制换成十进制次次。即将main函数里的内容全部初始化为0cccccccch。 所以如果变量不初始化那么就默认0cccccccch。 第五步给实参分配空间
将ebp-14h即b的值存放到eax里然后将eax压栈 。 第六步将实参拷贝到新地址
不用给形参分配新空间在函数调用之前就将实参拷贝到新空间。 第七步 call指令传参
call的地址是 然后call指令call指令跳到add函数的地址 call跳add函数的地址之后在添加call指令的下一条指令的地址。
所以call指令之后将call指令的下一条指令的地址压栈。 3.2 add函数的栈帧
然后才是真正的进入add函数。 第一步为add创建栈帧 所以我们并没有创建形参而是在调用函数的时候就把实参传递过去了。 将他们当成X,Y。 因此可以证明形参只是实参的拷贝。所以改变形参不会改变实参。 第二步将形参相加 3.3 return 的栈帧 形参是实参的临时拷贝不是在add栈帧里创建的只是调用一个压栈的空间。
第一步 z出了add栈帧被销毁但是值被临时放到eax寄存器里。 所以为了防止z出了作用域被销毁所以将z放到eax寄存器里临时保存寄存器是不会因为程序销毁而销毁的。 第二步 pop会导致esp esp上面的栈会被释放被回收了S。 第三步回收空间 将ebp赋值给esp的意思就是将esp挪动到edp的位置上面的空间被回收。 第四步pop edp pop edp将edp出栈这里栈顶元素edp是main函数的edp所以将他pop之后他会回到原main函数的edp位置。 然后esp这是esp和edp两个指针彻底回到main函数的作用域里。esp指向00C21450即回到了call指令的下一条指令的地址所以要执行call指令的下一条指令。 第五步回来之后执行call指令的下一条指令 将esp8这里加8的目的值将两个形参的空间给销毁。 第六步 将eax的值赋值给edp -20h刚刚我们为了防止z的值丢失所以我们将它的值存放在寄存器eax里所以函数的任务完成了现在需要将操作完的值还给main函数。 正好edp-20h就是main函数的C。这样返回值就被传回来了。 创建的完整过程没带销毁 四.面试问题
4.1 局部变量时怎么创建的 答首先我们为这个局部变量分配栈帧空间然后在为这个空间初始化空间然后在为局部变量分配空间。
4.2 为什么局部变量的值是随机值 答因为如果局部变量不初始化的话函数栈帧空间的初始化是随机值所以如果局部变量不初始化的话那么它的值就是它分配的那段空间的随机值。如果你将局部变量初始化了那么你初始化的值就会覆盖掉随机值。
4.3 函数是怎么传参的传参的顺序是什么 我们并没有创建形参而是在调用函数的时候就把实参传递过去了。在还没有调用函数的时候就以及将实参的拷贝push压栈到空间里到调用函数的时候并没有为形参分配空间而是使用esp偏移量找到实参的拷贝。 传参的顺序参数从右向左压栈。
4.4 形参和实参的关系是什么 答形参是实参的拷贝改变形参不会影响实参。因为他们的空间是独立的。
4.5 函数的调用是怎么做的
5.6 函数调用是结束后怎么返回的 在函数调用之前就将call指令的下一条指令的地址就压栈了然后再将edp此时的edp是调用函数的上一条函数如main函数的edp压栈这样在pop掉edp时edp会返回到原edp的位置由于pop操作会使esp这样esp就会调用call指令的下一条指令的地址这样就会时函数调用返回然后返回的值事先已被寄存器eax临时保存这样值也会被寄存器带回。