x86 保護模式 十 分頁管理機制


x86   保護模式  十  分頁管理機制

8.386開始支持分頁管理機制

段機制實現虛擬地址到線性地址的轉換,分頁機制實現線性地址到物理地址的轉換。如果不啟用分頁,那么線性就是物理地址

一  分頁管理簡介

  cr0中的pg位=1   分頁生效,將線性地址轉換為物理地址。

  只有在保證pe位為1的情況下  才能使pg位為1  否則將引起通用保護故障。

  分頁機制將線性地址空間和物理地址空間分別划分為大小相同的塊。這樣的塊稱為頁。線性的頁和物理的頁之間建立映射,完成線性到物理地址的轉換。線性地址空間的頁與物理地址空間之間的映射可根據需要而確定,可根據需要而改變。線性地址空間的任何一頁,可以映射為物理地址空間中的任何一頁。

  采用分頁機制的主要目的是便於實現虛擬存儲器,不像段的大小可變,頁的大小是固定的大小相等的,根據程序的邏輯划分段,根據實現虛擬存儲器方便划分頁。

  386中,頁的大小固定位4k字節,每一頁的邊界地址必須是4k的倍數。因此4g大小的地址空間被划分為1m個頁,頁的開始地址為xxxxx000h   因此,我們把頁開始地址的高20位xxxxxh稱為頁碼。線性地址空間的頁碼就是頁開始邊界線性地址的高20位,物理地址空間也是頁開始邊界物理地址的高20位。頁碼左移12位就是頁的開始地址,所以頁碼規定了頁 

  由於頁大小固定為4k,且頁的邊界是4k的倍數,所以在把32位線性地址轉換成32位物理地址的過程中,低12位地址保持不變。線性地址的低12位就是物理地址的低12位,假設分頁機制將線性地址空間的xxxxxh頁映射到物理地址空間的yyyyyh頁,那么線性地址XXXXXxxxh被轉換為YYYYYxxxh,因此,線性地址到物理地址的轉換要解決的是線性地址空間的頁到物理地址空間的頁的映射,頁就是線性地址高20位到物理地址高20位的轉換。

二  線性地址到物理地址的轉換

  1.映射表結構

    線性空間的頁到物理空間的頁之間的映射用表來描述。4g的地址空間划分為1m個頁,因此需要1m個表項,若每個表項占用4個字節,那么該映射表就要占用4m個字節。為了避免映射表占用如此巨大的存儲器資源,所以386將頁映射表分為兩級。

  第一級為頁目錄表   存儲在一個4k字節物理頁中。共有1k個表項,其中每個表項4字節長,包含對應第二級所在物理地址空間頁的頁碼。

  第二級為頁表,每張頁表安排在一個4k字節的頁中。每張頁表都已1k個表項,每項4字節長,包含對應物理地址空間的頁碼。

  由於頁目錄表和頁表均有1k個表項組成,所以使用10位的索引就能指定表項,即用10位的索引值乘以4加上基地址就得到了表項的物理地址。

  下圖顯示了由頁目錄表和頁表構成的頁映射表結構。從圖中可見,cr3指定頁目錄表,頁目錄表可以指定1k個頁表,這些頁表可以分散存放在任意的物理頁中,而不需要連續存放;每張頁表可以指定1k個物理地址空間的頁,這些物理地址空間的頁可以任意地分散在物理地址空間中。需要注意的是,存儲頁目錄表和頁表的基地址是對齊在4k字節邊界上的。

  

 

2.表項格式

  頁目錄表和頁表中的表項都采用如下圖所示的格式,從圖中可見,最高20位(12-31)包含物理地址空間也得頁碼,就是高20位。低12位包含頁的屬性。p位表示該表項是否有效,1位有效。在通過頁目錄表和頁表進行的線性地址到物理地址的轉換過程中,無論在頁目錄表還是頁表中遇到無效表項,都會引起頁故障。

 

 

 

 p為0時   386不解釋。

