国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
保護(hù)模式Protected Mode 簡寫為 pmode
保護(hù)模式, (Protected Mode,或有時簡寫為 pmode) 是一種 80286 系列和之后的 x86 兼容 CPU 操作模式。保護(hù)模式有一些新的特色,設(shè)計用來增強 多工 和系統(tǒng)穩(wěn)定度,像是 內(nèi)存保護(hù),分頁 系統(tǒng),以及硬件支援的 虛擬內(nèi)存。大部分的現(xiàn)今 x86 操作系統(tǒng) 都在保護(hù)模式下運行,包含 Linux、FreeBSD、以及 微軟 Windows 2.0 和之后版本。
目錄
概況
What is GDT
Setup GDT
Load GDT
Other Preparing Stuff
Start Kernel
概況
另外一種 286 和其之后 CPU 的操作模式是 真實模式,一種向前兼容且關(guān)閉這些特色的模式。設(shè)計用來讓新的芯片可以執(zhí)行舊的軟件。依照設(shè)計的規(guī)格,所有的 x86 CPU 都是在真實模式下開機來確保傳統(tǒng)操作系統(tǒng)的向前兼容性。在任何保護(hù)模式的特色可用前,他們必須要由某些程序手動地切換到保護(hù)模式。在現(xiàn)今的電腦,這種切換通常是由 操作系統(tǒng) 在開機時候必須完成的第一件工作的一個。它也可能當(dāng) CPU 在保護(hù)模式下運行時,使用 虛擬86模式 來執(zhí)行設(shè)計給真實模式的程序碼。
盡管用軟件的方式也有某些可能在真實模式的系統(tǒng)下使用多工,但保護(hù)模式下內(nèi)存保護(hù)的特色,可以避免有問題的程序破壞其他工作或是 操作系統(tǒng) 核心所擁有的內(nèi)存。保護(hù)模式也有中斷正在執(zhí)行程序的硬件支援,可以把 execution content 交給其他工作,得以實現(xiàn) 先占式多工。
大部分可以使用保護(hù)模式的 CPU 也擁有 32 位元暫存器 的特色 (例如 80386 系列和其后任何的芯片),導(dǎo)入了融合保護(hù)模式而成為 32 位元處理的概念。80286 芯片雖有支援保護(hù)模式,但是仍然只有 16 位元暫存器。Windows 2.0 和之后版本中的保護(hù)模式增強稱為 "386 增強模式",是因為他們除了保護(hù)模式外,還需要 32 位元的暫存器,并且無法在 286 上面執(zhí)行 (即使 286 支援保護(hù)模式)。
即使在 32 位元芯片上已經(jīng)打開了保護(hù)模式,但是 1 MB 以上的內(nèi)存并無法存取,是由于一種仿照 IBM XT 系統(tǒng)設(shè)計特性的 memory wrap-around(內(nèi)存連續(xù)) 的因素。這種限制可以由打開 A20 line 來回避。
在保護(hù)模式下,前面 32 個中斷都是保留給 CPU 例外處理用。舉個例子,中斷 0D (十進(jìn)制 13) 是 一般保護(hù)模式錯物 和 中斷 00 是 除以零。
在8086/8088時代,處理器只存在一種操作模式(Operation Mode),當(dāng)時由于不存在其它操作模式,因此這種模式也沒有被命名。自從80286到80386開始,處理器增加了另外兩種操作模式——保護(hù)模式PM (Protected Mode)和系統(tǒng)管理模式SMM(System Management Mode),因此,8086/8088的模式被命名為實地址模式RM(Real-address Mode)。
PM是處理器的native模式,在這種模式下,處理器支持所有的指令和所有的體系結(jié)構(gòu)特性,提供最高的性能和兼容性。對于所有的新型應(yīng)用程序和操作系統(tǒng)來說,建議都使用這種模式。為了保證PM的兼容性,處理器允許在受保護(hù)的,多任務(wù)的環(huán)境下執(zhí)行RM程序。這個特性被稱做虛擬8086模式(Virtual -8086 Mode),盡管它并不是一個真正的處理器模式。Virtual-8086模式實際上是一個PM的屬性,任何任務(wù)都可以使用它。
RM提供了Intel 8086處理器的編程環(huán)境,另外有一些擴展(比如切換到PM或SMM的能力)。當(dāng)主機被Power-up或Reset后,處理器處于RM下。
SMM是一個對所有Intel處理器都統(tǒng)一的標(biāo)準(zhǔn)體系結(jié)構(gòu)特性。出現(xiàn)于Intel386 SL芯片。這個模式為OS實現(xiàn)平臺指定的功能(比如電源管理或系統(tǒng)安全)提供了一種透明的機制。當(dāng)外部的SMM interrupt pin(SMI#)被激活或者從APIC(Advanced Programming Interrupt Controller)收到一個SMI,處理器將進(jìn)入SMM。在SMM下,當(dāng)保存當(dāng)前正在運行程序的整個上下文(Context)時,處理器切換到一個分離的地址空間。然后SMM指定的代碼或許被透明的執(zhí)行。當(dāng)從SMM返回時,處理器將回到被系統(tǒng)管理中斷之前的狀態(tài)。
由于機器在Power-up或Reset之后,處理器處于RM狀態(tài),而對于Intel 80386以及其后的芯片,只有使用PM才能發(fā)揮出最大的作用。所以我們就面臨著一個從RM切換到PM的問題。
本文不討論SMM,本節(jié)的重點集中于在Booting階段如何從RM切換到PM,這里不會過多的討論PM的細(xì)節(jié),因為《Intel Architecture Software Developer’s Manual Volume 3: System Programming》中有非常詳盡和準(zhǔn)確的介紹。What is GDT
在Protected Mode下,一個重要的必不可少的數(shù)據(jù)結(jié)構(gòu)就是GDT(Global Descriptor Table)。
為什么要有GDT?我們首先考慮一下在Real Mode下的編程模型:
在Real Mode下,我們對一個內(nèi)存地址的訪問是通過Segment:Offset的方式來進(jìn)行的,其中Segment是一個段的Base Address,一個Segment的最大長度是64 KB,這是16-bit系統(tǒng)所能表示的最大長度。而Offset則是相對于此Segment Base Address的偏移量。Base Address+Offset就是一個內(nèi)存絕對地址。由此,我們可以看出,一個段具備兩個因素:Base Address和Limit(段的最大長度),而對一個內(nèi)存地址的訪問,則是需要指出:使用哪個段?以及相對于這個段Base Address的Offset,這個Offset應(yīng)該小于此段的Limit。當(dāng)然對于16-bit系統(tǒng),Limit不要指定,默認(rèn)為最大長度64KB,而 16-bit的Offset也永遠(yuǎn)不可能大于此Limit。我們在實際編程的時候,使用16-bit段寄存器CS(Code Segment),DS(Data Segment),SS(Stack Segment)來指定Segment,CPU將段積存器中的數(shù)值向左偏移4-bit,放到20-bit的地址線上就成為20-bit的Base Address。
到了Protected Mode,內(nèi)存的管理模式分為兩種,段模式和頁模式,其中頁模式也是基于段模式的。也就是說,Protected Mode的內(nèi)存管理模式事實上是:純段模式和段頁式。進(jìn)一步說,段模式是必不可少的,而頁模式則是可選的——如果使用頁模式,則是段頁式;否則這是純段模式。
既然是這樣,我們就先不去考慮頁模式。對于段模式來講,訪問一個內(nèi)存地址仍然使用Segment:Offset的方式,這是很自然的。由于 Protected Mode運行在32-bit系統(tǒng)上,那么Segment的兩個因素:Base Address和Limit也都是32位的。IA-32允許將一個段的Base Address設(shè)為32-bit所能表示的任何值(Limit則可以被設(shè)為32-bit所能表示的,以2^12為倍數(shù)的任何指),而不象Real Mode下,一個段的Base Address只能是16的倍數(shù)(因為其低4-bit是通過左移運算得來的,只能為0,從而達(dá)到使用16-bit段寄存器表示20-bit Base Address的目的),而一個段的Limit只能為固定值64 KB。另外,Protected Mode,顧名思義,又為段模式提供了保護(hù)機制,也就說一個段的描述符需要規(guī)定對自身的訪問權(quán)限(Access)。所以,在Protected Mode下,對一個段的描述則包括3方面因素:[Base Address, Limit, Access],它們加在一起被放在一個64-bit長的數(shù)據(jù)結(jié)構(gòu)中,被稱為段描述符。這種情況下,如果我們直接通過一個64-bit段描述符來引用一個段的時候,就必須使用一個64-bit長的段積存器裝入這個段描述符。但I(xiàn)ntel為了保持向后兼容,將段積存器仍然規(guī)定為16-bit(盡管每個段積存器事實上有一個64-bit長的不可見部分,但對于程序員來說,段積存器就是16-bit的),那么很明顯,我們無法通過16-bit長度的段積存器來直接引用64-bit的段描述符。
怎么辦?解決的方法就是把這些長度為64-bit的段描述符放入一個數(shù)組中,而將段寄存器中的值作為下標(biāo)索引來間接引用(事實上,是將段寄存器中的高13 -bit的內(nèi)容作為索引)。這個全局的數(shù)組就是GDT。事實上,在GDT中存放的不僅僅是段描述符,還有其它描述符,它們都是64-bit長,我們隨后再討論。
GDT可以被放在內(nèi)存的任何位置,那么當(dāng)程序員通過段寄存器來引用一個段描述符時,CPU必須知道GDT的入口,也就是基地址放在哪里,所以Intel的設(shè)計者門提供了一個寄存器GDTR用來存放GDT的入口地址,程序員將GDT設(shè)定在內(nèi)存中某個位置之后,可以通過LGDT指令將GDT的入口地址裝入此積存器,從此以后,CPU就根據(jù)此積存器中的內(nèi)容作為GDT的入口來訪問GDT了。
GDT是Protected Mode所必須的數(shù)據(jù)結(jié)構(gòu),也是唯一的——不應(yīng)該,也不可能有多個。另外,正象它的名字(Global Descriptor Table)所揭示的,它是全局可見的,對任何一個任務(wù)而言都是這樣。
除了GDT之外,IA-32還允許程序員構(gòu)建與GDT類似的數(shù)據(jù)結(jié)構(gòu),它們被稱作LDT(Local Descriptor Table),但與GDT不同的是,LDT在系統(tǒng)中可以存在多個,并且從LDT的名字可以得知,LDT不是全局可見的,它們只對引用它們的任務(wù)可見,每個任務(wù)最多可以擁有一個LDT。另外,每一個LDT自身作為一個段存在,它們的段描述符被放在GDT中。
IA-32為LDT的入口地址也提供了一個寄存器LDTR,因為在任何時刻只能有一個任務(wù)在運行,所以LDT寄存器全局也只需要有一個。如果一個任務(wù)擁有自身的LDT,那么當(dāng)它需要引用自身的LDT時,它需要通過LLDT將其LDT的段描述符裝入此寄存器。LLDT指令與LGDT指令不同的時,LGDT指令的操作數(shù)是一個32-bit的內(nèi)存地址,這個內(nèi)存地址處存放的是一個32-bit GDT的入口地址,以及16-bit的GDT Limit。而LLDT指令的操作數(shù)是一個16-bit的選擇子,這個選擇子主要內(nèi)容是:被裝入的LDT的段描述符在GDT中的索引值——這一點和剛才所討論的通過段積存器引用段的模式是一樣的。
LDT只是一個可選的數(shù)據(jù)結(jié)構(gòu),你完全可以不用它。使用它或許可以帶來一些方便性,但同時也帶來復(fù)雜性,如果你想讓你的OS內(nèi)核保持簡潔性,以及可移植性,則最好不要使用它。
引用GDT和LDT中的段描述符所描述的段,是通過一個16-bit的數(shù)據(jù)結(jié)構(gòu)來實現(xiàn)的,這個數(shù)據(jù)結(jié)構(gòu)叫做Segment Selector——段選擇子。它的高13位作為被引用的段描述符在GDT/LDT中的下標(biāo)索引,bit 2用來指定被引用段描述符被放在GDT中還是到LDT中,bit 0和bit 1是RPL——請求特權(quán)等級,被用來做保護(hù)目的,我們這里不詳細(xì)討論它。
前面所討論的裝入段寄存器中作為GDT/LDT索引的就是Segment Selector,當(dāng)需要引用一個內(nèi)存地址時,使用的仍然是Segment:Offset模式,具體操作是:在相應(yīng)的段寄存器裝入Segment Selector,按照這個Segment Selector可以到GDT或LDT中找到相應(yīng)的Segment Descriptor,這個Segment Descriptor中記錄了此段的Base Address,然后加上Offset,就得到了最后的內(nèi)存地址。如下圖所示:Setup GDT
由上一節(jié)的討論得知,GDT是Protected Mode所必須的數(shù)據(jù)結(jié)構(gòu),那么我們在進(jìn)入Protected Mode之前,必須設(shè)定好GDT,并通過LGDT將其裝入相應(yīng)的寄存器。
盡管GDT允許被放在內(nèi)存的任何位置,但由于GDT中的元素——描述符——都是64-bit長,也就是說都是8個字節(jié),所以為了讓CPU對GDT的訪問速度達(dá)到最快,我們應(yīng)該將GDT的入口地址放在以8個字節(jié)對齊,也就是說是8的倍數(shù)的地址位置。
GDT中第一個描述符必須是一個空描述符,也就是它的內(nèi)容應(yīng)該全部為0。如果引用這個描述符進(jìn)行內(nèi)存訪問,則是產(chǎn)生General Protection異常。
如果一個OS不使用虛擬內(nèi)存,段模式會是一個不錯的選擇。但現(xiàn)代OS沒有不使用虛擬內(nèi)存的,而實現(xiàn)虛擬內(nèi)存的比較方便和有效的內(nèi)存管理方式是頁式管理。但是在IA-32上如果我們想使用頁式管理,我們只能使用段頁式——沒有方法可以完全禁止段模式。但我們可以盡力讓段的效果降低的最小。
IA-32提供了一種被稱作“Basic Flat Model”的分段模式可以達(dá)到這種效果。這種模式要求在GDT中至少要定義兩個段描述符,一個用來引用Data Segment,另一個用來引用Code Segment。這2個Segment都包含整個線性空間,即Segment Limit = 4 GB,即使實際的物理內(nèi)存遠(yuǎn)沒有那么多,但這個空間定義是為了將來由頁式管理來實現(xiàn)虛擬內(nèi)存。
在這里,我們只是處于Booting階段,所以我們只需要初步設(shè)置一下GDT,等真正進(jìn)入Protected Mode,啟動了OS Kernel之后,具體OS打算如何設(shè)置GDT,使用何種內(nèi)存管理模式,由Kernel自身來設(shè)置,Booting只需要給Kernel的數(shù)據(jù)段和代碼段設(shè)置全部線性空間就可以了。
段描述符的格式如下圖所示:
具體到代碼段和數(shù)據(jù)段,它們的格式如下圖所示:
下面就是在Booting階段為進(jìn)入Protected Mode而設(shè)置的臨時的gdt。這里定義了3個段描述符:第一個是系統(tǒng)規(guī)定的空描述符,第2個是引用4 GB線性空間的代碼段,第3個是引用4 GB線性空間的數(shù)據(jù)段。這是"Basic Flat Model"所要求的最下GDT設(shè)置,但就booting階段,只是為了進(jìn)入Protected Mode,并為內(nèi)核提供一個連續(xù)的,最大的線性空間這個目的而言,已經(jīng)足夠了。
# Descriptor tables
gdt:
.word 0, 0, 0, 0 # dummy
.word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb)
.word 0 # base address = 0
.word 0x9A00 # code read/exec
.word 0x00CF # granularity = 4096, 386
# (+5th nibble of limit)
.word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb)
.word 0 # base address = 0
.word 0x9200 # data read/write
.word 0x00CF # granularity = 4096, 386
# (+5th nibble of limit)Load GDT
設(shè)置好GDT之后,我們需要通過LGDT指令將設(shè)定的gdt的入口地址和gdt表的大小裝入GDTR寄存器。
GDTR寄存器包括兩部分:32-bit的線性基地址,以及16-bit的GDT大?。ㄒ宰止?jié)為單位)。需要注意的是,對于32-bit線性基地址,必須是32-bit絕對物理地址,而不是相對于某個段的偏移量。而我們在Booting階段,在進(jìn)入Protected Mode之前,我們CS和DS設(shè)置很可能不是0,所以我們必須計算出gdt的絕對物理地址。
為了執(zhí)行LGDT指令,你需要把這兩部分內(nèi)容放在內(nèi)存的某個位置,然后將這個位置的內(nèi)存地址作為操作數(shù)傳遞給LGDT指令。然后LGDT指令會自動將保存在這個位置的這兩部分值裝入GDTR寄存器。
# 這是存放GDTR所需的兩部分內(nèi)容的位置
gdt_48:
.word 0x8000 # gdt limit=2048,
# 256 GDT entries
.word 0, 0 # gdt base (filled in later)
# 下面這段代碼用來計算GDT的32-bit線性地址,并將其裝入GDTR寄存器。
xorl %eax, %eax # Compute gdt_base
movw %ds, %ax # (Convert %ds:gdt to a linear ptr)
shll , %eax
addl $gdt, %eax
movl %eax, (gdt_48+2)
lgdt gdt_48 # load gdt with whatever is appropriateOther Preparing Stuff
在進(jìn)入Protected Mode之前,除了需要設(shè)置和裝入GDT之外,還需要做如下一些事情:
屏蔽所有可屏蔽中斷;
裝入IDTR;
所有協(xié)處理器被正確的Reset。
由于在Real Mode和Protected Mode下的中斷處理機制有一些不同,所以在進(jìn)入Protected Mode之前,務(wù)必禁止所有可屏蔽中斷,這可以通過下面兩種方法之一:
使用CLI指令;
對8259A可編程中斷控制器編程以屏蔽所有中斷。
即使當(dāng)我們進(jìn)入Protected Mode之后,也不能馬上將中斷打開,這時因為我們必須在OS Kernel中對相關(guān)的Protected Mode中斷處理所需的數(shù)據(jù)結(jié)構(gòu)正確的初始化之后,才能打開中斷,否則會產(chǎn)生處理器異常。
在Real Mode下,中斷處理使用IVT(Interrupt Vector Table),在Protected Mode下,中斷處理使用IDT(Interrupt Descriptor Table),所以,我們必須在進(jìn)入Protected Mode之前設(shè)置IDTR。
IDTR的格式和GDTR相同,IDTR的裝入方式和GDTR也相同。由于IDT中相關(guān)的中斷處理程序需要讓OS Kernel來設(shè)定,所以在Booting階段,我們只需要將IDTR中IDT的基地址和Size都設(shè)為0就可以了,隨后,等進(jìn)入Protected Mode之后,由OS Kernel來真正設(shè)置它。
關(guān)于中斷機制和中斷處理,請參考 Interrupt & Exception ,這里不再贅述。
#
# 這是存放IDTR所需的兩部分內(nèi)容的位置
#
idt_48:
.word 0 # idt limit = 0
.word 0, 0 # idt base = 0L
# 對于IDTR的處理,只需要這一條指令即可
lidt idt_48 # load idt with 0,0
#
# 通過設(shè)置8259A PIC,屏蔽所有可屏蔽中斷
#
movb xFF, %al # mask all interrupts for now
outb %al, xA1
call delay
movb xFB, %al # mask all irq's but irq2 which
outb %al, x21 # is cascaded
# 保證所有的協(xié)處理都被正確的Reset
xorw %ax, %ax
outb %al, xf0
call delay
outb %al, xf1
call delay
# Delay is needed after doing I/O
delay:
outb %al,x80
ret
5. Let's Go
好了,一切準(zhǔn)備就緒,F(xiàn)ire!:)
進(jìn)入Protected Mode,還是進(jìn)入Real Mode,完全靠CR0寄存器的PE標(biāo)志位來控制:如果PE=1,則CPU切換到PM,否則,則進(jìn)入RM。
設(shè)置CR0-PE位的方法有兩種:
第一種是80286所使用的LMSW指令,后來的80386及更高型號的CPU為了保持向后兼容,都保留了這個指令。這個指令只能影響最低的4 bit,即PE,MP,EM和TS,對其它的沒有影響。
#
#通過LMSW指令進(jìn)入Protected Mode
#
movw , %ax # protected mode (PE) bit
lmsw %ax # This is it!
第二種是Intel所建議的在80386以后的CPU上使用的進(jìn)入PM的方式,即通過MOV指令。MOV指令可以設(shè)置CR0寄存器的所有域的值。
#
#通過MOV指令進(jìn)入Protected Mode
#
movl %cr0, %eax
xorb , %al # set PE = 1
movl %eax, %cr0 # go!!
OK,現(xiàn)在已經(jīng)進(jìn)入Protected Mode了。
很簡單,right?But It's not over yet!Start Kernel
我們已經(jīng)從Real Mode進(jìn)入Protected Mode,現(xiàn)在我們馬上就要啟動OS Kernel了。
OS Kernel運行在32-bit段模式,而當(dāng)前我們卻仍然處于16-bit段模式。這是怎么回事?為了了解這個問題,我們需要仔細(xì)探討一下IA-32的段模式的實現(xiàn)方法。
IA-32共提供了6個16-bit段寄存器:CS,DS,SS,ES,F(xiàn)S,GS。但事實上,這16-bit只是對程序員可見的部分,但每個寄存器仍然包括64-bit的不可見部分。
可見部分是為了供程序員裝載段寄存器,但一旦裝載完成,CPU真正使用的就只是不可見部分,可見部分就完全沒有用了。
不可見部分存放的內(nèi)容是什么?具體格式我沒有看到相關(guān)資料,但可以確定的是隱藏部分的內(nèi)容和段描述符的內(nèi)容是一致的(請參考段描述的格式),只不過格式可能不完全相同。但格式對我們理解這一點并不重要,因為程序員不可能能夠直接操作它。
我們以CS寄存器為例,對于其它寄存器也是一樣的:
在Real Mode下,當(dāng)我們執(zhí)行一個裝載CS寄存器的指令的時候(jmp,call,ret等),相關(guān)的值會被裝入CS寄存器的可見部分,但同時CPU也會根據(jù)可見部分的內(nèi)容來設(shè)置不可見部分。比如我們執(zhí)行"ljmp x1234, $go "之后,CS寄存器的可見部分的內(nèi)容就是1234h,同時,不可見部分的32-bit Base Address域被設(shè)置為00001234h,20-bit的Limit域被設(shè)置為固定值10000h,也就是64 KB,Access Information部分的其它值我們不去考慮,只考慮其D/B位,由于執(zhí)行此指令時處于Real Mode模式,所以D/B被設(shè)置為0,表示此段是一個16-bit段。當(dāng)對CS寄存器的可見部分和不可見部分的內(nèi)容都被設(shè)置之后,CS寄存器的裝載工作完成。隨后當(dāng)CPU需要通過CS的內(nèi)容進(jìn)行地址運算的時候,則僅僅引用不可見部分。
在Protected Mode下,當(dāng)我們執(zhí)行一個裝載CS寄存器的指令的時候,段選擇子(Segment Selector)被裝入CS寄存器的可見部分,同時CPU根據(jù)此選擇子到相應(yīng)的描述符表中(GDT或LDT)找到相應(yīng)的段描述符并將其內(nèi)容裝載入CS寄存器的不可見部分。隨后CPU當(dāng)需要通過CS的內(nèi)容進(jìn)行地址運算的時候,也僅僅引用不可見部分。
從上面的描述可以看出,事實上CPU在引用段寄存器的內(nèi)容進(jìn)行地址運算時,Real Mode和Protected Mode是一致的。另外,也明白了為什么我們在Real Mode下設(shè)置的段寄存器的內(nèi)容到了Protected Mode下仍然引用的是16-bit段。
那么我們?nèi)绾螌S設(shè)置為引用32-bit段?方法就像我們前面所討論的,使用jmp或call指令,引用一個段選擇子,到GDT中裝載一個引用32-bit段的段描述符。
需要注意的是,如果CS寄存器的內(nèi)容指出當(dāng)前是一個16-bit段,那么當(dāng)前的地址模式也就是16-bit地址模式,這與你當(dāng)前是出于Real Mode還是Protected Mode無關(guān)。而我們裝載32-bit段的jmp指令或call指令必須使用的是32-bit地址模式。而我們當(dāng)前的boot部分代碼是16-bit代碼,所以我們必須在此jmp/call指令前加上地址轉(zhuǎn)換前綴代碼66h。
下面的例子就是使用jmp指令裝入32-bit段。Jmpi指令的含義是段間跳轉(zhuǎn),其Opcode為Eah,其格式為:jmpi Offset, Segment Selector。
# 由于當(dāng)前的代碼是16-bit代碼,而我們要執(zhí)行32-bit地址模式的指令,指令前
# 需要有地址模式切換前綴66h,如果我們直接寫jmp指令,由編譯器來生成代碼
# 的話,是無法作到這一點的,所以我們直接寫相關(guān)數(shù)據(jù)。
.byte 0x66, 0xea # prefix + jmpi-opcode
.long 0x1000 # Offset
.word __KERNEL_CS # CS segment selector
上面的代碼相當(dāng)于32-bit指令:
jmpi 0x1000,__KERNEL_CS
如果__KERNEL_CS段選擇子所引用的段描述符設(shè)置的段空間為線形地址[0,4 GB],而我們將OS Kernel放在物理地址1000h,那么此jmpi指令就跳轉(zhuǎn)到OS Kernel的入口處,并開始執(zhí)行它。
此時,Booting階段結(jié)束,OS正式開始運行!
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
保護(hù)模式簡介
【實現(xiàn)操作系統(tǒng)05】完善Loader程序,并加載內(nèi)核(下)
Windows內(nèi)存管理
80x86保護(hù)模式系列教程(三.控制寄存器和系統(tǒng)地址寄存器)
操作系統(tǒng)啟動過程
一口氣看完45個寄存器,CPU核心技術(shù)大揭秘
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服