原文地址https://blog.csdn.net/farmwang/article/details/52333583
保護模式就是對程序的運行加以保護,所以說保護模式較實模式的增強的最主要體現還不是尋址能力而是對多任務的支持,所提到的保護就是對不同任務間和同一任務內的程序加以保護,使它們的運行不受對方“有意”或“無意”影響,但同時也要對兩個任務都要用到的部分代碼實現共享。另外一個重要的增強就是對虛擬存儲器的支持,從一定意義上說可以使程序設計人員不必考慮物理內存的大小。
有了新的模式,當然要有大量的新增寄存器的支持,學習這些寄存器也是學習保護模式的關鍵
三個重要的系統表GDT、LDT和IDT 首先說明的是,這三個表是在內存中由操作系統或系統程序員所建,並不是固化在哪里,所以從理論上是可以被讀寫的。
這三個表都是描述符表.描述符表是由若干個描述符組成,每個描述符占用8個字節的內存空間,每個描述符表內最多可以有8129個描述符.描述符是描述一個段的大小,地址及各種狀態的.描述符表有三種,分別為全局描述符表GDT、局部描述符表LDT和中斷描述符表IDT。
段是實現虛擬地址到線性地址轉換機制的基礎,在保護方式下,每個段由三個參數進行定義:段基地址,段界限,段屬性。段基地址規定線性地址空間中段的開始地址,段界限定義段的大小,段屬性中有一位對此進行定義,把該位稱為粒度位用G標記,G=0表示段界限以字節為單位,於是20位界限可表示的范圍是1字節到1M字節,增量為1字節,G=1表示段界限以4K字節為單位,於是20位的界限可表示的范圍是4K字節到4G字節,增量是4K字節。
邏輯地址-=>線性地址-=>物理地址
前面我們提到了當使用80x86微處理器時,有三種不同的地址:
邏輯地址(logical address):包含在機器語言指令中用來指定一個操作數或一條指令的地址。這個尋址方式在80x86著名的分段結構中表現得尤為具體,它促使MS- DOS或Windows程序員把程序分成若干段。每一個邏輯地址都由一個段(segment)和偏移量(offset或displacement)組成, 偏移量指明了從段開始的地方到實際地址之間的距離。
線性地址(linear address)(也稱虛擬地址virtual address):是一個32位無符號整數,可以用來表示高達4GB的地址,也就是,高達4294967296個內存單元。線性地址通常用十六進制數字表 示,范圍:0x0000 0000到0xffff ffff。
物理地址(physical address):用於內存芯片級內存單元尋址。它們與從微處理器的地址引腳發送到內存總線上的電信號相對應。物理地址由32位或36位無符號整數表示。
內存控制單元(MMU)通過一種稱為分段單元(segmentation unit)的硬件電路把一個邏輯地址轉換成線性地址;接着,第二個稱為分頁單元(paging unit)的硬件電路把線性地址轉換成一個物理地址。
分段管理機制
段寄存器
8086的段寄存器
為 了運用所有的內存空間,8086設定了四個段寄存器,專門用來保存段地址:CS(Code Segment):代碼段寄存器;DS(Data Segment):數據段寄存器;SS(Stack Segment):堆棧段寄存器;ES(Extra Segment):附加段寄存器。
當 一個程序要執行時,就要決定程序代碼、數據和堆棧各要用到內存的哪些位置,通過設定段寄存器 CS,DS,SS 來指向這些起始位置。通常是將DS固定,而根據需要修改CS。所以,程序可以在可尋址空間小於64K的情況下被寫成任意大小。 所以,程序和其數據組合起來的大小,限制在DS 所指的64K內,這就是COM文件不得大於64K的原因。
計算機需要對內存分段,以分配給不同的程序使用(類似於硬盤分頁)。在描述內存分段時,需要有如下段的信息:1.段的大小;2.段的起始地址;3.段的管理屬性(禁止寫入/禁止執行/系統專用等)。
保護模式下的段寄存器
而在80386以后的CPU中段值需要用8個字節(64位)存儲這些信息,但段寄存器只有16位,因此在實模式下,段寄存器含有段值,為訪問存儲器形成物理地址時,處理器引用相應的某個段寄存器並將其值乘以16,形成20位的段基地址。在保護模式下,段寄存器含有段選擇子
如 上所述,為了訪問存儲器形成線性地址時,處理器要使用選擇子所指定的描述符中的基地址等信息。為了避免在每次存儲器訪問時,都要訪問描述符表而獲得對應的 段描述符,從80286開始每個段寄存器都配有一個高速緩沖寄存器,稱之為段描述符高速緩沖寄存器或描述符投影寄存器,對程序員而言它是不可見的。每當把 一個選擇子裝入到某個段寄存器時,處理器自動從描述符表中取出相應的描述符,把描述符中的信息保存到對應的高速緩沖寄存器中。此后對該段訪問時,處理器都 使用對應高速緩沖寄存器中的描述符信息,而不用再從描述符表中取描述符在保護模式下段寄存器中只能存儲段號(segment selector,也譯作“段選擇符”),再由段號映射到存在內存中的GDT(global (segment) descriptor table,全局段號記錄表),讀取段的信息。
一個邏輯地址由兩部分組成:一個段標識符和一個指定段內相對地址的偏移量。段標識符是一個16位長的字段,稱為段選擇符(Segment Selector),而偏移量是一個32位長的字段。
保護模式下,處理器提供段寄存器,段寄存器的唯一目的是存放段選擇符。這些段寄存器稱為cs、ss、ds、es、fs和gs。盡管只有6個段寄存器,但程序可以把同一個段寄存器用於不同的目的,方法是先將其值保存在內存中,用完后再恢復。
下面三個段寄存器有專門的用途:
cs:代碼段寄存器,指向包含程序指令的段。
ss:棧段寄存器,指向包含當前程序棧的段。
ds:數據段寄存器,指向包含靜態數據或者全局數據段。
其它三個段寄存器作一般用途,可以指向任意的數據段。
cs寄存器還有一個很重要的功能:它包含一個兩位的字段,用以指明CPU的當前特權級(CPL)。值為0代表最高優先級,值為3代表最低優先級。Linux只用0級和3級,分別稱為內核態和用戶態。
前面講了那么多,我們不禁要問了,實模式下的地址轉換就是段基址左移四位+段內偏移,那么保護模式下的地址轉換是如何完成的呢。
段定義和虛擬地址到線性地址的轉換
段是實現虛擬地址到線性地址轉換機制的基礎。在保護方式下,每個段由如下三個參數進行定義:段基地址(Base Address)、段界限(Limit)和段屬性(Attributes)。
段基地址規定線性地址空間中段的開始地址。在80386保護方式下,段基地址長32位。因為基地址長度與尋址地址的長度相同,所以任何一個段都可以從32位線性地址空間中的任何一個字節開始,而不象實方式下規定的邊界必須被16整除。
段 界限規定段的大小。在80386保護模式下,段界限用20位表示,而且段界限可以是以字節為單位或以4K字節為單位。段屬性中有一位對此進行定義,把該位 成為粒度位,用符號G標記。G=0表示段界限以字節位位單位,於是20位的界限可表示的范圍是1字節至1M字節,增量為1字節;G=1表示段界限以4K字 節為單位,於是20位的界限可表示的范圍是4K字節至4G字節,增量為4K字節。當段界限以4K字節為單位時,實際的段界限LIMIT可通過下面的公式從 20 位段界限Limit計算出來:
LIMIT=limit*4K+0FFFH=(Limit SHL 12)+0FFFH
所以當粒度為1時,段的界限實際上就擴展成32位。由此可見,在80386保護模式下,段的長度可大大超過64K字節。
基地址和界限定義了段所映射的線性地址的范圍。基地址Base是線性地址對應於段內偏移為 0的虛擬地址,段內偏移為X的虛擬地址對應Base+X的線性地址。段內從偏移0到Limit范圍內的虛擬地址對應於從Base到Base+Limit范圍內的線性地址。
下圖表示一個段如何從虛擬地址空間定位到線性地址空間。圖中BaseA等代表段基地址, LimitA等代表段界限。另外,段C接在段A之后,也即BaseC=BaseA+LimitA。
例如:設段A的基地址等於00012345H,段界限等於5678H,並且段界限以字節為單位(G=0),那么段A對應線性地址空間中從00012345H-000179BDH的區域。如果段界限以4K字節為單位(G=1),那么段A對應線性地址空間中從00012345H-0568B344H(=00012345H+5678000H+0FFFH)的區域。
通過增加段界限,可以使段的容量得到擴展。這對於那些要在內存中擴展容量的普通數據段很有效,但對堆棧段情況就不是這樣。因為堆棧底在高地址端,隨着壓棧操作的進行,堆棧向低地址方向擴展。為了適應普通數據段和堆棧數據段在兩個相反方向上的擴展,數據段的段屬性中安排了一個擴展方向位,標記為ED。ED=0表示向高端擴展,ED=1表示向低端擴展。一般只有堆棧數據段才使用向低端擴展的屬性(堆棧段也可使用向上擴展的段),這是因為,向下擴展的段是為以下兩個目的而設計的:
第一,堆棧段被定義為獨特段,即DS和SS包含不同的選擇器。
第二,一個堆棧段是靠將它復制到一個更大的段來擴充自己(而不是靠將現存的頁增加到它的段上)。不打算用這種方法實現堆棧的設計者不需要定義向下擴展的段。
需要注意的是,只有數據段的段屬性中才有擴展方向屬性位ED,也就是說只有數據段(堆棧段作為特殊的數據段)才有向上擴展和向下擴展之分,其它段都是自然的向上擴展。
數據段的擴展方向和段界限一起決定了數據段內偏移的有效范圍。當段最大為1M字節時,在向高端擴展的段內,從0到Limit的偏移是合法有效的偏移,而從Limit+1到1M-1的偏移是非法無效的偏移;在向低端擴展的段內,情形剛好相反,從0到Limit的偏移是非法無效的偏移,而從Limit+1到1M-1的偏移是合法有效的偏移,注意邊界值Limit對應地址的有效性。段最大為4G時,情形類似。由此可見,如果一個段是向下擴展的,則所有的偏移必須大於限長,因為其限長是指下限,其基地址從高地址出開始。反之,若一個段是向上擴展的,則所有偏移必須小於等於限長,因為其限長是指上限,基地址從低地址處開始。通過使用段環繞,可以把向下擴展段定義到任何線性地址且可定義為任何大小。
在每次把虛擬地址轉換為線性地址的過程中,要對偏移進行檢查。如果偏移不在有效的范圍內,那么就引起異常。
段屬性規定段的主要特性。例如上面已經提到的段粒度G就是段屬性的一部分。在對段進行各種訪問時,將對訪問是否合法進行檢查,主要依據是段屬性。例如:如果向一個只讀段進行寫入操作,那么不僅不能寫入,而且會引起異常。在下面會詳細說明各個段熟屬性位的定義和作用。
存儲段描述符
用於表示上述定義段的三個參數的數據結構稱為描述符。每個描述符長8個字節。在保護方式下,每一個段都有一個相應的描述符來描述。按描述符所描述的對象來划分,描述符可分為如下三類:存儲段描述符、系統段描述符、門描述符(控制描述符)。下面先介紹存儲段描述符。
存儲段描述符的格式
存儲段是存放可由程序直接進行訪問的代碼和數據的段。存儲段描述符描述存儲段,所以存儲段描述符也被稱為代碼和數據段描述符。存儲段描述符的格式如下表所示。表中上面一排是對描述符8個字節的使用的說明,最低地址字節(假設地址為m)在最右邊,其余字節依次向左,直到最高字節(地址為m+7)。
下一排是對屬性域各位的說明。
從上表可知
段基址
長32位的段基地址(段開始地址)被安排在描述符的兩個域中,其位0—位23安排在描述符內的第2—第4字節中,其位24—位31被安排在描述符內的第7字節中。
段界限
長20位的段界限也被安排在描述符的兩個域中,其位0—位15被安排在描述符內的第0—第1字節中,其位16—位19被安排在描述符內的第6字節的低4位中。
使用兩個域存放段基地址和段界限的原因與80286有關。
在80286保護方式下,段基地址只有24位長,而段界限只有16位長。80286存儲段描述符盡管也是8字節長,但實際只使用低6字節,高2字節必須置為0。80386存儲段描述符這樣的安排,可使得80286的存儲段描述符的格式在80386下繼續有效。
段屬性
80386描述符中的段屬性也被安排在兩個域中。下面對其定義及意義作說明。
(1)G為就是段界限粒度(Granularity)位
G=0表示界限粒度為字節;G=1表示界限粒度為4K字節。注意,界限粒度只對段界限有效,對段基地址無效,段基地址總是以字節為單位。
(2)D/B位是一個很特殊的位在描述可執行段、向下擴展數據段或由SS寄存器尋址的段(通常是堆棧段)的三種描述符中的意義各不相同
在描述可執行段的描述符中,D位決定了指令使用的地址及操作數所默認的大小。
D=1表示默認情況下指令使用32位地址及32位或8位操作數,這樣的代碼段也稱為32位代碼段;
D=0表示默認情況下,使用16位地址及16位或8位操作數,這樣的代碼段也稱為16位代碼段,它與80286兼容。可以使用地址大小前綴和操作數大小前綴分別改變默認的地址或操作數的大小。
在向下擴展數據段的描述符中,D位決定段的上部邊界。
D=1表示段的上部界限為4G;
D=0表示段的上部界限為64K,這是為了與80286兼容。
在描述由SS寄存器尋址的段描述符中,D位決定隱式的堆棧訪問指令(如PUSH和POP指令)使用何種堆棧指針寄存器。
D=1表示使用32位堆棧指針寄存器ESP;
D=0表示使用16位堆棧指針寄存器SP,這與80286兼容。
(3)AVL位是軟件可利用位
80386對該位的使用未做規定,Intel公司也保證今后開發生產的處理器只要與80386兼容,就不會對該位的使用做任何定義或規定。此為被linux和windows操作系統忽略。
(4)P位稱為存在(Present)位
P=1表示描述符對地址轉換是有效的,或者說該描述符所描述的段存在,即在內存中;P=0表示描述符對地址轉換無效,即該段不存在。使用該描述符進行內存訪問時會引起異常。
(5)DPL表示描述符特權級(DescriptorPrivilegelevel)
共2位。它規定了所描述段的特權級,用於特權檢查,以決定對該段能否訪問。
(6)DT位說明描述符的類型
對於存儲段描述符而言,
DT=1,以區別與系統段描述符和門描述符(DT=0)。
(7)TYPE說明存儲段描述符所描述的存儲段的具體屬性
存儲段描述符中的TYPE字段所說明的屬性可歸納為下表:
任務狀態段描述符
表示這個段描述符代表一個任務狀態段,也就是說這個段用於保存處理器寄存器的內容。它只能出現在GDT中,根據相應的進程是否正CPU上運行,其Type字段的值分別為11或9。這個描述符的S標志置為0。
局部描述符表描述符
表示這個段描述符代表一個包含LDT的段,它只出現在GDT中。相應的Type字段的值加2,S標志置為0。
全局描述符表GDT和局部描述符表GDT
一個任務會涉及多個段,每個任務需要一個描述符來描述,為了便於組織管理,80386把描述符組織成線性表。由描述符組成的線性表稱為描述符表。在80386中有三種類型的描述符表:全局描述符表GDT(GlobalDescriptor Table)、局部描述符表LDT(LocalDescriptor Table)和中斷描述符表IDT(InterruptDescriptorTable)。
在整個系統中,全局描述符表GDT和中斷描述符表IDT只有一張,局部描述符表可以有若干張,每個任務可以有一張。
每個描述符表本身形成一個特殊的數據段。這樣的特殊數據段最多可包含有8K(8192)個描述符.
每個任務的局部描述符表LDT含有該任務自己的代碼段、數據段和堆棧段的描述符,也包含該任務所使用的一些門描述符,如任務門和調用門描述符等。隨着任務的切換,系統當前的局部描述符表LDT也隨之切換。
全局描述符表GDT含有每一個任務都可能或可以訪問的段的描述符,通常包含描述操作系統所使用的代碼段、數據段和堆棧段的描述符,也包含多種特殊數據段描述符,如各個用於描述任務LDT的特殊數據段等。
在任務切換時,切換LDT,並不切換GDT
通過LDT可以使各個任務私有的各個段與其它任務相隔離,從而達到受保護的目的。通過GDT可以使各任務都需要使用的段能夠被共享。
一個任務可使用的整個虛擬地址空間分為相等的兩半,一半空間的描述符在全局描述符表中,另一半空間的描述符在局部描述符表中。由於全局和局部描述符表都可以包含多達8192個描述符,而每個描述符所描述的段的最大值可達4G字節,因此最大的虛擬地址空間可為:
4GB*8192*2=64MMB=64TB
段選擇子
在實模式下,邏輯地址空間中存儲單元的地址由段值和段內偏移兩部分組成。在保護方式下,虛擬地址空間(相當於邏輯地址空間)中存儲單元的地址由段選擇子和段內偏移兩部分組成。與實模式相比,段選擇子代替了段值。
段選擇子長16位,其格式如下表所示。從表中可見,段選擇子的高13位是描述符索引(Index)。所謂描述符索引是指描述符在描述符表中的序號。段選擇子的第2位是引用描述符表指示位,標記為TI(TableIndicator),TI=0指示從全局描述符表GDT中讀取描述符;TI=1指示從局部描述符表LDT中讀取描述符。
段選擇子
在實模式下,邏輯地址空間中存儲單元的地址由段值和段內偏移兩部分組成。在保護方式下,虛擬地址空間(相當於邏輯地址空間)中存儲單元的地址由段選擇子和段內偏移兩部分組成。與實模式相比,段選擇子代替了段值。
段選擇子長16位,其格式如下表所示。
從表中可見,段選擇子的高13位是描述符索引(Index)。所謂描述符索引是指描述符在描述符表中的序號。段選擇子的第2位是引用描述符表指示位,標記為TI(TableIndicator),TI=0指示從全局描述符表GDT中讀取描述符;TI=1指示從局部描述符表LDT中讀取描述符。
選擇子確定描述符,描述符確定段基地址,段基地址與偏移之和就是線性地址。所以,虛擬地址空間中的由選擇子和偏移兩部分構成的二維虛擬地址,就是這樣確定了線性地址空間中的一維線性地址。
選擇子的最低兩位是請求特權級RPL(RequestedPrivilege Level),用於特權檢查。RPL字段的用法如下:
每當程序試圖訪問一個段時,要把當前特權級與所訪問段的特權級進行比較,以確定是否允許程序對該段的訪問。使用選擇子的RPL字段,將改變特權級的測試規則。在這種情況下,與所訪問段的特權級比較的特權級不是CPL,而是CPU與RPL中更外層的特權級。CPL存放在CS寄存器的RPL字段內,每當一個代碼段選擇子裝入CS寄存器中時,處理器自動地把CPL存放到CS的RPL字段。
由於選擇子中的描述符索引字段用13位表示,所以可區分8192個描述符。這也就是描述符表最多包含8192個描述符的原因。由於每個描述符長8字節,根據上表所示選擇子的格式,屏蔽選擇子低3位后所得的值就是選擇子所指定的描述符在描述符表中的偏移,這可認為是安排選擇子高13位作為描述符索引的原因。
有一個特殊的選擇子稱為空(Null)選擇子,它的Index=0,TI=0,而RPL字段可以為任意值。空選擇子有特定的用途,當用空選擇子進行存儲訪問時會引起異常。空選擇子是特別定義的,它不對應於全局描述符表GDT中的第0個描述符,因此處理器中的第0個描述符總不被處理器訪問,一般把它置成全0。但當TI=1時,Index為0的選擇子不是空選擇子,它指定了當前任務局部描述符表LDT中的第0個描述符。
段描述符高速緩沖寄存器
在實模式下,段寄存器含有段值,為訪問存儲器形成物理地址時,處理器引用相應的某個段寄存器並將其值乘以16,形成20位的段基地址。在保護模式下,段寄存器含有段選擇子,如上所述,為了訪問存儲器形成線性地址時,處理器要使用選擇子所指定的描述符中的基地址等信息。
為了避免在每次存儲器訪問時,都要訪問描述符表而獲得對應的段描述符,從80286開始每個段寄存器都配有一個高速緩沖寄存器,稱之為段描述符高速緩沖寄存器或描述符投影寄存器,對程序員而言它是不可見的。每當把一個選擇子裝入到某個段寄存器時,處理器自動從描述符表中取出相應的描述符,把描述符中的信息保存到對應的高速緩沖寄存器中。此后對該段訪問時,處理器都使用對應高速緩沖寄存器中的描述符信息,而不用再從描述符表中取描述符。
各段描述符高速緩沖寄存器之內容如下表所示。其中,32位段基地址直接取自描述符,32位的段界限取自描述符中20位的段界限,並根據描述符屬性中的粒度位轉換成以字節為單位。其它十個特性根據描述符中的屬性而定,“Y”表示“是”,“N”表示“否”,“R”表示必須可讀,“W”表示必須可寫,“P”表示必須存在,“D”表示根據描述符中屬性而定。
段描述符高速緩沖寄存器再處理器內,所以可對其進行快速訪問。絕大多數情況下,對存儲器的訪問是在對應選擇子裝入到段寄存器之后進行的,所以,使用段描述符高速緩沖寄存器可以得到很好的執行性能。
段描述符高速緩沖寄存器之內保存的描述符信息將一直保存到重新把選擇子裝載到段寄存器時再更新。程序員盡管不可見段描述符高速緩沖寄存器,但必須注意到它的存在和它的上述更新時機。例如,在改變了描述符表中的某個當前段的描述符后,也要更新對應的段描述符高速緩沖寄存器的內容,即使段選擇子未作改變,這可通過重新裝載段寄存器實現。
控制寄存器和系統地址寄存器
80386控制寄存器和系統地址寄存器如下表所示。它們用於控制工作方式,控制分段管理機制及分頁管理機制的實施。
控制寄存器
從上表可見,80386有四個32位的控制寄存器,分別命名位CR0、CR1、CR2和CR3。但CR1被保留,供今后開發的處理器使用,在80386中不能使用CR1,否則會引起無效指令操作異常。
CR0包括指示處理器工作方式的控制位,包含啟用和禁止分頁管理機制的控制位,包含控制浮點協處理器操作的控制位。
CR2及CR3由分頁管理機制使用。CR0中的位5—位30及CR3中的位0至位11是保留位,這些位不能是隨意值,必須為0。
控制寄存器CR0的低16位等同於80286的機器狀態字MSW。
保護控制位
控制寄存器CR0中的位0用PE標記,位31用PG標記,這兩個位控制分段和分頁管理機制的操作,所以把它們稱為保護控制位。
PE控制分段管理機制。
PE=0,處理器運行於實模式;
PE=1,處理器運行於保護方式。
PG控制分頁管理機制。
PG=0,禁用分頁管理機制,此時分段管理機制產生的線性地址直接作為物理地址使用;
PG=1,啟用分頁管理機制,此時線性地址經分頁管理機制轉換位物理地址。
關於分頁管理機制的具體介紹在后面的文章中進行。
下表列出了通過使用PE和PG位選擇的處理器工作方式。
由於只有在保護方式下才可啟用分頁機制,所以盡管兩個位分別為0和1共可以有四種組合,但只有三種組合方式有效。PE=0且PG=1是無效組合,因此,用PG為1且PE為0的值裝入CR0寄存器將引起通用保護異常。
需要注意的是,PG位的改變將使系統啟用或禁用分頁機制,因而只有當所執行的程序的代碼和至少有一部分數據在線性地址空間和物理地址空間具有相同的地址的情況下,才能改變PG位。
協處理器控制位
控制寄存器CR0中的位1—位4分別標記為MP(算術存在位)、EM(模擬位)、TS(任務切換位)和ET(擴展類型位),它們控制浮點協處理器的操作。
當處理器復位時,ET位被初始化,以指示系統中數字協處理器的類型。
如果系統中存在80387協處理器,那么ET位置1;如果系統中存在80287協處理器或者不存在協處理器,那么ET位清0。
EM位控制浮點指令的執行是用軟件模擬,還是由硬件執行。
EM=0時,硬件控制浮點指令傳送到協處理器;
EM=1時,浮點指令由軟件模擬。
TS位用於加快任務的切換,通過在必要時才進行協處理器切換的方法實現這一目的。每當進行任務切換時,處理器把TS置1。
TS=1時,浮點指令將產生設備不可用(DNA)異常。
MP位控制WAIT指令在TS=1時,是否產生DNA異常。
MP=1和TS=1時,WAIT產生異常;
MP=0時,WAIT指令忽略TS條件,不產生異常。
CR2和CR3
控制寄存器CR2和CR3由分頁管理機制使用。
CR2用於發生頁異常時報告出錯信息。當發生頁異常時,處理器把引起頁異常的線性地址保存在CR2中。
操作系統中的頁異常處理程序可以檢查CR2的內容,從而查出線性地址空間中的哪一頁引起本次異常。
CR3用於保存頁目錄表的其始物理地址。由於目錄是頁對齊的,所以僅高20位有效,低12位保留未用。
向CR3中裝入一個新值時,低12位必須為0;但從CR3中取值時,低12位被忽略。
每當用MOV指令重置CR3的值時,會導致分頁機制高速緩沖區的內容無效,用此方法,可以在啟用分頁機制之前,即把PG位置1之前,預先刷新分頁機制的高速緩存。
CR3寄存器即使在CR0寄存器的PG位或PE位為0時也可裝入,如在實模式下也可設置CR3,以便進行分頁機制的初始化。
在任務切換時,CR3要被改變,但是如果新任務中CR3的值與原任務中CR3的值相同,那么處理器不刷新分頁高速緩存,以便當任務共享也表時有較快的執行速度。
系統地址寄存器
全局描述符表GDT、局部描述符表LDT和中斷描述符表IDT等都是保護方式下非常重要的特殊段,它們包含有為段機制所用的重要表格。
為了方便快速地定位這些段,處理器采用一些特殊的寄存器保存這些段的基地址和段界限。我們把這些特殊的寄存器稱為系統地址寄存器。
全局描述符表寄存器GDTR
在整個系統中,全局描述符表GDT只有一張(一個處理器對應一個GDT),GDT可以被放在內存的任何位置,但CPU必須知道GDT的入口,也就是基地址放在哪里,Intel的設計者門提供了一個寄存器GDTR用來存放GDT的入口地址,程序員將GDT設定在內存中某個位置之后,可以通過LGDT指令將GDT的入口地址裝入此積存器,從此以后,CPU就根據此寄存器中的內容作為GDT的入口來訪問GDT了。
GDTR長48位,其中高32位為基地址,低16位為界限。由於GDT不能有GDT本身之內的描述符進行描述定義,所以處理器采用GDTR為GDT這一特殊的系統段提供一個偽描述符。GDTR給定了GDT。
GDTR中的段界限以字節為單位。由於段選擇子中只有13位作為描述符索引,而每個描述符長8個字節,所以用16位的界限足夠。通常,對於含有N個描述符的描述符表的段界限設為8*N-1。
局部描述符表寄存器LDTR
局部描述符表寄存器LDTR規定當前任務使用的局部描述符表LDT。
LDTR類似於段寄存器,由程序員可見的16位的寄存器和程序員不可見的高速緩沖寄存器組成。實際上,每個任務的局部描述符表LDT作為系統的一個特殊段,由一個描述符描述。而用於描述符LDT的描述符存放在GDT中。
在初始化或任務切換過程中,把描述符對應任務LDT的描述符的選擇子裝入LDTR,處理器根據裝入LDTR可見部分的選擇子,從GDT中取出對應的描述符,並把LDT的基地址、界限和屬性等信息保存到LDTR的不可見的高速緩沖寄存器中。
隨后對LDT的訪問,就可根據保存在高速緩沖寄存器中的有關信息進行合法性檢查。
LDTR寄存器包含當前任務的LDT的選擇子。所以,裝入到LDTR的選擇子必須確定一個位於GDT中的類型為LDT的系統段描述符,也即選擇子中的TI位必須是0,而且描述符中的類型字段所表示的類型必須為LDT。
可以用一個空選擇子裝入LDTR,這表示當前任務沒有LDT。在這種情況下,所有裝入到段寄存器的選擇子都必須指示GDT中的描述符,也即當前任務涉及的段均由GDT中的描述符來描述。
如果再把一個TI位為1的選擇子裝入到段寄存器,將引起異常。
中斷描述符表寄存器IDTR
中斷描述符表寄存器IDTR指向中斷描述符表IDT。
IDTR長48位,其中32位的基地址規定IDT的基地址,16位的界限規定IDT的段界限。
由於80386只支持256個中斷/異常,所以IDT表最大長度是2K,以字節位單位的段界限為7FFH。IDTR指示IDT的方式與GDTR指示GDT的方式相同。
任務狀態段寄存器TR
任務狀態段寄存器TR包含指示描述當前任務的任務狀態段的描述符選擇子,從而規定了當前任務的狀態段。
TR也有程序員可見和不可見兩部分。當把任務狀態段的選擇子裝入到TR可見部分時,處理器自動把選擇子所索引的描述符中的段基地址等信息保存到不可見的高速緩沖寄存器中。
在此之后,對當前任務狀態段的訪問可快速方便地進行。裝入到TR的選擇子不能為空,必須索引位於GDT中的描述符,且描述符的類型必須是TSS。
虛擬地址轉換為線性地址
為了將虛擬地址轉換為線性地址,分段單元執行如下操作。
先檢查段選擇子的T1字段,已決定段描述符號,存儲在全局段描述符表GDL還是局部段描述符表中。如果在全局段描述符表GDL中,則分段單元則從GDTR中得到GDT的線性基地址,相反如果局部段描述符表中則從LDTR中獲取到LDT的線性基地址。
從段選擇子的index索引字段,計算段描述符的地址,index字段的值乘以8(一個段描述符的大小是8個字節),然后這個值(偏移)與GDTR或者LDTR的寄存器的值(全局/局部段描述符表的基地址)相加,全局/局部段描述符表中偏移為index*8的這個地址就存儲着我們當前段的段描述符。
把得到的段描述符的base字段與邏輯地址額偏移offset值相加就得到了線性地址