跟我學彙編(三)暫存器和實體地址的形成
一、通用暫存器
對於一個彙編程式設計師來說,CPU中主要部件是暫存器。暫存器是CPU中程式設計師可以用指令讀寫的部件。程式設計師通過改變各種暫存器的內容來實現對CPU的控制。
不同的CPU,暫存器的個數、結構是不同的。8086CPU 有14個暫存器,每個暫存器有一個名稱。這些暫存器是:AX、BX、CX、DX、SI、BP、IP、CS、SS、DS、ES、PSW。在今後的學習中我們用到這些暫存器時就對這些暫存器進行介紹。
AX、BX、CX、DX四個暫存器可以存放一般性的資料,所以這四個暫存器稱為通用暫存器。在8086CPU中,暫存器都是16位的,可以存放兩個位元組的資料,所以表示的最大值是2^16-1。
8086CPU的上一代CPU使用的是8位的暫存器,所以為了保證程式的相容性,使的針對上一代CPU開發的彙編程式能夠在8086CPU上執行,8086將通用暫存器分成兩個8位的暫存器:
- AX可以分為AH和AL
- BX可以分為BH和BL
- CX可以分為CH和CL
DX可以分為DH和DL
以AX為例,如上圖所示。AX的0~7位為AL,8~15位為AH。對AX中存放的資料有兩種解釋方式,如果是看做16位的AX則表示20000,如果看做8位的暫存器,則AH表示78,AL表示32。
二、幾條彙編指令
下面我們來看一下彙編中兩個最常用的指令mov和add,下表展示了它們的用法。
注意:彙編指令是不區分大小寫的,所以寫成ADD AX,8和add ax,8的效果是一樣的。
我們結合著剛剛講過的暫存器來看一下彙編指令是如何改變暫存器中的內容的。
我們假定開始時,AX和BX中的資料都是0000H。
現在我們來分析一下最後的?是怎麼回事。最後一條指令執行之前AX=8226H,BX=8226H,如果執行ADD操作,則A的值應該是1044CH,但是AX是16位的暫存器,最大值就為FFFFH,所以超出16位的部分就會被省略,所以AX=044CH。
再來看看對AH和AL的操作例項:
我們還是假設,開始時AX和BX中的資料為0000H。
下面來看一下最後的?應該是什麼值,ADD AL,93H執行後AL的數值為158H,但是AL為8位暫存器最大隻能儲存FFH,所以超過8位的部分會自動省略,於是AX中資料就變成了0058H。
三、實體地址的形成
8086CPU是16位的結構,這就意味著字長是16位,暫存器的最大寬度為16位,運算器一次可以處理16位的資料,暫存器和運算器之間的資料通路為16位。
然而8086CPU卻有20位地址匯流排,可以傳送20位地址,所以能夠達到1MB的定址空間,但是由於是16位架構的CPU,所以如果僅僅從CPU內部簡單的將地址送出則只能形成16位的地址,定址能力也只有64KB,這可咋辦呢。
為了解決上述問題,8086CPU採用了一種使用兩個16位地址合成一個20位地址的方法來形成一個20位的實體地址,從而擴大了定址能力。
實體地址=段地址*16+偏移地址
地址加法器採用實體地址=段地址*16+偏移地址的方法用段地址和偏移地址合成物理地址。例如,8086CPU想要訪問123C8H的記憶體單元,此時,加法器就利用1230H和00C8H兩個地址形成123C8H這個地址。
我們可以用一個簡單的例子來描述一下這個思想,如下圖所示,假如學校、體育館和圖書館的位置如下:
假如你有一張可以寫4位數的紙條,那麼圖書館的位置可以被表述為2826,如果不幸你沒有4位的紙條只有兩張三位的紙條,那麼圖書館的位置就必須藉助上面的思想,我們可以用200和826兩個三位數字來表示,圖書館的位置就在200*10+826=2826m上。
四、段暫存器
上面我們一直說段地址,但實際上記憶體中並沒有分段,段的劃分來自CPU,由於8086CPU用基礎地址(段地址)*16+偏移地址=實體地址的方式給出記憶體的實體地址,使得我們可以用分段的方式來管理記憶體。我們可以認為10000H~100FFH的記憶體單元為一個段,段的起始地址是10000H,段地址為1000H,大小為100H;我們也可以認為10000H~1007FH、10080H~100FFH的記憶體單元組成兩個段,它們的起始地址為10000H和10080H,段地址為1000H和1008H,段大小為80H。
既然地址加法部件要用段地址和偏移地址形成實體地址,那麼這兩個地址就必須都被儲存下來。8086CPU有四個段暫存器:CS、DS、SS、ES。
CS和IP是8086CPU中兩個關鍵的暫存器,他們指示了CPU當前要讀取指令的地址。CS為程式碼段暫存器,IP為指令指標暫存器。如果CS中的內容為M,IP中的內容為N,那麼CPU就將從記憶體M*16+N單元開始,讀取一條指令並執行。也可以表述為如下:
8086機中,任意時刻,CPU將CS:IP指向的內容當做指令執行。
下面通過一組圖的方式展示8086CPU讀取、執行一條指令的過程。
初始狀態,CS:2000H,IP:0000H。
地址加法器利用CS和IP中的地址形成實體地址。
地址加法器將實體地址送入輸入輸出控制電路。
輸入輸出電路將地址送上地址匯流排。
從記憶體20000H單元開始存放的機器指令B8 23 01通過資料匯流排被送入CPU
輸入輸出電路將機器指令送入指令緩衝器。
讀取一條指令後,IP中值會自動增加,以使CPU可以讀取下一條指令,因為當前讀入的指令為3個位元組,所以IP的值加3。
執行控制器執行指令。
AX中的內容被改變。
後面的過程與這個過程是相同的,這裡不再畫出來了,因為文章的篇幅已經很長了。
注意:在8086CPU加電啟動後或復位後,CS和IP被設定為CS=FFFFH,IP=00000H,即8086CPU在剛啟動時,CPU從記憶體FFFF0H單元中讀取指令執行。
五、修改CS、IP的指令
那麼我們是否能夠通過指令改變CS和IP的值呢?答案是肯定的,但是不是通過MOV指令,8086提供了單獨的指令來改變這兩個暫存器的值。
1、若想同時改變CS和IP的值,可以用“JMP 段地址:偏移地址”的指令來完成。
例如:JMP 2AE3:3,執行後:CS=2AE3H,IP=0003H,CPU將從2AE33H單元讀取指令。
2、若想僅修改IP的內容,可以使用形如“JMP 某個合法暫存器”的指令來完成。
例如:JMP AX,指令執行前:AX=1000H,CS=2000H,IP=00003H,指令執行後:AX=1000H,CS=20000H,IP=1000H