3.線性地址到物理地址的轉換

  通過上述頁目錄表和頁表實現32位線性地址到32位物理地址的轉換。cr3的高20位作為頁目錄表所在物理頁的頁碼。

  a  將線性地址的高10位作為目錄表的索引,對應表項所包含的頁碼指定頁表

  b  將線性地址空間的中間10位作為所指定的目錄表中的頁表項的索引,對應表項所包含的頁碼指定物理地址空間中的一頁;

  c  將所指定的物理頁的頁碼作為高20位,將線性地址的低12位不變作為32位物理地址的低12位。

   為了避免在每次存儲器訪問時都要訪問內存中的頁表,cpu將最近使用的線性-物理地址轉換函數存儲在cpu內部的頁轉換高速緩沖存儲器中。在訪問存儲器頁表之前總是先查閱高速緩存,僅當必須的轉換不在高速緩存時,才訪問存儲器中的兩級頁表。頁高速緩存頁稱為頁轉換查找緩存,記為TLB.

  在分頁機制轉換高速緩存中的數據與頁表中數據的相關性,不是cpu進行維護,而由os保存。cpu不知道什么時候會修改頁表,在一個合理的系統中,頁表只能由os修改,操作系統可以直接地在軟件修改頁表后通過刷新高速緩存來保證相關性。高速緩存的刷新通過裝入cpu的cr3來完成,實際上通過兩條指令完成。

  mov   eax,cr3

  mov   cr3,eax

  一個修改頁表項但是不用刷新高速緩存的情況是:修改不存在的表項的一部分,因為無效的表項不會存入高速緩存。當從磁盤上讀入一頁使其存在時,不必刷新高速緩存。

  在一個多cpu的系統中,通過使用不可分的讀,寫,修改周期,對於頁表項的軟件更新需要借助於LOCK前綴,從而保證修改頁表的指令工作在不可分的讀寫修改周期中,

  在改變一個可能由另外的cpu使用的頁表之前,最好使用一條加鎖的AND指令在一個不分的操作中將p位清除為0.然后,該表項可根據要求進行修改,並隨后把p位置成1而使表項稱為可用。當修改頁表項時必須及時通知(通常是中斷的方式)系統中該表項已經被高速緩存的所有處理器刷新各自的頁轉換高速緩存,以撤銷該表項的拷貝。在表項的舊拷貝被刷新之前,各cpu仍可繼續訪問舊的頁,並可以設置正在被修改的表項的D位。如果這樣做引起表項修改失敗,則分頁機制高速緩存最好標記為不存在之后,並在對表項進行另外的修改之前進行刷新。

4.不存在的頁表

  存儲全部1k張頁表需要4m字節 (1個頁表共1k個表項*4字節=4k,1k個表項*4k=4m字節),4k個字節用於存儲頁目錄表,兩級頁表映射結構對於現行地址空間中不存在的或未使用的部分不必分配頁表。除了給頁目錄表分配物理頁外,僅當需要時才給頁表分配物理頁,所以頁映射表的大小就對應於實際使用的線性地址空間的大小。

  頁目錄表項中的存在位p表明對應頁表是否有效     有效則轉換,p=0則無效不轉換,會引起頁故障。所以也目錄表項中的屬性位p使得os只需給覆蓋實際使用的線性地址范圍的頁表分配物理頁。

  頁目錄表項中的屬性p位可用於把頁表存儲在虛擬存儲器中,當發生由於所需頁表無效而引起的頁故障時,頁故障處理程序再申請物理頁,從磁盤上吧對應的頁表讀入,並把對應頁目錄表項中的p位置為1.即當需要時才位所需要的頁表分配物理頁。這樣頁表占用的物理頁數量可以降到最小。

5.頁的共享

  每個任務可以使用自己的頁映射表獨立的實現線性到物理地址的轉換。但是如果使每個人物所用的頁映射表具有部分相同的映射,那么也就可以實現部分頁的共享。

  常用的實現頁共享的方法是線性地址空間的共享,頁就是不同任務的部分相同的線性地址空間的映射信息相同,具體表現為部分也表相同或頁表內的部分頁表項的頁碼相同。

  例如  a和b兩個任務分別使用也目錄表a和b    內的第00項的頁碼相同,就是頁表0相同,那么a和b的00000000h到003fffffh的線性地址空間映射到相同的物理頁。

  a和b使用的頁表0不同,但是兩張也表內的第0到第0ffh項的頁碼對應相同,那么a和b的00000000h到000fffffh線性地址空間映射到相同的物理頁。

注意:共享的頁表最好由兩個也目錄中同樣的目錄項所指定。因為他保證了在兩個任務中同樣的線性地址范圍將映射到該全局區域。

