在Protected Mode下,一個重要的必不可少的數據結構就是GDT(Global Descriptor Table)。 爲何要有GDT?咱們首先考慮一下在Real Mode下的編程模型: 在Real Mode下,咱們對一個內存地址的訪問是經過Segment:Offset的方式來進行的,其中Segment是一個段的Base Address,一個Segment的最大長度是64 KB,這是16-bit系統所能表示的最大長度。而Offset則是相對於此Segment Base Address的偏移量。Base Address+Offset就是一個內存絕對地址。由此,咱們能夠看出,一個段具有兩個因素:Base Address和Limit(段的最大長度),而對一個內存地址的訪問,則是須要指出:使用哪一個段?以及相對於這個段Base Address的Offset,這個Offset應該小於此段的Limit。固然對於16-bit系統,Limit不要指定,默認爲最大長度64KB,而 16-bit的Offset也永遠不可能大於此Limit。咱們在實際編程的時候,使用16-bit段寄存器CS(Code Segment),DS(Data Segment),SS(Stack Segment)來指定Segment,CPU將段積存器中的數值向左偏移4-bit,放到20-bit的地址線上就成爲20-bit的Base Address。 到了Protected Mode,內存的管理模式分爲兩種,段模式和頁模式,其中頁模式也是基於段模式的。也就是說,Protected Mode的內存管理模式事實上是:純段模式和段頁式。進一步說,段模式是必不可少的,而頁模式則是可選的——若是使用頁模式,則是段頁式;不然這是純段模 式。 既然是這樣,咱們就先不去考慮頁模式。對於段模式來說,訪問一個內存地址仍然使用Segment:Offset的方式,這是很天然的。因爲 Protected Mode運行在32-bit系統上,那麼Segment的兩個因素:Base Address和Limit也都是32位的。IA-32容許將一個段的Base Address設爲32-bit所能表示的任何值(Limit則能夠被設爲32-bit所能表示的,以2^12爲倍數的任何指),而不象Real Mode下,一個段的Base Address只能是16的倍數(由於其低4-bit是經過左移運算得來的,只能爲0,從而達到使用16-bit段寄存器表示20-bit Base Address的目的),而一個段的Limit只能爲固定值64 KB。另外,Protected Mode,顧名思義,又爲段模式提供了保護機制,也就說一個段的描述符須要規定對自身的訪問權限(Access)。因此,在Protected Mode下,對一個段的描述則包括3方面因素:[Base Address, Limit, Access],它們加在一塊兒被放在一個64-bit長的數據結構中,被稱爲段描述符。這種狀況下,若是咱們直接經過一個64-bit段描述符來引用一個 段的時候,就必須使用一個64-bit長的段積存器裝入這個段描述符。但Intel爲了保持向後兼容,將段積存器仍然規定爲16-bit(儘管每一個段積存 器事實上有一個64-bit長的不可見部分,但對於程序員來講,段積存器就是16-bit的),那麼很明顯,咱們沒法經過16-bit長度的段積存器來直 接引用64-bit的段描述符。 怎麼辦?解決的方法就是把這些長度爲64-bit的段描述符放入一個數組中,而將段寄存器中的值做爲下標索引來 間接引用(事實上,是將段寄存器中的高13 -bit的內容做爲索引)。這個全局的數組就是GDT。事實上,在GDT中存放的不只僅是段描述符,還有其它描述符,它們都是64-bit長,咱們隨後再 討論。 GDT能夠被放在內存的任何位置,那麼當程序員經過段寄存器來引用一個段描述符時,CPU必須知道GDT的入口,也就是基地址放在哪裏, 因此 Intel的設計者門提供了一個寄存器GDTR用來存放GDT的入口地址,程序員將GDT設定在內存中某個位置以後,能夠經過LGDT指令將GDT的入口 地址裝入此積存器,今後之後,CPU就根據此積存器中的內容做爲GDT的入口來訪問GDT了。 GDT是Protected Mode所必須的數據結構,也是惟一的——不該該,也不可能有多個。另外,正象它的名字(Global Descriptor Table)所揭示的,它是全局可見的,對任何一個任務而言都是這樣。 除 了GDT以外,IA-32還容許程序員構建與GDT相似的數據結構,它們被稱做LDT(Local Descriptor Table),但與GDT不一樣的是,LDT在系統中能夠存在多個,而且從LDT的名字能夠得知,LDT不是全局可見的,它們只對引用它們的任務可見,每一個 任務最多能夠擁有一個LDT。另外,每個LDT自身做爲一個段存在,它們的段描述符被放在GDT中。 IA-32爲LDT的入口地址也提供了一 個寄存器LDTR,由於在任什麼時候刻只能有一個任務在運行,因此LDT寄存器全局也只須要有一個。若是一個任務擁有自身的LDT,那麼當它須要引用自身的 LDT時,它須要經過LLDT將其LDT的段描述符裝入此寄存器。LLDT指令與LGDT指令不一樣的時,LGDT指令的操做數是一個32-bit的內存地 址,這個內存地址處存放的是一個32-bit GDT的入口地址,以及16-bit的GDT Limit。而LLDT指令的操做數是一個16-bit的選擇子,這個選擇子主要內容是:被裝入的LDT的段描述符在GDT中的索引值——這一點和剛纔所 討論的經過段積存器引用段的模式是同樣的。