80386開始支持存儲(chǔ)器分頁管理機(jī)制。分頁機(jī)制是存儲(chǔ)器管理機(jī)制的第3二部分。段管理機(jī)制實(shí)現(xiàn)虛擬地址(由段和偏移構(gòu)成的邏輯地址)到線性地址的轉(zhuǎn)換,分頁管理機(jī)制實(shí)現(xiàn)線性地址到物理地址的轉(zhuǎn)換。如果不啟用分頁管理機(jī)制,那么線性地址就是物理地址。本文將介紹80386的存儲(chǔ)器分頁管理機(jī)制和線性地址如何轉(zhuǎn)換為物理地址。
<一>存儲(chǔ)器分頁管理機(jī)制
在保護(hù)模式下,控制寄存器CR0中的最高位PG位控制分頁管理機(jī)制是否生效。如果PG=1,分頁機(jī)制生效,把線性地址轉(zhuǎn)換為物理地址。如果PG=0,分頁機(jī)制無效,線性地址就直接作為物理地址。必須注意,只有在保護(hù)方式下分頁機(jī)制才可能生效。只有在保證使PE位為1的前提下,才能夠使PG位為1,否則將引起通用保護(hù)故障。
分頁機(jī)制把線性地址空間和物理地址空間分別劃分為大小相同的塊。這樣的塊稱之為頁。通過在線性地址空間的頁與物理地址空間的頁之間建立的映射,分頁機(jī)制實(shí)現(xiàn)線性地址到物理地址的轉(zhuǎn)換。線性地址空間的頁與物理地址空間的頁之間的映射可根據(jù)需要而確定,可根據(jù)需要而改變。線性地址空間的任何一頁,可以映射為物理地址空間中的任何一頁。
采用分頁管理機(jī)制實(shí)現(xiàn)線性地址到物理地址轉(zhuǎn)換映射的主要目的是便于實(shí)現(xiàn)虛擬存儲(chǔ)器。不象段的大小可變,頁的大小是相等并固定的。根據(jù)程序的邏輯劃分段,而根據(jù)實(shí)現(xiàn)虛擬存儲(chǔ)器的方便劃分頁。
在80386中,頁的大小固定為4K字節(jié),每一頁的邊界地址必須是4K的倍數(shù)。因此,4G大小的地址空間被劃分為1M個(gè)頁,頁的開始地址具有“XXXXX000H”的形式。為此,我們把頁開始地址的高20位XXXXXH稱為頁碼。線性地址空間頁的頁碼也就是頁開始邊界線性地址的高20位;物理地址空間頁的頁碼也就是頁開始邊界物理地址的高20位。可見,頁碼左移12位就是頁的開始地址,所以頁碼規(guī)定了頁。
由于頁的大小固定為4K字節(jié),且頁的邊界是4K的倍數(shù),所以在把32位線性地址轉(zhuǎn)換成32位物理地址的過程中,低12位地址保持不變。也就是說,線性地址的低12位就是物理地址的低12位。假設(shè)分頁機(jī)制采用的轉(zhuǎn)換映射把線性地址空間的XXXXXH頁映射到物理地址空間的YYYYYH頁,那么線性地址XXXXXxxxH被轉(zhuǎn)換為YYYYYxxxH。因此,線性地址到物理地址的轉(zhuǎn)換要解決的是線性地址空間的頁到物理地址空間的頁的映射,也就是線性地址高20位到物理地址高20位的轉(zhuǎn)換。
<二>線性地址到物理地址的轉(zhuǎn)換
1.映射表結(jié)構(gòu)
線性地址空間的頁到物理地址空間的頁之間的映射用表來描述。由于4G的地址空間劃分為1M個(gè)頁,因此,如果用一張表來描述這種映射,那么該映射表就要有1M個(gè)表項(xiàng),若每個(gè)表項(xiàng)占用4個(gè)字節(jié),那么該映射表就要占用4M字節(jié)。為避免映射表占用如此巨大的存儲(chǔ)器資源,所以80386把頁映射表分為兩級(jí)。
頁映射表的第一級(jí)稱為頁目錄表,存儲(chǔ)在一個(gè)4K字節(jié)的物理頁中。頁目錄表共有1K個(gè)表項(xiàng),其中,每個(gè)表項(xiàng)為4字節(jié)長,包含對(duì)應(yīng)第二級(jí)表所在物理地址空間頁的頁碼。頁映射表的第二級(jí)稱為頁表,每張頁表也安排在一個(gè)4K字節(jié)的頁中。每張頁表都有1K個(gè)表項(xiàng),每個(gè)表項(xiàng)為4字節(jié)長,包含對(duì)應(yīng)物理地址空間頁的頁碼。由于頁目錄表和頁表均由1K個(gè)表項(xiàng)組成,所以使用10位的索引就能指定表項(xiàng),即用10位的索引值乘以4加基地址就得到了表項(xiàng)的物理地址。
下圖顯示了由頁目錄表和頁表構(gòu)成的頁映射表結(jié)構(gòu)。從圖中可見,控制寄存器CR3指定頁目錄表;頁目錄表可以指定1K個(gè)頁表,這些頁表可以分散存放在任意的物理頁中,而不需要連續(xù)存放;每張頁表可以指定1K個(gè)物理地址空間的頁,這些物理地址空間的頁可以任意地分散在物理地址空間中。需要注意的是,存儲(chǔ)頁目錄表和頁表的基地址是對(duì)齊在4K字節(jié)邊界上的。
2.表項(xiàng)格式
頁目錄表和頁表中的表項(xiàng)都采用如下圖所示的格式。從圖中可見,最高20位(位12—位31)包含物理地址空間頁的頁碼,也就是物理地址的高20位。低12位包含頁的屬性。下圖所示的屬性中內(nèi)容為0的位是Intel公司為80486等處理器所保留的位,在為80386編程使用到它們時(shí)必須設(shè)置為0。在位9至位11的AVL字段供軟件使用。表項(xiàng)的最低位是存在屬性位,記作P。P位表示該表項(xiàng)是否有效。P=1表項(xiàng)有效;P=0表項(xiàng)無效,此時(shí)表項(xiàng)中的其余各位均可供軟件使用,80386不解釋P=0的表項(xiàng)中的任何其它的位。在通過頁目錄表和頁表進(jìn)行的線性地址到物理地址的轉(zhuǎn)換過程中,無論在頁目錄表還是在頁表中遇到無效表項(xiàng),都會(huì)引起頁故障。其它屬性位的作用在下文中介紹。
頁目錄表或頁
表的表項(xiàng)格式 BIT31—BIT12 BIT11—BIT9 BIT8 BIT7 BIT6 BIT5 BIT4 BIT3 BIT2 BIT1 BIT0 物理頁碼 AVL 0 0 D A 0 0 U/S R/W P
3.線性地址到物理地址的轉(zhuǎn)換
分頁管理機(jī)制通過上述頁目錄表和頁表實(shí)現(xiàn)32位線性地址到32位物理地址的轉(zhuǎn)換。控制寄存器CR3的高20位作為頁目錄表所在物理頁的頁碼。首先把線性地址的最高10位(即位22至位31)作為頁目錄表的索引,對(duì)應(yīng)表項(xiàng)所包含的頁碼指定頁表;然后,再把線性地址的中間10位(即位12至位21)作為所指定的頁目錄表中的頁表項(xiàng)的索引,對(duì)應(yīng)表項(xiàng)所包含的頁碼指定物理地址空間中的一頁;最后,把所指定的物理頁的頁碼作為高20位,把線性地址的低12位不加改變地作為32位物理地址的低12位。
為了避免在每次存儲(chǔ)器訪問時(shí)都要訪問內(nèi)存中的頁表,以便提高訪問內(nèi)存的速度,80386處理器的硬件把最近使用的線性—物理地址轉(zhuǎn)換函數(shù)存儲(chǔ)在處理器內(nèi)部的頁轉(zhuǎn)換高速緩存中。在訪問存儲(chǔ)器頁表之前總是先查閱高速緩存,僅當(dāng)必須的轉(zhuǎn)換不在高速緩存中時(shí),才訪問存儲(chǔ)器中的兩級(jí)頁表。頁轉(zhuǎn)換高速緩存也稱為頁轉(zhuǎn)換查找緩存,記為TLB。
在分頁機(jī)制轉(zhuǎn)換高速緩存中的數(shù)據(jù)與頁表中數(shù)據(jù)的相關(guān)性,不是由80386處理器進(jìn)行維護(hù)的,而必須由操作系統(tǒng)軟件保存,也就是說,處理器不知道軟件什么時(shí)候會(huì)修改頁表,在一個(gè)合理的系統(tǒng)中,頁表只能由操作系統(tǒng)修改,操作系統(tǒng)可以直接地在軟件修改頁表后通過刷新高速緩存來保證相關(guān)性。高速緩存的刷新通過裝入處理器控制寄存器CR3完成,實(shí)際過程可能用如下的兩條指令實(shí)現(xiàn):
mov eax,cr3
mov cr3,eax
一個(gè)重要的修改頁表項(xiàng)的特殊情況不需要對(duì)頁轉(zhuǎn)換高速緩存刷新,這種情況是指修改不存在表項(xiàng)的任一部分,即使P位本身從P=0改變?yōu)镻=1時(shí)也一樣,因?yàn)闊o效的表項(xiàng)不會(huì)存入高速緩存。因此,當(dāng)無效的表項(xiàng)被改變時(shí),不需要刷新高速緩存。這表明在從磁盤上讀入一頁使其存在時(shí),不必刷新高速緩存。
在一個(gè)多處理器系統(tǒng)中,必須特別注意是否在一個(gè)處理器中執(zhí)行的程序,會(huì)改變可能由另外的處理器同時(shí)訪問的頁表。在80386處理器中,每當(dāng)要更新頁表項(xiàng)并設(shè)置D位和A位時(shí),通過使用不可分的讀/修改/寫周期支持多處理器的配置。對(duì)于頁表項(xiàng)的軟件更新需要借助于使用LOCK前綴,從而保證修改頁表的指令工作在不可分的讀/修改/寫周期中。在改變一個(gè)可能由另外的處理器使用的頁表之前,最好使用一條加鎖的AND指令在一個(gè)不可分的操作中將P位清除為0,然后,該表項(xiàng)可根據(jù)要求進(jìn)行修改,并隨后把P位置成1而使表項(xiàng)成為可用。當(dāng)修改頁表項(xiàng)時(shí)必須及時(shí)通知(通常使用中斷方式)系統(tǒng)中該表項(xiàng)已被高速緩存的所有處理器刷新各自的頁轉(zhuǎn)換高速緩存,以撤消該表項(xiàng)的舊拷貝。在表項(xiàng)的舊拷貝被刷新之前,各處理器仍可繼續(xù)訪問舊的頁,并可以設(shè)置正被修改的表項(xiàng)的D位。如果這樣做引起表項(xiàng)修改失敗,則分頁機(jī)制高速緩存最好在標(biāo)記為不存在之后,并在對(duì)表項(xiàng)進(jìn)行另外的修改之前進(jìn)行刷新。
4.不存在的頁表
采用上述頁映射表結(jié)構(gòu),存儲(chǔ)全部1K張頁表需要4M字節(jié),此外還需要4K字節(jié)用于存儲(chǔ)頁目錄表。這樣的兩級(jí)頁映射表似乎反而比單一的整張頁映射表多占用4K字節(jié)。其實(shí)不然,事實(shí)上不需要在內(nèi)存中存儲(chǔ)完整的兩級(jí)頁映射表。兩級(jí)頁映射表結(jié)構(gòu)中對(duì)于線性地址空間中不存在的或未使用的部分不必分配頁表。除必須給頁目錄表分配物理頁外,僅當(dāng)在需要時(shí)才給頁表分配物理頁,于是頁映射表的大小就對(duì)應(yīng)于實(shí)際使用的線性地址空間大小。因?yàn)槿魏我粋€(gè)實(shí)際運(yùn)行的程序使用的線性地址空間都遠(yuǎn)小于4G字節(jié),所以用于分配給頁表的物理頁也遠(yuǎn)小于4M字節(jié)。
頁目錄表項(xiàng)中的存在位P表明對(duì)應(yīng)頁表是否有效。如果P=1,表明對(duì)應(yīng)頁表有效,可利用它進(jìn)行地址轉(zhuǎn)換;如果P=0,表明對(duì)應(yīng)頁表無效。如果試圖通過無效的頁表進(jìn)行線性地址到物理地址的轉(zhuǎn)換,那么將引起頁故障。因此,頁目錄表項(xiàng)中的屬性位P使得操作系統(tǒng)只需給覆蓋實(shí)際使用的線性地址范圍的頁表分配物理頁。
頁目錄表項(xiàng)中的屬性位P頁可用于把頁表存儲(chǔ)在虛擬存儲(chǔ)器中。當(dāng)發(fā)生由于所需頁表無效而引起的頁故障時(shí),頁故障處理程序再申請(qǐng)物理頁,從磁盤上把對(duì)應(yīng)的頁表讀入,并把對(duì)應(yīng)頁目錄表項(xiàng)中的P位置1。換言之,可以當(dāng)需要時(shí)才為所要的頁表分配物理頁。這樣頁表占用的物理頁數(shù)量可降到最小。
5.頁的共享
由上述頁映射表結(jié)構(gòu)可見,分頁機(jī)制沒有全局頁和局部頁的規(guī)定。每一個(gè)任務(wù)可使用自己的頁映射表獨(dú)立地實(shí)現(xiàn)線性地址到物理地址的轉(zhuǎn)換。但是,如果使每一個(gè)任務(wù)所用的頁映射表具有部分相同的映射,那么也就可以實(shí)現(xiàn)部分頁的共享。
常用的實(shí)現(xiàn)頁共享的方法是線性地址空間的共享,也就是不同任務(wù)的部分相同的線性地址空間的映射信息相同,具體表現(xiàn)為部分頁表相同或頁表內(nèi)的部分表項(xiàng)的頁碼相同。例如,如果任務(wù)A和任務(wù)B分別使用的頁目錄表A和頁目錄表B內(nèi)的第0項(xiàng)中的頁碼相同,也就是頁表0相同,那么任務(wù)A和任務(wù)B的00000000H至003FFFFFH線性地址空間就映射到相同的物理頁。再如,任務(wù)A和任務(wù)B使用的頁表0不同,但這兩張頁表內(nèi)第0至第0FFH項(xiàng)的頁碼對(duì)應(yīng)相同,那么任務(wù)A和任務(wù)B的00000000H至000FFFFFH線性地址空間就映射到相同的物理頁。
需要注意的是,共享的頁表最好由兩個(gè)頁目錄中同樣的目錄項(xiàng)所指定。這一點(diǎn)很重要,因?yàn)樗WC了在兩個(gè)任務(wù)中同樣的線性地址范圍將映射到該全局區(qū)域。
<三>頁級(jí)保護(hù)和虛擬存儲(chǔ)器支持
1.頁級(jí)保護(hù)
80386不僅提供段級(jí)保護(hù),也提供頁級(jí)保護(hù)。分頁機(jī)制只區(qū)分兩種特權(quán)級(jí)。特權(quán)級(jí)0、1和2統(tǒng)稱為系統(tǒng)特權(quán)級(jí),特權(quán)級(jí)3稱為用戶特權(quán)級(jí)。在上圖所示頁目錄表和頁表的表項(xiàng)中的保護(hù)屬性位R/W和U/S就是用于對(duì)頁進(jìn)行保護(hù)。
表項(xiàng)的位1是讀寫屬性位,記作R/W。R/W位指示該表項(xiàng)所指定的頁是否可讀、寫或執(zhí)行。若R/W=1,對(duì)表項(xiàng)所指定的頁可進(jìn)行讀、寫或執(zhí)行;若R/W=0,對(duì)表項(xiàng)所指定的頁可讀或執(zhí)行,但不能對(duì)該指定的頁寫入。但是,R/W位對(duì)頁的寫保護(hù)只在處理器處于用戶特權(quán)級(jí)時(shí)發(fā)揮作用;當(dāng)處理器處于系統(tǒng)特權(quán)級(jí)時(shí),R/W位被忽略,即總可以讀、寫或執(zhí)行。
表項(xiàng)的位2是用戶/系統(tǒng)屬性位,記作U/S。U/S位指示該表項(xiàng)所指定的頁是否是用戶級(jí)頁。若U/S=1,表項(xiàng)所指定的頁是用戶級(jí)頁,可由任何特權(quán)級(jí)下執(zhí)行的程序訪問;如果U/S=0,表項(xiàng)所指定的頁是系統(tǒng)級(jí)頁,只能由系統(tǒng)特權(quán)級(jí)下執(zhí)行的程序訪問。下表列出了上述屬性位R/W和U/S所確定的頁級(jí)保護(hù)下,用戶級(jí)程序和系統(tǒng)級(jí)程序分別具有的對(duì)用戶級(jí)頁和系統(tǒng)級(jí)頁進(jìn)行操作的權(quán)限。
頁級(jí)
保護(hù)
屬性 U/S R/W 用戶級(jí)訪問權(quán)限系統(tǒng)級(jí)訪問權(quán)限 0 0 無讀/寫/執(zhí)行 0 1 無讀/寫/執(zhí)行 1 0 讀/執(zhí)行讀/寫/執(zhí)行 1 1 讀/寫/執(zhí)行讀/寫/執(zhí)行
由上表可見,用戶級(jí)頁可以規(guī)定為只允許讀/執(zhí)行或規(guī)定為讀/寫/執(zhí)行。系統(tǒng)級(jí)頁對(duì)于系統(tǒng)級(jí)程序總是可讀/寫/執(zhí)行,而對(duì)用戶級(jí)程序總是不可訪問的。于分段機(jī)制一樣,外層用戶級(jí)執(zhí)行的程序只能訪問用戶級(jí)的頁,而內(nèi)層系統(tǒng)級(jí)執(zhí)行的程序,既可訪問系統(tǒng)級(jí)頁,也可訪問用戶級(jí)頁。與分段機(jī)制不同的是,在內(nèi)層系統(tǒng)級(jí)執(zhí)行的程序,對(duì)任何頁都有讀/寫/執(zhí)行訪問權(quán),即使規(guī)定為只允許讀/執(zhí)行的用戶頁,內(nèi)層系統(tǒng)級(jí)程序也對(duì)該頁有寫訪問權(quán)。
頁目錄表項(xiàng)中的保護(hù)屬性位R/W和U/S對(duì)由該表項(xiàng)指定頁表所指定的全部1K各頁起到保護(hù)作用。所以,對(duì)頁訪問時(shí)引用的保護(hù)屬性位R/W和U/S的值是組合計(jì)算頁目錄表項(xiàng)和頁表項(xiàng)中的保護(hù)屬性位的值所得。下表列出了組合計(jì)算前后的保護(hù)屬性位的值,組合計(jì)算是“與”操作。
組合頁的
保護(hù)>屬性目錄表項(xiàng)U/S 頁表項(xiàng)U/S 組合U/S 目錄表項(xiàng)R/W 頁表項(xiàng)R/W 組合R/W 0 0 0 0 0 0 0 1 0 0 1 0 1 0 0 1 0 0 1 1 1 1 1 1
正如在80386地址轉(zhuǎn)換機(jī)制中分頁機(jī)制在分段機(jī)制之后起作用一樣,由分頁機(jī)制支持的頁級(jí)保護(hù)也在由分段機(jī)制支持的段級(jí)保護(hù)之后起作用。先測(cè)試有關(guān)的段級(jí)保護(hù),如果啟用分頁機(jī)制,那么在檢查通過后,再測(cè)試頁級(jí)保護(hù)。如果段的類型為讀/寫,而頁規(guī)定為只允許讀/執(zhí)行,那么不允許寫;如果段的類型為只讀/執(zhí)行,那么不論頁保護(hù)如何,也不允許寫。
頁級(jí)保護(hù)的檢查是在線性地址轉(zhuǎn)換為物理地址的過程中進(jìn)行的,如果違反頁保護(hù)屬性的規(guī)定,對(duì)頁進(jìn)行訪問(讀/寫/執(zhí)行),那么將引起頁異常。
2.對(duì)虛擬存儲(chǔ)器的支持
頁表項(xiàng)中的P位是支持采用分頁機(jī)制虛擬存儲(chǔ)器的關(guān)鍵。P=1,表示表項(xiàng)指定的頁存在于物理存儲(chǔ)器中,并且表項(xiàng)的高20位是物理頁的頁碼;P=0,表示該線性地址空間中的頁所對(duì)應(yīng)的物理地址空中的頁不在物理存儲(chǔ)器中。如果程序訪問不存在的頁,會(huì)引起頁異常,這樣操作系統(tǒng)可把該不存在的頁從磁盤上讀入,把所在物理頁的頁碼填入對(duì)應(yīng)表項(xiàng)并把表項(xiàng)中的P位置為1,然后使引起異常的程序恢復(fù)運(yùn)行。
此外,表項(xiàng)中的訪問位A和寫標(biāo)志位D也用于支持有效地實(shí)現(xiàn)虛擬存儲(chǔ)器。
表項(xiàng)的位5是訪問屬性位,記作A。在為了訪問某存儲(chǔ)單元而進(jìn)行線性地址到物理地址的轉(zhuǎn)換過程中,處理器總是把頁目錄表內(nèi)的對(duì)應(yīng)表項(xiàng)和其所指定頁表內(nèi)的對(duì)應(yīng)表項(xiàng)中的A位置1,除非頁表或頁不存在,或者訪問違反保護(hù)屬性規(guī)定。所以,A=1表示已訪問過對(duì)應(yīng)的物理頁。處理器永不清除A位。通過周期性地檢測(cè)及清除A位,操作系統(tǒng)就可確定哪些頁在最近一段時(shí)間未被訪問過。當(dāng)存儲(chǔ)器資源緊缺時(shí),這些最近未被訪問的頁很可能就被選擇出來,將它們從內(nèi)存換出到磁盤上去。
表項(xiàng)的位6是寫標(biāo)志位,記作D。在為了訪問某存儲(chǔ)單元而進(jìn)行線性地址到物理地址的轉(zhuǎn)換過程中,如果是寫訪問并且可以寫訪問,處理器就把頁表內(nèi)對(duì)應(yīng)表項(xiàng)中的D位置1,但并不把頁目錄表內(nèi)對(duì)應(yīng)表項(xiàng)中的D置1。當(dāng)某頁從磁盤上讀入內(nèi)存時(shí),頁表中對(duì)應(yīng)對(duì)應(yīng)表項(xiàng)的D位被清0。所以,D=1表示已寫過對(duì)應(yīng)的物理頁。當(dāng)某頁需要從內(nèi)存換出到磁盤上時(shí),如果該頁的D位為1,那么必須進(jìn)行寫操作(把內(nèi)存中的頁寫入磁盤時(shí),處理器并不清除對(duì)應(yīng)頁表項(xiàng)的D位)。但是,如果要寫到磁盤上的頁的D位為0,那么不需要實(shí)際的磁盤寫操作,而只要簡(jiǎn)單地放棄內(nèi)存中該頁即可。因?yàn)閮?nèi)存中的頁與磁盤中的頁具有完全相同的內(nèi)容。
<四>頁異常
啟用分頁機(jī)制后,線性地址不再直接等于物理地址,線性地址要經(jīng)過分頁機(jī)制轉(zhuǎn)換才成為物理地址。在轉(zhuǎn)換過程中,如果出現(xiàn)下列情況之一就會(huì)引起頁異常:
(1)涉及的頁目錄表內(nèi)的表項(xiàng)或頁表內(nèi)的表項(xiàng)中的P=0,即涉及到頁不在內(nèi)存;
(2)發(fā)現(xiàn)試圖違反頁保護(hù)屬性的規(guī)定而對(duì)頁進(jìn)行訪問。
報(bào)告頁異常的中斷向量號(hào)是14(0EH)。頁異常屬于故障類異常。在進(jìn)入故障處理程序時(shí),保存的指令指針CS及EIP指向發(fā)生故障的指令。一旦引起頁故障的原因被排除后,即可從頁故障處理程序通過一條IRET指令,直接地重新執(zhí)行產(chǎn)生故障的指令。
當(dāng)頁故障發(fā)生時(shí),處理器把引起頁故障的線性地址裝入CR2。頁故障處理程序可以利用該線性地址確定對(duì)應(yīng)的頁目錄項(xiàng)和頁表項(xiàng)。
頁故障還在堆棧中提供一個(gè)出錯(cuò)碼,出錯(cuò)碼的格式如下圖所示。其中,U位表示引起故障程序的特權(quán)級(jí),U=1表示用戶特權(quán)級(jí)(特權(quán)級(jí)3),U=0表示系統(tǒng)特權(quán)級(jí)(特權(quán)級(jí)0、1或2);W位表示訪問類型,W=0表示讀/執(zhí)行,W=1表示寫;P位表示異常類型,P=0表示頁不存在故障,P=1表示保護(hù)故障。頁故障的響應(yīng)處理模式同其它故障一樣。
出錯(cuò)碼
的格式 BIT15—BIT3 BIT2 BIT1 BIT0 未使用 U W P
<五>演示分頁機(jī)制的實(shí)例(實(shí)例十)
下面給出一個(gè)演示如何啟用分頁管理機(jī)制的實(shí)例。該實(shí)例的邏輯功能是,在屏幕上顯示一條表示已啟用分頁管理機(jī)制的提示信息。該實(shí)例演示內(nèi)容包括:初始化頁目錄表和部分頁表;啟用分頁管理機(jī)制;關(guān)閉分頁管理機(jī)制等。該實(shí)例假設(shè)系統(tǒng)至少有4M字節(jié)物理內(nèi)存。
1.演示步驟和源程序清單
為了簡(jiǎn)單化,實(shí)例只有一個(gè)任務(wù),并且沒有局部描述符表和中斷描述符表,不允許中斷,也不考慮發(fā)生異常,甚至沒有使用堆棧。實(shí)例執(zhí)行步驟如下:
(1)在實(shí)模式下為進(jìn)入保護(hù)模式作初始化;
(2)切換到保護(hù)模式后進(jìn)入臨時(shí)代碼段,把部分演示代碼傳送到預(yù)定的內(nèi)存,然后轉(zhuǎn)演示代碼段;
(3)建立頁目錄表;
(4)建立頁表;
(5)啟用分頁管理機(jī)制;
(6)演示在分頁管理機(jī)制啟用后的程序執(zhí)行和數(shù)據(jù)存取;
(7)關(guān)閉分頁管理機(jī)制;
(8)退出保護(hù)模式,結(jié)束。
實(shí)例十源程序清單如下:
;名稱:ASM10.ASM
;功能:演示使用分頁管理機(jī)制
;編譯:TASM ASM10.ASM
;連接:TLINK ASM10.OBJ
;============================================================================
INCLUDE 386SCD.INC
;============================================================================
PDT_AD = 200000h ;頁目錄表所在物理頁的地址
PT0_AD = 202000h ;頁表0所在物理頁的地址
PT1_AD = 201000h ;頁表1所在物理頁的地址
PhVB_AD = 0b8000h ;物理視頻緩沖區(qū)地址
LoVB_AD = 0f0000h ;程序使用的邏輯視頻緩沖區(qū)地址
MPVB_AD = 301000h ;線性地址0B8000H所映射的物理地址
PhSC_AD = 303000h ;部分演示代碼所在內(nèi)存的物理地址
LoSC_AD = 402000h ;部分演示代碼的邏輯地址
;============================================================================
GDTSeg SEGMENT PARA USE16 ;全局描述符表數(shù)據(jù)段(16位)
;----------------------------------------------------------------------------
;全局描述符表GDT
GDT LABEL BYTE
;空描述符
DUMMY Desc <>
;規(guī)范段描述符及選擇子
Normal Desc <0ffffh,,,ATDW,,>
Normal_Sel = Normal-GDT
;頁目錄表所在段描述符(在保護(hù)方式下初始化時(shí)用)及選擇子
PDT Desc <0fffh,PDT_AD AND 0ffffh,PDT_AD SHR 16,ATDW,,>
PDT_Sel = PDT-GDT
;頁表0所在段描述符(在保護(hù)方式下初始化時(shí)用)及選擇子
PT0 Desc <0fffh,PT0_AD AND 0ffffh,PT0_AD SHR 16,ATDW,,>
PT0_Sel = PT0-GDT
;頁表1所在段描述符(在保護(hù)方式下初始化時(shí)用)及選擇子
PT1 Desc <0fffh,PT1_AD AND 0ffffh,PT1_AD SHR 16,ATDW,,>
PT1_Sel = PT1-GDT
;邏輯視頻緩沖區(qū)段描述符及選擇子
LoVideo Desc <3999,LoVB_AD AND 0ffffh,LoVB_AD SHR 16,ATDW,,>
LoVideo_Sel = LoVideo-GDT
;邏輯上的部分演示代碼段的描述符及選擇子
LoCode Desc <SCodeLen-1,LoSC_AD AND 0ffffh,LoSC_AD SHR 16,ATCE,,>
LoCode_Sel = LoCode-GDT
;預(yù)定內(nèi)存區(qū)域(用于部分演示代碼)的段描述符及選擇子
TPSCode Desc <SCodeLen-1,PhSC_AD AND 0ffffh,PhSC_AD SHR 16,ATDW,,>
TPSCode_Sel = TPSCode-GDT
;----------------------------------------------------------------------------
;以下是需額外初始化的描述符
EFFGDT LABEL BYTE
;臨時(shí)代碼段描述符及選擇子
TempCode Desc <0ffffh,TempCodeSeg,,ATCE,,>
TempCode_Sel = TempCode-GDT
;演示代碼段描述符及選擇子
DemoCode Desc <DemoCodeLen-1,DemoCodeSeg,,ATCE,,>
DemoCode_Sel = DemoCode-GDT
;演示任務(wù)數(shù)據(jù)段描述符及選擇子
DemoData Desc <DemoDataLen-1,DemoDataSeg,,ATDW,,>
DemoData_Sel = DemoData-GDT
;初始化時(shí)要移動(dòng)的代碼段描述符及選擇子(移動(dòng)時(shí)作為數(shù)據(jù)對(duì)待)
SCode Desc <SCodeLen-1,SCodeSeg,,ATDR,,>
SCode_Sel = SCode-GDT
;----------------------------------------------------------------------------
GDTLen = $-GDT ;全局描述符表長度
GDNum = ($-EFFGDT)/(SIZE Desc) ;需特殊處理的描述符數(shù)
;----------------------------------------------------------------------------
GDTSeg ENDS ;全局描述符表段定義結(jié)束
;============================================================================
;這部分代碼在初始化時(shí)被復(fù)制到預(yù)定的內(nèi)存區(qū)域,其功能是在屏幕上顯示提示信息
;----------------------------------------------------------------------------
SCodeSeg SEGMENT PARA USE16
ASSUME CS:SCodeSeg,DS:DemoDataSeg
;----------------------------------------------------------------------------
SBegin PROC FAR
mov ax,LoVideo_Sel
mov es,ax
mov di,0
mov ah,17h
mov cx,MessLen
S1: lodsb
stosw
loop S1
JUMP16 DemoCode_Sel,Demo3
SBegin ENDP
;----------------------------------------------------------------------------
MLen = $-SBegin
SCodeLen = $
SCodeSeg ENDS
;============================================================================
DemoDataSeg SEGMENT PARA USE16 ;演示任務(wù)數(shù)據(jù)段
Mess DB 'Page is OK!'
MessLen = $-Mess
DemoDataLen = $
DemoDataSeg ENDS
;============================================================================
DemoCodeSeg SEGMENT PARA USE16 ;演示任務(wù)代碼段
ASSUME CS:DemoCodeSeg
;----------------------------------------------------------------------------
DemoBegin PROC FAR
mov ax,PDT_Sel
mov es,ax
xor di,di
mov cx,1024
xor eax,eax ;先把全部表項(xiàng)置成無效
rep stosd ;再置表項(xiàng)0和表項(xiàng)1
mov DWORD PTR es:[0],PT0_AD OR (USU+RWW+PL)
mov DWORD PTR es:[4],PT1_AD OR (USU+RWW+PL)
mov ax,PT0_Sel ;初始化頁表0
mov es,ax
xor di,di
mov cx,1024
xor eax,eax
or eax,USU+RWW+PL
Demo1: stosd
add eax,1000h ;先全部置成對(duì)應(yīng)等地址的
loop Demo1 ;物理頁,再特別設(shè)置兩廣表項(xiàng)
mov di,(PhVB_AD SHR 12)*4
mov DWORD PTR es:[di],MPVB_AD+USS+RWW+PL
mov di,(LoVB_AD SHR 12)*4
mov DWORD PTR es:[di],PhVB_AD+USU+RWR+PL
mov ax,PT1_Sel ;初始化頁表1
mov es,ax
xor di,di
mov cx,1024
mov eax,400000h
Demo2: stosd ;先把全部表項(xiàng)設(shè)置為無效
add eax,1000h
loop Demo2 ;再特別設(shè)置1項(xiàng)
mov di,((LoSC_AD SHR 12)AND 3ffh)*4
mov DWORD PTR es:[di],PhSC_AD+USU+RWR+PL
mov eax,PDT_AD
mov cr3,eax
mov eax,cr0
or eax,80000000h
mov cr0,eax
jmp SHORT PageE
PageE: mov ax,DemoData_Sel
mov ds,ax
mov si,OFFSET Mess
JUMP16 LoCode_Sel,SBegin
Demo3: mov eax,cr0
and eax,7fffffffh ;關(guān)閉分頁機(jī)制
mov cr0,eax
jmp SHORT PageD
PageD: mov ax,Normal_Sel
JUMP16 TempCode_Sel,ToDOS
DemoBegin ENDP
;----------------------------------------------------------------------------
DemoCodeLen = $
DemoCodeSeg ENDS
;============================================================================
TempCodeSeg SEGMENT PARA USE16 ;臨時(shí)任務(wù)的代碼段
ASSUME CS:TempCodeSeg
;----------------------------------------------------------------------------
Virtual PROC FAR
cld ;為演示在啟用分頁機(jī)制后執(zhí)
mov ax,SCode_Sel ;行位于較高線性地址空間中
mov ds,ax ;的代碼作準(zhǔn)備
mov ax,TPSCode_Sel
mov es,ax
mov si,OFFSET SBegin
mov di,si
mov cx,MLen ;把分頁演示代碼復(fù)制到預(yù)定
rep movsb ;內(nèi)存
JUMP16 DemoCode_Sel,DemoBegin
ToDOS: mov ds,ax
mov es,ax
mov eax,cr0 ;準(zhǔn)備返回實(shí)模式
and al,11111110b
mov cr0,eax
JUMP16 <SEG Real>,<OFFSET Real>
Virtual ENDP
;----------------------------------------------------------------------------
TempCodeSeg ENDS
;============================================================================
RCodeSeg SEGMENT PARA USE16 ;實(shí)方式的初始化代碼和數(shù)據(jù)
ASSUME CS:RCodeSeg,DS:RCodeSeg
;----------------------------------------------------------------------------
VGDTR PDesc <GDTLen-1,>
;----------------------------------------------------------------------------
Start PROC
push cs
pop ds
cld
call InitGDT ;初始化全局描述符表GDT
EnableA20
lgdt QWORD PTR VGDTR ;裝載GDTR
cli ;關(guān)中斷
mov eax,cr0
or al,1
mov cr0,eax
JUMP16 <TempCode_Sel>,<OFFSET Virtual>
Real: DisableA20
sti
mov ax,4c00h
int 21h
Start ENDP
;----------------------------------------------------------------------------
InitGDT PROC
push ds
mov ax,GDTSeg
mov ds,ax
mov cx,GDNum
mov si,OFFSET EFFGDT
InitG: mov ax,[si].BaseL
movzx eax,ax
shl eax,4
shld edx,eax,16
mov WORD PTR [si].BaseL,ax
mov BYTE PTR [si].BaseM,dl
mov BYTE PTR [si].BaseH,dh
add si,SIZE Desc
loop InitG
pop ds
mov bx,16
mov ax,GDTSeg
mul bx
mov WORD PTR VGDTR.Base,ax
mov WORD PTR VGDTR.Base+2,dx
ret
InitGDT ENDP
;----------------------------------------------------------------------------
RCodeSeg ENDS
END Start
2.關(guān)于實(shí)例十的說明
上述演示程序的許多內(nèi)容與其它實(shí)例相同,下面僅就演示分頁管理機(jī)制方面的內(nèi)容作些說明:
(1)部分演示代碼的移動(dòng)
為了充分說明分頁機(jī)制所實(shí)現(xiàn)的線性地址到物理地址的轉(zhuǎn)換,在初始化時(shí)把部分演示代碼移動(dòng)到預(yù)定的內(nèi)存區(qū)域。預(yù)定的內(nèi)存區(qū)域從00303000H開始,即頁碼為00303H的物理頁。該部分演示代碼的功能是顯示指定的字符串。在進(jìn)入保護(hù)模式后做此初始化工作的原因是預(yù)定的內(nèi)存區(qū)域在擴(kuò)展內(nèi)存中,注意初始化時(shí)還沒有啟用分頁機(jī)制。
(2)頁映射表的初始化
頁目錄表安排在頁碼為00200H的物理頁中,頁表0安排在頁碼為00202H的物理頁中,頁表1安排在頁碼為00201H的物理頁中。演示程序涉及的線性地址空間不超過007FFFFFH,所以只使用兩張頁表,為此頁目錄表中的其它項(xiàng)被置為無效(P=0)。
頁表0把線性地址空間中的00000000H—003FFFFFH映射到物理地址空間中。實(shí)例在初始化頁表0時(shí),使該線性地址空間直接映射到相同地址的物理地址空間,除線性地址空間中頁碼為000B8H和000F0H這兩頁以外。000B8H頁被映射到頁碼為00301H的物理頁,而000F0H頁被映射到頁碼為000B8H的物理頁。
頁表1把線性地址空間中的00400000H—007FFFFFH映射到物理地址空間中。實(shí)例在初始化頁表1時(shí),似乎使該線性地址空間直接映射到相同地址的物理地址空間,但是處理對(duì)應(yīng)線性地址空間中00402H的表項(xiàng)被另外設(shè)置外,其它表項(xiàng)中的P位為0,也即表示對(duì)應(yīng)物理頁不存在。初始化后,頁表1的第2項(xiàng)把線性地址空間中的00402H頁映射到頁碼為00303H的物理頁,也就是存放部分演示代碼的指定內(nèi)存區(qū)域。
(3)啟動(dòng)分頁管理機(jī)制
在建立好頁映射表后,啟用分頁機(jī)制所要做的操作是簡(jiǎn)單的,只要把控制寄存器CR0中的最高位,也就是PG位置1。具體指令如下:
mov eax,cr0
or eax,80000000h
mov cr0,eax
jmp SHORT PageE
PageE: ...
在啟用分頁機(jī)制前,線性地址就是物理地址;在啟用分頁機(jī)制后,線性地址要通過分頁機(jī)制的轉(zhuǎn)換,才成為物理地址。盡管使用一條轉(zhuǎn)移指令,可清除預(yù)取隊(duì)列,但隨后在取指令時(shí)使用的線性地址就要經(jīng)過分頁機(jī)制轉(zhuǎn)換才成為物理地址。為了順利過渡,在啟用分頁機(jī)制之后的過渡代碼段,仍要維持線性地址等同于物理地址。為了作到這一點(diǎn),在建立也映射表時(shí),必須使實(shí)現(xiàn)過渡的代碼所在的線性地址空間頁映射到具有相同地址的物理地址空間頁。實(shí)例中頁表0就做到了這一點(diǎn)。
(4)關(guān)閉分頁管理機(jī)制
只要把控制寄存器CR0中的PG位清0,便關(guān)閉了分頁機(jī)制。在這一過渡階段,也要保持地址轉(zhuǎn)換前后的一致。
(5)地址轉(zhuǎn)換的演示
在啟用分頁機(jī)制之后,就轉(zhuǎn)移到位于線性地址空間中00402000H處開始的代碼,該部分代碼的功能是顯示提示信息"Page is OK!"。實(shí)際上這部分代碼存放在從物理地址00303000H開始的物理內(nèi)存區(qū)域中,是在初始化時(shí)被移到此區(qū)域的。
在顯示提示信息時(shí),要把顯示的ASCII字符和顯示屬性填到線性地址空間中000F0000H開始的區(qū)域中,而不是000B8000H開始的區(qū)域。從初始化時(shí)建立的映射表可見,線性地址空間中的000F0H頁,被映射到物理地址空間中的000B8H頁。所以,向線性地址空間中的000F0H頁寫,實(shí)際上是向物理地址空間中的000B8H頁寫,也就是真正顯示。
(6)頁級(jí)保護(hù)的說明
在進(jìn)入保護(hù)模式之后,特權(quán)級(jí)一直是0,所以,無論系統(tǒng)級(jí)和用戶級(jí)頁,無論只能讀/執(zhí)行,還是讀/執(zhí)行/寫,總是可進(jìn)行各種形式的訪問。