三   頁級保護和虛擬存儲器的支持

 1.頁級保護

  386不僅提供段保護,也提供頁保護。分頁機制只區分兩種權級:0 1 2為系統權級,3為用戶特權級。

  上圖所示的頁目錄表和頁表的表項中的保護屬性位R/W和U/S就是用於對頁進行保護

  表項的位1是讀寫屬性位,記做R/W   指示表項所指定的頁是否可讀、寫、或執行。

  如果為1   則可讀寫和執行

  如果為0則可讀和執行,不能寫

  上面的兩條僅在cpu處於用戶級時才能有效。當cpu處於系統級時總是可讀可寫可執行。

 

  表項的位2是用戶/系統屬性位,記做U/S.指示該表項所指定的頁是否是用戶級的頁。

  如果為1   則為用戶級的頁,可由任何權級下執行的程序訪問。

  為0則為系統級的頁,僅僅由系統級下的執行程序訪問。

         

 

上圖可知,用戶級的頁有兩種狀態:讀/執行      或讀/寫/執行  。系統級頁對於系統級程序總是讀寫和執行,而對於用戶級程序總是不可訪問的。

與分段機制相同點:

  外層用戶級執行的程序只能訪問用戶級的頁,而內層系統級執行的程序,既可訪問系統級頁,頁可訪問用戶級的頁。

  不同點:

  內層系統級的執行程序,對任何頁都有讀,寫,執行的訪問權,即使規定為只允許讀、執行的用戶也,內層程序也有寫的訪問權。

  頁目錄表項中的保護屬性位R/W和U/S對由該表項指定的頁表所指定的全部1k各頁起到保護作用。所以對頁訪問時引起的保護屬性位R/W和U/S的值組合計算頁目錄表項和頁表項中的保護屬性位的值所得   如下圖所示   組合為與操作

  

分頁的保護機制在分段保護機制之后起作用。

先測試有關的段級保護,如果啟用分頁機制,那么在檢查通過后,再測試頁級保護。

如果段的類型為讀/寫,而頁規定為只允許讀/執行,那么不允許寫

如果段的類型為讀/執行,那么不論頁如何保護,都不允許寫

2.對虛擬存儲器的支持

頁表項中的p位時支持采用分頁機制虛擬存儲器的關鍵

p為1   表示表項指定的頁位於物理存儲器中,並且表項的高20位是物理頁的頁碼

p為0  表示該線性地址空間中的頁對應的物理地址空間中的頁不在物理存儲器中

如果程序訪問不存在的頁,會引起頁異常,這樣os可把該不存在的頁從磁盤上讀入,把所在物理頁的頁碼填入對應表項並把表項中的p位置為1,然后使引起異常的程序恢復運行。

表項中訪問位A和寫標志位D   也用於支持有效地實現虛擬存儲器

 表項的位5時訪問屬性位   A      在為了訪問某存儲單元而進行線性地址到物理地址的轉換過程中,cpu總是把頁目錄表內的對應表項和其所指定頁的對應表項中的A位置1,除非頁表或頁不存在,或者訪問違反保護屬性的規定。所以A=1表示已訪問過對應的物理頁。

  cpu不清除A位,通過周期性檢測及清除A位,os就可確定哪些頁在最近一段時間未被訪問過,當資源緊缺時,這些最近未被訪問的頁很可能就被選擇出來,將他們從內存換出到硬盤上去。

  表項位6是寫標志位  D     在訪問存儲單元從線性到物理的轉換過程中,如果是寫訪問並且可以寫訪問,cpu就把頁表內對應表項中D位置1,但並不把頁目錄表內對應表項中的D位置1.

  當頁從磁盤讀入到內存時,頁表中對應表項的D位被清0.所以D=1表示已寫過對應的物理頁。

  當頁從內存換出到磁盤上時,如果該頁的D位位1,那么必須進行寫操作(把內存中的頁寫入磁盤時,cpu並不清除對應頁表項的D位),但是如果要寫到磁盤上的頁的D位位0,那么不需要實際的磁盤寫操作,只要簡單第放棄內存中的該頁即可,因為內存中的頁與磁盤中的頁具有完全先相同的內容。

