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