首先,我们先来了解下栈帧和栈的基本知识:
    • 栈帧也常被称为“活动记录”(activation record),是编译器用来实现过程/函数调用的一种数据结构。
    • 从逻辑上讲,栈帧就是一个函数执行的环境,包含所有与函数调用相关的数据:主要包括函数参数、函数中的局部变量、函数执行完后的返回地址,被函数修改的需要恢复的任何寄存器的副本。
  另外,需要注意的是:栈是从高地址向低地址延伸的。每个函数的每次调用,都有它自己独立的一个栈帧,这个栈帧中维持着所需要的各种信息。寄存器ebp用来指向当前的栈帧的底部(高地址),寄存器esp用来指向当前的栈帧的顶部(低地址),即在函数调用执行过程中,寻找所需参数或变量信息时使用寄存器ebp来寻址,因为寄存器esp的值是经常变化的,而寄存器ebp的值对一个函数的栈帧来讲是不变的。
  栈是一种LIFO形式的数据结构,所有的数据都是后进先出。这种形式的数据结构正好满足我们调用函数的方式: 父函数调用子函数,父函数在前,子函数在后;返回时,子函数先返回,父函数后返回栈支持两种基本操作,push和pop。push将数据压入栈中,pop将栈中的数据弹出并存储到指定寄存器或者内存中。
  pop操作后,栈中的数据并没有被清空,只是该数据我们无法直接访问。栈的形式不一定必须时向下生长的,也可以向上生长,只是我们的系统调用栈(call stack)用到的是向下生长形式而已。
  有了上面的基础知识,让我们以一个实际的例子来讲解一下。
int Add(int a, int b)
{
int c;
c=a+b;
return c;
}
Main()
{
Add(10, 5);
printf("hello world!");
}

程序从main()函数开始执行,首先将main()函数压入系统调用栈(call stack)(下面如无特殊说明,用代指系统调用栈(call stack)),并给它分配一个栈帧用以保存所需信息。然后执行main函数中第一条语句,这是一条函数调用语句,在实际调用执行Add函数前需要做一些准备工作。

  首先将5和10两个参数压入栈,同时更新ESP指针的值,如下图所示:

 
  注意,参数5和10压入栈的顺序,应该是从右向左依次压入系统调用栈(call stack)。
  接下来我们需要搞清楚的是:当Add函数调用执行完毕之后,我们需通过某种方式返回到main函数中继续执行下面的指令,在本例中也就是执行print函数。解决这个问题的方式就是将下一条指令的地址压入栈中。
  以上准备工作就绪,下面开始调用执行Add函数。
  首先,我们需要将main函数用来寻址参数或变量信息的EBP寄存器值压入栈中保存,以便于从Add函数返回之后,从栈中取出EBP的值赋给EBP寄存器让main函数用来寻址参数或变量信息,同时更新ESP的值。为了Add函数能够寻址到所需信息,将此时的ESP寄存器的值赋值给EBP寄存器(图中的EBP-new)。此时将接着执行int c语句,为变量c开辟一段内存空间压入栈中,同时更新ESP的值。接下来执行c=a+b,然后返回c,但main函数中并没有声明变量来存储该返回值,故该返回值丢失。函数返回时将ESP更新为EBP-new,接着将EBP-old弹出赋值给EBP寄存器,让main函数拿来寻址所需信息,此时就从Add函数的栈帧恢复到了main函数的栈帧。接着弹出RET(Add函数的返回地址),对应的汇编代码中会有一条ret指令,该指令会将RET返回地址保存到EIP寄存器中,然后处理器根据这个地址无条件跳转到main函数的相应位置去取下一条指令即print函数继续执行。print函数调用执行过程中压栈出栈过程与Add函数类似,不再细说。
 

