最近在研究栈帧的结构,但总是有点乱,所以写了一个小程序来看看esp和ebp在栈帧中的作用。这个程序如下:

这个程序很简单,就是求两个数的值,然后输出即可。所以首先把它用gcc编译链接成a.out,进入gdb进行调试。

首先在main和add两处设置断点。运行到第一个断点,查看main的汇编代码:

我们主要是观察调用add后我们的esp和ebp的变化,于是输入命令:c,继续运行到add处,观察add的汇编:

其实也就是运行到了main的call指令处进入add函数了。这时到了观察esp和ebp的时刻了。

上图其实已经很明显了。我们来看下面的图,这样立体观察(栈帧结构图)就会瞬间明白了:

我把栈帧的每个字节都拆开来看就会有下面的结论,通过GDB,查找出这时esp和ebp的值,均为0xbffff0a8。

详解如下:

我们知道调用call指令后会有下面的三件事:

  • call指令保存返回地址所谓保存返回地址(return address)其实就是 call指令将那一时刻的PC(%eip值,即call的下一条指令的地址)压入栈(如上图中的0x8048447)。还记得吗?因为PC自增在先,指令执行在后。所以执行完add的所有代码后,ret指令会恢复PC的值,程序就可以继续执行main的剩余代码了。
  • add()保存main()的%ebp将add()栈帧的base地址压入到栈上。

这时查看从0xbffff0a8开始每个字节里的内容,从上面看出从0xbffff0a8开始向上的16个字节的内容(我把其中的8个放到了栈帧结构图中了)。main栈帧的最后4个字节代表着返回地址,通过gdb的查看也可以明显看出里边的内容就是main中call指令的下一条指令的地址。当我们读取0xbffff08a中的内容时(按双字节读)结果显示0xbffff0d8.可见这里是小端存储,读取是从高地址开始读取,其值表示main中的基址。这里有一个误区就是:我们在数据结构中学的栈顶指针总是指向栈顶元素的下一个位置,但在这里确实指向栈顶元素。这里千万要注意。

esp和ebp详解的更多相关文章

  1. 栈帧%ebp,%esp详解

    首先应该明白,栈是从高地址向低地址延伸的.每个函数的每次调用,都有它自己独立的一个栈帧,这个栈帧中维持着所需要的各种信息.寄存器ebp指向当前的栈帧的底部(高地址),寄存器esp指向当前的栈帧的顶部( ...

  2. Linux 中断详解 【转】

    转自:http://blog.csdn.net/tiangwan2011/article/details/7891818 原文地址 http://www.yesky.com/20010813/1921 ...

  3. 异常处理与MiniDump详解(4) MiniDump

    http://blog.csdn.net/vagrxie/article/details/4398721 异常处理与MiniDump详解(4) MiniDump 分类:             [Wi ...

  4. 异常处理与MiniDump详解(转)

    一.   综述 总算讲到MiniDump了. Dump有多有用我都无法尽数,基本上属于定位错误修复BUG的倚天剑.(日志可以算是屠龙刀)这些都是对于那些不是必出的BUG,放在外面运行的时候出现的BUG ...

  5. gcc/g++等编译器 编译原理: 预处理,编译,汇编,链接各步骤详解

    摘自http://blog.csdn.net/elfprincexu/article/details/45043971 gcc/g++等编译器 编译原理: 预处理,编译,汇编,链接各步骤详解 C和C+ ...

  6. Linux进程上下文切换过程context_switch详解--Linux进程的管理与调度(二十一)

    1 前景回顾 1.1 Linux的调度器组成 2个调度器 可以用两种方法来激活调度 一种是直接的, 比如进程打算睡眠或出于其他原因放弃CPU 另一种是通过周期性的机制, 以固定的频率运行, 不时的检测 ...

  7. C/C++堆、栈及静态数据区详解

    转自:https://www.cnblogs.com/hanyonglu/archive/2011/04/12/2014212.html  做略微修改 C/C++堆.栈及静态数据区详解   本文介绍C ...

  8. ZT --- extern "C"用法详解 2010-08-21 19:14:12

    extern "C"用法详解 2010-08-21 19:14:12 分类: C/C++ 1.前言: 时常在cpp的代码之中看到这样的代码: #ifdef __cplusplus ...

  9. Linux Ptrace 详解

    转 https://blog.csdn.net/u012417380/article/details/60470075 Linux Ptrace 详解 2017年03月05日 18:59:58 阅读数 ...

随机推荐

  1. SQL 实现,如果存在就更新,如果不存在就添加

    alter proc proc_DataSummary as begin begin try begin tran --PV --统计的信息存入临时表 ), CreateDate, ) ), Crea ...

  2. java 中的fanal

    三.java中有final final 修饰符 关键字可用于修饰类,变量和方法,final关键字有点类似于C#里的sealed 关键字,用于表示它修饰的类,方法和变量不可改变. fina修饰变量时,表 ...

  3. C++中rapidxml用法及例子

    rapidxml是一个快速的xml库,比tinyxml快了50-100倍.本文给出创建.读取.写入xml的源码. 由于新浪博客不支持文本文件上传,在使用下面代码需要先下载 rapidxml,关于这个库 ...

  4. ionic cordova file download and load

    1.先添加插件 cordova plugin add org.apache.cordova.file cordova plugin add org.apache.cordova.file-transf ...

  5. 简单的使用AngularJS的解析JSON

    使用AngularJS+Struts2进行前后台的数据交互与显示. struts.xml 配置文件需要将设置extends="json-default"  type="j ...

  6. (笔记)angular 事件传递获取当前

  7. javascript之delete操作符

    理解delete 理论 代码段的类型 执行上下文 活动对象 / 变量对象 属性的特性 内置属性与 DontDelete 未声明的赋值 Firebug的困惑 在eval中删除变量 浏览器兼容性 Geck ...

  8. openssl mac中使用终端生成RSA私钥和公钥文件

    RSA密钥生成命令生成RSA私钥openssl>genrsa -out rsa_private_key.pem 1024生成RSA公钥openssl>rsa -in rsa_private ...

  9. 如何实现Android 中断线程的处理

    我现在对一个用户注册的功能1.用ProgressDialog将当前页面设成不可操作(保留返回键 退出ProgressDialog)2.用一个线程clientThread执行数据的提交和返回 问题:考虑 ...

  10. dedecms 调用channel子栏目的id问题

    dedecms 说明文档:http://www.dedecms.com/archives/templethelp/help/taghelp.htm {dede:channel type='son' t ...