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

布吉商城网站建设基本流程百度官网下载安装到桌面上

布吉商城网站建设基本流程,百度官网下载安装到桌面上,免费学做美食视频网站,wordpress主题width=1 height=1图片不显示在开发软件的过程中我们经常会遇到错误,如果你用 Google 搜过出错信息,那你多少应该都访问过Stack Overflow这个网站。作为全球最大的程序员问答网站,Stack Overflow 的名字来自于一个常见的报错,就是栈溢出(stack ove…

在开发软件的过程中我们经常会遇到错误,如果你用 Google 搜过出错信息,那你多少应该都访问过Stack Overflow这个网站。作为全球最大的程序员问答网站,Stack Overflow 的名字来自于一个常见的报错,就是栈溢出(stack overflow)。

今天,我们就从程序的函数调用开始,讲讲函数间的相互调用,在计算机指令层面是怎么实现的,以及什么情况下会发生栈溢出这个错误。

为什么我们需要程序栈?

和前面一样,我们还是从一个非常简单的 C 程序 function_example.c 看起。

// function_example.c
#include <stdio.h>
int static add(int a, int b)
{return a+b;
}int main()
{int x = 5;int y = 10;int u = add(x, y);
}

这个程序定义了一个简单的函数 add,接受两个参数 a 和 b,返回值就是 a+b。而 main 函数里则定义了两个变量 x 和 y,然后通过调用这个 add 函数,来计算 u=x+y,最后把 u 的数值打印出来。

$ gcc -g -c function_example.c
$ objdump -d -M intel -S function_example.o

我们把这个程序编译之后,objdump 出来。我们来看一看对应的汇编代码。

int static add(int a, int b)
{0:   55                      push   rbp1:   48 89 e5                mov    rbp,rsp4:   89 7d fc                mov    DWORD PTR [rbp-0x4],edi7:   89 75 f8                mov    DWORD PTR [rbp-0x8],esireturn a+b;a:   8b 55 fc                mov    edx,DWORD PTR [rbp-0x4]d:   8b 45 f8                mov    eax,DWORD PTR [rbp-0x8]10:   01 d0                   add    eax,edx
}12:   5d                      pop    rbp13:   c3                      ret    
0000000000000014 <main>:
int main()
{14:   55                      push   rbp15:   48 89 e5                mov    rbp,rsp18:   48 83 ec 10             sub    rsp,0x10int x = 5;1c:   c7 45 fc 05 00 00 00    mov    DWORD PTR [rbp-0x4],0x5int y = 10;23:   c7 45 f8 0a 00 00 00    mov    DWORD PTR [rbp-0x8],0xaint u = add(x, y);2a:   8b 55 f8                mov    edx,DWORD PTR [rbp-0x8]2d:   8b 45 fc                mov    eax,DWORD PTR [rbp-0x4]30:   89 d6                   mov    esi,edx32:   89 c7                   mov    edi,eax34:   e8 c7 ff ff ff          call   0 <add>39:   89 45 f4                mov    DWORD PTR [rbp-0xc],eax3c:   b8 00 00 00 00          mov    eax,0x0
}41:   c9                      leave  42:   c3                      ret

可以看出来,在这段代码里,main 函数和上一节我们讲的的程序执行区别并不大,它主要是把 jump 指令换成了函数调用的 call 指令。call 指令后面跟着的,仍然是跳转后的程序地址。

这些你理解起来应该不成问题。我们下面来看一个有意思的部分。

我们来看 add 函数。可以看到,add 函数编译之后,代码先执行了一条 push 指令和一条 mov 指令;在函数执行结束的时候,又执行了一条 pop 和一条 ret 指令。这四条指令的执行,其实就是在进行我们接下来要讲压栈(Push)和出栈(Pop)操作。

你有没有发现,函数调用和上一节我们讲的 if…else 和 for/while 循环有点像。它们两个都是在原来顺序执行的指令过程里,执行了一个内存地址的跳转指令,让指令从原来顺序执行的过程里跳开,从新的跳转后的位置开始执行。

但是,这两个跳转有个区别,if…else 和 for/while 的跳转,是跳转走了就不再回来了,就在跳转后的新地址开始顺序地执行指令,就好像徐志摩在《再别康桥》里面写的:“我挥一挥衣袖,不带走一片云彩”,继续进行新的生活了。而函数调用的跳转,在对应函数的指令执行完了之后,还要再回到函数调用的地方,继续执行 call 之后的指令,就好像贺知章在《回乡偶书》里面写的那样:“少小离家老大回,乡音未改鬓毛衰”,不管走多远,最终还是要回来。

那我们有没有一个可以不跳转回到原来开始的地方,来实现函数的调用呢?直觉上似乎有这么一个解决办法。你可以把调用的函数指令,直接插入在调用函数的地方,替换掉对应的 call 指令,然后在编译器编译代码的时候,直接就把函数调用变成对应的指令替换掉。

不过,仔细琢磨一下,你会发现这个方法有些问题。如果函数 A 调用了函数 B,然后函数 B 再调用函数 A,我们就得面临在 A 里面插入 B 的指令,然后在 B 里面插入 A 的指令,这样就会产生无穷无尽地替换。就好像两面镜子面对面放在一块儿,任何一面镜子里面都会看到无穷多面镜子。

Infinite Mirror Effect,如果函数 A 调用 B,B 再调用 A,那么代码会无限展开,图片来源

看来,把被调用函数的指令直接插入在调用处的方法行不通。那我们就换一个思路,能不能把后面要跳回来执行的指令地址给记录下来呢?就像前面讲 PC 寄存器一样,我们可以专门设立一个“程序调用寄存器”,来存储接下来要跳转回来执行的指令地址。等到函数调用结束,从这个寄存器里取出地址,再跳转到这个记录的地址,继续执行就好了。

//未完待续....

http://www.15wanjia.com/news/17480.html

相关文章:

  • 深圳营销型网站费用线下营销推广方式都有哪些
  • 微信网站建设费用百度收录技术
  • 恶意网站的防治互动营销公司
  • 政府网站 建设依据百度经验
  • 武汉网上商城网站建设创建站点的步骤
  • html下载安装网站优化搜索排名
  • 舞蹈培训机构网站模板搜索引擎优化seo培训
  • 做seo推广做网站有用吗网络营销推广方案
  • 大连网站建设方案案例市场营销证书含金量
  • 营销网站建设专业公司关键词搜索排名推广
  • 网站底部给网站地图做链接b站推广
  • 长安网站建设友情链接交易平台源码
  • dnf交易网站建设seo搜索引擎招聘
  • 擅自给公司做网站有什么责任门户网站制作
  • 用HBuilder做网站的模板百度搜索关键词设置
  • 网站建设公司的服务器上海网络营销有限公司
  • 哪些网站使用wordpress加盟教育培训哪个好
  • 台州网站排名优化公司郑州网站优化顾问
  • 怎么在360自己做网站在线网页编辑平台
  • 做企业网站怎么收费的品牌推广方式都有哪些
  • 给公司在百度上做网站关键词优化怎么优化
  • 网站开发前期工作开鲁网站seo免费版
  • 常德网站建设seo视频教学网站
  • 简述网站开发的流程网络营销课程设计
  • 公司地址查询网站新媒体营销成功案例
  • 杭州网站建设app如何搜索关键词热度
  • 中国建设银行网站不好用58同城安居客
  • 免费自助建网站网上营销培训课程
  • tomcat做网站百度登录入口百度
  • 优化网站排名怎么制作制作网页完整步骤代码