栈是一种只能在一端进行插入或者删除操作的数据结构(比如弹夹,最后压入的子弹最先别射出)
现今的cpu都有栈的设计,以<span style="color:red">**字**</span>为单位
字通常分为若干个字节(每个字节一般是8bit)。
在存储器中,通常每个单元存储一个字。因此每个字都是可以寻址的。
字的长度用位数来表示, 32位系统则32位为一个字,64位系统以64位为1个字,这里讨论的的8086为16位为一个字
>[info]入栈:push 将会一个新的元素放到栈顶
出栈:pop 从栈顶取出一个元素
特征: 后进先出
![](https://img.kancloud.cn/eb/e0/ebe04f143b16f99a91b87e6dd1af7e91_814x645.gif)
赋值0123H给cpu寄存器ax,然后通过push ax 将指针指向栈顶最后将寄存器中的值压入内存中
上面的例子是将1000H作为栈使用的那么:
1、CPU如何知道一段内存空间被当作栈使用?
8086CPU中,有两个与栈相关的寄存器:
* 栈段寄存器SS:存放栈顶的段地址
* 栈顶指针寄存器SP:存放栈顶的偏移
2、执行push和pop的时候,如何知道哪个单元是栈顶单元?
任意时刻, SS:SP指向栈顶元素。
**例子:**
将10000H~10001H-1(1000FH)这段空间作为栈
```
mov ax,1000H
//栈段地址设为1000H
mov ss,ax
//将栈顶指针设为0010H
mov sp,0010H
```
8086是16位一个字(一个字等于一个存储单元),栈操作的是字
![](https://img.kancloud.cn/4f/e6/4fe65c82ff97f1d39c7bc95bf1647118_299x260.png)
```
mov ax,001AH
mov bx,001BH
push ax
puh bx
```
![](https://img.kancloud.cn/c1/16/c116c1025cd9875ba031f4c7bc2617f1_533x487.png)
![](https://img.kancloud.cn/2f/aa/2faab2a64ff8cfa708b04611bc18e810_746x182.png)
```
pop ax
pop bx
```
注意AX与BX发生了交换 ,此时 ax=001BH bx=001AH
![](https://img.kancloud.cn/ad/6c/ad6c2066acd56b9fc51b3b462990d24b_731x166.png)
## **超界问题**
执行入栈(push)时,栈顶会超出栈空间
执行出栈(pop)时,栈顶也会超出栈空间
8086CPU不保证对栈的操作不会超界:
8086CPU只知道栈顶在何处(由SS:SP指示),不知道程序安排的栈空间有多大。
我们在编程的时候要自己操心栈顶超界的问题,要根据可能用到的最大栈空间,来安排栈的大小,防止入栈的数据太多而导致的超界;防止出栈时栈空了仍然继续出栈而导致的超界。