Linux核心系列—作業系統開發之進入32位保護模式,linux保護模式

來源:互聯網
上載者:User

Linux核心系列—作業系統開發之進入32位保護模式,linux保護模式

源碼如下:

; ==========================================; pmtest1.asm; 編譯方法:nasm pmtest1.asm -o pmtest1.bin; ==========================================%include"pm.inc"; 常量, 宏, 以及一些說明org07c00hjmpLABEL_BEGIN[SECTION .gdt]; GDT;                                                                         段基址,        段界限     ,                              屬性LABEL_GDT:                      Descriptor          0,                0,                                         0                  ; 空描述符LABEL_DESC_CODE32: Descriptor           0,             SegCode32Len - 1,    DA_C + DA_32   ; 非一致程式碼片段LABEL_DESC_VIDEO:    Descriptor    0B8000h,     0ffffh,                              DA_DRW       ; 顯存首地址; GDT 結束GdtLenequ$ - LABEL_GDT; GDT長度GdtPtrdwGdtLen - 1; GDT界限dd0; GDT基地址; GDT 選擇子SelectorCode32equLABEL_DESC_CODE32- LABEL_GDTSelectorVideoequLABEL_DESC_VIDEO- LABEL_GDT; END of [SECTION .gdt][SECTION .s16][BITS16]LABEL_BEGIN:movax, csmovds, axmoves, axmovss, axmovsp, 0100h; 初始化 32 位程式碼片段描述符xoreax, eaxmovax, csshleax, 4addeax, LABEL_SEG_CODE32movword [LABEL_DESC_CODE32 + 2], axshreax, 16movbyte [LABEL_DESC_CODE32 + 4], almovbyte [LABEL_DESC_CODE32 + 7], ah; 為載入 GDTR 作準備xoreax, eaxmovax, dsshleax, 4addeax, LABEL_GDT; eax <- gdt 基地址movdword [GdtPtr + 2], eax; [GdtPtr + 2] <- gdt 基地址; 載入 GDTRlgdt[GdtPtr]; 關中斷cli; 開啟地址線A20inal, 92horal, 00000010bout92h, al; 準備切換到保護模式moveax, cr0oreax, 1movcr0, eax; 真正進入保護模式jmpdword SelectorCode32:0; 執行這一句會把 SelectorCode32 裝入 cs,; 並跳轉到 SelectorCode32:0  處; END of [SECTION .s16][SECTION .s32]; 32 位程式碼片段. 由實模式跳入.[BITS32]LABEL_SEG_CODE32:movax, SelectorVideomovgs, ax; 視頻段選擇子(目的)movedi, (80 * 11 + 79) * 2; 螢幕第 11 行, 第 79 列。movah, 0Ch; 0000: 黑底    1100: 紅字moval, 'P'mov[gs:edi], ax; 到此停止jmp$SegCode32Lenequ$ - LABEL_SEG_CODE32; END of [SECTION .s32]

運行結果如下,在螢幕最右邊有一個紅色的P:

源碼解析:

1.首先程式跳轉至LABEL_BEGIN處,jmp LABEL_BEGIN。將ds、es、ss段寄存器全部初始化為當前程式碼片段。

2.初始化32位程式碼片段描述符

在實模式下,也就是8086的16位的CPU的定址方式是段x16+位移,而在保護模式下,段寄存器值變成了一個索引,這個索引指向段描述符,也就是GDT中對應的那個描述符,描述符中包含了最終的基地址。

 38-41行表示將當前程式碼段左移4位也就是x16,再加上LABEL_SEG_CODE32的位移地址,最終形成LABEL_SEG_CODE32的物理地址,42-45表示把此物理地址載入到段描述符對應的段基址位置,段描述符格式如所示

段基地址0-15位也就是LABEL_DESC_CODE32 + 2地址處,將16位的ax傳入,第43行向右移動16位表示已經傳入的16位消除,然後將剩餘的兩個8位高低寄存器值傳入對應的段基地址處。

Descriptor是在pm.inc中定義的宏,如所示,表示的就是段描述符的格式:

3.載入GDTR,GDRT的結構圖如下所示

GDTR是唯一的一個指向段描述符表的寄存器,48-55行就是把段描述符表的基地址載入到GDTR寄存器當中。48行清除eax值,49-52是把LABEL_GDT的物理地址載入到20行的GdtPtr的雙字處,也就是GDT基地址。55行把GdtPtr地址的內容載入到GDTR,雙位元組dw對應的是16位界限,雙字dd對應的是32位基地址。

4.關中斷和開啟A20

保護模式下中斷處理機制和實模式不同,所以先關閉中斷,指令為cli。開啟A20為曆史原因防止位移超出最大值時復原。58-63行

5.切換到保護模式

只要把寄存器cr0的第0位置為1就行了。66-68行

6.真正進入保護模式

jmp dword SelectorCode32:0,這一行是真正進入保護模式的代碼,SelectorCode32是個段選擇子,段選擇子的作用是找到對應的段描述符從而找到對應的段基地址。段選擇子的格式如所示

從位3開始表示為段描述符表的索引,這句代碼執行完之後就會把描述符LABEL_DESC_CODE32中的段基址也就是LABEL_SEG_CODE32載入到cs。

dword的作用是因為當前還是16位的代碼,如果沒有dword,SelectorCode32:0的位移地址如果超出16位那麼只會截取16位。

 

到此已經完全進入32位保護模式了。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.