栈帧ebp,esp详解
栈帧%ebp,%esp详解
分类专栏: 汇编
首先应该明白,栈是从高地址向低地址延伸的。每个函数的每次调用,都有它自己独立的一个栈帧,这个栈帧中维持着所需要的各种信息。寄存器ebp指向当前的栈帧的底部(高地址),寄存器esp指向当前的栈帧的顶部(地址地)。下图为典型的存取器安排,观察栈在其中的位置
入栈操作:push eax; 等价于 esp=esp-4,eax->[esp];如下图
出栈操作:pop eax; 等价于 [esp]->eax,esp=esp+4;如下图
我们来看下面这个C程序在执行过程中,栈的变化情况
void func(int m, int n) {
int a, b;
a = m;
b = n;
}
main() {
...
func(m, n);
L: 下一条语句
...
}
在main调用func函数前,栈的情况,也就是说main的栈帧:
从低地址esp到高地址ebp的这块区域,就是当前main函数的栈帧。当main中调用func时,写成汇编大致是:
push m
push n; 两个参数压入栈
call func; 调用func,将返回地址填入栈,并跳转到func
当跳转到了func,来看看func的汇编大致的样子:
__func:
push ebp; 这个很重要,因为现在到了一个新的函数,也就是说要有自己的栈帧了,那么,必须把上面的函数main的栈帧底部保存起 ; 来,栈顶是不用保存的,因为上一个栈帧的顶部讲会是func的栈帧底部。(两栈帧相邻的)
mov ebp, esp; 上一栈帧的顶部,就是这个栈帧的底部
;暂时先看现在的栈的情况
;到这里,新的栈帧开始了
sub esp, 8 ; int a, b 这里声明了两个int,所以esp减小8个字节来为a,b分配空间
mov dword ptr [esp+4], [ebp+12]; a=m
mov dword ptr [esp], [ebp+8]; b=n
这样,栈的情况变为:
ret 8 ; 返回,然后8是什么意思呢,就是参数占用的字节数,当返回后,esp-8,释放参数m,n的空间
由此可见,通过ebp,能够很容易定位到上面的参数。当从func函数返回时,首先esp移动到栈帧底部(即释放局部变量),然后把上一个函数的栈帧底部指针弹出到ebp,再弹出返回地址到cs:ip上,esp继续移动划过参数,这样,ebp,esp就回到了调用函数前的状态,即现在恢复了原来的main的栈帧
最近在看汇编码,经常在程序的开头看到ESP和EBP寄存器的出现,由于本人基础知识的不牢靠,便上网查阅相关的资料,可惜网上的资料都不给力,都只是流于形式,没有好好的解释这两个东西是什么.终于通过google国外的网站,得到一个相当不错的网页,上面解释的很清晰http://www.tenouk.com/Bufferoverflowc/Bufferoverflow2a.html 英文好的可以上去看看(我好像很喜欢这句话)
(1)ESP:栈指针寄存器(extended stack pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的栈顶。
(2)EBP:基址指针寄存器(extended base pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的底部。
在这里要注意由于在intel系统中栈是向下生长的(栈越扩大其值越小,堆恰好相反)
(1)ESP:栈指针寄存器(extended stack pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的栈顶。
(2)EBP:基址指针寄存器(extended base pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的底部。
根据上述的定义,在通常情况下ESP是可变的,随着栈的生产而逐渐变小,而ESB寄存器是固定的,只有当函数的调用后,发生入栈操作而改变。
在上述的定义中使用ESP来标记栈的底部,他随着栈的变化而变化
pop ebp;出栈 栈扩大4byte 因为ebp为32位
push ebp;出栈,栈减少4byte
add esp, 0Ch;表示栈减小12byte
sub esp, 0Ch;表示栈扩大12byte
而ebp寄存器的出现则是为了另一个目标,通过固定的地址与偏移量来寻找在栈参数与变量。而这个固定值者存放在ebp寄存器中,。但是这个值会在函数的调用过程发生改变。而在函数执行结束之后需要还原,因此,在函数的出栈入栈过程中进行保存。
下面根据汇编码来对上面的内容进行解释
现在利用VS2013的反汇编功能进行解释注意设置好断点
在上述的汇编码中我们可以看到在函数开始的时候,习惯上以这么两端代码开始
push ebp
mov ebp,esp
按照字面上理解,上面两句话的意思是将ebp推入栈中,之后让ebp等于esp
为什么这么做呢?因为ebp作为一个用于寻址的固定值是有时间周期的。只有在某个函数执行过程中才是固定的,在函数调用与函数执行完毕后会发生改变。
在函数调用之前,将调用者的函数(caller)的ebp存入栈,以便于在执行完毕后恢复现场是还原ebp的值。下一步,foo必须为它的局部变量分配空间,同时,也必须为它可能用到的一些临时变量分配空间。
sub esp, 0cch;减去的值根据程序而定
之后会根据情况看是否保存某些特定的寄存器(EBX,ESI和EDI)
之后ebp的值会保持固定。此后局部变量和临时存储都可以通过基准指针EBP加偏移量找到了
在函数执行完毕,控制流返回到调用者的函数(caller)之前会进行下述操作
pop edi
pop esi
pop ebx
mov esp,ebp
pop ebp
Ret
所谓有始有终,这是会还原上面保存的寄存器值,之后还原esp的值(上一个函数调用之前的esp被保存在固定的ebp中)与ebp值。这一过程被称为还原现场之后通过ret返回上一个函数。
栈帧ebp,esp详解相关推荐
- 栈帧%ebp,%esp详解
首先应该明白,栈是从高地址向低地址延伸的.每个函数的每次调用,都有它自己独立的一个栈帧,这个栈帧中维持着所需要的各种信息.寄存器ebp指向当前的栈帧的底部(高地址),寄存器esp指向当前的栈帧的顶部( ...
- ebp 函数堆栈esp_函数参数压栈,栈帧ebp,esp怎样移动的?
压栈一次esp-4,ebp不变 esp是栈顶指针寄存器,堆栈操作只和esp有关 比如有一个函数a,有两个参数,一般是这样的 PUSH 1 参数2压栈,esp-4 PUSH 2 参数1压栈,esp-4 ...
- 汇编-栈帧-寄存器esp, ebp
转载 原文地址 栈帧%ebp,%esp详解 分类专栏: 汇编 首先应该明白,栈是从高地址向低地址延伸的.每个函数的每次调用,都有它自己独立的一个栈帧,这个栈帧中维持着所需要的各种信息.寄存器ebp指向 ...
- Java堆和栈的区别/联系详解
Java堆和栈的区别/联系详解 关于Java中堆栈内存的知识,算是基础知识,和C语言中的指针有一些类似,面试中也经常会被问到,特别是跟Java和C都有关的开发工作. 一.堆栈的联系 在Java中,内存 ...
- dicom多帧转换_Python解析多帧dicom数据详解
概述 pydicom是一个常用python DICOM parser.但是,没有提供解析多帧图的示例.本文结合相关函数和DICOM知识做一个简单说明. DICOM多帧数据存储 DICOM标准中关于多帧 ...
- 【数据结构】共享栈详解 判断共享栈满条件栈顶指针变化详解记忆方法例题
摘要:简单易懂,详细地介绍共享栈概念,指针,判断共享栈栈满条件以及记忆方法等 目录 共享栈概念 栈顶指针&变化详解 栈顶指针种类的记忆方法 判断栈满条件 判断栈满条件的记忆方法 例题 解题思路 ...
- 顺序栈基本操作(入栈和出栈)C语言详解
#include <stdio.h> #include <stdlib.h> /*顺序栈基本操作(入栈和出栈)C语言详解栈的具体实现(1)顺序栈(2)链栈栈的应用(1)回退 ( ...
- 利用Animation控件制作帧动画过程详解
利用Animation控件制作帧动画过程详解 前言 通过Animation控件来达到序列图的播放(素材和示例视频在文章末尾) 一.序列图 (此素材为已经分割好的序列图) 如若序列图在一张图片上,请参考 ...
- 【genius_platform软件平台开发】第五十八讲:Linux系统之V4L2视频驱动-VIDIOC_REQBUFS向驱动申请帧缓冲代码详解
VIDIOC_REQBUFS向驱动申请帧缓冲代码详解 1. 概述 2. 应用层 3. 内核驱动 3.1 vb2_ioctl_reqbufs函数 3.2 vb2_core_reqbufs函数 3.3 _ ...
最新文章
- 数据中心机房布线设计方案
- MYSQL专题-使用Binlog日志恢复MySQL数据
- 【Java报错】借助@PostConstruct解决使用@Component注解的类用@Resource注入Mapper接口为null的问题(原因解析+解决方法)
- html添加背景音乐记事本,肿么在用记事本写的html网页中添加视频
- 用fft对信号进行频谱分析实验报告_示波器上的频域分析利器,Spectrum View测试分析...
- mysql 用户授权
- Python 最强编辑器PyCharm详细使用指南!
- CSC 121, 122.. MAT 181, 182, 252, 271, 281, 474.. ECN 272, 273, 372, 472
- python时间显示_python脚本之日期格式显示
- mssql linux性能,MSSQL 的Top 和 MAX 效率测试
- 智能语音升级用户体验,标贝以创新优势布局儿童有声内容市场
- 实验1-6 输出带框文字 (5 分)
- 2017 ACM-ICPC乌鲁木齐网络赛 G. Query on a string(KMP+树状数组)
- GitHub 使用教程图文详解(转)
- Oracle StorageTek磁带库产品线或将终结
- python往npy写入数据_数据存储在*.npy中的方式是什么?
- latex加下划线_Latex学习系列之粗体、斜体和下划线
- WordPress使用邮箱服务功能
- 支付宝APP支付集成文档
- LCD显示异常分析——撕裂(tear effect)
热门文章
- Delphi 鼠标模拟点击
- 开源备份工具duplicity支持阿里云OSS后端存储
- HaLoop—适用于迭代计算的Hadoop
- meda中的一些小事项
- ROS项目开发实战(三)——使用QT进行ROS的GUI界面设计(详细教程附代码!!!)
- 室内定位技术的应用及室内定位技术的种类-新导智能
- el-table大数据量渲染卡顿的一种思路
- 《像三国》3D动效制作经验分享
- luat c语言开发例程,Luat实例教程:tcp透传
- bcm4322linux驱动下载,苹果MAC BOOK PRO 5.5 2009年中 安装fedora26——broadcom BCM4322 无线驱动在fedora上的安装...