實地址模式與保護模式之間的切換


9.1  實地址模式與保護模式之間的切換

 

我們知道,IA-32計算機在加電或者Reset信號有效之后,首先進入實地址模式,執行BIOS程序,然后再進入保護模式,執行Windows環境下的程序。因此,IA-32 CPU在工作的時候,需要從實地址模式切換到保護模式。從實地址模式切換到保護模式,通常需要建立描述符表(descriptor table),設置控制寄存器CR0的PE位,如例9.1所示。

 

例9.1  IA-32 CPU從實地址模式切換到保護模式,然后又切換回實地址模式。

;

;IA-32 CPU enters into protected mode from real address mode,

;a string is displayed on the screen, IA-32 CPU returns into real

;address mode from protected mode.

;

.386p

.model   small,c

.stack   100h

;

Descriptor      STRUCT

  limit         word     0

  basel         word     0

  basem         byte     0

  attrib        word     0

  baseh         byte     0

Descriptor      ENDS

;

Data            Segment  use16

;

gdt0          Descriptor <>

;

DataSel       equ      $-gdt0

DataDes       Descriptor <0ffffh,,,92h,>

;

CodeSel       equ      $-gdt0

CodeDes       Descriptor <0ffffh,,,98h,>

;

VideoSel      equ      $-gdt0

VideoDes      Descriptor <0ffffh,8000h,0Bh,92h,>

;

GdtLen        equ      $-gdt0

;

GdtPtr        word     GdtLen

dword    0

;

Mess          byte     ‘IA-32 CPU is in Protected Mode.’,0

;

JmpTable      dword    0

;

Data            ends

;

Code            Segment  use16

    assume cs:Code,ds:Data

;

Start:          xor      eax,eax          ;Clear eax.

;

mov      ax,Data          ;Initialize DS.

mov      ds,ax            ;

;

;Prepare for entering into protected mode.

;

shl      eax,4          ;create base address for data segment

;

mov      dword ptr [GdtPtr+2],eax ;Base address for load GDTR

;

mov      DataDes.basel,ax ;Fill base address for data segment

shr      eax,16           ;into data segment descriptor.

mov      DataDes.basem,al ;

mov      DataDes.baseh,ah ;

;

xor      eax,eax              ;Fill base address for code segment

mov      ax,Code          ;into code segment descriptor.

shl      eax,4            ;

mov      CodeDes.basel,ax ;

shr      eax,16           ;

mov      CodeDes.basem,al ;

mov      CodeDes.baseh,ah ;

;

lgdt     fword ptr GdtPtr ;Load GDTR

;

cli                      ;Disable interrupt.

mov      eax,cr0            ;SetPE of CR0 into 1.

or       eax,1

mov      cr0,eax

;

mov      dx,CodeSel     ;Use “jmp far ptr [esi]” to flush

shl      edx,16         ;instruction prefetch queue.

mov      dx,offset Code16

mov      JmpTable,edx

lea      esi,JmpTable

jmp      far ptr [esi]

;

;Enter into protected mode.

;

Code16:         mov      ax,DataSel   ;The string is displayed on the screen.

mov      ds,ax

mov      ax,VideoSel

mov      es,ax

mov      si,offset Mess

mov      di,80*46+48

mov      ah,47h

Load:           mov      al,[si]

inc      si

cmp      al,0

jz       ReadyToRmode

mov      es:[di],ax

add      di,2

jmp      Load

;

;Prepare for returning to real address mode.

;

ReadyToRmode:   mov      eax,cr0        ;Clear PE of CR0.

and      eax,0fffffffeh

mov      cr0,eax

;

mov      dx,seg Rmode   ;Use “jmp far ptr [esi]” to flush

shl      edx,16         ;instruction prefetch queue.

mov      dx,offset Rmode

mov      JmpTable,edx

lea      esi,JmpTable

jmp      far ptr [esi]

;

;Return to real address mode.

;

Rmode:          sti                     ;Set IF.

;

mov      ax,Data        ;Initialize DS and ES.

mov      ds,ax

mov      es,ax

;

mov      ax,4c00h       ;Retire.

int      21h

;

Code            ends                    ;Code segment is over.

;

                end      Start          ;The source program is over.

 

課堂練習:對於例9.1中所示的程序,我們可以在MASM 6.11環境下進行匯編和鏈接,然后運行並觀察其結果:

A.  啟動PWB。

B.  更改設置:點Options,在彈出的選單上選中Build Options,在彈出的Build Options窗口中選中Use Release Options,點OK。

C.  打開源程序文件sam9-1.asm,建立可執行程序sam9-1.exe。注意,請不要進入CodeView環境去運行sam9-1.exe。

D.  重啟計算機,根據計算機的不同,進行適當操作,使其進入MS-DOS方式。

E.  在MS-DOS方式下,運行sam9-1.exe,即可看到在屏幕上顯示出的字符串。

 

現在對例9.1中所示程序的工作原理進行分析:

1.  聲明結構類型Descriptor

保護模式下的段寄存器:其內容不再是段的基地址,而是稱之為選擇符(selector),其功能在於從全局段描述符表(Global Descriptor Table,GDT)或者局部段描述符表(Local Descriptor Table,LDT)中選出一個段描述符。選擇符的字段結構如表9.1所示。

 

表9.1  選擇符的字段結構

b15~b3

b2

b1~b0

Index

TI

RPL

 

