试图理解80836实模式转变为保护模式
8086cpu內(nèi)存地址線有20位,尋址空間可以達到1M,但是寄存器卻只有16位,所以為了訪問到所有的內(nèi)存空間,必須得使用兩個寄存器。于是就有了段寄存器和基址寄存器。但是兩個寄存器就一共有32位了,所以用不完,主要是第一個寄存器分多少位,第二個分多少位。第一個寄存器代表的內(nèi)容叫段,第二個寄存器代表的內(nèi)容叫偏移量。使用段寄存器的值和基址寄存器的值來定位一個內(nèi)存。形成了 段:偏移量 的內(nèi)存訪問方式。通常情況下,偏移量都是直接拉滿,使用16位。
8086存在的問題是誰都可以訪問內(nèi)存,可以自由修改內(nèi)存上任意位置的數(shù)據(jù),也就是說,在8086下,我隨便寫一個程序,把操作系統(tǒng)的數(shù)據(jù)給改了也是沒問題的。
因此80286引入了分段的保護機制,首先也是給內(nèi)存分段,每段的大小可以不一致。先在內(nèi)存中留下一小塊,記錄下每段的起始位置和大小,同時還有每個段讀寫屬性的和訪問等級等,讀寫屬性包括可讀可寫等權(quán)限,當要訪問這個段上的數(shù)據(jù)時,只有等級夠了才允許訪問。這就達到了內(nèi)存保護的目的。6個字節(jié)就可以記錄一個段的信息。記錄下這寫信息的那一塊內(nèi)存就叫做描述符表,里邊記錄了所有的段,每個段6個字節(jié)。這個表的起始位置通過一個寄存器GDTR保存起來,因此所有程序都可以找到這個表。一般對于我們的現(xiàn)在使用的電腦來說,計算機一旦開機,把整塊內(nèi)存的所有段都規(guī)劃好了,就往GDTR寄存器保存表的起始地址。
當進入80386后,地址線拓展到了32條,可訪問內(nèi)存空間達到了4GB,寄存器也達到了32位。按道理說就不需要兩個寄存器來定位一個地址了,也就是不需要分段了。但80386為了達到內(nèi)存保護功能,還是使用了分段的思想。原理也是和80826一樣,只是位數(shù)變了,段描述符變成了8個字節(jié)。如果要切換到64位模式我暫時不知道是怎么樣的,那樣基址就有64位了。
坑爹的是為了向下兼容,80386剛開機時使用的是8086的模式,也稱為實模式。也就是說,電腦運行后,沒有段描述符表,訪問內(nèi)存的方式也是段:偏移量的方式。很多支持32位保護模式的寄存器都沒用上。
于是存在了模式切換的需要。
模式切換,主要就是建立段描述符表,通知CPU,讓CPU改變尋址方式、轉(zhuǎn)換到相關(guān)32位的操作,應該就是切換到相關(guān)線路。
模式切換的方法也不難,就是執(zhí)行一段代碼。實現(xiàn)這段代碼的原理或者說步驟為:
第一步,寫模式切換代碼之前,先規(guī)劃你的內(nèi)存分段,理論上隨便你怎么分,分多少段都行,但是CPU要求第一個段描述符必須為空。按照慣例,一般都有數(shù)據(jù)段、代碼段、堆棧段。這樣比較好對程序進行處理,因為數(shù)據(jù)段可讀可寫、代碼段可讀不可寫,它們是不一樣的。
第二步,創(chuàng)建段描述符表,怎么創(chuàng)建呢?首先是找一塊內(nèi)存,起始位置作為段描述符的基址,因為運行這段代碼前,CPU在16位的8086模式下運行,因此你可以把你的段描述符表寫在任何地方,從那塊內(nèi)存開始,前8個字節(jié)寫入空值(第一段為空),第二個8字節(jié)就開始寫入設(shè)計的好的第一個段描述符了,8個字節(jié)保存一個段描述符,以此類推。
第三步,通知CPU,主要包括填寫GDTR寄存器和修改cR0寄存器pe位的值。GDTR一共有48位,前16位記錄的是段描述符表的大小,后32位記錄的是段描述符表的基址,因為一個地址有32位嘛,如此,其他寄存器就可以找到GDTR寄存器的值啦!這樣一來,CPU就通知完畢了。
第四步,清空緩沖區(qū)的代碼,因為之前的代碼都是16位了,以后要切換到32位模式運行了,這些代碼不能運行了。
模式切換的這段代碼也可以放在啟動扇區(qū)里,達到程序一運行就立馬改成32位保護模式的效果。
需要說明的是:內(nèi)存分段是可以重疊的,比如把所有的整塊內(nèi)存空間作為數(shù)據(jù)段,然后其中一部分或者也是整塊內(nèi)存空間作為代碼段,當數(shù)據(jù)段是4GB的整塊空間,代碼段也是4GB的整塊空間時,叫做平坦模式。
參考:
全局描述符表
進入保護模式
結(jié)合p21、p27、p28一起看
觀察到的小細節(jié):
1,匯編中,db表示一個字節(jié),dw表示兩個字節(jié),這個d并不代表double的意思,但是dword表示四個字節(jié),這個d是double的意思,所以dw并不是dword的縮寫。
2.注意看以下兩張圖片中的匯編代碼都不帶變量名的。就可以定義段界限、段基地址。并且大小不一樣。
原因是定了標號,比如NullDescriptor, DataDescriptor,CodeDescriptot.標號的作用是記錄了位置,可以理解為數(shù)組名,雖然里邊的每一段大小不一樣。
總結(jié)
以上是生活随笔為你收集整理的试图理解80836实模式转变为保护模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 计算机与USB沟通方式
- 下一篇: 关于程序为什么要代码段,程序段