進入保護模式

來源:互聯網
上載者:User

以下圖2, 圖4和圖5截自Intel手冊


通用描述元表 通用描述元表中存放著段描述符, 每個段描述符8個位元組. 為了跟蹤通用描述元表, 處理器內部有一個48位寄存器, 叫做通用描述元表寄存器(GDTR), GDTR分為兩部分,分別為32位的線性地址和16的邊界, 32位線性基地址部分儲存的是通用描述元表在記憶體中的起始線性地址, 16位邊界部分是通用描述元表的邊界(界限), 其值等於表的大小(總位元組數) - 1, 因為從位移0開始. 如果界限值是0, 表示表的大小是1位元組.
因為GDT的界限是16位的, 故該表最大是2 ^ 16位元組, 也就是65536位元組(64KB), 又因為一個描述符8位元組, 所以該表最多定義8192個描述符.在進入保護模式之後, 處理器立即要按新的記憶體訪問模式工作, 所以, 必須在進入保護模式之前定義GDT, 但是, 由於實模式下只能訪問1MB的記憶體, 故GDT通常多定義在1MB以下的記憶體範圍中, 當然, 允許在進入保護模式後換個位置重新定義GDT


儲存空間段描述符

每個描述符佔8位元組, 下圖中, 上面位高32位, 下面為低32位


段描述符中, 指定了32位的段起始地址和20位的段邊界, 在實模式下, 段地址並非真實的物理地址, 計算物理地址時需要左移4位. 和實模式不同, 32位保護模式下, 段地址是32位的,如果未開啟分頁功能, 該線性地址就是物理地址. 段基地址可以是0~4GB範圍內的任意地址, 段界限用來限制段的擴充範圍, 因為訪問記憶體的方法是用段基地址加上位移量, 所以, 對於向上擴充的段, 如程式碼片段和資料區段來說, 位移量從0開始遞增, 段界限決定了位移量的最大值; 對於向下擴充的段,如棧段來說, 段界限決定了位移量的最小值.
G位是粒度位, 用於解釋段界限的含義, G = 0時, 段界限以位元組為單位, 此時段的擴充範圍是從1位元組到1MB, 因為段界限是20位的, 當G = 1時, 段界限以4KB位單位, 這樣, 段的擴充範圍是從4KB到4GB. S位用於指定描述符的類型, S = 0時, 表示是一個系統段, S = 1時, 表示是一個程式碼片段或資料區段(棧也屬於特殊資料區段) DPL表示描述符的特權級, 特權級分別是0, 1, 2, 3, 其中0是最高特權級, 3是最低特權級, 剛進保護模式時執行的代碼具有0特權級(可以看成是從處理器那裡繼承來的), 在這裡, 描述符的特權級用於指定要訪問該段做必須具有的特權級, 如果這裡的數值是2, 那麼, 只有特權級0, 1和2的程式能夠訪問該段, 特權級3訪問時, 處理器會予以阻止. P是段存在位, P位用於指示描述符所對應的段是否存在, 一般來說, 描述符所指示的段都位於記憶體中. 但是, 當記憶體緊張時, 有可能只是建立了描述符, 對應的記憶體空間並不存在, 這時, 就應當把描述符P位清0, 表示段並不存在. 另外, 同樣是在記憶體緊張的情況下, 會把很少用到的段換出到硬碟, 騰出空間給急需記憶體的程式使用(當前正在執行的), 這時, 同樣要把P位清0, 當再次輪到它執行時, 再裝入記憶體, 然後將P位置1. P位是由處理器負責檢查的, 每當通過描述符訪問記憶體中的段時, 如果P位是0, 處理器就產生一個中斷, 通常該中斷處理常式是由作業系統提供, 該處理過程的任務是負責將該段從硬碟換回記憶體, 並將P位置1, 在多使用者, 多任務的系統中, 這時一種常用的虛擬記憶體調度策略. D/B位是預設的運算元大小或預設的棧指標大小, 該標誌對不同的段有不同的效果, 對於程式碼片段, 此位稱作D位, 用於指示指令中預設的位移地址和運算元大小, D = 0表示是16位的, D = 1, 指示是32位的.  如果D = 0, 處理器在這個段執行時, 將使用16位指令指標寄存器IP, 否者使用32位的EIP.    對於棧段來說, 該位就做B位, 用於在進行隱式的棧操作時, 是使用SP還是使用ESP, 隱式的棧指令包括 push, pop和call等, 如果該位位0, 則使用SP, 棧段的上部邊界位0xffff,  否者使用ESP, 上部邊界為0xffffffff. L位是64位代碼位, 保留此位給64位處理器使用 TYPE共4位, 指示描述符的子類型, 或者說是類別, 對資料區段來說, 分別是X, E, W, A位, 對程式碼片段來說是X, C, R, A位                                          上表中, A位是已訪問位, 每當該段被訪問時, 處理器自動將該位置1, 對該位清0是由軟體(作業系統)負責的, 通過定期監視該位的狀態, 可以統計出該段的使用頻率. X代表執行, E位指示擴充方向, W位指示可寫, C位指示段是否為特權級依從的, C = 0表示非依從的程式碼片段, 這樣的程式碼片段只能供同特權級的程式使用, 或者通過門調用, C = 1則表示這樣的程式碼片段為依從程式碼片段, 可以從特權級比它低的程式調用並進入. 程式碼片段總是可以執行的, 但是為了防止程式被破壞, 它是不能寫入的. 它的R位不是用來限制處理器是否可讀的, 而是用來限制程式的, 一個典型的例子是使用段超越首碼CS:來存取碼段中的記憶體. AVL位是軟體可以使用的位, 通常由作業系統來使用他, 處理器不使用它. 段選擇子

