顺序栈
头文件
1 |
|
实现
1 | //My_SeqStack.cpp |
测试
1 | //TestStack.cpp |
链栈
头文件
1 | //LinkStack.h |
实现
1 | //LinkStack.cpp |
测试
1 |
1 |
|
1 | //My_SeqStack.cpp |
1 | //TestStack.cpp |
1 | //LinkStack.h |
1 | //LinkStack.cpp |
1 |
1 | //4字节入栈 |
1 | //8字节入栈 |
1 | //12字节入栈 |

可以理解为CPU中的变量
如何去标志一个栈?——栈底和栈顶指针。
esp:栈顶寄存器。
ebp:栈底寄存器。
参数入栈(C语言)
4字节参数(dword)入栈
8字节参数入栈
(>8字节)12字节参数入栈

C++中,只要是自定义类型,无论多大字节,都采用先esp上移开辟空间,之后分次赋值的方式(即方式3),即>8字节的情况。
函数栈帧开辟
其中,1、2步是为了保存现场。3、4步是开辟新的栈帧。



ebp=esp(让ebp上移到esp的位置)esp=esp-0**h(上移若干空间,开辟此函数的空间)0xcccccccc函数返回值
4字节返回值:将返回值先存到eax再赋给接收变量


8字节返回值:将返回值分开放到两个寄存器,再赋给接收变量




(>8字节)12字节返回值:

C++中,自定义类型都按照入栈一个调用方地址的方式
函数栈退出
esp=ebp(回缩栈帧)pop操作(即将pop的位置是esp指向的位置)。pop ebp,意为:ebp=pop,esp指向的是原来main的ebp地址,赋给ebp,同时esp下移4字节。则ebp回指到原来的位置。形成现场恢复。
ret),实际上,也是一个pop,返回保留的地址值,esp下移4字节。
当前演示的函数调用规则是依赖于C语言默认的调用约定__cdecl,其他的还有__stdcall/__fastcall。三种差异并不大,只是负责的事情不同,清除参数是调用方执行的,stdcall是被调用方执行的。
1 | struct Node __cdecl fun(int a, int b) |