四  頁異常

    啟用分頁機制后  線性地址不再直接等於物理地址,在轉換過程中出現如下的情況之一,會引起異常

  1.涉及的頁目錄表內的表項或也表內的表項中P=0   即該頁不在內存

  2.發現試圖違反頁保護屬性的規定而對頁進行訪問。

  報告頁異常的中斷向量號時14(0eh)   頁異常屬於故障類異常。進入故障處理程序時,保存的指針cs及eip指向發生故障的指令。排除故障后,iret   返回並重新執行產生故障的指令。

  當頁故障發生時,cpu把引起頁故障的線性地址裝入cr2   頁故障處理程序利用該線性地址確定對應的頁目錄表項和頁表項

  頁故障處理程序提供一個出錯碼,出錯嗎的格式16位  如下圖

  

 

  U表示引起故障的權級,U=1表示用戶權級為3   U=0表示系統級0 1 2.w表示訪問類型,W=0表示讀/執行,W=1表示寫,P表示異常類型,P=0表示頁不存在故障,P=1表示保護故障。頁故障的相應處理模式同其他故障一樣。

 

五 演示分頁機制的實例   十    需要看楊季文的匯編教材

  

下面給出一個演示如何啟用分頁管理機制的實例。該實例的邏輯功能是,在屏幕上顯示一條表示已啟用分頁管理機制的提示信息。該實例演示內容包括:初始化頁目錄表和部分頁表;啟用分頁管理機制;關閉分頁管理機制等。該實例假設系統至少有4M字節物理內存。

 

1.演示步驟和源程序清單

 

為了簡單化,實例只有一個任務,並且沒有局部描述符表和中斷描述符表,不允許中斷,也不考慮發生異常,甚至沒有使用堆棧。實例執行步驟如下:

 

(1)在實模式下為進入保護模式作初始化;

 

(2)切換到保護模式后進入臨時代碼段,把部分演示代碼傳送到預定的內存,然后轉演示代碼段;

 

(3)建立頁目錄表;

 

(4)建立頁表;

 

(5)啟用分頁管理機制;

 

(6)演示在分頁管理機制啟用后的程序執行和數據存取;

 

(7)關閉分頁管理機制;

 

(8)退出保護模式,結束。

 

實例十源程序清單如下:

 

;名稱:ASM10.ASM
;功能:演示使用分頁管理機制
;編譯:TASM ASM10.ASM
;連接:TLINK ASM10.OBJ
;============================================================================
INCLUDE         386SCD.INC
;============================================================================
PDT_AD = 200000h ;頁目錄表所在物理頁的地址 PT0_AD = 202000h ;頁表0所在物理頁的地址 PT1_AD = 201000h ;頁表1所在物理頁的地址 PhVB_AD = 0b8000h ;物理視頻緩沖區地址 LoVB_AD = 0f0000h ;程序使用的邏輯視頻緩沖區地址 MPVB_AD = 301000h ;線性地址0B8000H所映射的物理地址 PhSC_AD = 303000h ;部分演示代碼所在內存的物理地址 LoSC_AD = 402000h ;部分演示代碼的邏輯地址
;============================================================================
GDTSeg          SEGMENT PARA USE16                ;全局描述符表數據段(16位)
;----------------------------------------------------------------------------
                ;全局描述符表GDT
GDT             LABEL   BYTE
                ;空描述符
DUMMY           Desc    <>
                ;規范段描述符及選擇子
Normal          Desc    <0ffffh,,,ATDW,,>
Normal_Sel      =       Normal-GDT
                ;頁目錄表所在段描述符(在保護方式下初始化時用)及選擇子
;頁目錄
PDT Desc <0fffh,PDT_AD AND 0ffffh,PDT_AD SHR 16,ATDW,,>  ;界限為4k,PDT_AD的物理地址與0ffffh相與 低16位不變,高位全為0成為基地址的低16位;
                      ;右移16位變為基地址的中8位
