實模式

實模式是對80286或更高級微處理器支持的操作模式。

基本概念

保護模式
保護模式:定址採用32位段和偏移量,最大定址空間4GB,最大分段4GB (Pentium Pre及以後為64GB)。在保護模式下CPU可以進入虛擬8086方式,這是在保護模式下的實模式程式運行環境。

實模式下程式的運行

程式運行的實質是什麼?其實很簡單,就是指令的執行,顯然CPU
是指令得以執行的硬體保障,那么CPU如何知道指令在什麼地方呢?
對了,80x86系列是使用CS暫存器配合IP暫存器來通知CPU指令在記憶體
中的位置.
程式指令在執行過程中一般還需要有各種數據,80x86系列有DS、
ES、FS、GS、SS等用於指示不同用途的數據段在記憶體中的位置。
程式可能需要調用系統的服務子程式,80x86系列使用中斷機制
來實現系統服務。
總的來說,這些就是實模式下一個程式運行所需的主要內容
(其它如跳轉、返回、連線埠操作等相對來說比較次要。)

保護模式

保護模式---從程式運行說起
無論實模式還是保護模式,根本的問題還是程式如何在其中運行。
因此我們在學習保護模式時應該時刻圍繞這個問題來思考。
和實模式下一樣,保護模式下程式運行的實質仍是“CPU執行指令,
操作相關數據”,因此實模式下的各種代碼段、數據段、堆疊段、中
斷服務程式仍然存在,且功能、作用不變。
那么保護模式下最大的變化是什麼呢?答案可能因人而異,我的
答案是“地址轉換方式”變化最大。

地址轉換方式比較

先看一下實模式下的地址轉換方式,假設我們在ES中存入0x1000,
DI中存入0xFFFF,那么ES:DI=0x1000*0x10+0xFFFF=0x1FFFF,這就是眾
所周知的“左移4位加偏移”。
那么如果在保護模式下呢?假設上面的數據不變ES=0x1000,
DI=0xFFFF,現在ES:DI等於什麼呢?
公式如下:(註:0x1000=1000000000000b= 10 0000 0000 0 00)
ES:DI=全局描述符表中第0x200項描述符給出的段基址+0xFFFF
現在比較一下,好象是不一樣。再仔細看看,又好象沒什麼區別!
為什麼說沒什麼區別,因為我的想法是,既然ES中的內容都不是
真正的段地址,憑什麼實模式下稱ES為“段暫存器”,而到了保護模式
就說是“選擇子”?
其實它們都是一種映射,只是映射規則不同而已:在實模式下這
個“地址轉換方式”是“左移4位”;在保護模式下是“查全局/局部描述表”
。前者是系統定義的映射方式,後者是用戶自定義的轉換方式。而它
影響的都是“shadow register”
從函式的觀點來看,前者是表達式函式,後者是列舉式函式:
實模式: F(es-->segment)={segment |segment=es*0x10}
保護模式:F(es-->segment)={segment |(es,segment)∈GDT/LDT}
其中GDT、LDT分別表示全局描述符表和局部描述符表。

保護模式基本組成

保護模式最基本的組成部分是圍繞著“地址轉換方式”的變化增設了
相應的機構。
1、數據段
前面說過,實模式下的各種代碼段、數據段、堆疊段、中斷服務程
序仍然存在,我將它們統稱為“數據段”,本文從此向下凡提到數據段都
是使用這個定義。
2、描述符
保護模式下引入描述符來描述各種數據段,所有的描述符均為8個字
節(0-7),由第5個位元組說明描述符的類型,類型不同,描述符的結構也
有所不同。
若干個描述符集中在一起組成描述符表,而描述符表本身也是一種
數據段,也使用描述符進行描述。
從現在起,“地址轉換”由描述符表來完成,從這個意義上說,描述符
表是一張地址轉換函式表。
3、選擇子
選擇子是一個2位元組的數,共16位,最低2位表示RPL,第3位表示查表
是利用GDT(全局描述符表)還是LDT(局部描述符表)進行,最高13位給
出了所需的描述符在描述符表中的地址。(註:13位正好足夠定址8K項)
有了以上三個概念之後可以進一步工作了,現在程式的運行與實模式
下完全一樣!!!各段暫存器仍然給出一個“段值”,只是這個“假段值”
到真正的段地址的轉換不再是“左移4位”,而是利用描述符表來完成。但
現在出現一個新的問題是:
系統如何知道GDT/LDT在記憶體中的位置呢?
為了解決這個問題,顯然需要引入新的暫存器用於指示GDT/LDT在內
存中的位置。在80x86系列中引入了兩個新暫存器GDTR和LDTR,其中GDTR用於
表示GDT在記憶體中的段地址和段限(就是表的大小),因此GDTR是一個48
位的暫存器,其中32位表示段地址,16位表示段限(最大64K,每個描述
符8位元組,故最多有64K/8=8K個描述符)。LDTR用於表示LDT在記憶體中的位
置,但是因為LDT本身也是一種數據段,它必須有一個描述符,且該描述
符必須放在GDT中,因此LDTR使用了與DS、ES、CS等相同的機制,其中只
存放一個“選擇子”,通過查GDT表獲得LDT的真正記憶體地址
對了,還有中斷要考慮,在80x86系列中為中斷服務提供中斷/陷阱描
述符,這些描述符構成中斷描述符表(IDT),並引入一個48位的全地址
暫存器存放IDT的記憶體地址。理論上IDT表同樣可以有8K項,可是因為80x86
只支持256箇中斷,因此IDT實際上最大只能有256項(2K大小)。

