美文网首页
栈中函数调用原理详解

栈中函数调用原理详解

作者: 细雨听风 | 来源:发表于2016-01-17 22:43 被阅读814次

一、eip、ebp、esp介绍

    EIP,EBP,ESP都是系统的寄存器,里面存储的是些地址,我们系统中栈的实现上离不开他们三个。 我知道栈的数据结构主要特点是 后进先处。它还有两个作用: 1.栈是用来存储临时变量,函数传递的中间结果。 2.操作系统维护的,对于程序员是透明的。

    下面我们就通过一个小例子说说栈的原理。

     先写个小程序:

void fun(void)

{

    printf("helloworld");

}

void main(void)

{

    fun()

     printf("函数调用结束");

}

当程序进行函数调用的时候,我们经常说的是先将函数压栈,当函数调用结束后,再出栈。这一切的工作都是系统帮我们自动完成的。但在完成的过程中,系统会用到下面三种寄存器:EIP、ESP、EBP。

当调用fun函数开始时,三者的作用。

EIP寄存器里存储的是CPU下次要执行的指令的地址。 也就是调用完fun函数后,让CPU知道应该执行main函数中的printf("函数调用结束")语句了。

EBP寄存器里存储的是是栈的栈底指针,通常叫栈基址,这个是一开始进行fun()函数调用之前,由ESP传递给EBP的。(在函数调用前你可以这么理解:ESP存储的是栈顶地址,也是栈底地址。)

ESP寄存器里存储的是在调用函数fun()之后,栈的栈顶。并且始终指向栈顶。

当调用fun函数结束后,三者的作用:

系统根据EIP寄存器里存储的地址,CPU就能够知道函数调用完,下一步应该做什么,也就是应该执行main函数中的printf(“函数调用结束”)。

EBP寄存器存储的是栈底地址,而这个地址是由ESP在函数调用前传递给EBP的。等到调用结束,EBP会把其地址再次传回给ESP。所以ESP又一次指向了函数调用结束后,栈顶的地址。

二、堆和栈

首先要清楚的是程序对内存的使用分为以下几个区:

栈区(stack):由编译器自动分配和释放,存放函数的参数值,局部变量的值等。操作方式类似于数据结构中的栈。

堆区(heap):一般由程序员分配和释放,若程序员不释放,程序结束时可能由操作系统回收。与数据结构中的堆是两码事,分配方式类似于链表。

全局区(static):全局变量和静态变量存放在此。

文字常量区:常量字符串放在此,程序结束后由系统释放。

程序代码区:存放函数体的二进制代码。

典型的内存区域分配如图所示:

其次是堆和栈的申请方式:栈由系统自动分配,速度较快,在windows下栈是向低地址扩展的数据结构,是一块连续的内存区域,大小是2MB。堆需要程序员自己申请,并指明大小,速度比较慢。在C中用malloc,C++中用new。另外,堆是向高地址扩展的数据结构,是不连续的内存区域,堆的大小受限于计算机的虚拟内存。因此堆空间获取和使用比较灵活,可用空间较大。

三、栈帧结构和函数调用过程

首先应该明白,栈是从高地址向低地址延伸的。每个函数的每次调用,都有它自己独立的一个栈帧,这个栈帧中维持着所需要的各种信息。寄存器ebp指向当前的栈帧的底部(高地址),寄存器esp指向当前的栈帧的顶部(地址地)。下图为典型的存取器安排,观察栈在其中的位置

入栈操作:push eax; 等价于esp=esp-4,eax->[esp];如下图

相关文章

  • 栈中函数调用原理详解

    一、eip、ebp、esp介绍 EIP,EBP,ESP都是系统的寄存器,里面存储的是些地址,我们系统中栈的实现...

  • iOS 如何实现Aspect Oriented Programm

    (接上篇) 五. Aspects hook过程详解 先看看函数调用栈的情况 从调用栈可以看出,Aspects ho...

  • 宏、普通函数、内联函数之间的区别

    普通函数 调用时向栈中push函数帧,调用结束后pop函数帧。编译器会在函数调用语句的前后,插入入栈和出栈的辅助代...

  • golang中defer的执行过程是怎样的?

    在同一个goroutine中: 多个defer的调用栈原理是什么?defer函数是如何调用的? 为了探究其中的奥秘...

  • 6. Oops栈回溯

    1. 解读系统崩溃2. linux中oops信息的调试及栈回溯3. 根据函数调用过程谈栈回溯原理 ESP的问题 虽...

  • Stack Queue

    在函数调用的过程中,操作系统使用函数调用栈来维护函数调用的状态。每个函数运行过程中有一段属于自己的栈帧结构,主要用...

  • 详解 JS 中 new 调用函数原理

    JavaScript 中经常使用构造函数创建对象(通过 new 操作符调用一个函数),那在使用 new 调用一个函...

  • 2017-07-17

    在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回...

  • 巧用函数栈实现栈的反转

    一、函数栈 函数的调用过程其实就是一个压栈的过程,在函数栈中,每个函数所占空间成为一个 栈帧。栈帧中保存着函数的形...

  • 函数调用栈平衡

    栈平衡 栈平衡:函数调用前后的栈顶指针指向的位置不变 内平栈 外平栈 内平栈: 指的是在函数调用返回之前使栈保持...

网友评论

      本文标题:栈中函数调用原理详解

      本文链接:https://www.haomeiwen.com/subject/lsrzhttx.html