首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

C语言函数的栈帧详解

EDI 目标索引寄存器,存放目标字符串指针 ESP 存放栈顶指针 EBP 存放栈底指针 汇编指令 用途 mov mov A,B 将数据B移动到A push 压栈 pop 出栈 call 函数调用 add...引用百度百科:C语言中,每个栈帧对应着一个未运行完的函数。栈帧中保存了该函数的返回地址和局部变量。从这句话中,可以提炼以下几点信息: 栈帧是一块因函数运行而临时开辟的空间。...在函数栈帧、局部变量创建完毕后,进行Add()函数运算过程: PLAINTEXT c = a + b; 00AA13E5 mov eax,dword ptr [ebp+8] 00AA13E8...3.3.4 函数返回 PLAINTEXT return c; 00AA13EE mov eax,dword ptr [ebp-8] 将返回值传递至寄存器eax中,因此在函数调用结束函数栈帧被销毁时...在函数拿到返回值后,开始出栈: PLAINTEXT 00AA13F1 pop edi 00AA13F2 pop esi 00AA13F3 pop

2.2K20

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

如图: 二、栈帧的建立 首先要明白几个地方:每一个函数都有自己的栈帧空间,并且独占自己的栈帧空间, 当前正在运行的函数的栈帧总是在栈顶。...然后继续执行下一条语句:mov ebp,esp即把esp的值赋给ebp,这样,ebp也就指向了现在esp的位置 然后sub esp 0C0h 这样就为main函数开辟了一段空间然后将ebx、esi、edi...如此一来,几乎所有的c函数都由如下两个指令开 始: push ebp mov ebp, esp 下一步,fun必须为它的局部变量分配空间,同时,也必须为它可能用到的一些临时变量分配 空间。...比如,foo中的一些C语句可能包括复杂的表达式,其子表达式的中间值就必须得有地方存放。...紧接着当被调用者执行完毕时将消除栈帧结构,调用pop指令。 在把程序控制权返还给调用者前,被调用者foo必须先把返回值保存在EAX寄存器中。其次,foo必须恢复EBX,ESI和EDI寄存器的值。