3~15是段描述符在描述符中的索引, TI = 0時表示描述符在GDT中, TI = 1時, 描述符在LDT中, RPL是請求特權級, 表示給出當前選擇子的那個程式的特權級, 正是該程式要求訪問這個記憶體段. 段描述符快取器

如上圖所示, 在32位處理器上運行時, 每個段寄存器還包括一個不可見的部分, 稱為描述符快取器, 用來存放段的線性基地址, 段界限和段屬性, 既然不可見, 那就是處理器不希望我們訪問它. 事實上, 我們也沒有任何辦法來訪問這個不可見部分, 它是由處理器內部使用的. 當處理器在執行任何改變段選取器(段寄存去CS, DS等)的指令時(比如pop, jmp, call, ret等), 就將指令中提供的索引號(就是選擇子中的索引)乘以8(一個描述符8位元組)作為位移地址, 同GDTR中提供的線性基地址相加, 以訪問GDT, 如果沒有發現什麼問題(比如超出了GDT的界限), 就自動將找到的描述符載入到不可見的描述符快取部分. 載入的部分包括段的線性基地址, 段界限和段的訪問屬性. 此後, 每當有訪問記憶體時, 就不再訪問GDT中的描述符, 直接用當前段寄存器描述符快取器提供的線性基地址. 進入保護模式 從0x92連接埠讀取的資料, 第2位為開A20, 第一位 = 1為重啟
在保護模式下, 不允許使用mov指令改變段寄存器CS的內容, 比如: mov cs, ax, 企圖這樣做將導致處理器產生一個無效作業碼的異常中斷.

下面是一段主引導區代碼, 實驗環境書中也有說, 我的資源中也有配書資源下載, 裡面有說如何配置VirtualBox和Bochs, 這裡說一下配置Bochs, 配書資源中關於配置Bochs中的

