iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 8
3

學過資料結構的朋友應該都知道 棧 stack 的概念,棧就像一個開口向上的容器,可以將數據放入和取出,由於開口只有一邊,所以有 後進先出 LIFO 的特性,先放入的數據會被壓在下方,需要等上面的都被拿完後才能取出。

棧示意圖:

https://ithelp.ithome.com.tw/upload/images/20181023/2010686537hWOYC6XU.jpg

棧段暫存器

段暫存器有四個 CS、DS、SS、ES,前面已經介紹過 CS 代碼段暫存器和 DS 數據段暫存器,除去 ES 外,剩最後一個 SS 棧段暫存器。

8086 CPU 透過 SS 棧段暫存器SP 棧指標暫存器 實現棧的機制,SS + SP 會指向棧的 頂部,加入元素時將 SS - 2、取出元素時將 SS + 2,棧的操作是以 為單位,不能像 mov 一樣操作字節,所以加入和取出是以 2 個字節為單位。

有沒有人發現哪裡怪怪的,為什麼加入元素是用減而不是用加,因為組合語言棧的方向和我們習慣的陣列相反,陣列索引由 0 開始向後遞增,而棧是由 記憶體高位開始向低位遞減,所以加入元素才會用減的。

假設將記憶體 10000 到 1000F 當作棧,示意圖如下:

https://ithelp.ithome.com.tw/upload/images/20181023/20106865G9Ni4yjjal.jpg

棧頂初始時會位於棧的 最後一格再加一的位置,加入元素就往上移動 2 格、取出元素就往下移動 2 格。這裡的取出元素其實只是移動 SS 指標的位置,並不會真正的清除記憶體上的資料,只有當下次加入資料時才會將原資料覆蓋掉。

push 和 pop 指令

8086 CPU 提供了兩個指令來操作棧。

  • push: 將元素加入棧
  • pop: 從棧中取出元素

push 指令可分解為,先將 SS - 2,再將元素加入棧。
pop 指令可分解為,先將元素從棧中取出,再將 SS + 2。

用法:

push ax         ; push 暫存器
pop ax          ; pop  暫存器

push ds         ; push 段暫存器
pop ds          ; pop  段暫存器

mov ax, 2000H
mov ds, ax      ; 使用記憶體偏移地址需設置 ds 數據段暫存器
push [0]        ; push 記憶體
pop [0]         ; pop  記憶體

SP 溢位

接著用 Debug 工具執行下列指令,並將 SP 設為 0000H 看看。

mov ax, ff01
push ax
pop bx

觀察下方第一個 t 命令,因為執行 mov ax, FF01,AX 暫存器的值被改為 FF01。

接著執行 push 指令,因為 SP 的值為 0000 已經在整個棧的最頂端,所以再減 2 就發生了溢位,SP 跑到了底部 FFFE 的位置,由此可以看出 棧是一個循環結構,如果超過範圍就會從另一端開始,要小心不要因為循環而覆蓋到重要數據造成程式出錯。

最後執行 pop 指令後,SP 恢復到 0000,BX 正確被改變為 FF01。

https://ithelp.ithome.com.tw/upload/images/20181023/20106865QL9paoMH3c.jpg

棧越界

這裡的棧越界不是上面提到的 SP 溢位,而是透過 SS + SP 我們只能知道棧頂的位置,並不能知道這個棧的範圍和大小,例如 C++ 的 stack 就會去紀錄棧的大小,如果想從空的棧中取出數據就會引發例外狀況,如下。

https://ithelp.ithome.com.tw/upload/images/20181023/20106865ChoHjJc5pv.jpg

而 8086 CPU 的棧並沒有這樣的機制,我們並不能去設定棧的大小,只能知道棧頂的位置在哪,寫程式時我們會定義數據段、代碼段和棧段,如果不小心棧越界了,就可能覆蓋到其他段的數據造成程式出錯,因此在規劃棧段時需特別注意空間的配置以防棧越界。

結語

棧在組合語言中是個很重要的概念用途很廣,這樣講大家可能無法體會,舉 C 語言的函數為例,呼叫函數時會將當前暫存器的值和區域變數入棧,返回時再透過出棧還原之前的狀態,遞迴的呼叫也是這個原理,平常寫程式可能很少用到,但程式底層的應用卻非常廣,今天就到這裡摟,感謝大家觀看。


上一篇
[Day07] 字型數據的儲存和數據段暫存器
下一篇
[Day09] 回頭再看 Hello World
系列文
8086下16位元DOS組合語言學習筆記12
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
Homura
iT邦高手 1 級 ‧ 2018-10-23 20:35:06

stack 不是叫堆疊嗎?
棧這翻譯好像第一次聽過@@

看更多先前的回應...收起先前的回應...
暐翰 iT邦大師 1 級 ‧ 2018-10-23 20:43:45 檢舉

對岸這滿常使用棧這詞。

Homura iT邦高手 1 級 ‧ 2018-10-23 20:46:09 檢舉

暐翰
原來是對岸啊
我們系上的教授好像有點排斥對岸的名詞
以前我們班有人說幀數這詞
教授還說你是大陸人喔/images/emoticon/emoticon04.gif

暐翰 iT邦大師 1 級 ‧ 2018-10-23 20:48:51 檢舉

其實聽著看著習慣一下就好 XD
現在簡體技術文章雖然亂了點,但也有些可以參考、學習

Homura iT邦高手 1 級 ‧ 2018-10-23 21:34:31 檢舉

暐翰
也是
簡體技術文真的幫助到我蠻多的/images/emoticon/emoticon12.gif

哈哈哈,對~是對岸用語,
我參考的資料是對岸的,所以像 存儲器字節 這些都是。
/images/emoticon/emoticon37.gif

我要留言

立即登入留言