1.7K30
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    【C语言】函数——栈帧的创建和销毁

    ✨作者:@平凡的人1 ✨专栏:《C语言从0到1》 ✨一句话:凡是过往,皆为序章 ✨说明: 过去无可挽回, 未来可以改变 ---- 目录 前言 什么是栈 什么是函数的栈帧 认识相关寄存器和汇编指令...下面我们要先来理解一些概念 什么是栈 在学习C语言中,我们关注内存中的3个区域,栈区、堆区和静态区 那究竟什么是栈呢?...⏩ 栈(stack)是现代计算机程序里最为重要的概念之一,几乎每一个程序都使用了栈,没有栈就没有函 数,没有局部变量,也就没有我们如今看到的所有的计算机语言。...函数栈帧的销毁下 00BE177F pop edi //在栈顶弹出一个值,存放到edi中,esp+4 00BE1780 pop esi //在栈顶弹出一个值,存放到esi中,esp+4 00BE1781...pop ebp //弹出栈顶的值存放到ebp,栈顶此时的值恰好就是main函数的ebp,esp+4,此时恢复了main函数的栈帧维护,esp指向main函数栈帧的栈顶,ebp指向了main函数栈帧的栈底

    62610

    【C语言底层】函数栈帧的创建和销毁

    () { int a = 10; int b = 20; int c = 0; c =Add(a, b); printf("%d",c); return 0; } 最粗略的整体的逻辑 我们知道每一个函数调用都要在栈区创建一块空间...() 函数的上方,有兴趣的大家可以打开监视窗口查看一下,这里我们为了缩短篇幅只讲结果)(与push相对的叫做pop,出栈,从栈顶删除一个元素) 在我们创建 __tmainCRTStartup() 这个函数时...传参过程 然后mov push 给到eax和ecx call是调用函数,它会压栈一个00C21450,这是call指令的下一条指令,以便call返回时继续使用 这里的汇编语言指令在前面都说到过...ebp,此时两个指针指向相同的地方,上面的函数所占的空间被系统回收了,即Add函数被回收了 此时再pop最上面的ebp,这里面存放的是最开始main函数的栈底指针,这样我们就能很容易的找到main...函数栈底的位置,此时ebp指针回到这个位置,然后esp指向00C21450的这个位置,并且此时两指针之间的这一区域就是main函数所占的区域。

    10510

    c语言实现栈(顺序栈,链栈)

    个人主页: :✨✨✨初阶牛✨✨✨ 推荐专栏: C语言进阶 个人信条: 知行合一 本篇简介:>:讲解用c语言实现:“数据结构之"栈”,分别从"顺序栈"和"链栈"的接口讲解...."栈"不需要进行随机访问其中的元素,只能从栈顶访问,链表是可以完成的. 2.1 初始化"链栈" 对于链表实现的栈,如果不带头结点: 我们不需要特意去写一个初始化函数.只需要创建一个栈顶指针,将其初始化指向...(下面的代码是采用这种形式) //创建一个栈顶指针,并完成初始化 SLStackNode* SLStack = NULL; 如果是带头结点的单链表: 我们可以定义一个初始化函数,申请一个头结点(头结点的数据域不存数据...(ST* ps);//返回栈顶元素 void STDestory(ST* ps);//栈的销毁 接口实现区( stack.c) #include "stack.h" //初始化栈 void InitST...void STDestory(SLStackNode* ps);//栈的销毁 接口实现区(SLStack.c) #include "SLStack.h" //SLStackNode* InitStack

    30920

    【C语言】函数栈帧的创建和销毁(逐步分析)

    什么是函数栈帧 我们在写C语言代码的时候,经常会把一个独立的功能抽象为函数,所以C程序是以函数为基本单位的。 那函数是如何调用的?函数的返回值又是如何返回的?函数参数是如何传递的?...= 0; c = Add(a, b); printf("%d\n", c); return 0; } 首先我们先建立main函数的栈帧空间,但我们思考一下,main函数是不是也有可能被其他函数调用那...调用完就开始返回了,pop意思是跳出 ,把这三个元素先跳出 再将esp返回到ebp的位置 此刻esp指向的是我们先前放进的ebp在main函数底栈时的地址,把当时ebp在main函数底栈位置读取用pop...然后esp+8,跳出俩传参的空间 再三个pop,将edi,esi,ebx跳出去,到达main函数的空间。...最后将承载着z的值也就是两数和的值的寄存器eax,将值付给ebp-20h也就是c的地址  此时c就为30了  结论 局部变量是怎么创建的 创建好函数栈帧后,我们初始化一部分函数空间,而局部变量就在这个空间里分配一个空间

    15310

    C语言——F函数的栈帧的创建和销毁

    栈(stack)是现代计算机程序里最为重要的概念之一,几乎每一个程序都使用了栈,没有栈就没有函数,没有局部变量,也就没有我们如今看到的所有的计算机语言。         ...转入目标函数 jump:通过修改eip,转入目标函数,进行调用 ret:恢复返回地址,压入eip,类似pop eip命令 lea:预加载,装入有效地址的意思,它的操作数就是地址 3、解析函数栈帧的创建和销毁...,这就是局部的变量的创建和初始化 //其实是局部变量的创建时在局部变量所在函数的栈帧空间中创建的 //调用Add函数 c = Add(a, b); //调用Add函数时的传参 //其实传参就是把参数push...00BE177F pop edi //在栈顶弹出一个值,存放到edi中,esp+4 00BE1780 pop esi //在栈顶弹出一个值,存放到esi中,esp+4 00BE1781 pop ebx...//在栈顶弹出一个值,存放到ebx中,esp+4 00BE1782 mov esp,ebp //再将Add函数的ebp的值赋值给esp,相当于回收了Add函数的栈帧空间 00BE1784 pop ebp

    13010

    C语言:底层剖析——函数栈帧的创建和销毁

    一、究竟什么是函数栈帧      C语言的使用是面向过程的, 面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。...所以C语言的程序都是以函数作为基本单位的,如果能够深入理解函数,无疑对于c语言会有更深刻地理解,修炼自己的内功,那么函数是如何调用的?函数返回值是如何返回的?...栈(stack)是现代计算机程序里最为重要的概念之一,几乎每一个程序都使用了栈,没有栈就没有函数,没有局部变量,也就没有我们如今看到的所有的计算机语言。        ...3.5.5.6Add函数的栈帧销毁 此图为Add函数的栈帧销毁 pop         edi     在栈顶弹出一个值,存放到edi中,esp+4 pop         esi     在栈顶弹出一个值...相当于回收了Add函数的栈帧空间 pop         ebp       弹出栈顶的值存放到ebp,栈顶此时的值恰好就是main函数的ebp, esp+4,此时恢复了main函数的栈帧维护,esp

    62510

    C语言内功的修炼--函数栈帧创建和销毁

    目录 什么是栈帧 什么是栈 栈帧的创建与销毁 main函数调用过程  Add函数的调用过程 ---- 什么是栈帧 简单地说 程序的执行过程可看作连续的函数调用,而C语言中,每个栈帧对应着一个未运行完的函数...每个函数的每次调用(通常使用堆栈实现),都有它自己独立的一个栈帧 这个栈帧中保存了该函数的返回地址和局部变量维持着所需要的各种信息 所以栈帧也叫过程活动记录,是编译器用来实现过程/函数调用的一种数据结构...从逻辑来看 栈帧就是一个函数执行的环境:函数参数、函数的局部变量、函数执行完后返回到哪里等 ---- 什么是栈 在详解之前我们还得明白一点栈: 栈,也叫堆栈,是一种数据结构,具有先进后出的特点...(类似子弹上弹夹) 在函数栈帧创建过程中,内存从高地址往低地址使用 寄存器edp存放了指向函数栈帧栈底的地址(高地址) 寄存器esp存放了指向函数栈帧栈顶的地址(低地址) esp和ebp...中 从这里看来,函数返回值的传递实质上是通过寄存器传递的 ---- 函数结束,pop(出栈)指令,将edi, esi,ebx寄存器退出栈顶 并用mov(赋值)命令将ebp寄存器中的地址赋值给esp(ebp

    54220

    C语言栈的实现

    因为方便:试想一下我们要判断栈是否空就只需要判断top是否等于buttom,如果buttom指向栈底显然就会麻烦许多 下面我们先用C语言来实现一下: 首先我们需要对这个装东西的“盒子”定义,而这个盒子就是栈...,然后节点可以放在里面(不过实际上的代码是一个概念,只是形象的用了两个结构体表示) 回到上面的话题,栈定义完了,接下来就是栈的操作,栈操作主要有入栈(push)和出栈(pop),还有遍历输出,其次就是一些诸如清栈...如果你不delete它它就会一直在堆中,每出栈一次就有一个无用节点占用内存,所以我们还要设法把这个无用节点删除,因此我们需要引入一个临时变量 void pop(struct stack *sk){ node...*n=sk->top; sk->top=n->next; delete n; } 就像上面,另还要注意出栈需要考虑栈是否为空,我没有写 至此,一个C语言版本的栈及其主要操作就完成了,这也是我第一次写栈结构...,因为我用C++ stack sk; sk.push(5); //..

    3.9K40

    洛谷 || 栈(C语言)

    题目背景 栈是计算机中经典的数据结构,简单的说,栈就是限制在一端进行插入删除操作的线性表。 栈有两种最重要的操作,即 pop(从栈顶弹出一个元素)和 push(将一个元素进栈)。...栈的重要性不言自明,任何一门数据结构的课程都会介绍栈。宁宁同学在复习栈的基本概念时,想到了一个书上没有讲过的问题,而他自己无法给出答案,所以需要你的帮忙。...题目描述 宁宁考虑的是这样一个问题:一个操作数序列1,2,…,n(图示为 1 到 3 的情况),栈 A 的深度大于n。...现在可以进行两种操作, 将一个数,从操作数序列的头端移到栈的头端(对应数据结构栈的 push 操作) 将一个数,从栈的头端移到输出序列的尾端(对应数据结构栈的 pop 操作) 使用这两种操作,由一个操作数序列就可以得到一系列的输出序列

    1.3K30

    C语言----C语言内存函数

    1.这个函数在遇到\0的时候并不会停下来 2.如果source和destination有任何的重叠,复制的结果都是未定义的 memcpy函数最终返回的是目标空间的起始地址 //函数的一种写法: 这个函数最终返回的是目标空间的起始地址...: //函数的一种写法: //这个函数最终返回的是目标空间的起始地址 void* my_memcpy(void *dest, const void*src, size_t num) { assert...,非要使用,结果就是未定义的 //只负责不重叠的内存 函数的返回值是void*类型的数据 这个memcpy函数有三个数据 2.memmove--内存移动--使用和模拟实现 2.memmove--内存移动...//总之:这个拷贝是分三块区域的,最前面的一块区域满足dest<src //我们只能从前往后进行拷贝,不然会出错误 //而剩下的两块区域可以同时从后往前进行拷贝,那么我们就将这两块区域放在一起 在C语言标准中...,明确规定了memcpy只要能实现不重叠的拷贝就行,重叠的拷贝交给memmove 我们发现vs上面的库函数memcpy函数也能实现重叠内存的拷贝 我们在以后的拷贝中,我们可以用memmove,因为不管是重叠的还是不重叠的都能搞定

    11710

    C语言——函数

    导读 : 这篇文章主要讲解一下C语言函数的一些基本知识。 前言:函数的概念 C语言中的函数又常常被称为子程序,是用来完成某项特定的工作的一段代码。...从函数的定义角度:我们可以把函数分为库函数和自定义函数 一,库函数: 库函数是由C语言编译系统提供的,已经有一定功能的,我们只需在程序前包含有该函数原型的头文件就可以直接使用这些函数。...("yeah"); // printf就是C语言提供的有打印功能的库函数,不需要我们自己定义 } 寻找C中的库函数及其有关的头文件的网址(C/C++官方的链接): http://zh.cppreference.com...2,实参列表中的参数(即实参)可以是变量,常量和表达式 3,实参之间用逗号隔开 4,在C语言中,出了main函数,其余的函数调用前要有函数声明(原型) 函数声明 ret_type name(形式参数...C语言中的函数之间都是平行的,不分上下级。

    9910

    【C语言】函数

    其实在C语言也引入函数(function)的概念,有些翻译为:子程序,子程序这种翻译更加准确一些。 C语言中的函数就是一个完成某项特定的任务的一小段代码。这段代码是有特殊的写法和调用方法的。...C语言的程序其实是由无数个小的函数组合而成的,也可以说:一个大的计算任务可以分解成若干个较小的函数(对应较小的任务)完成。...同时一个函数如果能完成某项特定任务的话,这个函数也是可以复用的,提升了开发软件的效率。 在C语言中我们一般会见到两类函数: 库函数 自定义函数 2....库函数 2.1 标准库和头文件 C语言标准中规定了C语言的各种语法规则,C语言并不提供库函数;C语言的国际标准ANSIC规定了一些常用的函数的标准,被称为标准库,那不同的编译器厂商根据ANSI提供的C语言标准就给出了一系列函数的实现...结论:static修饰局部变量改变了变量的生命周期,生命周期改变的本质是改变了变量的存储类型,本来一个局部变量是存储在内存的栈区的,但是被static修饰后存储到了静态区。

    7310

    【C语言】函数

    其实在C语⾔也引⼊函数(function)的概念,有些翻译为:⼦程序,⼦程序这种翻译更加准确⼀些。     C语⾔中的函数就是⼀个完成某项特定的任务的⼀⼩段代码。...在C语⾔中我们⼀般会⻅到两类函数: 库函数 自定义函数 二、库函数 1.标准库和头文件     C语⾔标准中规定了C语⾔的各种语法规则,C语⾔并不提供库函数;C语⾔的国际标准ANSI C规定了⼀些常⽤的函数的标准...,相关的函数和类型等信息,库函数的学习不⽤着急⼀次性全部学会,慢慢学习,各个击破就⾏ 2.库函数使用方法 库函数的学习和查看⼯具很多,⽐如: C/C++官⽅的链接:https://zh.cppreference.com...⼀个⽂件中;我们往往会根据程序的功能,将代码拆分放在多个⽂件中    ⼀般情况下,函数的声明、类型的声明放在头⽂件(.h)中,函数的实现是放在源⽂件(.c)⽂件中,如: //add.c文件 int...修饰局部变量改变了变量的⽣命周期,⽣命周期改变的本质是改变了变量的存储类型,本来⼀个局部变量是存储在内存的栈区的,但是被 static 修饰后存储到了静态区。

    10910
    领券