函数的调用过程——栈帧。

今天我们来看一下函数的调用过程与栈帧。

我们通过一段简单的代码和图示来介绍这个过程:

#include<stdio.h>
int add(int x,int y)
{
    int z = x + y;
    return z;
}
int main()
{
    int a = 0xaaaaaaaa;
    int b = 0xbbbbbbbb;
    int c = add(a, b);
    printf("run here!%d\n", c);
    return 0;
}

将这个过程用图示表示出来:

在cpu中,两个寄存器EBP、ESP分别指向栈的底端和顶端。

当程序开始运行时,先会创建两个变量a、b,

这时在栈中就会创建两段空间,地址中分别存放a和b的值,且由于a比b先创建,所以a先入栈,

即a的地址比b的地址高。

而EIP中存放的是main代码。

当进行运算时,在栈中会生成两个临时变量a、b(变量a、b的拷贝),

而临时变量生成的位置则是在栈顶,且参数赋值的顺序是从右向左进行。

此时转到汇编代码时,会出现很多命令,如:mov、call、add等命令代码。

mov eax,dword ptr [ebp-8]

这个操作是指:

将b([ebp-8]在这里指的是b)移动到eax寄存器中,eax是cpu中的寄存器,然后把eax里的b压入栈中,此时ESP寄存器指向b的位置。

mov ecx,dword ptr[ebp-4]

这段命令代码和上面的操作一致,不同的是这里的[ebp-4]指的是a。

这里的-4和-8指的是相对于ebp的偏移量。

call指令会执行两段操作:

1、将当前指令的下一条指令的地址压入栈中;

2、跳转至目标函数的地址开始过程调用。

所以当执行call操作时,会跳转到add函数中,执行后续的操作。

再接下来会执行一段ebp和esp指向位置的改变:

mov ebp,esp

这里指ebp将指向esp所指向的地方。

esp-44h

这里指将esp往小地址移。
完成这两步操作后,就完成了新的ebp和esp的指向。

再经过一系列操作后,我们会得到返回值。

其中会执行pop操作,释放之前临时变量所创建的空间。

这时过程调用会结束。

时间: 2024-10-09 14:01:33

函数的调用过程——栈帧。的相关文章

C函数的调用过程 &nbsp; 栈帧

C语言中,每个栈帧对应着一个未运行完的函数.栈帧中保存了该函数的返回地址和局部变量. 首先,栈是从高地址向低地址延伸的.寄存器ebp指向当前的栈帧的底部(高地址),寄存器esp指向当前的栈帧的顶部(低地址). 先来看一个代码 #include <stdio.h> void fun() {     int tmp = 10;     int*p = (int*)(*(&tmp + 1));     *(p - 1) = 20; } int main() {     int a = 0;

[Android Pro] 深入理解函数的调用过程——栈帧

cp :http://blog.csdn.net/x_perseverance/article/details/78897637 每一个函数被调用时,都会为函数开辟一块空间,这块空间就称为栈帧. 首先,我们了解一下不同种类的寄存器: (1)eax,ebx,ecx,edx :通用寄存器 (2)ebp:存放指向函数栈帧栈底的地址 (3)esp:存放指向函数栈帧栈顶的地址 (4)eip:程序计数器——保存程序当前正在执行指令的下一个指令的地址 接着我们以下面这段代码为例,深入到函数的调用过程中去: #

函数的调用过程(栈帧)

1.什么是栈帧? 栈帧也叫过程活动记录,是编译器用来实现函数调用过程的一种数据结构.C语言中,每个栈帧对应着一个未运行完的函数.从逻辑上讲,栈帧就是一个函数执行的环境:函数调用框架.函数参数.函数的局部变量.函数执行完后返回到哪里等等.栈是从高地址向低地址延伸的.每个函数的每次调用,都有它自己独立的一个栈帧,这个栈帧中维持着所需要的各种信息.寄存器ebp指向当前的栈帧的底部(高地址),寄存器esp指向当前的栈帧的顶部(低地址). 2.Add()函数的调用过程 我们以Add()函数为例深入的研究一

手动跟踪函数的调用过程【转】

转自:https://blog.csdn.net/ccjjnn19890720/article/details/6871036/ 今天是10月13号,不知道为什么日子过的如此的快,大概是假期的原因吧.在十一国庆以后,上了3天课又放假了...感觉研究生的生活越来越没有学生样子啦...老师在很久以前就安排了一个任务给我,叫我完成在arm板子上的视频显示,做过了前期的JPEG的显示,觉得这个问题本身不是很大.大概是自己对这种事情了解的太少,当真正的去接触的时候就觉得难度很大. 视频本身是有一帧一帧的数

使用IDA PRO+OllyDbg+PEview 追踪windows API 动态链接库函数的调用过程

http://bbs.pediy.com/showthread.php?p=1354999 标 题: [原创]使用IDA PRO+OllyDbg+PEview 追踪windows API 动态链接库函数的调用过程.作 者: shayi时 间: 2015-02-12,05:19:54链 接: http://bbs.pediy.com/showthread.php?t=197829 使用IDA PRO+OllyDbg+PEview 追踪windows API 动态链接库函数的调用过程. (本文同步更

函数递归调用过程中的调用堆栈的情况

为了加深对函数递归调用过程中的理解,本Demo程序特意在VS2008 C#控制台程序实现了阶乘的计算功能,用于观察函数递归调用过程中的调用堆栈的情况. 源码如下: using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace RecursiveTset { class Program { //阶乘的定义:n!=n*(n-1)!,特别的,1!=1:0!=1 //阶乘的实

函数调用过程栈帧变化详解

http://www.cnblogs.com/fxplove/articles/2574451.html 数调用另一个词语表示叫作 过程.一个过程调用包括将数据和控制从代码的一部分传递到另一部分.另外,它还必须在进入时为过程的局部变量分配空间,并在推出时释放这些空间.而数据传递,局部变量的分配和释放通过操纵程序栈来实现.在了解本文章之前,您需要先对程序的进程空间有所了解,即对进程如何使用内存?如果你知道这些,下面的内容将是很easy的事情了.为了您的回顾还是将简单的分布图贴出来,便于您的回顾.

函数堆栈调用过程

从内存的角度详细的分析C语言中的函数调用过程: 首先写一个测试用的代码: #include <stdio.h> int add(int x, int y) { int z = 0; z = x + y; return z; } int main() { int a = 1, b = 2; int c = 0; c = add(a, b); return 0; } 这是一个简单的的求和函数. 其次,让我们确定一下,程序是从哪里开始运行的: 调试程序,按一下F10(博主用的VS2013), 进入m

函数的调用原理——栈桢

函数调用过程------栈桢 例:剖析"比较两个数之间的大小关系,并把较大数返回"的调用原理: int Max(int x, int y) {                  int z = 0;                  if (x > y)                                 z = x;                  else                                 z = y;