新要求

前面介紹了保護模式的基本問題,也是核心問題,解決了上面的問題,
程式就可以在保護模式下運行了。
但眾所周知80286以後在保護模式下實現了對多任務的硬體支持。我
的第一反應是:為什麼不在實模式下支持多任務,是不能還是不願?
思考之後,我的答案是:實模式下能實現多任務(也許我錯了:))。
因為多任務的關鍵是有了描述符,可以給出關於數據段的額外描述,如權
限等,進而在這些附加信息的基礎上進行相應的控制,而實模式下缺乏描
述符,但假設我們規定各段的前2個位元組或若干位元組用於描述段的附加屬性,
我覺得和使用描述符這樣的機制沒有本質區別,如果再附加其他機制...
基於上述考慮,我更傾向於認為任務是獨立於保護模式之外的功能。
下面我們來分析一下任務。任務的實質是什麼呢?很簡單,就是程式嘛!!
所謂任務的切換其實就是程式的切換!!
現在問題明朗了。實模式下程式一個接一個運行,因此程式運行的
“環境”不必保存;保護模式下可能一個程式在運行過程中被暫停,轉而執行
下一個程式,我們要做什麼?很容易想到保存程式運行的環境就行了(想
想遊戲程式的保存進度功能),比如各暫存器的值等。
顯然這些“環境”數據構成了一類新的數據段(即TSS)。延用前面的思路,
給這類數據段設定描述符(TSS描述符),將該類描述符放在GDT中(不能
放在LDT中,因為80x86不允許:)),最後再加一個TR暫存器用於查表。
TR是一個起“選擇子”作用的暫存器,16位。
好了,任務切換的基本工作就是將原任務的“環境”存入TSS數據段,更
新TR暫存器,系統將自動查GDT表獲得並裝載新任務的“環境”,然後轉到新
任務執行。

附加要求

為什麼叫附加要求,因為現在任務還不能很好地工作。前面說過,任務
實質上是程式,不同的程式是由不同的用戶寫的,所有這些程式完全可能
使用相同的地址空間,而任務的切換過程一般不會包括記憶體數據的刷新,
不是不可能,而是如果那樣做太浪費了。因此必須引入分頁機制才可能有效
地完成對多任務的支持。
分頁引入的主要目標就是解決不同任務相互之間發生地址衝突的問題。
分頁的實質就是實現程式內地址到物理地址的映射,這也是一個“地址轉換”
機制,同樣可以使用前面的方案(即類似GDT的做法):首先建立頁表這樣
一種數據段,在80x86中使用二級頁表方案,增設一個CR3暫存器用於存放
一級頁表(又稱為頁目錄)在記憶體中的地址,CR3共32位,其低12位總是為
零,高20位指示頁目錄的記憶體地址,因此頁目錄總是按頁對齊的。CR3作為
任務“環境”的一部分在任務切換時被存入TSS數據段中。
當然還得有相應的缺頁中斷機制及其相關暫存器CR2(頁故障線性地址暫存器)。

總結

保護模式下增加了什麼?
1、暫存器 GDR LDR IDR TR CR3
2、數據段 描述符表(GDT LDT) 任務數據段(TSS) 頁表(頁目錄 二級頁表)
3、機制 許可權檢測(利用選擇子/描述符/頁表項的屬性位)
線性地址到物理地址的映射

保護模式常用名詞解釋

前面內容中出現過的不再解釋。
1、RPL 選擇子當中的許可權位確定的許可權
2、CPL 特指CS中的選擇子當中的許可權位確定的許可權
3、EPL EPL=Max(RPL,CPL),即RPL和CPL中數值較大的,或說許可權等級較小的
4、DPL 描述符中的許可權位確定的許可權
5、PL 泛指以上4種特權級
6、任務特權 =CPL
7、I/O特權 由EFLAGS暫存器的位13、14確定的許可權
8、一致代碼段 一種特殊的代碼段,它在CPL>=DPL時允許訪問
正常的代碼段在CPL=DPL RPL<=DPL時才允許訪問

相關詞條

相關搜尋

熱門詞條

聯絡我們