PDT_Sel = PDT-GDT
======
;頁表 ;頁表0所在段描述符(在保護方式下初始化時用)及選擇子 PT0 Desc <0fffh,PT0_AD AND 0ffffh,PT0_AD SHR 16,ATDW,,>  ;同上 先設置段的描述符 確定段基地址 同時確定頁表物理地址 PT0_Sel = PT0-GDT ;頁表1所在段描述符(在保護方式下初始化時用)及選擇子 PT1 Desc <0fffh,PT1_AD AND 0ffffh,PT1_AD SHR 16,ATDW,,>  ;同上 PT1_Sel = PT1-GDT
========= ;邏輯視頻緩沖區段描述符及選擇子 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
========= ;預定內存區域(用於部分演示代碼)的段描述符及選擇子 TPSCode Desc <SCodeLen-1,PhSC_AD AND 0ffffh,PhSC_AD SHR 16,ATDW,,>  ;確定物理地址 TPSCode_Sel = TPSCode-GDT ;---------------------------------------------------------------------------- ;以下是需額外初始化的描述符                需要初始化的gdt表項 EFFGDT LABEL BYTE ;臨時代碼段描述符及選擇子 TempCode Desc <0ffffh,TempCodeSeg,,ATCE,,> TempCode_Sel = TempCode-GDT ;演示代碼段描述符及選擇子 DemoCode Desc <DemoCodeLen-1,DemoCodeSeg,,ATCE,,> DemoCode_Sel = DemoCode-GDT ;演示任務數據段描述符及選擇子 DemoData Desc <DemoDataLen-1,DemoDataSeg,,ATDW,,> DemoData_Sel = DemoData-GDT ;初始化時要移動的代碼段描述符及選擇子(移動時作為數據對待) SCode Desc <SCodeLen-1,SCodeSeg,,ATDR,,> SCode_Sel = SCode-GDT ;---------------------------------------------------------------------------- GDTLen = $-GDT ;全局描述符表長度 GDNum = ($-EFFGDT)/(SIZE Desc) ;需特殊處理的描述符數 ;---------------------------------------------------------------------------- GDTSeg ENDS ;全局描述符表段定義結束 ;============================================================================ ;這部分代碼在初始化時被復制到預定的內存區域,其功能是在屏幕上顯示提示信息 ;---------------------------------------------------------------------------- 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       ;??? 顯示塊結束符 查詢ascii碼表 mov cx,MessLen      ;計數為 字符串長度 字節長度 S1: lodsb            ;將es:di指向的字節傳送到al stosw            ;寫字 ax--》es:di 其中ah恆為17h 區塊傳輸結束對應ascii碼表 loop S1 JUMP16 DemoCode_Sel,Demo3 ;跳轉到演示代碼段的demo3的位置 SBegin ENDP ;---------------------------------------------------------------------------- MLen = $-SBegin SCodeLen = $ SCodeSeg ENDS ;============================================================================ DemoDataSeg SEGMENT PARA USE16 ;演示任務數據段 Mess DB 'Page is OK!' MessLen = $-Mess DemoDataLen = $ DemoDataSeg ENDS ;============================================================================ DemoCodeSeg SEGMENT PARA USE16 ;演示任務代碼段 ASSUME CS:DemoCodeSeg ;---------------------------------------------------------------------------- DemoBegin PROC FAR mov ax,PDT_Sel        ;頁目錄表所在段 初始化頁目錄表項 mov es,ax xor di,di          ;di清零 mov cx,1024           xor eax,eax ;先把全部表項置成無效 rep stosd ;再置表項0和表項1 雙字傳送 4個字節傳送 借助eax ---》es:di 從寄存器到存儲單元 mov DWORD PTR es:[0],PT0_AD OR (USU+RWW+PL)  ;初始化頁目錄表項中的第0項 mov DWORD PTR es:[4],PT1_AD OR (USU+RWW+PL)  ;初始化頁目錄表項中的第1項 mov ax,PT0_Sel ;初始化頁表0   mov es,ax xor di,di            ;指向段的基地址 mov cx,1024 xor eax,eax            ;eax清0 or eax,USU+RWW+PL        ; Demo1: stosd                  ;eax--》es:di   add eax,1000h ;先全部置成對應等地址的 最低12位保持不變 1000h 2000h 3000h... 確定1024個頁表項的頁碼 loop Demo1 ;物理頁,再特別設置兩個表項 mov di,(PhVB_AD SHR 12)*4          ; 看下方的說明7和8 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         ;eax為400000h的原因是什么? Demo2: stosd ;先把全部表項設置為無效 add eax,1000h loop Demo2 ;再特別設置1項 mov di,((LoSC_AD SHR 12)AND 3ffh)*4  ;      說明9 mov DWORD PTR es:[di],PhSC_AD+USU+RWR+PL  ;
mov eax,PDT_AD        ;頁目錄表所在的物理地址 送入eax寄存器 mov cr3,eax          ;將也目錄表中的物理地址送入cr3控制寄存器 mov eax,cr0          ;開啟分頁模式 cr0中的最高位為1 or eax,80000000h      ;確保eax的最高位為1 mov cr0,eax         jmp SHORT PageE     PageE: mov ax,DemoData_Sel        ;演示任務數據段 顯示其中的字符 mov ds,ax               mov si,OFFSET Mess          ;si指向數據段中的mess的偏移位置 JUMP16 LoCode_Sel,SBegin        ;跳轉到部分演示代碼段 sbegin位置 scode段被復制到指定的內存區
          ;locode_sel指向locode邏輯演示代碼段 通過段機制和頁機制轉換,實際的地址為phscode的物理地址
          ;對應關系為 從402000h頁機制轉換到303000h 執行的是303000h處的指令
          ;tpscode 段描述符中 表明 此段的基地址正好是phsc_ad 所以此位置的指令就是初始化時移動過來的SCodeSEG中的代碼 Demo3: mov eax,cr0 and eax,7fffffffh     ;關閉分頁機制 cr0 最高位置為0 mov cr0,eax jmp SHORT PageD PageD: mov ax,Normal_Sel        ;將所有寄存器指向規范的選擇子 JUMP16 TempCode_Sel,ToDOS      宏跳轉演示代碼中的TODOS位置 DemoBegin ENDP ;---------------------------------------------------------------------------- DemoCodeLen = $ DemoCodeSeg ENDS ;============================================================================ TempCodeSeg SEGMENT PARA USE16 ;臨時任務的代碼段 ASSUME CS:TempCodeSeg ;---------------------------------------------------------------------------- Virtual PROC FAR cld ;為演示在啟用分頁機制后執 mov ax,SCode_Sel ;行位於較高線性地址空間中 mov ds,ax ;的代碼作准備 mov ax,TPSCode_Sel mov es,ax mov si,OFFSET SBegin mov di,si          ;相對於基地址的偏移地址送給di mov cx,MLen ;把分頁演示代碼復制到預定 rep movsb ;內存 字節傳送 JUMP16 DemoCode_Sel,DemoBegin    ;跳轉到演示代碼段 ToDOS: mov ds,ax            ;返回實模式前的准備 ds es 指向規范選擇子 mov es,ax mov eax,cr0 ;准備返回實模式 and al,11111110b        ;最低位設置為0 mov cr0,eax JUMP16 <SEG Real>,<OFFSET Real> Virtual ENDP ;---------------------------------------------------------------------------- TempCodeSeg ENDS ;============================================================================ RCodeSeg SEGMENT PARA USE16 ;實方式的初始化代碼和數據 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 ;關中斷 mov eax,cr0 or al,1 mov cr0,eax JUMP16 <TempCode_Sel>,<OFFSET Virtual> Real: DisableA20        ;關閉a20地址線 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

 

 程序解讀說明

