当前位置: 首页 > news >正文

网站建设和维护面试题合肥建设集团招聘信息网站

网站建设和维护面试题,合肥建设集团招聘信息网站,郑州短视频培训机构,网站后台更新栏目目录 前言 补充知识 一、函数线帧是什么#xff1f; 二、函数线帧的实现#xff08;举例说明#xff09; 两数之和代码 ​编辑两数之和 汇编代码分析 执行第一条语句 执行第二条语句 执行第三条语句 执行第四、五、六条语句 执行第七条语句 执行第八、九、十条语句 执行第十… 目录 前言 补充知识 一、函数线帧是什么 二、函数线帧的实现举例说明 两数之和代码 ​编辑两数之和 汇编代码分析  执行第一条语句 执行第二条语句 执行第三条语句 执行第四、五、六条语句 执行第七条语句 执行第八、九、十条语句 执行第十三条语句 执行第十四、十五条语句 执行第十六条语句 执行第十七条语句  执行第十七、十八条语句  执行第十九、二十条语句 进入Add函数里面  Add函数预开辟空间 创建z  相加 实际传参 返回z 弹出 回收没用空间回到main函数 将数放进c中 三、总结 局部变量是怎么创建的局部变量的创建  为什么局部变量的值是随机值 函数是怎么传参的传参的顺序是什么样的 形参和实参是什么关系 函数调用结果是怎么返回的 前言 这里补充一下函数线帧的创建和销毁我们知道函数调用一次就会占用一次栈内存。每一次函数调用都会为本次函数调用分配内存空间是在内存的栈区为本次函数调用分配的内存空间叫做被称为这次函数调用的栈帧空间函数栈帧的创建和销毁。 编译器越高级那么 就越不容易发现在函数调用的过程中线帧的创建具体细节取决于编译器的实现。新的编译器由于考虑各种各样的问题所以封装的更加复杂不容易分离出来函数栈帧创建的过程。 栈空间的使用是从高地址向地地址增长。 寄存器是集成到cpu上的跟mian函数是没有关系的是独立的硬盘内存寄存器是相互独立的。 补充知识 我们知道计算机中有寄存器而寄存器包括很多例如eaxebxecxedxebpesp等。 而ebpesp这两个寄存器中存放的是地址这两个地址是用来维护函数栈帧的。 每一个函数调用都要在栈区上创建一个空间而当调用哪个函数esp和ebp就会维护哪个函数线帧。通常esp称为栈顶指针sbp称为栈底指针。 当我们在调用main函数之前会调用_tmainCRTStartup这个函数这个函数内部调用了main函数而这个函数又是被mainCRTStartup这个函数调用的。 其实在VS2013中main函数也是被其他函数调用的。 一、函数线帧是什么 函数栈帧是指在函数调用过程中为了保存函数的局部变量、参数和执行上下文等信息而创建的一块存储区。 每次函数调用时都会在栈上创建一个新的栈帧用于存储该函数的局部变量、参数和执行上下文等信息。栈帧通常包括以下几个部分 局部变量区域用于存储函数内部定义的局部变量和临时变量等。 参数区域用于存储函数的参数值。 返回地址用于保存函数调用完成后的返回地址以便能够返回到调用方继续执行。 上一级函数的栈帧指针用于保存上一级函数的栈帧地址以便能够返回到上一级函数。 其他上下文信息如调用方的寄存器值、异常处理信息等。 函数栈帧的创建和销毁是由编译器和操作系统自动完成的开发者一般无需手动管理。函数栈帧的创建和销毁按照函数调用的顺序形成一个栈结构因此也被称为调用栈或执行栈。在函数调用完成后栈帧被销毁栈指针回退到上一级函数的栈帧继续执行上一级函数。这种递归结构的栈帧可以保证函数调用的嵌套和返回顺序的正确性。 二、函数线帧的实现举例说明 两数之和代码 #define _CRT_SECURE_NO_WARNINGS #includestdio.h int Add(int x, int y) {int z 0;z x y;return z; }int main() {int a 10;int b 20;int c 0;c Add(a, b);printf(%d\n, c);return 0; } 我们通过用vs2022来进行讲解例子用的上述代码两数之和函数。 两数之和 汇编代码分析 我们通过F10来调试代码之后在代码界面点击右键选择反汇编就会出现一个新页面而这个页面就是图中右侧的这是C语言对应的汇编代码。 把显示符号取消勾选因为选上会显示符号名而我们想要看其地址和布局所以就去掉。 这时候里面就写的是符号的地址了而不是符号名字了。 因为main函数是其它函数调用的所以调用的__tmainCRTStartup已经分配好栈空间了此时esp和ebp就会维护这个函数线帧前提下面是高地址上面是高地址 执行第一条语句 意思是将ebp进行压栈所以栈顶就多了一个元素ebp因为esp维护的是栈顶所以esp指向往上移动了一步。内存就压进去一个ebp。 执行第二条语句 mov的意思就是把后者的值赋给前者这里也就也是将esp的值赋给ebp我们知道esp的值赋给了ebp那么ebp的地址就指向esp而esp又指向栈顶ebp就指向了之前esp指的地方所以就变成了下面 执行第三条语句 sub是前者减去后者也就是esp减去后面的数字0E4h是八进制esp减去这个数后值变小了所以esp就指向了上面的某一位置,我们知道esp和ebp之间的就是函数的栈帧空间所以他们俩之间的就是开辟出来main函数的预留空间也就是main函数的栈帧。 执行第四、五、六条语句 分别压栈压进去三个元素ebx,esi,edi同时esp的值会往上走。每一个pushesp都会往上挪一下。 执行第七条语句 lea实际上是 load effecitive address加载有效地址的意思这里面就是将后面的有效地址加载到edi中相当于edi里面加上了一个地址。它实际上就似乎找了第三条语句的地址。 执行第八、九、十条语句 这三步真正有意义的是第三步前两步是把后面的值放到前面的里面。而第三步则是从edi开始将39h这么多个空间全部改成eax的内容每一次初始化dword个字节一个4个字节。实际就是将main函数预开辟的空间的全部数据改成0ccccccch。 自此main函数的栈帧就已经准备好了。接下来才是操作的代码。 执行第十三条语句 这里就是将0Ah10 放到ebp-8这个地址的地方也就是a的地方这块地方就放了10 执行第十四、十五条语句 与第十三条语句一样差不多都是赋值给对应地址。 这就可以总结出函数创建的时候局部变量的创建规律 首先创建这个函数的函数栈帧 之后找到一些空间把变量放进去 接下来就是调用函数因为函数调用需要传参 执行第十六条语句 从这里我们可以看见后面这个地址与前面的有一个地址一样这里就是b的地址所以这里把b的值也就是20放进了eax. 执行第十七条语句 这里进行压栈把eax压栈放到栈顶。如下图 执行第十七、十八条语句 这里与前两句一样先把a的值存到ecx中之后在把ecx进行压栈。  执行第十九、二十条语句 执行call指令会调用一个地址并且把地址压入栈中而压入栈中的地址就是下一条指令的地址也就是add的地址00521918每次编译可能会不同。 为什么要调用下一条指令的地址因为call指令会进入add函数但进入函数后还需要回来回来怎么回来就需要一个地址来进行返回来回到call指令的下一条指令再从这个地址往下执行命令。 进入Add函数里面  Add函数预开辟空间 再往下运行就进入到了Add函数里面而上面这些就是为了为Add函数预开辟线帧空间。 与之前开辟main函数的线帧空间一样。开辟之后就如上图所示。 创建z 在ebp-8的地址传入z这里面放的是0 相加 我们知道ebp -8就是ecx的位置ebp-12就是eax的位置同时ecx里面是a的值eax里面是b的值所以给他们给他们命名为是a和b。 这里面吧ebp8的值10加到eax里面去所以eax就为10之后吧ebp0ch12的值20再加入eax中这时候eax里面就为30加起来之后再把eax的值放进ebp-8的地址里面去而z恰好是ebp-8的地址所以z就为30。 这里我们发现函数参数x,y并没有而是通过调用指令进行传参将形参进行push压栈压到某一位置参数是从右向左传的当真的来到函数内部来调用这两个数相加的时候会发现形参根本不是在函数内部创建的而是回来找刚才调入进来传参传入的这个空间压进去这个空间上图a就认为是xb就认为是y也就是xy,之后传入z的空间。 实际传参 实际传参是还没有调用这个函数的时候参数a和b就已经传过去了在函数栈帧中压入了两个参数b和a压进去之后真正用函数内部的时候其实是再找回之前压入栈中的这两个值然后相加之后再给z。所以形参是实参的临时拷贝这句话得到了验证。 返回z 因为我们知道函数调用完后会销毁同时z也会销毁所以把ebp-8里的值也就是z的值30放进eax寄存器中寄存器不会因为函数的销毁而销毁所以放在这里就安全了先保存起来。 弹出 pop就是弹出的意思弹出一个esp就往下移动一个地址之后就如下图了 这时候发现有些空间没有用到所以应该回收。 回收没用空间回到main函数 这里将ebp的位置传入esp用pop把栈顶的元素 弹出来放到ebp里面去因为此时ebp(main地址存的是之前下面的ebp地址所以ebp又回到了下面之前的地方而esp则指向下call指向下一条指令的地址因为之前的ebp已经弹出了。 这样就回到了main函数里面这样栈帧空间又是又esp和ebp开始维护。 现在栈顶元素是call指令下一条指令的地址 这条指令就是回到了call指向下一条指令的地址。再往下执行就是 esp8之后esp就指向了如下图 当指向这里的时候就说明把ecx和eax就还给了操作系统。所以这时候形参的空间就还给了操作系统释放了。 将数放进c中 这里将eax计算的和放进ebp-20hc里面去这样返回值就带了回来。 至此函数线帧的创建和销毁就结束了。 总图 三、总结 局部变量是怎么创建的局部变量的创建 首先先分配好栈帧空间然后在这个空间里面分配一些空间来创建局部变量 为什么局部变量的值是随机值 因为这个随机值是我们自己放进去的初始化后就把随机值覆盖了这时候就不是随机值了 函数是怎么传参的传参的顺序是什么样的 当我们要调用这个函数的时候其实函数还没有调用的时候就已经把两个参数从右向左push压栈压进去了当真正进入函数的时候通过指针的偏移量来找到之前传入的这两个形参参数 形参和实参是什么关系 形参是实参的一份临时拷贝形参确实是在压栈的时候开辟的空间它和实参只是值是相同的、空间是独立的改变形参是不会影响实参的。 函数调用结果是怎么返回的 之前就把call指令的下一个指令的地址就压进栈了把ebp调用这个函数的上一个函数栈帧的ebp就存进去了当我们函数调用完要返回时候弹出edp就可以找到原始上一个函数调用的ebp指针往下走就可以找到esp的地址回到了mian函数。 记住call指令的下一个指令地址就可以回来进行下一个命令。 返回值通过寄存器来临时保存之后进行返回。
http://www.hkea.cn/news/14436384/

