天天看點

x86保護模式

處理器架構實際上是不斷擴充的,新處理器必須延續舊的設計思路,并保持相容性和一緻性;同時還會有所擴充和增強。

盡管8086是16位的處理器,但它也是32位架構内的一部分。原因在于,32為處理器架構是從8086那裡發展來的,是基于8086的,具有延續性和相容性。

寄存器的擴充

32位處理器在16位處理器的從基礎上,擴充了這8個通用寄存器(AX,BX,CX,DX,SI,DI,BP,SP)的長度,使之達到32位。

32位通用寄存器的高16位是不可獨立使用的,但低16位保持同16位處理器相容性。是以,在任何時候他們都可以照往常一樣使用。

但是32位處理器并不是16位處理器簡單的增強。事實上32位處理器有自己的32位工作模式,而我學習的32模式是32位保護模式。在這種模式下,處理器可以使用它全部的32跟位址線,能夠通路4GB記憶體。

在32位模式下,為了生成32位實體位址,處理器需要使用32位的指令指針寄存器。為此,32位處理器擴充了IP,使之達到32位,工作在32位模式下時使用EIP,但是當工作在16位模式下仍使用IP。

對于32位模式下因為IA-32架構的處理器是基于分段模型,可是32位模式下,對記憶體的通路從理論上不需要分段,因為它可以自由通路任何一個記憶體位置。是以引入了平坦模型,即隻分一個段,段的基址是0x00000000,段的長度是4GB,在這種情況下視為不分段。

在32位模式下,處理器要求在加在程式時,先定義該程式所擁有的段,然後允許使用這些段。定義段時,除了基位址外,還附加了段界限,特權級别,類型等屬性。當程式通路一個段時,處理器将用固件實施各種檢查工作,以防止對記憶體的違規通路。

在32位模式下,傳統的段寄存器,如CS,SS,DS,ES,儲存的不再是16位段基位址,而是段的選擇子(實模式下是段寄存器,在保護模式下就是段選擇子,因為在保護模式下他們存儲的不再是段位址而是段描述符在描述符表中的索引号),即用于選擇要通路的段,除了段選擇子外,每個段寄存器還包括一個不可見部分,稱為描述符高速緩沖器,裡面有段的基位址和各種通路屬性。

在保護模式下通路一個段的時候,傳送到段選擇器的是段選擇子。他由三個部分組成,第一部分是索引号,用來在描述符表種選擇一個段描述符。T1是描述符表訓示器,T1=0時,描述符在GDT中,T1=1時,描述符在LDT中。RPL是請求特權級,表示給出目前選擇子的那個程式的特權級

x86保護模式

線性位址

我們傳統上講的,段位址個偏移位址稱為邏輯位址,偏移位址叫做有效位址,在指令中給出有效位址的方式叫做尋址方式。

然而段的管理是由處理器的段部件負責進行的,段部件将段位址和偏移位址相加,得到通路記憶體的位址。一般來說,段部件産生的位址就是實體位址。

但是為了解決記憶體空間碎片化(記憶體每次配置設定大小不定,時間長後會産生過多過小的記憶體空間塊),IA-32處理器支援分頁功能,分頁功能将實體記憶體空間劃分成邏輯上的頁。通過使用頁,可以簡化記憶體管理。

當頁功能開啟時,段部件産生的位址就不再是實體位址了,而是線性位址,線性位址還要經過頁部件轉換後,才是實體位址。

線性位址的概念用來描述任務的位址空間。IA-32處理器上的每個任務擁有4GB的虛拟記憶體空間,這是一段長4GB的平坦空間,就像一段平直的線段。相應的,由段部件産生的位址,就對應着線性位址空間上的每一個點,這就是線性位址。

全劇描述符表

在保護模式下,對記憶體的通路仍能使用段位址和偏移位址,但是,在每個段能夠通路之前,必須先進行登記。當你通路的偏移量超出段的界限時,處理器就會阻止這種通路,并産生一個叫做内部異常的中斷。

斷描述符,用八個位元組來描述一個段有關的資訊。為了存放這些描述符,需要在記憶體中開辟一段空間,在這段空間裡,所有的描述符都是挨在一起,集中存放的,這就形成了一個描述符表。

最主要的描述符表是全局描述符表(GDT),在進入保護模式前,必須要定義全局描述符表。

x86保護模式

圖品出自

為了跟蹤全局描述符表,處理器内部有一個48位的寄存器,稱為全局描述符表寄存器(GDTR)。該寄存器高32為存放全局描述符表線性基位址,低16位存放全局描述符表邊界。

因為GDT的界限是16位是以表的大小最多是2^16位元組(64KB),又因為全局描述符大小為8位元組,是以最多可以定義8192個描述符。

雖說基位址有32位,但是由于在進入保護模式之後,處理器立即要按新的記憶體通路模式工作,是以,必須在進入保護模式之前定義GDT。但是,由于在實模式下隻能通路1MB的記憶體,故GDT通常都定義在1MB以下的範圍内。也允許在進入保護模式之後換位置重新定義GDT。

段描述符中的段屬性也被安排在兩個域中。下面對其定義及意義作說明。

(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。

在描述由SS寄存器尋址的段描述符中,D位決定隐式的堆棧通路指令(如PUSH和POP指令)使用何種堆棧指針寄存器。

D=1表示使用32位堆棧指針寄存器ESP;

D=0表示使用16位堆棧指針寄存器SP。

(3)AVL位是軟體可利用位

80386對該位的使用未做規定,此位被linux和windows作業系統忽略。

(4)P位稱為存在(Present)位

P=1表示描述符對位址轉換是有效的,或者說該描述符所描述的段存在,即在記憶體中;P=0表示描述符對位址轉換無效,即該段不存在。使用該描述符進行記憶體通路時會引起異常。

(5)DPL表示描述符特權級(Descriptor Privilege level)

共2位。它規定了所描述段的特權級,用于特權檢查,以決定對該段能否通路。

(6)DT位說明描述符的類型

對于存儲段描述符而言,

DT=1,以差別與系統段描述符和門描述符(DT=0)。

(7)TYPE說明存儲段描述符所描述的存儲段的具體屬性

x86保護模式

其中的位0訓示描述符是否被通路過(Accessed),用符号A标記。

A=0表示尚未被通路,

A=1 表示段已被通路,

當把描述符的相應選擇子裝入到段寄存器時,80386把該位置為1,表明描述符已被通路,作業系統可測試通路位,已确定描述符是否被通路過。

此為位1,對應的type為奇數,是以type對應的數值為奇數時辨別該描述符被通路過,否則為偶數辨別未被通路過(可從前面的表中看出)

綜上我們可以看到在類型不同時,段描述符的差別之處,如下所示

代碼段描述符

表示這個段描述符代表一個代碼段,它可以放在GDT中。該描述符置S标志為1。

資料段描述符

表示這個段描述符代表一個資料段,它可以放在GDT中,該描述符置S标志為1。

任務狀态段描述符

表示這個段描述符代表一個任務狀态段,也就是說這個段用于儲存處理器寄存器的内容。它隻能出現在GDT中,根據相應的程序是否正CPU上運作,其Type字段的值分别為11或9。這個描述符的S标志置為0。