1.部分演示代碼的移動

 為了充分說明分頁機制所實現的線性地址到物理地址的轉換,在初始化時把部分演示代碼移動到預定的內存區域。預定的內存區域從00303000h開始,即頁碼為00303h的物理頁。該部分演示代碼的功能是顯示指定的字符串。在進入保護模式后做此初始化工作的原因是預定的內存區域在擴展內存中,注意初始化時還沒有啟用分頁機制

2.頁映射表的初始化

 頁目錄表安排在頁碼為00200h的物理頁中,頁表0安排在頁碼為00202h的物理頁中,頁表1安排在頁碼為00201h的物理頁中。演示程序涉及的線性地址空間不超過007fffffh,所以只使用兩張頁表,為此頁目錄表中的其他項被設置為無效    p=0

頁表0把線性地址空間中的00000000h-003fffffh映射到物理地址空間中。實例在初始化頁表0時,使該線性地址空間直接映射到相同地址的物理地址空間,除線性地址空間頁表1把線性地址空間中頁碼為00b8h和000f0h這兩項意外。000b8h頁被映射到頁碼為00301h的物理頁,而000f0h頁被映射到頁碼為000b8h的物理頁。

頁表1把線性地址空間中的00400000h--007fffffh映射到物理地址空間中。實例在初始化頁表1時,似乎使該線性地址空間直接映射到相同地址的物理地址空間,但是處理對應線性地址空間中00402h的表項被另外設置外,其它表項中的p位為0,也即表示對應物理頁不存在。初始化后,頁表1的第2項把線性地址空間中的00402h頁映射到頁碼為00303h的物理頁,也就是存放部分演示代碼的指定內存區域。

