一.什么是“栈”
“栈”的概念,是指它的访问规则。二.“栈”在内存中的实现
“栈”的定义是,最后存入的东西,总是第一个被取走。
如下图,我们放入一个整形数据18
![]()
文章图片
再放入一个整形数据20![]()
文章图片
注意,我们放的顺序是18 20 ,可当拿出数据时,先出来的却是20,后出来的是18。
就像是我们向木桶里放苹果,最后放进去的苹果是最先拿出的。
这是栈区别于其他结构的主要特点,即“后入先出”((last in first out)。
![]()
文章图片
在各种计算机系统中,最常见的栈实现方式如图所示。
它是由一段连续内存空间和一个寄存器(栈指针)组成。
栈指针是一个寄存器,它始终指向栈的顶部(即最近被压入的元素)。
每个被压入栈中的元素,在内存空间里占据一个独立的位置。

文章图片
我们把放入数据成为压栈(一个苹果压在另一个苹果上面)。
首先,我们压入(PUSH)数据18,栈指针TOP移动,指向最后压入的值。

文章图片
我们把弹出(POP)数据成为出栈(把一个苹果从另一个苹果上面拿走)。
上图中,我们压栈三次,出栈两次,TOP指针下移两次,指向最后压入的值。
三.函数栈帧的创建和销毁 1.我们先了解寄存器的概念

文章图片
2.让我们以以下代码为例
int Add(int x, int y)
{
int z = 0;
z = x + y;
return z;
}int main()
{
int a = 10;
int b = 20;
int c = 0;
c = Add(a, b);
printf("%d", c);
}
每一个函数调用,都要在栈区上创建一块空间。进入main函数,ebp和esp维护main函数的函数栈帧
正在调用哪个函数,ebp和esp就维护哪个函数的函数栈帧

文章图片
我们按下F10,右键转到反汇编,可看到以下代码

文章图片
由于main函数是由__tmainCRTStartup调用的,
先分配__tmainCRTStartup的函数栈帧。

文章图片
观察反汇编,第一行有push ebp
我们把ebp压入栈中,sep顺势上移指向ebp

文章图片
我们看下一行
mov ebp,espmov是把后面的值给前面,
esp存的是地址,因此ebp上移到esp的位置上
sub esp,0e4hesp地址减小了0e4h,向上移到低地址的某个位置
如下图所示:

文章图片
而他们之间的空间就是为main函数开辟的

文章图片
我们继续向下走:

文章图片
遇到三个PUSH,在顶上压进三个元素。

文章图片
继续向下:
lea edi ebp-04ehlea即 Load effective address
诶嘿,好熟悉的04eh
mov ecx 39h要把从刚刚edi开始向下的39h次double word 初始化为 0CCCCCCCCh
mov eax 0CCCCCCCCh
rep stos dword ptr es :[edi]

文章图片
我们继续:

文章图片
ebp-8处放置a

文章图片
经过验证,b和a隔了两个字节

文章图片
到这里,我们就明白了局部变量是如何创建的。
【噬人之风|这是我的“栈”争】首先我们为函数调用创建函数栈帧,在函数栈帧里找到一些空间,把变量放进去。继续向下:

文章图片
mov eax,dword ptr [ebp-14h]ebp-14h,这不是b吗?
push eax
把b的值放进eax里
压栈eax
同理得:

文章图片
call指令调用函数,又把下一条指令的地址压栈
进入Add函数

文章图片
进行同样的处理,可得:

文章图片

文章图片
把ebp+8的值给eax,这不是之前压栈的a吗
把ebp+12的值和ebp+8的值求和给eax,这不是a+b吗
最后把ebp-8的值(z)给寄存器eax

文章图片
pop三次

文章图片
mov esp,ebp把ebp赋给esp,esp指向ebp
pop ebppop之后,ebp回到main函数的函数栈帧底部
esp向下移动一位,回到main函数的函数栈帧顶部

文章图片
这块空间又由esp和ebp维护。
retret返回call指令下一条指令的地址。

文章图片
add esp,8至此,esp+8,a和b的空间被销毁
并把z传出。
推荐阅读
- c语言|leetcode707 设计链表 (C语言实现)
- C语言标准库|C语言保留字
- C进阶|C语言深度解析之六(自定义类型详解(结构体+枚举+联合))
- C语言重难点进阶|自定义类型详解(结构体+枚举+联合)【C进阶】
- C语言|C语言--自定义类型详解(结构体+枚举+联合)
- C语言初阶|自定义类型详解(结构体+枚举+联合)
- html|自定义类型~结构体~位段~枚举~联合~超详解~一遍就会
- 小程序|C语言实现通讯录
- C语言笔记|c语言入门笔记