- 堆栈:一块内存,操作系统在程序启动时就已经申请好了,供程序执行时使用(如存临时变量)。
与数据结构里的“堆栈”无关
如图:
命令行里输入EIP的s(…还不太清楚)
这里操作系统将内存编号为0022c000到00230000的这部分内存申请作为 堆栈。
程序从后往前用内存,(先从00230000开始)
若在程序执行过程中,这部分内存被用完了,就会出现内存泄漏,程序将终止。(比如递归)
如何知晓此时程序执行处,堆栈用到哪个位置了??
- ESP栈指针寄存器:
存储了当前堆栈用到哪个地方(内存编号)
上面未使用的堆栈,未必是零,所以这也是c语言中为什么局部变量要赋初值的原因。
当给后面的两个内存地址存数据
如图:
-
就会出现下图,此时,ESP上的内存地址未能自动更新
所以,还需要: -
SUB ESP ,8//因为这里使用了8个字节
-
释放临时变量的内存空间
(若3X4个字节不用了,比如(上图)栈指针从…BC到…C4)
ADD ESP,0xC//十六进制c是元素的第12个
1.PUSH指令
- 功能:将上述的mov和sub操作合并:
push 1
--------直接往堆栈中下一个内存地址存1,并更新ESP里的内存编号。
注意:无PUSH r8/m8
下面介绍一些操作:
ecx:计数寄存器
将ecx的值作为临时变量存入堆栈暂存
改变ecx的值
还原ecx的值
- push ecx
//ecx的数据存入堆栈区中,并且esp指向下一个- mov ecx,要改变的值
- mov ecx,dword ptr ds:[esp]
//将原来ecx的数据放回ecx中,此时的“栈顶”应该是原数据的内存编号,所以可以用[esp]- add esp 4//释放原数据的内存空间
2.pop指令
- 功能:
MOV,将栈顶元素复制给寄存器/内存
ADD,修改esp指向的内存编号,加4(取决于释放的空间有多少字节),释放栈顶空间
一些疑问:
- 此时:运行到0022ffbc
push 9后:
0022ffb8–00000009
为什么是这样?只能以四个内存块(一个内存块一字节)为移动单元吗
- 有个细节:
当前一次堆栈区显示的是0022ffe0时,按f8进入下一次push word ptr ds:[0x…],
堆栈区显示的是0022ffe2,(没有e0结尾的了)