3.啟用分頁管理機制

 在建立好頁映射表后,啟用分頁機制所要做的操作時簡單的,只要把控制寄存器cr0中的最高位,也就是PG位置1。具體指令如下:

  mov   eax,cr0

  or  eax,80000000h

  mov  cr0,eax

  jmp  SHORT  PageE

 PageE:  ...

在啟用分頁機制前,線性地址就是物理地址;在啟用分頁機制后,線性地址要通過分頁機制的轉換,才成為物理地址。盡管使用一條轉移指令,可清除預取隊列,但隨后在取指令時使用的線性地址就要經過分頁機制轉換才成為物理地址。為了順利過渡,在啟用分頁機制之后的過渡代碼段,仍要維持線性地址等同於物理地址。為了做到這一點,在建立頁映射表時,必須使實現過渡的代碼所在的線性地址空間頁映射到具有相同地址的物理地址空間頁.實例中頁表0就做到了這一點。

4.關閉分頁管理機制

只要把控制寄存器cr0中的PG位清0,便關閉了分頁機制。在這一過渡階段,也要保持地址轉換前后的一致。

5.地址轉換的演示

 在啟用分頁機制之后,就轉移到位於線性地址空間中00402000h處開始的代碼,該部分代碼的功能是顯示提示“page is ok”。實際上這部分代碼存放在從物理地址00303000h開始的物理內存區域中,是在初始化時被移到此區域的。

在現實提示信息時,要把現實的ASCII字符和顯示屬性填到線性地址空間中000f0000h開始的區域中,而不是000b8000h開始的區域。從初始化建立的映射表可見,線性地址空間中的000f0h頁,被映射到物理地址空間中的000b8h頁。所以向線性地址空間中的000f0h頁寫,實際上是向物理地址空間中的000b8h頁寫,頁就是真正顯示。

6.頁級保護的說明

 在進入保護模式之后,權級一直是0,所以,無論系統級和用戶級的頁,無論只讀/執行,還是讀寫執行,總是可以進行各種形式的訪問。

 7.說明   mov di,(PhVB_AD SHR 12)*4     此時頁表0的物理地址為202000h    頁表0中的第0項的內容為高20位的內容為00000h,第1項為00001h,順延全部設置成對應等地址的物理頁,然后設置第0b8h索引項的內容為mpvb_AD的物理地址  即000b8000h線性地址對應的物理地址為00301000h,設置di的值為上面的式子是因為將phvb_ad的值0b8000h右移12位正好是線性地址000b8000線性地址中的中間十位作為頁表0中的索引值0b8h *4正好是di指向的頁表0所在頁的0b8索引指向字節單元的指針,下面的指令

 mov DWORD PTR es:[di],MPVB_AD+USS+RWW+PL 將上面中的0b8000h的線性地址對應的物理地址00301000h加上權限位變為實際的物理地址
存入di指向的內存單元 變為頁表0中的第0b8h索引指向的頁表0項的實際內容。
虛擬地址到物理地址即 0b8000h到mpvb_ad地址的轉換過程
8.
          mov di,(LoVB_AD SHR 12)*4
 mov DWORD PTR es:[di],PhVB_AD+USU+RWR+PL 
      程序使用的邏輯視頻緩沖區地址 
      LOVB_AD右移12位 作為頁表0中的索引為0f0h指向的表項,
  同上乘4的到di指向的頁表0中的字節單元 相對於頁表0的基地址
  將phvb_ad 實際的物理地址加上權限 送入es:di指向的內存空間 共32位4字節
實際上就是將程序使用的邏輯地址轉換成物理地址的一個過程
LoVB_AD到phvb_ad    邏輯到物理   
9.
  mov     di,((LoSC_AD SHR 12)AND 3ffh)*4   mov DWORD PTR es:[di],PhSC_AD+USU+RWR+PL 
losc_ad 右移12位 得到402 為索引 超出了索引的最大值,所以需要去掉高位,保留低10位獲取真正的索引值 
即與3ffh做與操作。
部分演示代碼的物理地址填充到di指向的內存單元
功能為將部分演示代碼的邏輯地址轉換為物理地址 即losc_ad變為phsc_ad










 

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM