相关文章推荐
1.栈是用来存储临时变量,函数传递的中间结果。
2.操作系统维护的,对于程序员是透明的。
我们可能只强调了它的后进先出的特点,至于栈实现的原理,没怎么讲?下面我们就通过一个小例子说说栈的原理。
先写个小程序:
void fun(void)
printf("hello world");
void main(void)
fun()
printf("函数调用结束");
这是一个再简单不过的函数调用的例子了。
当程序进行函数调用的时候,我们经常说的是先将函数压栈,当函数调用结束后,再出栈。这一切的工作都是系统帮我们自动完成的。
但在完成的过程中,系统会用到下面三种寄存器:
1.EIP
2.ESP
3.EBP
当调用fun函数开始时,三者的作用。
1.EIP寄存器里存储的是CPU下次要执行的指令的地址。
也就是调用完fun函数后,让CPU知道应该执行main函数中的printf("函数调用结束")语句了。
2.EBP寄存器里存储的是是栈的栈底指针,通常叫栈基址,这个是一开始进行fun()函数调用之前,由ESP传递给EBP的。(在函数调用前你可以这么理解:ESP存储的是栈顶地址,也是栈底地址。)
3.ESP寄存器里存储的是在调用函数fun()之后,栈的栈顶。并且始终指向栈顶。
当调用fun函数结束后,三者的作用:
1.系统根据EIP寄存器里存储的地址,CPU就能够知道函数调用完,下一步应该做什么,也就是应该执行main函数中的printf(“函数调用结束”)。
2.EBP寄存器存储的是栈底地址,而这个地址是由ESP在函数调用前传递给EBP的。等到调用结束,EBP会把其地址再次传回给ESP。所以ESP又一次指向了函数调用结束后,栈顶的地址。
其实我们对这个只需要知道三个指针是什么就可以,可能对我们以后学习栈溢出的问题以及看栈这方面的书籍有些帮助。当有人再给你说EIP,ESP,EBP的时候,你不能一头雾水,那你水平就显得洼了许多。其实不知道我们照样可以编程,因为我们是C级别的程序员,而不是ASM级别的程序员。
详细解析ESP寄存器与EBP寄存器     最近在看汇编码,经常在程序的开头看到ESP和EBP寄存器的出现,由于本人基础知识的不牢靠,便上网查阅相关的资料,可惜网上的资料都不给力,都只是流于形式,没有... 来自: 南浦 esp是栈指针,是cpu机制决定的,push、pop指令会自动调整esp的值;ebp只是存取某时刻的esp,这个时刻就是进入一个函数内后,cpu会将esp的值赋给ebp,此时就可以通过ebp对栈进行操... 来自: 因热爱而执着,因执着而成功。 原文: http://blog.csdn.net/zsJum/article/details/6117043一直对寄存器ESP和EBP的概念总是有些混淆,查看定义ESP是栈顶指针,EBP是存取堆栈指针... 来自: Robin Hu的专栏 基本概念:(1)ESP:栈指针寄存器(extended stack pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的栈顶。(2)EBP:基址指针寄存器(extended ba... 来自: yu97271486的成长历程 080483b4: 80483b4:      55                     push  %ebp 80483b5:      89e5                  mov   ... 来自: wzj5530的专栏 一直对寄存器ESP和EBP的概念总是有些混淆,查看定义ESP是栈顶指针,EBP是存取堆栈指针。还是不能很透彻理解。之后借于一段汇编代码,总算是对两者有个比较清晰的理解。下面是按调用约定__stdcal... 来自: zsJum的专栏 因为对堆栈的操作寄存器有EBP和ESP两个。EBP是堆栈的基址,ESP一直指向栈顶(只要有PUSH动作,ESP就自动减小,栈的生长方向从大往小,不需要手动改变ESP。)所以要压入EBP,然后再用EBP... 来自: 晚晴小筑 #includeintfunc(intparam1,intparam2,intparam3){intvar1=param1;intvar2=param2;intvar3=param3;printf("... 来自: BAOLIANG196的博客 参考一:EAX、ECX、EDX、EBX寄存器的作用一般寄存器:AX、BX、CX、DXAX:累积暂存器,BX:基底暂存器,CX:计数暂存器,DX:资料暂存器索引暂存器:SI、DISI:来源索引暂存器,D... 来自: 人生代码,代码人生。。。 eax,ebx,ecx,edx,esi,edi,ebp,esp等都是X86汇编语言中CPU上的通用寄存器的名称,是32位的寄存器。如果用C语言来解释,可以把这些寄存器当作变量看待。 比方说:a... 来自: 上善若泪 windows32位汇编的环境下0A10FF61 call     0A11FFAA0A10FF66 MOVEAX,DWORDPTRSS:[EBP+3C]call      CALL  地址1   功... 来自: comeonow的博客 本AI的汇编环境是32位80*86nasm就是这样。先讲下刚刚听那个视频感受,比人类给我讲的要直观些,毕竟是看着跟着汇编代码看olydbg里堆栈区。也不能说讲得多好,就是暂时性让我明白,这个汇编里堆栈... 来自: 努力专业 练习屠龙技 eax,ebx,ecx,edx,esi,edi,ebp,esp等都是X86汇编语言中CPU上的通用寄存器的名称,是32位的寄存器。如果用C语言来解释,可以把这些寄存器当作变量看待。比方说:addeax... 来自: chenlycly的专栏 可以看到,初始情况下,ebp此时值为0012FEDC,也就是栈帧的地址,而栈顶地址esp值为0012FDFC。可以看到两个值有一定的关系。而帧指针的地址较高。     然后我们让它执行前两句,push... 来自: u011555996的博客 一.概念分析经常看到下面这两句:pushl%ebpmovl%esp,%ebpesp是堆栈指针 ebp是基址指针 那两条指令的意思是 将栈顶指向 ebp 的地址 ————————————————————... 来自: 无聊的专栏 ebp和esp是32位的SP,BP esp是堆栈指针     ebp是基址指针 ESP与SP的关系就象AX与AL,AH的关系.32位CPU所含有的寄存器有:4个数据寄存器(EAX、EBX、ECX和ED... 来自: chenlycly的专栏 一.概念分析经常看到下面这两句:pushl%ebp movl%esp,%ebp ------------------------------------------------------------... 来自: chenglinhust的专栏 moveax,ebx //eax=ebxleaeax,[ebx+30]//eax=ebx+30pushpop //入栈,出栈pushaxpopax//全部入栈,全部出栈addeax,5//eax+=5... 来自: 南的专栏 EBP+C:secondparameterEBP+8:firstparameterEBP+4:returnaddressEBP: previousEBPEBP-4:localvariableEBP-8... 来自: 十八进 函数的工作借助于栈。栈在内存中是一块特殊的存储空间,它的存储原则是“先进后出”,最先被存储的数据最后被释放。esp被称为栈顶指针,ebp称为栈底指针,通过这两个指针寄存器保存当前栈的起始地址与结束地址... 来自: 经典的误导的专栏 ebp:作为函数调用的基址地址,指向函数在栈的起始位置esp:指向当前执行函数的栈顶指针eip:指向下一个将要执行的cpu指令在内存中的位置如果怀疑一个dump为堆栈溢出,可以通过观察这几个指针所指向... 来自: erikaIT的博客 3、缓冲区溢出之JMPESP本文属于原创,如有错误请指正。其中引用他人的部分已经标出,如涉及版权问题请联系本人这里不得不讲一讲JMPESP的原理了,在实验之前我一直没看懂他是如何试下跳转ESP之后回到... 来自: 大头的博客 正常情况下我们栈的寻址方式是EBP+偏移的方式来寻址的//保留调用前的栈底 PUSHEBP 这里会保留栈底 //提升堆栈 MOVEBP,ESP 我们可以知道这种方式EBP(栈底)寻址... 来自: 随心记 (1)ESP:栈指针寄存器(extendedstackpointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的栈顶。 由于栈的地址大小是从上到下从大到小,所以ESP指在栈的最底端。(... 来自: weixin_36627946的博客 首先明白一点:开启一个线程之后,会产生8M的栈空间,在这8M的栈空间中,只要有函数的使用,都会在这8M的基础上开启一个新的栈帧,而不是在开启一个栈 13发生跳转时将跳转指令的下一条指令保存进来也就是l... 来自: chengchaonan的博客 eax,ebx,ecx,edx,esi,edi,ebp,esp等都是X86汇编语言中CPU上的通用寄存器的名称,是32位的寄存器。如果用C语言来解释,可以把这些寄存器当作变量看待。比方说:addeax... 来自: gettogetto的博客 首先应该明白,栈是从高地址向低地址延伸的。每个函数的每次调用,都有它自己独立的一个栈帧,这个栈帧中维持着所需要的各种信息。寄存器ebp指向当前的栈帧的底部(高地址),寄存器esp指向当前的栈帧的顶部(... 来自: 波波诸葛伟 PS:EBP是当前函数的存取指针,即存储或者读取数时的指针基地址;ESP就是当前函数的栈顶指针。每一次发生函数的调用(主函数调用子函数)时,在被调用函数初始时,都会把当前函数(主函数)的EBP压栈,以... 来自: wangkr的专栏 在linux内核中使用的寄存器。运行时栈由cpu进行控制。使用的是SS、ESPSS:记录的是段选择器,用户程序不可以进程修改。ESP:指向堆栈内部特定位置的32位的指针。//一般用于指向内核栈位置。C... 来自: 码小农 EIP寄存器,用来存储CPU要读取指令的地址,CPU通过EIP寄存器读取即将要执行的指令。每次CPU执行完相应的汇编指令之后,EIP寄存器的值就会增加。 一、因为80386CPU的寻址范围是4GB,所... 来自: striver1205的专栏 1.EIP2.ESP3.EBP 1.EIP寄存器里存储的是CPU下次要执行的指令的地址。 也就是调用完fun函数后,让CPU知道应该执行main函数中的printf("函数调用结束")语句了。2... 来自: dadalan的专栏 函数调用是程序设计中的重要环节,本文就函数调用的过程进行分析。一、eip、ebp、esp介绍 EIP,EBP,ESP都是系统的寄存器,里面存储的是些地址,我们系统中栈的实现上离不开他们三个。 我知道栈... 来自: 一小平民 第一 栈首先我们需要了解一下在函数调用时候栈的结构  栈的生长方向由高地址向低地址生长,栈顶指针由sp或者esp确定,当压栈时sp减法操作 每一个函数都是一个栈框架(framestack)。 我们简单... 来自: hoppboy的专栏 以下是在读《深入理解计算机系统》前面的章节“程序的机器级表示”时,自己动手在linux上使用了gdb对一个简单的C程序进行反汇编,通过不懈的努力终于查清楚弄明白了绝大多数的语句。且均以注释的形式列在汇... 来自: Windness的技术生活 什么栈帧?从逻辑上讲,栈帧就是一个函数执行的环境:函数参数、函数的局部变量、函数执行完后返回到哪里等等。实现上有硬件方式和软件方式(有些体系不支持硬件栈)首先应该明白,栈是从高地址向低地址延伸的。每个... 来自: sinat_14840443的专栏 =问题= pushl%ebpmovl%esp,%ebp干嘛要这样?  -----------------------------------------------------------------... 来自: running_noodle的专栏 #includeintfunc(intparam1,intparam2,intparam3){    intvar1=param1;    intvar2=param2;    intvar3=par... 来自: fei的专栏 EIP寄存器里存储的是CPU下次要执行的指令的地址。即函数调用完后要执行的地址。EBP寄存器里存储的是栈的栈底指针,通常叫栈基址。这个是在将要进行函数调用时,由ESP传递给EBP的。即函数调用前的ES... 来自: qq_31202403的博客 修改my.ini文件加上default-character-set=gb2312设定数据库字符集alter database da_name default character set charset... 来自: 血色残阳的专栏 人类之所以进步,在于会使用工具我们知道,有代码比对工具;有版本控制控制工具比对同一个文件不同人修改的地方;还有eclipse工具提供的Compare History 工具;我同事比较“同情”我每次发布... 来自: skygreen_2001的专栏 网上关于caffe的安装教程非常多,但是关于每一步是否操作成功,出现了什么样的错误又该如何处理没有给出说明。因为大家的操作系统的环境千差万别,按照博客中的教程一步步的安装,最后可能失败——这是很... 来自: 张学志の博客 让我们用Validator框架来给SpringMVC实现验证功能吧 Validator框架源码地址:https://github.com/devefx/validator 完成这一章教程的要求 来自: devefx的博客 最近好长时间都没有写blog了,主要是因为最近工作上的事以及下载Android源码的事耽误的(下载源码这件事会在后续的blog中写道,这个真的很有意义呀~~),那么今天来写点什么呢?主要的灵感来自于早... 来自: Android应用安全防护和逆向分析-----作者 QT 创建文件夹 bool QDir::mkdir ( const QString & dirName ) const 创建一个子目录名为目录名。[喝小酒的网摘]http://blog.... 来自: 路楷的专栏 本篇文章是根据我的上篇博客,给出的改进版,由于时间有限,仅做了一个简单的优化。相关文章:将excel导入数据库2018年4月1日,新增下载地址链接:点击打开源码下载地址十分抱歉,这个链接地址没有在这篇... 来自: Lynn_Blog 最近在做一个每天定点从FTP自动下载节目.xml并更新到数据库的功能。首先想到用 FileSystemWatcher来监控下载到某个目录中的文件是否发生改变,如果改变就执行相应的操作,然后用timer... 来自: kongwei521的专栏 特征空间的隐式映射:核函数     咱们首先给出核函数的来头:在上文中,我们已经了解到了SVM处理线性可分的情况,而对于非线性的情况,SVM 的处理方法是选择一个核函数 κ(⋅,⋅) ,通过将数据映... 来自: redis的专栏 docx4j官方提供了一些例子,本文只是其中一部分应用的简单例子。需要注意的地方是页眉和页脚,必须创建对应关系才能起作用。页眉和页脚添加图片的时候,第二个参数sourcePart是必须的,调用的cre... 来自: 偶尔记一下 问题背景: 我要在一个表单里同时一次性提交多名乘客的个人信息到SpringMVC,前端HTML和SpringMVC Controller里该如何处理? 第1种方法:表单提交,以字段数组接收; 第2种... 来自: 一个情绪猿的脖克... 一. 密码学简介 据记载,公元前400年,古希腊人发明了置换密码。1881年世界上的第一个电话保密专利出现。在第二次世界大战期间,德国军方启用“恩尼格玛”密码机,密码学在战争中起... 来自: leolewin的博客 Java中的ThreadLocal类允许我们创建只能被同一个线程读写的变量。因此,如果一段代码含有一个ThreadLocal变量的引用,即使两个线程同时执行这段代码,它们也无法访问到对方的Thread... 来自: u011860731的专栏 最近买了max系统的笔记本,花了一万多,心疼不行不行的。之前的window 7 的有专门的window 远程连接服务器。Mac怎么办了,微软就开发出来了parallels desktop... 来自: 老程 花了几天,终于把matlab版的人脸检测运行成功了,虽然正确率不是很高,看着各种论文上的人脸检测正确率都出奇的高,我是不怎么相信的,有的论文连基于平均脸的人脸检测正确率都能达到98%,汗啊~~  也许... 来自: 海海人生 问题场景描述整个项目通过Maven构建,大致结构如下: 核心Spring框架一个module spring-boot-base service和dao一个module server-core 提供系统... 来自: 开发随笔 最近用软碟通制作了一个win7原版映像,但是在装新系统的时候发现了一个问题,进入安装界面后,显示没有找到驱动器,但是明明是差了U盘的,通过“shift+f12”调出命令行窗口,输入disk list命... 来自: g_newbie的博客 Settings界面结构简单分析Setting是android系统很重要的模块,这个模块并不是很复杂,这部分也一直在看,很多时候都是在看某个具体的选项,比如WLAN,蓝牙这样具体的源码,但是对于主界面... 来自: H_Gao的专栏 本文介绍如何使用VS2015作为编译开发环境,调用OpenCV3.31和Qt5.9.1写图像处理的GUI。 1.目录结构 假设我们要创建一个名为VideoZoom的工程,那么首先按下图构建目录结构... 来自: zhhp1001的博客 上一章只为大家介绍了Validator的后端验证功能,接下来就为大家介绍一下Validator前端功能,你会发现他的巧妙之处。 Validator框架源码地址:https://github.com... 来自: devefx的博客 Linux下安装mantis配置指... qq_34889607: 你好,请问你在网页配置mantis连接数据库那一块时有没有遇到过这种报错啊“INTERNAL APPLICATION ERROR”,我之前成功搭建过一次,但是笔记关于网页配置mantis连接数据库那一步没有截图,现在总感觉哪里不对劲。

Oracle中实例(Instanc... wjp867530559: 我问一下,那一个数据库,多个实例是什么关系?数据库集群是什么概念?为什么要有多个实例对一个数据库?帮忙解释一下,谢谢!很多书上解释不清楚。

软件测试经理是这样炼成的!(连载2) sun5smile: 看来测试也不是好当的。。。

堆栈中的EIP EBP ESP sun5smile: 多亏了你,谢谢

Linux下安装mantis配置指... huangjingxue110: 这个是成功的案例吗