外部結構就是封裝出來的輸入輸出引腳。8086/8088有40個引腳。
- 8086片內片外的資料匯流排都是16位元
- 8088片內16位元,而片外8位元
如此前緒論所說,部分引腳專用,部分引腳複用,複用部分需要掌握其時序。
CPU的這些引腳功能:
舉個例子講解一下這些引腳:
當CPU向外部(記憶體/IO介面)寫資料時,上圖的WR引腳應為有效(低電平)
RD是讀訊號。
而區分操作記憶體和I/O介面的是M/IO引腳
在此基礎上可以設計邏輯電路來控制更具體的事情,比如WR和M/IO連線一個或門,就能產生IOW訊號等。
8086CPU有20條地址線A19A<sub>16</sub>、A<sub>15</sub>A0,可以定址\(2^{20}\)位元組的空間,也就是1M空間,地址空間大小為1MB。
匯流排競爭:多個裝置埠同時啟用。
埠如下圖右下角部分所示:
具體而言,外設晶片是有手冊的,當我們操作顯示卡,就要查VGA相關的手冊,滑鼠和鍵盤就有另一個晶片來管理。
手冊上會詳細說明埠的作用,在程式中用指令向埠賦值即可。
上面提到,一個IO埠至少佔用一個IO地址----IO埠地址。根據埠地址和記憶體是否一起編址,有:
統一編址
獨立編制
舉個例子
某個I/O埠的地址為2000H,則存取如果要輸出資料到該埠,組合語言應該這樣寫:
mov AL,01H
;這裡是要輸出的資料量,僅是一個參考
;該課程中這裡要點一個燈
mov DX,2000H
mov DX,AL
;注意這裡跟記憶體的並不同,沒有中括號
不論CPU型號如何,其內部基本都有以下結構:
ALU:必須,算術邏輯運算
地址暫存器可以充當資料暫存器
資料暫存器不能充當地址暫存器
控制器:負責取指令,放在指令暫存器中,譯碼
I/O控制邏輯:與外部I/O打交道,使得CPU可以響應I/O裝置發出的中斷請求。
這部分要與其實跟計組沒多大差別了,要結合CPU"取指執行"的思想來理解。
有一個問題,地址匯流排20位,意味著可以定址1MB地址空間;而CPU內部暫存器只有16位元。
如何用16位元暫存器存放20位的地址資訊呢?
8086的設計是:講記憶體分為邏輯段,一個暫存器負責定址段,一個暫存器負責定址段內空間,也就是一個段內最多64KB(\(2^{16}\)byte)空間。
各種段基址暫存器以及指令暫存器就在上圖BIU右上角
這裡的轉化的具體過程就是在上圖的地址產生與匯流排控制單元進行的。
轉化公式為:
CS:IP(CS左移4位元+IP),也就是
(CS << 4) + IP
BIU右下角的指令佇列充當的是2.3節的IR指令暫存器的角色,8086中有6個位元組,8088中4個位元組。
這是兩個CPU內部結構唯一的區別。
總結,BIU負責外部記憶體取出指令、取出資料,並將取出的指令放入指令佇列,對應 「取指」。資料通過ALU匯流排直接送入EU。
總結放在前面:負責從指令佇列中獲取指令,對該指令譯碼並執行,對應「執行」。
這裡可以看出,指令佇列的存在,可以使得兩個部分的效能都得到提升。
而外部匯流排在上圖過程中始終處於忙狀態,匯流排的使用率也上升。
8086內部共有14個16位元暫存器:
通用暫存器 (EU左上角)
地址指標暫存器與變址暫存器
地址指標暫存器
SP:堆疊指標暫存器
BP:地址指標暫存器
BP與BX在做地址指標時的區別:
mov BX,002H mov BP,002H mov AL,34H mov [BX],AL;1 mov [BP],AL;2
1處AL值預設放到了資料段的BX偏移處,2處AL值預設放到了堆疊段的BP偏移處。
如果要使它們不預設,可以將上面程式碼錶示地址的中括號內加上它們的目的段基址暫存器如:
mov SS:[BX],AL ;此時BX表示堆疊偏移 mov DS:[BP],AL ;此時BP表示資料段偏移
變址暫存器
SI:源變址暫存器
DI:目的變址暫存器
找到的都是DS段的地址
變址暫存器中「變」的概念來自於8086對字串的處理。
具體涉及8086指令系統中的字串操作指令。
如將字串搬運到記憶體另一個位置,源字串的位置需要定義在DS:SI,目的字串的位置定義在DS:DI。
DS:SI==(DS<<4)+SI
當使用movsb或movsw(無運算元指令),自動從源字串搬運到目的字串。(兩者的區別是按位元組搬運和按字搬運)
在這個字串操作過程中,DI和SI是在自動增加的,所以其名字中的「變」不言而喻。
當DI和SI像BP一樣進行普通資料段操作時,不會自己增加。
段暫存器
8086組合程式結構分為若干邏輯段,組合後放到記憶體的不同段。
CS:程式碼段基址暫存器
DS:資料段基址暫存器
ES:附加資料段基址暫存器
SS:堆疊段基址暫存器
在程式碼段開始時,賦值DS ES SS,使其符合自己安排的位置,而CS由作業系統安排。
所以不會出現mov CS,AX
突然感覺這個原理有點古董。
控制暫存器
IP:指令指標暫存器,相當於2.3節的程式計數器PC
程式碼段的偏移地址
PSW:處理器狀態字暫存器,設定9個狀態位。
6個狀態位表達ALU運算後的程式狀態。
控制標誌:控制CPU的執行狀態
DF方向控制,在字串操作中,DF0,變址暫存器SI DI自增;DF1,SI DI自減
即控制SI DI的變化方向
IF中斷允許標誌,IF=1時,CPU可以響應可遮蔽中斷請求(也就是外部中斷);IF=0時,CPU不響應中斷請求。
中斷是作業系統中很重要的概念,開中斷和閉中斷的指令為
sti cli
TF陷阱標誌/單步標誌:TF=1時,CPU處於單步執行方式,每次執行一條指令自動執行一次特定的內部中斷,具體應用就是Debug。
組合語言中的pushF
表示將PSW標誌暫存器壓棧,popF
表示將棧頂出給PSW
地址線:A19-A16,A15-A10,A9-A0
8086給記憶體編址20根地址線,IO16根地址線(A0~A15)
在早期IBM pc機中,給IO分配A9-A0地址線來定址1KB空間,
三種格式:位元組型、字型、雙字型
位元組型資料:
一個位元組型資料對應一個地址單元。
組合語言設計中,位元組型資料定義在記憶體中的DS段,具體用DB這個偽指令來定義
偽指令用於組合器如何來翻譯組合程式碼。
字型資料:
對應兩個相鄰的地址單元。
定義偽指令為DW,如將字型資料5678H放入記憶體0003H和0004H位置,則78H放在字的低地址0003H,56放在字的高地址0004H。
這裡有一個對準和不對準的問題。如果字資料地址為奇地址,則稱為未對準,偶地址則對準(比如上面的例子就是未對準)
對準的資料 進行 訪存指令花費時間更短。未對準會多花費一個時間週期,這與資料匯流排的傳輸機制有關。
為了防止自己腦袋忘記,提示:對準情況下,高位元組對應高地址,地址單元為奇,走高八位傳輸線(一個是線,一個是位元組)
雙字型資料:
對應兩個字,也就是4個儲存單元。
定義偽指令為DD。
在組合語言中使用[BX /BP/ SI/ DI],是指暫存器所存的內容,也就是地址;使用BX BP SI DI—指的是暫存器本身。
為什麼要分段
如何分段:
一個邏輯段最大64K,每個邏輯段的起始地址必須可以被16整除
因此理論上講,1MB的地址空間,可以分64K(\(2^{16}\))個邏輯段,正好是16位元暫存器可以描述的。
實體地址
這個上面3.1部分也提到過,要從段基址(段的起始地址)+段偏移的形式重新得到真實的實體地址。
實體地址的唯一性:
由於段相互有疊加(按照被16整除的判斷標準),所以一個單元的邏輯地址只是可能不同。但是實體地址一定不同,實體地址是站在記憶體全域性為每個單元分配的門牌號。
雖然段在理論上(按16整除)會重疊,但實際上,組合源程式是自己定義的各個段,作業系統分別將其裝入記憶體,不會發生段覆蓋的情況。
程式設計、偵錯都是邏輯地址
實體地址(PA)的形成
也就是上面3.1節的轉化公式。
實體地址=段基址X16(16進位制左移一位)+段內偏移地址(段內有效地址)。
取指令
CPU如何實現取指令?
CS:IP
即 CS(段基地址)X16+IP(段內偏移地址),取指令所儲存的實體地址
接著8086按照計算後的實體地址去記憶體找指令取出。
課程這裡(11講21分鐘時)提到了無條件跳轉,老師講的是程式碼段間的無條件跳轉。
據我所知,這部分比較複雜,老師估計是想強調一下cs:ip的記憶體取指特性,所以具體的後續再提。
特性:CS和IP是使用者不可寫入的,CS是作業系統將程式碼從磁碟放入記憶體後初始化的,IP不可寫入但是會改變,除了自增外還會跳轉。
為了更明確說明實體地址的形成,再舉一個例子,記憶體寫操作:
mov [bx],ax
這就是將ax中的值寫入ds:bx中去,如果硬要扯一下第3部分EU BIU的知識,那就是EU先將16位元地址BX沿內部資料匯流排傳送到BIU,BIU停下取指操作,配合EU去進行寫記憶體的操作,BIU將BX放到加法器中產生實體地址,輸出20位實體地址後放到地址線,AX值放到傳輸線。
如果對齊,一個時間週期完成;如果不對齊,兩個時間週期。
堆疊操作(SS:SP),跟上述過程相似。
這部分跟指令系統中的定址方式是分不開的,指令系統會在下一部分整理。
關於各種邏輯段偏移暫存器指定與不可指定的靈活性,下面是一個小總結:
這個表裡總結了操作中的預設暫存器以及可以替代的暫存器,比如取指令CS必須與IP搭配,不得自己指定暫存器定址或者段地址。