保护模式及其编程——实模式与保护模式的切换
生活随笔
收集整理的這篇文章主要介紹了
保护模式及其编程——实模式与保护模式的切换
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
機器上電,CPU進入實模式,從物理地址0xFFFFFFFF0處開始執行初始化代碼,設置基本系統功能操作必要的數據結構信息,例如處理中斷和異常的IDT表。接下來,如果繼續在保護模式工作,需要加載操作系統模塊;如果要進入實模式,那么需要進行模式切換。
1)保護模式中斷描述符表IDT
2)GDT
3)任務狀態段TSS
4)LDT
5)如果使用分頁機制,起碼要設置一個頁目錄和一個頁表
6)處理器切換到保護模式下運行的代碼段
能夠切換到保護模式運行之前,需要設置以下系統寄存器
1)GDTR
2)中斷描述符表基地址寄存器
3)控制寄存器CR1~CR3
初始化這些數據結構、代碼模塊和系統寄存器之后,通過設置CR0寄存器的保護模式標志位PE,處理器就可以切換到保護模式運行了。
為了實現無分頁的平坦內存模型,必須設置至少一個代碼段和數據段到GDT。在GDT可以使用之前,必須要使用LGDT指令將GDT表的基地址和長度加載到GDTR之中。
多段模型需要操作系統的其他段,以及用于每個應用程序的段和LDT表段。
初始化代碼必須設置一個保護模式IDT,其中至少包含有處理器可能產生的每個異常向量對應的門描述符。
在可以使用IDT之前,必須使用LIDT指令將IDT表基地址和長度加載到IDTR寄存器之中。
分頁寄存器由控制寄存器CR0中的PG標志設置,在設置PG標志之前,必須先初始化以下數據結構和寄存器:
1)軟件必須在物理內存中建立至少一個頁目錄和一個頁表
2)把頁目錄表的物理基地址加載到CR3寄存器中
3)處理器處在保護模式下
為了保持兼容性,設置PG標志時候必須遵從以下規則:
1)設置PG標志的指令應該立即跟隨一條JMP指令
2)設置PG標志和JMP之間的代碼必須來自對等映射(跳轉之前的線性地址與開啟分頁之后的物理地址相同)的一個頁面上。
如果需要使用多任務機制或者允許改變特權級,那么軟件初始化代碼需要設置一個TSS及相應的TSS段描述符(因為特權級0、1、2的各棧段指針都需要從TSS中取得)。
在處理器切換到保護模式以后,可以用LTR指令把TSS段描述符的選擇符加載到任務寄存器TR中。在保護模式中,軟件進行第一次任務切換之前必須首先加載在TSS段的選擇符,因為任務切換會把當前任務狀態復制到該TSS中。
在LTR指令執行之后,隨后對任務寄存器的操作由任務切換進行。
切換到保護膜是之前,必須首先加載一些起碼的系統數據結構和代碼模塊。切換操作的步驟:
1)使用cli指令禁止終端
2)執行LGDT命令,加載GDT
3)設置CR0(PE位)
4)mov cr0 之后立刻跟一個遠程JMP或者遠程call指令
5)選擇性執行LLDT
6)執行LTR指令,用初始保護模式任務的段選擇符或者可寫內存區域的段描述符加載任務寄存器TR
7)進入保護模式后,段寄存器仍人含有在實地址模式時候的內容,需要進一步處理
8) LIDT
9)開中斷 sti
1)禁止終端
2)如果開啟分頁機制,那么需要執行:
把程序的控制轉移到對等映射的線性地址處
確保GDT和LDT在對等映射的頁面上
清楚CR0中的PG標志
設置CR3寄存器為0x00,用于刷新TLB緩沖
3)把程序的控制轉移到長度為64KB(0xFFFF)的可讀段中。這部操作使用實模式要求的段長度加載CS寄存器
4)使用含有一下設置值的描述符選擇符來加載SS、DS、ES、FS、GS
段長=64kb
顆粒 G=0
向上擴展 E=0
可寫 w=1
存在 p=1
5)執行LIDT指令來指向在1MB實模式地址范圍內的實地址模式中斷表
6)清楚cr0中的PE位
7)執行一個遠跳轉指令跳轉到一個實模式程序中。這個操作會刷新指令隊列,并且為CS寄存器加載何時的基地址和訪問權限值
8)加載實地址模式程序代碼會使用的SS、DS、ES、FS、GS
1.進入保護模式時的初始化操作
1)保護模式中斷描述符表IDT
2)GDT
3)任務狀態段TSS
4)LDT
5)如果使用分頁機制,起碼要設置一個頁目錄和一個頁表
6)處理器切換到保護模式下運行的代碼段
能夠切換到保護模式運行之前,需要設置以下系統寄存器
1)GDTR
2)中斷描述符表基地址寄存器
3)控制寄存器CR1~CR3
初始化這些數據結構、代碼模塊和系統寄存器之后,通過設置CR0寄存器的保護模式標志位PE,處理器就可以切換到保護模式運行了。
1.1保護模式系統結構表
為了實現無分頁的平坦內存模型,必須設置至少一個代碼段和數據段到GDT。在GDT可以使用之前,必須要使用LGDT指令將GDT表的基地址和長度加載到GDTR之中。
多段模型需要操作系統的其他段,以及用于每個應用程序的段和LDT表段。
1.2保護模式異常和中斷初始化
初始化代碼必須設置一個保護模式IDT,其中至少包含有處理器可能產生的每個異常向量對應的門描述符。
在可以使用IDT之前,必須使用LIDT指令將IDT表基地址和長度加載到IDTR寄存器之中。
1.3分頁機制初始化
分頁寄存器由控制寄存器CR0中的PG標志設置,在設置PG標志之前,必須先初始化以下數據結構和寄存器:
1)軟件必須在物理內存中建立至少一個頁目錄和一個頁表
2)把頁目錄表的物理基地址加載到CR3寄存器中
3)處理器處在保護模式下
為了保持兼容性,設置PG標志時候必須遵從以下規則:
1)設置PG標志的指令應該立即跟隨一條JMP指令
2)設置PG標志和JMP之間的代碼必須來自對等映射(跳轉之前的線性地址與開啟分頁之后的物理地址相同)的一個頁面上。
1.4多任務初始化
如果需要使用多任務機制或者允許改變特權級,那么軟件初始化代碼需要設置一個TSS及相應的TSS段描述符(因為特權級0、1、2的各棧段指針都需要從TSS中取得)。
在處理器切換到保護模式以后,可以用LTR指令把TSS段描述符的選擇符加載到任務寄存器TR中。在保護模式中,軟件進行第一次任務切換之前必須首先加載在TSS段的選擇符,因為任務切換會把當前任務狀態復制到該TSS中。
在LTR指令執行之后,隨后對任務寄存器的操作由任務切換進行。
2.模式切換
2.1切換到保護模式
切換到保護膜是之前,必須首先加載一些起碼的系統數據結構和代碼模塊。切換操作的步驟:
1)使用cli指令禁止終端
2)執行LGDT命令,加載GDT
3)設置CR0(PE位)
4)mov cr0 之后立刻跟一個遠程JMP或者遠程call指令
5)選擇性執行LLDT
6)執行LTR指令,用初始保護模式任務的段選擇符或者可寫內存區域的段描述符加載任務寄存器TR
7)進入保護模式后,段寄存器仍人含有在實地址模式時候的內容,需要進一步處理
8) LIDT
9)開中斷 sti
2.2切換回來實模式
1)禁止終端
2)如果開啟分頁機制,那么需要執行:
把程序的控制轉移到對等映射的線性地址處
確保GDT和LDT在對等映射的頁面上
清楚CR0中的PG標志
設置CR3寄存器為0x00,用于刷新TLB緩沖
3)把程序的控制轉移到長度為64KB(0xFFFF)的可讀段中。這部操作使用實模式要求的段長度加載CS寄存器
4)使用含有一下設置值的描述符選擇符來加載SS、DS、ES、FS、GS
段長=64kb
顆粒 G=0
向上擴展 E=0
可寫 w=1
存在 p=1
5)執行LIDT指令來指向在1MB實模式地址范圍內的實地址模式中斷表
6)清楚cr0中的PE位
7)執行一個遠跳轉指令跳轉到一個實模式程序中。這個操作會刷新指令隊列,并且為CS寄存器加載何時的基地址和訪問權限值
8)加載實地址模式程序代碼會使用的SS、DS、ES、FS、GS
9)執行STI指令開啟可屏蔽硬件中斷,并且執行必要的硬件操作開啟NMI中斷
這里,我們特別留意其中的第4步和第8步,尤其是第4步中,設置SS等寄存器的目的是為了保證SS等寄存器的不可見部分,到了實模式之下,仍然有正確的屬性值。
參考:《linux內核0.12完全剖析》
總結
以上是生活随笔為你收集整理的保护模式及其编程——实模式与保护模式的切换的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: loader.asm 注释
- 下一篇: 内核初始化kernel.asm