Disk&Boot --> ATA channel 0 --> First HD/CD on channel 0 --> Type of disk image這個選項是vpc, 我用2.6.2配置時選vpc無法啟動, 得選flat才可以, 2.6.0貌似選vpc可以
[plain] view plain copy print ?         mov ax, cs           mov ss, ax           mov sp, 0x7c00                      ; 計算GDT所在地址的邏輯段地址           mov ax, [cs:gdt_base + 0x7c00]           mov dx, [cs:gdt_base + 2 +0x7c00]           mov bx, 0x10           div bx           mov ds, ax              ; 商為段地址           mov bx, dx              ; 餘數為位移地址                      ; 全域描述符#0, 第一項必須為0           mov dword [bx + 0x00], 0x00000000           mov dword [bx + 0x04], 0x00000000                      ; 全域描述符#1, 程式碼片段描述符           ; 線性基地址: 0x00007c00, 段界限: 0x01ff, 段界限在數值上等於段的長度 - 1, 因此該段的長度是0x200, 即512位元組           ; 粒度位位元組(G = 0), 屬於儲存空間段(S = 1)           ; 32位的段(D/B = 1), 位於記憶體當中(P = 1)           ; 段的特權級位0(DPL = 00)           ; 只執行(TYPE = 1000)           mov dword [bx + 0x08], 0x7c0001ff                  mov dword [bx + 0x0c], 0x00409800                      ; 全域描述符#2, 資料區段描述符           ; 線性基地址: 0x000b8000, 段界限: 0xffff           ; 粒度位位元組(G = 0), 屬於儲存空間段(S = 1)           ; 32位的段(D/B = 1), 位於記憶體當中(P = 1)           ; 段的特權級位0(DPL = 00)           ; 可讀可寫, 向上擴充的資料區段(TYPE = 0010)           mov dword [bx + 0x10], 0x8000ffff           mov dword [bx + 0x14], 0x0040920b                      ; 全域描述符#3, 棧段描述符           ; 線性基地址: 0x00000000, 段界限: 0x07a00           ; 粒度位位元組(G = 0), 屬於儲存空間段(S = 1)           ; 32位的段(D/B = 1), 位於記憶體當中(P = 1)           ; 段的特權級位0(DPL = 00)           ; 可讀可寫, 向下擴充的資料區段, 在這裡是棧段(TYPE = 0110)           mov dword [bx + 0x18], 0x00007a00           mov dword [bx + 0x1c], 0x00409600                      ; 初始化通用描述元表           mov word [cs:gdt_size + 0x7c00], 31     ; 通用描述元表界限(總位元組數 - 1)           lgdt [cs:gdt_size + 0x7c00]             ; 載入通用描述元表                      ; 開A20           in al, 0x92           or al, 0x02           out 0x92, al                      cli                                     ; 保護模式下中斷機制尚未建立, 關中斷                      ; 開啟保護模式, cr0寄存器0位置1           mov eax, cr0           or eax, 1           mov cr0, eax                      ; 進入保護模式, 詳情參見本書P199 11.7 清空流水線並序列化處理器           ; 注意, 不管你用的是16位遠轉移, 還是32位遠轉移           ; 因為現在已經處於保護模式下, 處理器都將把第一個參數0x0008視為選擇子           ; 而不是實模式下的邏輯段地址           jmp dword 0x0008:_ProtectMode                      [bits 32]              _ProtectMode:           ; 選擇子00000000000_10_000B, 索引為2的描述符           mov ax, 0x10           mov ds, ax                      mov byte [0x00], 'H'           mov byte [0x02], 'e'           mov byte [0x04], 'l'           mov byte [0x06], 'l'           mov byte [0x08], '0'           mov byte [0x0a], ' '           mov byte [0x0c], 'O'           mov byte [0x0e], 'n'           mov byte [0x10], 'z'           mov byte [0x12], '.'           mov byte [0x14], '.'           mov byte [0x16], '.'                      hlt                   ; 因為關中斷, 所以處理器不會被喚醒              gdt_size    dw 0   gdt_base    dd 0x7e00      times       510 - ($ - $$) db 0               dw 0xaa55 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.