stack和stack frame的更多相关文章

  1. 栈帧示意图:stack pointer、frame pointer

    更多参考:http://www.embeddedrelated.com/usenet/embedded/show/31646-1.php 一: The calling convention descr ...

  2. Struts2(六.用标签显示用户列表及Value Stack和Stack Context)

    一.用Struts2标签显示用户列表 原理: 在struts中可以通过在action中将所有用户的信息存入到某个范围中,然后转向userlist.jsp,进行访问 原则: 在jsp网页上,尽量不要出现 ...

  3. java:stack栈: Stack 类表示后进先出(LIFO)的对象堆栈

    //Stack 类表示后进先出(LIFO)的对象堆栈 //它提供了通常的 push 和 pop 操作,以及取栈顶点的 peek 方法.测试堆栈是否为空的 empty 方法.在堆栈中查找项并确定到栈顶距 ...

  4. 155. Min Stack (stack)

    Design a stack that supports push, pop, top, and retrieving the minimum element in constant time. pu ...

  5. 自己理解BFC 和 stack context , stack order

    1. stack order 发生在BFC计算好了之后. 2.一个一个的BFC里面,不同的block 里面的stack context 会根据 stack order的顺序,进行堆叠.呈现互相遮盖的效 ...

  6. Java-JVM 栈帧(Stack Frame)

    一.概述 栈帧位置 JVM 执行 Java 程序时需要装载各种数据到内存中,不同的数据存放在不同的内存区中(逻辑上),这些数据内存区称作运行时数据区(Run-Time Data Areas). 其中 ...

  7. (android 源码下开发应用程序) 如何在 Android 各 level ( 包含 user space 與 kernel space ) 使用dump call stack的方法

    http://janbarry0914.blogspot.com/2014/07/androiddump-call-stack.html dump call stack [文章重點] 了解 Andro ...

  8. 聊一聊goroutine stack

    通过阅读这篇文章对内存的处理以及栈的扩容有了新的认识,我们在生产环境中也遇到了内存使用量超大的情况,现在怀疑也可能是由于栈扩容导致的 很好的一片文章: 推送在外卖订餐中扮演着重要的角色,为商家实时接单 ...

  9. pthread中如何追踪stack over flow

    通常在程序挂掉的时候我们会catch 他们挂掉的signal,然后在signal中打印出当时的一个stack,来方便问题调查, 但是在stack overflow的情况发生时,会没有拿到stack.s ...

随机推荐

  1. Bootstrap的介绍和响应式媒体查询

    Bootstrap的介绍 凡是使用过Bootstrap的开发者,都不在乎做这么两件事情:复制and粘贴.哈哈~,是的使用Bootstrap非常简单,但是在复制粘贴之前,需要先对Bootstrap的用法 ...

  2. 20165233 Java第五、六章学习总结

    20165233 2017-2018-2 <Java程序设计>第四周学习总结 教材学习内容总结 ch05 子类与父类以及子类的继承性 一个子类只能有一个父类 使用extends关键字定义子 ...

  3. tensorflow-windows下安装,python3.6

    安装: pip install tensorflow ps:我第一次安装了,但是导入却失败了. 进入\python3\Lib\site-packages\删除了tensorflow,再次pip ins ...

  4. django2.0实现数据详情页展示的流程

    思路整理 1 先在urls.py中,定义路由获取的格式 url(r'^detail/(\d+)/$', views.blog_detail), 2 然后在views.py,定义数据获取的方法 def ...

  5. Seetaface 向树莓派 移植

    seetaface由中科院计算所山世光研究员带领的人脸识别研究组研发.代码基于C++实现,不依赖第三方库.然而,目前开源的代码,是在windows vs上编译的,对于我们这帮mac/linux用户来说 ...

  6. 字符串转码 将文本转为PDF

    @Test public void testBasic64Code() throws Exception { String strdata = new String("how are you ...

  7. Java 8 新特新 工具类 ZonedDateTime

    类ZonedDateTime java.lang.Object继承 java.time.ZonedDateTime 所有实现的接口: Serializable,Comparable < Chro ...

  8. 创建django的8大步骤xxx.setAttribute('name', 'user'); 添加属性和值 xxx.attr('name') 查看属性的值 $(xxx).addClass 添加样式 $().after() 添加在标签后面

    第一步.创建django 方法一:django-admin startproject 方法二: 直接在python上创建 第二步:创建工程名cmdb python manage.py startapp ...

  9. 3 MySQL数据库--初识sql语句

    1.初识sql语句 服务端软件 mysqld SQL语句:后面的分号mysql -uroot -p123 操作文件夹(库) 增 create database db1 charset utf8; 查 ...

  10. SELinux导致的docker启动失败

    安装docker yum install -y docker 启动docker systemctl start docker 报错 Job for docker.service failed beca ...