選擇符的位b1~b0稱之為請求特權級(Requested Privilege Level,RPL)。RPL的數字必須小於當前特權級(Current privilege level,CPL)的數字,才可以訪問某個段的數據。CPL是當前正在執行的任務所具有的特權級,也就是段寄存器CS和SS中b1~b0所具有的數字。另外,段描述符的訪問權限字節(字節5)的b6~b5稱之為段描述符特權級(Descriptor privilege level,DPL)。DPL、CPL、RPL是Windows操作系統中保護機制的重要基礎。

TI位:為0時,說明段描述符在GDT中,應該訪問GDT;為1時,說明段描述符在LDT中,應該訪問LDT。

Index:利用它可以從GDT或者LDT中選出一個段描述符。具體作法是,由CPU硬件首先把Index的值乘以8,然后把乘積加到段描述符表的基地址上。段描述符表的基地址和限長分別存在全局段描述符表寄存器(Global Descriptor Table Register,GDTR)和局部段描述符表寄存器(Local Descriptor Table Register,LDTR)中。

GDT和LDT都放在內存中,由Windows操作系統維護。通常,系統任務的段描述符存放在GDT中,用戶任務的段描述符存放在LDT中。每個段描述符表包含8192( )個段描述符。

GDT和LDT中的段描述符可以認為是一種數據結構,每個段描述符具有8個字節的長度,其結構如表9.2所示。

 

 

表9.2  段描述符的結構

字節7

字節6

字節5

字節4~2

字節1~0

基址b31~b24

控制位

段限b19~b16

訪問權限

基址b23~b0

段限b15~b0

           

 

在例9.1中,所聲明的結構類型Descriptor與表9.2所示的段描述符結構是完全一致的。

 

2.  關於完全段

本例中的數據段和代碼段都使用了完全段來定義。原因在於只有使用完全段才可以實現在保護模式下,定義16位段的功能。

 

3.  數據段

定義結構變量必須在數據段中,而聲明結構類型則可不必在數據段中。

gdt0:NULL段描述符,Windows操作系統要求第一個段描述符必須定義為NULL。

DataSel:定義數據段選擇符。

DataDes:定義數據段描述符,基地址需用指令填充。

CodeSel:定義代碼段選擇符。

CodeDes:定義代碼段描述符,基地址需用指令填充。

VideoSel:定義視頻緩沖區段選擇符。

VideoDes:定義視頻緩沖區段描述符。

GdtLen:全局段描述符表限長。

GdtPtr:指向全局段描述符表限長和基地址的指針。

Mess:進入保護模式后顯示在屏幕上的字符串。

JmpTable:在jump指令的間接尋址方式下,用來存放轉移目標地址。

 

4.  代碼段:初始化DS,建立數據段基地址,建立用來裝入GDTR的基地址,把數據段基地址填入數據段描述符,把代碼段基地址填入代碼段描述符。

 

5.  代碼段:裝全局描述符表寄存器指令

該指令助記符用“LGDT”表示,其功能是把內存數據段中的GDT的限長和基地址裝入GDTR。

GDTR的字段結構如表9.3所示。

 

表9.3  GDTR的字段結構

b47~b16

b15~b0

GDT的基地址

GDT的限長

 

LGDT指令只需要一個操作數。由表9.3知道GDTR的長度具有6個字節,所以其操作數的類型也應該是6個字節。LGDT指令的形式和操作列在表9.4中。

 

表9.4  LGDT指令的形式和操作

匯編語句格式

編碼示例

尋址方式與操作

LGDT m16&32

LGDT     fword ptr GdtPtr

直接尋址

注:在表9.4中,m代表memory,ptr代表pointer,以下同。

 

LGDT指令只能由操作系統使用,用戶程序不能使用。通常,LGDT指令運行在實地址模式下,以便於CPU在切換到保護模式以前能夠執行初始化操作。

 

6.  代碼段:關中斷,設置CR0的PE位,清除指令預取隊列

用cli指令關中斷。

控制寄存器(Control Register,CR)CR0具有32位的長度,其b0為保護模式允許位(Protection Enable,PE)。當該位為1時,允許CPU工作在保護模式下;當該位為0時,禁止CPU工作在保護模式下。系統加電啟動時,該位被置0。

用“jmp far ptr [esi]”指令,執行一個無條件轉移,以便於清除指令預取隊列,保證順利地進入保護模式。此處jmp指令使用了間接尋址方式,方法是:首先把轉移目標地址存入內存數據段變量JmpTable中,然后把JmpTable的偏移量傳送到esi中,最后執行一個以esi內容為指針的far轉移。

 

7.  代碼段:進入保護模式

在屏幕上顯示字符串“IA-32 CPU is i.n Protected Mode.”。此處采用直接寫顯示緩沖區的方法。

顯示緩沖區的基地址:實地址模式下為B8000H(以物理地址形式表示),保護模式下為000B8000H(以物理地址形式表示)。

指定屏幕上的顯示坐標:mov      di,80*46+48。屏幕上可顯示字符的容量為24行×80字符。在顯示緩沖區中,每個字符用兩個字節來表示,高字節表示顏色與屬性,低字節存儲字符的ASCII代碼。

指定屏幕上的顯示屬性:mov      ah,47h,請參考MASM 6.11的聯機幫助。

 

8.  代碼段:准備返回到實地址模式

清除CR0的PE位,以便於CPU能夠工作在實地址模式下。

用“jmp far ptr [esi]”指令,執行一個無條件轉移,以便於清除指令預取隊列,保證順利地返回到實地址模式。

 

9.  代碼段:返回到實地址模式

設置ds和es,返回到系統。

 

課堂練習:調節屏幕顯示坐標和顏色與屬性。


免責聲明!

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



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