這一節主要講述8086/8088 存儲器分段的概念。
目的
從8086 CPU開始采用了分段的方法管理存儲器,只有充分理解存儲器分段的概念和存儲器邏輯地址和物理地址的關系,才能有助於我們掌握8086/8088匯編語言。
存儲器分段的原因
在此之前,我假設大家都理解存儲地址以及大端小端的概念。如上圖所示為存儲器的示意圖。那么為什么要引入分段的概念。
其實,8086/8088引入存儲器的分段是有原因的。我們都知道8086/8088 CPU有20根地址線,這樣可以直接尋址的物理地址空間為1M字節(存儲單元以字節為單位),范圍是00000H至FFFFFH。但是我在前一節介紹中說到8086/8088 CPU的寄存器都是16位,那么在傳輸地址時顯然一次只能傳輸16位有效地址,也就是只足夠訪問64K字節地址空間。為了實現尋址1M字節物理空間,8086/8088引入了分段的概念。
存儲器分段的概念
所謂分段,就是可以根據需要把1M字節地址空間划分為若干邏輯段。每個邏輯段必須滿足如下兩個條件:
1. 邏輯段的開始地址必須是16的倍數,因為段寄存器長為16位;
2. 邏輯段的最大長度為64K,因為指針寄存器長為16位。
那么1M字節地址空間最多可划分成64K個邏輯段,最少也要划分成16個邏輯段。邏輯段與邏輯段可以相連,也可以不相連,還可以部分重疊。
這種存儲器分段的方法不僅有利於實現尋址1M字節空間,而且也十分有利於對1M字節存儲空間的管理。如下圖所示為存儲器邏輯段的一種划分。
存儲地址形成
要訪問某個存儲單元,根據我們划分的邏輯段,計算存儲單元的地址與所在段的起始地址的差值,稱段內偏移(簡稱偏移)。
在整個1M地址空間中,存儲單元的物理地址等於段起始地址加上段內偏移。物理地址計算公式如下所示:
物理地址 = 段值 * 10H + 段內偏移
舉個例子:用16進制表示的邏輯地址1234:3456H所對應的存儲單元的物理地址為12340H+3456H=15796H。
其中,段值由段寄存器給出,段內偏移可由指令指針IP、堆棧指針SP和其他可作為存儲器指針使用的存儲器(SI、DI、BX和BP)給出,段內偏移還可以直接用16位數給出。
段寄存器的使用
當然,段寄存器的使用也是有規定的。在8086/8088 CPU中有四個段寄存器,可以保存四個段值,但這四個段分工不同。如下圖所示為段和段寄存器的引用。
-
在取指令時,CPU會自動引用代碼段寄存器CS,再加上由IP所給出的16位段內偏移,得到要取指令的物理地址。
-
當涉及堆棧操作時,CPU會自動引用堆棧段寄存器SS,再加上由SP所給出的16位段內偏移,得到堆棧操作所需的物理地址。
-
當段內偏移涉及BP寄存器時,缺省引用的段寄存器也為堆棧段寄存器SS。
-
在一般數據存取的情況下,則自動選擇數據段寄存器DS或附加段寄存器ES,再加上16位偏移,得到存儲器操作數的物理地址。此時的16位偏移有多重可能性,取決於指令的尋址方式,下一節將會講到。
通常如果整個程序不超過64K字節,那么使用1個64K字節的段就可以了;如果程序的數據區長度超過64K字節,那么就要在兩個或多個數據段中存取數據,這只需要改變數據段寄存器內的段值就可以了。最后,附上段寄存器的引用規定表。