1、引入程序員
保護模式下的段寄存器 由 16位的選擇器 與 64位的段描述符寄存器 構成spa
段描述符寄存器: 存儲段描述符設計
選擇器:存儲段描述符的索引blog
段寄存器索引
PS:原先實模式下的各個段寄存器做爲保護模式下的段選擇器,80486中有6個(即CS,SS,DS,ES,FS,GS)80位的段寄存器。由選擇器CS對應表示的段仍爲代碼段,選擇器SS對應表示的段仍爲堆棧段。進程
2、詳解ip
先說明一下概念內存
(1)全局描述符表GDT(Global Descriptor Table)在整個系統中,全局描述符表GDT只有一張(一個處理器對應一個GDT),GDT能夠被放在內存的任何位置,但CPU必須知道GDT的入口,也就是基地址放在哪裏,Intel的設計者門提供了一個寄存器GDTR用來存放GDT的入口地址,程序員將GDT設定在內存中某個位置以後,能夠經過LGDT指令將GDT的入口地址裝入此寄存器,今後之後,CPU就根據此寄存器中的內容做爲GDT的入口來訪問GDT了。GDTR中存放的是GDT在內存中的基地址和其表長界限。get
基地址指定GDT表中字節0在線性地址空間中的地址,表長度指明GDT表的字節長度值。指令LGDT和SGDT分別用於加載和保存GDTR寄存器的內容。在機器剛加電或處理器復位後,基地址被默認地設置爲0,而長度值被設置成0xFFFF。在保護模式初始化過程當中必須給GDTR加載一個新值。擴展
GDTR
(2)段選擇子(Selector)由GDTR訪問全局描述符表是經過「段選擇子」(實模式下的段寄存器)來完成的。段選擇子是一個16位的寄存器(同實模式下的段寄存器相同)
段選擇子
段選擇子包括三部分:描述符索引(index)、TI、請求特權級(RPL)。他的index(描述符索引)部分表示所須要的段的描述符在描述符表的位置,由這個位置再根據在GDTR中存儲的描述符表基址就能夠找到相應的描述符。而後用描述符表中的段基址加上邏輯地址(SEL:OFFSET)的OFFSET就能夠轉換成線性地址,段選擇子中的TI值只有一位0或1,0表明選擇子是在GDT選擇,1表明選擇子是在LDT選擇。請求特權級(RPL)則表明選擇子的特權級,共有4個特權級(0級、1級、2級、3級)。
關於特權級的說明:任務中的每個段都有一個特定的級別。每當一個程序試圖訪問某一個段時,就將該程序所擁有的特權級與要訪問的特權級進行比較,以決定可否訪問該段。系統約定,CPU只能訪問同一特權級或級別較低特權級的段。
例如給出邏輯地址:21h:12345678h轉換爲線性地址
a. 選擇子SEL=21h=0000000000100 0 01b 他表明的意思是:選擇子的index=4即100b選擇GDT中的第4個描述符;TI=0表明選擇子是在GDT選擇;左後的01b表明特權級RPL=1
b. OFFSET=12345678h若此時GDT第四個描述符中描述的段基址(Base)爲11111111h,則線性地址=11111111h+12345678h=23456789h
(3)局部描述符表LDT(Local Descriptor Table)局部描述符表能夠有若干張,每一個任務能夠有一張。咱們能夠這樣理解GDT和LDT:GDT爲一級描述符表,LDT爲二級描述符表。如圖
局部描述符表LDT
LDT和GDT從本質上說是相同的,只是LDT嵌套在GDT之中。LDTR記錄局部描述符表的起始位置,與GDTR不一樣,LDTR的內容是一個段選擇子。因爲LDT自己一樣是一段內存,也是一個段,因此它也有個描述符描述它,這個描述符就存儲在GDT中,對應這個表述符也會有一個選擇子,LDTR裝載的就是這樣一個選擇子。LDTR能夠在程序中隨時改變,經過使用lldt指令。如上圖,若是裝載的是Selector 2則LDTR指向的是表LDT2。舉個例子:若是咱們想在表LDT2中選擇第三個描述符所描述的段的地址12345678h。
1. 首先須要裝載LDTR使它指向LDT2 使用指令lldt將Select2裝載到LDTR
2. 經過邏輯地址(SEL:OFFSET)訪問時SEL的index=3表明選擇第三個描述符;TI=1表明選擇子是在LDT選擇,此時LDTR指向的是LDT2,因此是在LDT2中選擇,此時的SEL值爲1Ch(二進制爲11 1 00b)。OFFSET=12345678h。邏輯地址爲1C:12345678h
3. 由SEL選擇出描述符,由描述符中的基址(Base)加上OFFSET可獲得線性地址,例如基址是11111111h,則線性地址=11111111h+12345678h=23456789h
4. 此時若再想訪問LDT1中的第三個描述符,只要使用lldt指令將選擇子Selector 1裝入再執行二、3兩步就能夠了(由於此時LDTR又指向了LDT1)
因爲每一個進程都有本身的一套程序段、數據段、堆棧段,有了局部描述符表則能夠將每一個進程的程序段、數據段、堆棧段封裝在一塊兒,只要改變LDTR就能夠實現對不一樣進程的段進行訪問。
當進行任務切換時,處理器會把新任務LDT的段選擇符和段描述符自動地加載進LDTR中。在機器加電或處理器復位後,段選擇符和基地址被默認地設置爲0,而段長度被設置成0xFFFF。
3、實例(對理解很是有用)
1:訪問GDT
段描述符在GDT中
當TI=0時表示段描述符在GDT中,如上圖所示:
①先從GDTR寄存器中得到GDT基址。
②而後再GDT中以段選擇器高13位位置索引值獲得段描述符。
③段描述符符包含段的基址、限長、優先級等各類屬性,這就獲得了段的起始地址(基址),再以基址加上偏移地址yyyyyyyy才獲得最後的線性地址。
2:訪問LDT
段描述符在LDT中
當TI=1時表示段描述符在LDT中,如上圖所示:
①仍是先從GDTR寄存器中得到GDT基址。
②從LDTR寄存器中獲取LDT所在段的位置索引(LDTR高13位)。
③以這個位置索引在GDT中獲得LDT段描述符從而獲得LDT段基址。
④用段選擇器高13位位置索引值從LDT段中獲得段描述符。
⑤段描述符符包含段的基址、限長、優先級等各類屬性,這就獲得了段的起始地址(基址),再以基址加上偏移地址yyyyyyyy才獲得最後的線性地址。
擴展
除了GDTR、LDTR外還有IDTR和TR
(1)中斷描述符表寄存器IDTR
與GDTR的做用相似,IDTR寄存器用於存放中斷描述符表IDT的32位線性基地址和16位表長度值。指令LIDT和SIDT分別用於加載和保存IDTR寄存器的內容。在機器剛加電或處理器復位後,基地址被默認地設置爲0,而長度值被設置成0xFFFF。
(2)任務寄存器TR
TR用於尋址一個特殊的任務狀態段(Task State Segment,TSS)。TSS中包含着當前執行任務的重要信息。
TR寄存器用於存放當前任務TSS段的16位段選擇符、32位基地址、16位段長度和描述符屬性值。它引用GDT表中的一個TSS類型的描述符。指令LTR和STR分別用於加載和保存TR寄存器的段選擇符部分。當使用LTR指令把選擇符加載進任務寄存器時,TSS描述符中的段基地址、段限長度以及描述符屬性會被自動加載到任務寄存器中。當執行任務切換時,處理器會把新任務的TSS的段選擇符和段描述符自動加載進任務寄存器TR中。