相关文章:

  • 英国网站后缀佛山网站建设专业品牌
  • 做网站的价格参考天津多媒体设计公司
  • 怎么用织梦源代码做网站上海前十名文化传媒公司
  • 为什么上传网站模板网站上没有文字和图片wordpress注册提示404
  • 天津网站建设noakj想在微信公众号上做网站链接
  • 广州网站制作到诺然wordpress一键排版
  • 网站做地区定位跳转wordpress 阿里短信
  • 品牌网站建设3a小蝌蚪东莞事件最新消息新闻
  • 企业网站的购买方式wordpress设置密码
  • 网站建设亿码酷出名5城阳网站建设公司
  • 付费阅读插件wordpress网站做优化一般几个字
  • php 企业网站系统下载个人网站模板之家
  • 网站如何做词网站建设都用什么软件
  • 精品课程网站建设内容wordpress 爱无
  • 大气环保网站模板马化腾称视频号是全公司希望
  • 网站做点击收费标准中国包装创意设计大赛
  • 网站访问大小 计算流量全国企业信息公示查询系统官网
  • 哈尔滨网站建设有限公司网站做外链是什么意思
  • 外文网站制作地推的60种方法
  • 广西网站建设产品优化怎么做网站教程++用的工具
  • 寻找企业网站建设通辽市做网站公司
  • 网站开发框架 知乎dyndns免费域名
  • 外国人做外贸都会浏览哪些网站wordpress主题视频
  • 手机网站安全证书过期怎么处理哪些企业网站做得好
  • 营销型网站如何建设郑州新一网站建设
  • 网站名和域名的区别wordpress标题设置方法
  • e点互动网站江苏省工程建设标准网站
  • 做营销推广外包的网站图片压缩wordpress
  • 芦苞网站建设捡个校花做老婆是哪个网站的
  • 重庆做网站优化wordpress相册样式