初识堆栈
2018-12-21 本文已影响47人
豆瓣奶茶
什么是堆栈
引出堆栈
在学习堆栈之前,我们需要从之前寄存器和内存中引出堆栈,我们要思考堆栈有什么必要性?
现在假设我们需要一块内存,它可以满足如下功能
1.主要用于临时存储一些数据
- 能够记录存储了多少数据
- 可以很方便的找到需要的数据
对于第一条,有人说直接放寄存器不就可以了吗?但是如果我们有2个字节的数据,有5个字节的数据,都好说。但是如果我有几百,几千个数据呢?寄存器明显就不行了
还好有高人
还有在我们之前,有那么多厉害的人。有人设计出这样一块内存,虽然简单,但却刚好满足了上面我们的三个需求。
为了满足第二条,我们直接top-base;
对于第三条,比如我们存储了500个数据,我们需要第50个,我们直接base+50个单位的偏移就可以找到。突然又需要第200个数据,base+200单位的偏移就是。这里的单位是指byte
还需要注意一点,在window系统中堆栈是往低位扩展了,起初会选择一个值比较大的位置作为base,然后每次往低位扩展,top不断变小。
实验,自己实现堆栈
1.我们使用32位寄存器EBX和EDX作为栈顶和栈底 。
- 为了实验的方便,主要是DTDebug显示的方便。我们每次操作都操作4字节
压入数据
我们就选中内存地址0019FF74吧
MOV EBX,0019FF74 //栈底的内存地址(base)
MOV EDX,0019FF74 //栈顶的内存地址(top)
接下来我们有三种实现方式
方式一:
先存储数据,再移动栈顶
MOV DWORD PTR ds:[EDX-4],0xAAAAAAAA
SUB EDX,4
方式二:
先移动栈顶,再存储数据
SUB EDX,4
MOV DWORD PTR DS:[EDX],0xBBBBBBBB
方法三
先存储数据,再用LEA
mov dword ptr ds:[edx-4],0xCCCCCCCC
lea edx, dword ptr ds:[edx-4]
第二句话为什么不是这样
lea edx,byte ptr ds:[edx-4]
,暂时没有明白?
不就是取地址吗?为了一定要4个字节呢?
方法四:
先lea,再存储数据
读取数据
读取第N个数
方式一
方式二
弹出数据
不光要读取栈顶的数据,还需要将栈顶的位置进行移动
image.png
操作系统实现的堆栈
堆栈是软件设计常用的概念。如果每次我们需要的时候,都需要自己手动实现,效率也太低了。
为此,操作系统联合cpu给我们实现了堆栈。如何联合的呢?
cpu提供两个32位的寄存器,ESP和EBP,一个用来存储宅顶,一个用来存储栈底。其实对于cpu来说,这两个寄存器和其他的寄存器并没有什么特殊的地方,只是操作系统按照自己的习惯把他两区别对待了。这两个就用来存储栈顶和栈底,相当于cpu和操作系统的之间的约定。(突然想到了协议)
那之前我们所有的操作就可以再两个命令代替了
入栈用push
出战用POP