函数的调用--栈帧

原创 2018年04月16日 12:48:15

对于函数的调用过程的了解层面你是否还停留在仅仅如下图所示的程度:
这里写图片描述

只知道大致过程而对于具体过程还不够了解,没有关系通过这篇博客,希望我们彼此都可以更深一层的了解函数具体的调用过程。

一. 什么是栈帧?

C语言中,每个栈帧对应着一个未运行完的函数,栈帧中保存了该函数的返回地址和局部变量。栈帧也叫过程活动记录,是编译器用来实现函数调用的一种数据结构。从逻辑上讲,栈帧就是一个函数执行的环境。
栈是从高地址向低地址延伸的。每个函数的调用的每一次调用,都有它自己独立的一个栈帧,这个栈帧保存着调用过程中所需要的各种信息。寄存器ebp指向当前栈帧的底部(高地址),寄存器esp指向当前栈帧的顶部(低地址)。

二. 我们用一个简单函数的调用来说明调用的过程

#include<stdio.h>
#include<stdlib.h>
int ADD(int x, int y)
{

    int z = 0;
    z = x + y;
    return z;

}
int main()
{
    int a = 10;
    int b = 15;
    int ret = 0;
    ret=ADD(a, b);
    printf("%d\n", ret);
    system("pause");
    return 0;
}

1.每一次函数的调用都要开辟空间,这块空间是由esp和ebp这两个寄存器来维护的。
2.push ebp
将ebp的值压到栈中,并且esp减小4个字节
3.mov ebp,esp
将esp的值给ebp
sub esp,0E4h
4. 用esp的值减去0E4h,esp变小,为main函数预开辟空间,用来存储函数内部定义的局部变量
5. push ebx
push esi
push edi
在栈顶压进去ebx、esi和edi,esp向上移动
6.lea edi,[ebp-0E4h]
mov ecx,39h
rep stos dword ptres:[edi]
从ebp-0E4h开始的位置向下拷贝eax中的内容0cccccccch ,39h次,每次拷贝4个字节
7.mov dword ptr [a],0Ah
mov dword ptr [b],0Fh
mov dword ptr [ret],0
将a、b和ret的值从栈底往上分别存储起来
8. mov eax,dword ptr [b]
push eax
mov ecx,dword ptr [a]
push ecx
call _ADD (0104112Ch)
add esp,8
mov dword ptr [ret],ea
将b的值给eax,将a的值给ecx,这里的a和b与main中的值虽然相同但是存储空间不一样,所以说函数调用过程中的形参是实参的临时拷贝。然后存储call指令下一条指令的地址,再将main函数的ebp存起来,以便函数调用完可以返回到main函数的栈空间。
9.push ebp
mov ebp,,0CCh
push esi
lea edi,[ebp-0CCh]
mov ecx,33h
mov eax,0CCCCCCCCh
rep stos dword ptr es:[edi]
跳转到ADD函数,同之前main函数执行之前一样为ADD函数开辟空间并且进行初始化
10. mov dword ptr [z],0
将z的值存储起来
11.mov eax,dword ptr [x]
add eax,dword ptr [y]
mov dword ptr [z],eax
计算z=x+y;这里的x和y调用的是之前存储的形参,然后将25赋给z
11. pop edi
pop esi
pop ebx
函数调用完对自己所创建的栈空间进行销毁
12. mov esp,ebp
13.pop ebp
将刚才存储的ebp给esp,回到main函数的ebp,调用完ADD函数后回到main函数中调用ADD函数的位置继续执行下一条指令
如下图所示
这里写图片描述

栈帧---函数调用原理

下面我通过一个简单的实例来分析函数调用原理------栈帧 首先应该明白,栈是从高地址向低地址延伸的。每个函数的每次调用,都有它自己独立的一个栈帧,这个栈帧中维持着所需要的各种信息。 寄存器ebp指向...
  • dream_1996
  • dream_1996
  • 2016-12-23 23:27:16
  • 1012

函数调用过程原理及栈帧分析

一、栈帧 栈帧:“栈帧也叫过程活动记录,是编译器用来实现过程/函数调用的一种数据结构。 实际上,可以简单理解为:栈帧就是存储在用户栈上的(当然内核栈同样适用)每一次函数调用涉及的相关信息的记录单元...
  • yangle4695
  • yangle4695
  • 2016-08-09 22:34:52
  • 492

函数调用过程——栈帧

函数的调用是一个过程,那么在函数的调用过程中要开辟栈空间,用来对本次函数的调用中需要的临时变量保存。这块空间叫栈帧。这个过程调用包括将数据和控制从代码的一部分传递到另一部分。过程调用的任务:为过程的局...
  • weixin_40921797
  • weixin_40921797
  • 2017-12-06 20:25:27
  • 120

【C】函数的调用过程,栈帧的创建和销毁

每一次函数调用都是一个过程,这个过程我们称之为:函数的调用过程。 函数调用过程要为函数开辟栈空间,用于本次函数的调用中临时变量的保存、现场保护。这块栈空间我们称之为函数栈帧。 栈帧的维护需要我们了解e...
  • qq_37924645
  • qq_37924645
  • 2017-04-23 16:33:43
  • 159

函数调用栈帧过程带图详解

这里,我们来研究如下代码的栈帧过程。为了初学者理解汇编指令,所以编译环境是在vc++6.0下#include #includeint sum(int _a,int _b) { int c=0;...
  • IT_10
  • IT_10
  • 2016-10-31 22:29:29
  • 2194

C语言函数调用及栈帧分析

C语言函数调用及栈帧分析
  • Rxan1234
  • Rxan1234
  • 2015-11-16 10:00:54
  • 1489

函数的栈帧创建与销毁

#include #include int Add(int x, int y) { int z = 0; z = x + y; return z; } int main() { int a =...
  • baidu_37964044
  • baidu_37964044
  • 2017-08-07 22:43:22
  • 246

Windows x64 栈帧结构

Windows x64 栈帧结构 一、前言   Windows 64位下函数调用约定变为了快速调用约定,前4个参数采用rcx、rdx、r8、r9传递,多余的参数从右向左依次使用堆栈...
  • yy405145590
  • yy405145590
  • 2017-06-22 20:55:44
  • 463

C语言函数调用及栈帧结构

一、地址空间与物理内存 (1)地址空间与物理内存是两个完全不同的概念,真正的代码及数据都存在物理内存中。 物理储存器是指实际存在的具体储存器芯片,CPU在操纵物理储存器的时候都把他们当做内存来对待...
  • qq_29403077
  • qq_29403077
  • 2016-11-17 19:10:11
  • 3484

堆栈、栈帧、函数调用过程

一、堆和栈首先,栈是从高地址向低地址延伸的。每个函数的每次调用,都有它自己独立的一个栈帧,这个栈帧中维持着所需要的各种信息。程序对内存的使用分为以下几个区:(1)栈区(stack):由编译器自动分配和...
  • will130
  • will130
  • 2015-10-26 14:11:35
  • 595
收藏助手
不良信息举报
您举报文章:函数的调用--栈帧
举报原因:
原因补充:

(最多只允许输入30个字)