如今的CPU都有提供棧機制,8086也不例外。
8086提供的最基本的兩個指令就是push and pop.
1push ax ;將寄存器ax中的數據送入棧頂
2pop ax ;將棧頂的數據送入ax
我們知道CS:IP寄存器存放了下一條指令的段地址和偏移地址,那麼CPU是如何知道棧頂在哪吶? 顯然也有兩個寄存器專門存放棧頂的地址,那就是SS:SP寄存器,SS = 段地址, SP = 偏移地址
任意時刻,SS:SP都指向棧頂元素。push和pop指令執行時CPU將從SS和SP中獲得棧頂的地址。
push 有2步:
- SP -= 2 SS:SP指向棧頂前面的單元,以這個位置為新棧。
- 將AX中的內容送入 SS:SP 所指的位置.
110000H |_______|
2 |_______|
3 |_______|
4 |_______|
5 |_______|
6 |_______|
7 |_______|
8 |_______|
9 |_______|
10 |_______|
111000EH |__23___| <= SS:SP
121000FH |__01___|
110000H |_______|
2 |_______|
3 |_______|
4 |_______|
5 |_______|
6 |_______|
7 |_______|
8 |_______|
9 |_______| <= SS:SP: 換個位置
10 |_______|
111000EH |__23___|
121000FH |__01___|
110000H |_______|
2 |_______|
3 |_______|
4 |_______|
5 |_______|
6 |_______|
7 |_______|
8 |_______| ;來自ax寄存器的數據
9 |__54___| <= SS:SP: 換個位置
10 |__11___|
111000EH |__23___|
121000FH |__01___|
假設 10000H -> 1000FH 這段空間是棧,那麼棧空時,SS:SP在吶?
110000H |_______|
2 |_______|
3 |_______|
4 |_______|
5 |_______|
6 |_______|
7 |_______|
8 |_______|
9 |_______|
10 |_______|
111000EH |_______|
121000FH |_______| <= SS:SP: 我在這?
110000H |_______|
2 |_______|
3 |_______|
4 |_______|
5 |_______|
6 |_______|
7 |_______|
8 |_______|
9 |_______|
10 |_______|
111000EH |_______|
121000FH |_______|
1310010H |_______| <= SS:SP: 其實爺在這裡。
至於為什麼只要想想 SP -= 2 你就知道了。
關於爆棧
棧一旦爆了,SS:SP就會指到別的地方去。 這麼一想CPU應該會知道棧頂在哪裡。
每次push,pop都會檢查棧頂和棧底的位置,保證棧不會超。這麼一想美滋滋。
然而,8086CPU並沒有做這樣的設計。 它只知道棧頂在哪裡。不知道棧有多大。
換個說法就是:只知道下一條指令在哪裡,而不知道要處理的指令有多少條。