實模式到保護模式:第11章讀書筆記
在這一章的主要任務就是從實模式進入保護模式
- 首先創建幾個初始化描述符,確保在進入保護模式之后程序能夠正常運行,
- 將初始化描述符的內容放到GDT表中,此時雖然將GDT表的基地址和大小加載到GDT寄存器中,但是GDT表所在位置已經定義好了
- 接下來將GDT表所在位置和大小全部加載到GDT寄存器中
- 接下來開啟第21根地址線,禁止中斷,將cr0寄存器的PE位的值置為1,進入保護模式,但是此時還是處于16位的保護模式
2. 什么是GDT表?
- 在保護模式中,內存訪問方式與實模式不同,在實模式中,尋址方式是
段寄存器*16+偏移量
在32處理器中,段寄存器的結構發生了變化,結構如下

- 在保護模式下的內存訪問的方式
- 段寄存器中存儲的值為段描述符的索引,也就是0-15位可見部分
- 當將索引加載到寄存器中,處理器會自動到GDT表中根據索引找到對應的描述符,然后將描述符的內容加載到描述符高速緩沖器部分
- 內存訪問的方式是根據段寄存器的高速緩沖器中的基地址的內容加上指令的偏移值(描述符的內容在將索引加載到寄存器時,會將描述符的值加載到寄存器的不可見部分),最終得到物理地址
- GDT表其實是對應了一塊內存區域,GDT寄存器保存了GDT表的基地址和表的最大偏移量(GDT表的大小 - 1),所有的全局描述符都存儲在這塊內存區域中,便形成了GDT表
- GDT寄存器的格式如下:
- 全局描述符表的邊界總共占據了16位,而一個描述符占據8個字節,所以GDT表最多可以存儲8192個描述符,而0號描述符不允許使用,所以最多是8191個全局描述符
3. 那么什么是描述符呢?
在實模式模式下,我們是采用分段機制對內存進行訪問的,在32位保護模式下,仍然是采用分段模式,即使是開啟分頁模式后,分段模式仍然使用,而描述符便是用來描述內存段(代碼段和數據段)的屬性
- 描述符的格式如下:

- 其中一些將要使用的屬性如下:
- 段基地址:總共32位,存儲了該段在內存中的位置
- 段界限:聲明了該段的大小
- D/B:默認操作數大小,當值為1時,默認為32位,當值為0時,默認為16位
- type字段:用于指示描述符的類別,數據段寄存器只能裝載數據類型的描述符,而cs寄存器之能裝載代碼段的描述符
type字段占據4個位,具體描述如下 
- X:表示是否為可執行的
- E:表明擴展方向
- R:是否可讀
- A:accessed,表明最近是否被訪問
4. 接下來就是開啟第21根地址了,這個主要是以前為了兼容,在實模式下第21根地址線是默認關閉的,所以當進入保護模式就必須開啟第21根地址線
5. 進入保護模式就只要簡單將cr0寄存器的PE位置為1即可
此時仍然是處于16位保護模式下,并且cs寄存器的值仍然是原先在實模式下的值,所以通過jmp指令跳轉到下一條指令,但是cs寄存器的值將能夠更新為對應代碼段的選擇子,并且還能夠清空流水線
貼下代碼
;代碼清單11-1 ;文件名:c11_mbr.asm ;文件說明:硬盤主引導扇區代碼 ;創建日期:2011-5-16 19:54 ;設置堆棧段和棧指針 mov ax,cs mov ss,ax mov sp,0x7c00 ;計算GDT所在的邏輯段地址 mov ax,[cs:gdt_base+0x7c00] ;低16位 mov dx,[cs:gdt_base+0x7c00+0x02] ;高16位 mov bx,16 div bx mov ds,ax ;令DS指向該段以進行操作 mov bx,dx ;段內起始偏移地址 ;創建0#描述符,它是空描述符,這是處理器的要求 mov dword [bx+0x00],0x00 mov dword [bx+0x04],0x00 ;創建#1描述符,保護模式下的代碼段描述符 mov dword [bx+0x08],0x7c0001ff mov dword [bx+0x0c],0x00409800 ;創建#2描述符,保護模式下的數據段描述符(文本模式下的顯示緩沖區) mov dword [bx+0x10],0x8000ffff mov dword [bx+0x14],0x0040920b ;創建#3描述符,保護模式下的堆棧段描述符 mov dword [bx+0x18],0x00007a00 mov dword [bx+0x1c],0x00409600 ;初始化描述符表寄存器GDTR mov word [cs: gdt_size+0x7c00],31 ;描述符表的界限(總字節數減一) lgdt [cs: gdt_size+0x7c00] in al,0x92 ;南橋芯片內的端口 or al,0000_0010B out 0x92,al ;打開A20 cli ;保護模式下中斷機制尚未建立,應 ;禁止中斷 mov eax,cr0 or eax,1 mov cr0,eax ;設置PE位 ;以下進入保護模式... ... jmp dword 0x0008:flush ;16位的描述符選擇子:32位偏移 ;清流水線并串行化處理器 [bits 32] flush: mov cx,00000000000_10_000B ;加載數據段選擇子(0x10) mov ds,cx ;以下在屏幕上顯示"Protect mode OK." mov byte [0x00],'P' mov byte [0x02],'r' mov byte [0x04],'o' mov byte [0x06],'t' mov byte [0x08],'e' mov byte [0x0a],'c' mov byte [0x0c],'t' mov byte [0x0e],' ' mov byte [0x10],'m' mov byte [0x12],'o' mov byte [0x14],'d' mov byte [0x16],'e' mov byte [0x18],' ' mov byte [0x1a],'O' mov byte [0x1c],'K' ;以下用簡單的示例來幫助闡述32位保護模式下的堆棧操作 mov cx,00000000000_11_000B ;加載堆棧段選擇子 mov ss,cx mov esp,0x7c00 mov ebp,esp ;保存堆棧指針 push byte '.' ;壓入立即數(字節) sub ebp,4 cmp ebp,esp ;判斷壓入立即數時,ESP是否減4 jnz ghalt pop eax mov [0x1e],al ;顯示句點 ghalt: hlt ;已經禁止中斷,將不會被喚醒 ;------------------------------------------------------------------------------- gdt_size dw 0 gdt_base dd 0x00007e00 ;GDT的物理地址 times 510-($-$$) db 0 db 0x55,0xaa
總結:第11章中伴隨著的任務就是從實模式進入保護模式,順便介紹了GDT表,段描述符的結構,cr0寄存器的內容,其實這個只是一個筆記,沒有說很詳細,有興趣的同學可以看一下這本書,我個人的理解就是這一章有一個中心,那就是從實模式到保護模式,這一章的內容都是根據這個的需要來介紹的

浙公網安備 33010602011771號