《電子技術(shù)應(yīng)用》
您所在的位置:首頁(yè) > 嵌入式技術(shù) > 解決方案 > 匯編實(shí)模式與保護(hù)模式切換實(shí)例

匯編實(shí)模式與保護(hù)模式切換實(shí)例

2017-07-23
關(guān)鍵詞: 匯編語(yǔ)言

本文介紹兩個(gè)實(shí)現(xiàn)實(shí)模式與保護(hù)模式切換的實(shí)例,,通過(guò)他們說(shuō)明如何實(shí)現(xiàn)實(shí)模式與保護(hù)模式的切換,,也說(shuō)明保護(hù)模式下的80386及其編程。

<一>演示實(shí)模式和保護(hù)模式切換的實(shí)例(實(shí)例一)

實(shí)例一的邏輯功能是,,以十六進(jìn)制數(shù)的形式顯示從內(nèi)存地址110000H開(kāi)始的256個(gè)字節(jié)的值。本實(shí)例指定該內(nèi)存區(qū)域的目的僅僅是想說(shuō)明切換到保護(hù)模式的必要性,,因?yàn)樵趯?shí)模式下不能訪問(wèn)該指定內(nèi)存區(qū)域,,只有在保護(hù)模式下才能訪問(wèn)到該指定區(qū)域。

本實(shí)例的具體實(shí)現(xiàn)步驟是:(1)作切換到保護(hù)方式的準(zhǔn)備,;(2)切換到保護(hù)方式,;(3)把指定內(nèi)存區(qū)域的內(nèi)容傳送到位于常規(guī)內(nèi)存的緩沖區(qū)中;(4)切換回實(shí)模式,;(5)顯示緩沖區(qū)內(nèi)容,。

1.包含文件

386保護(hù)模式匯編語(yǔ)言程序用到的包含文件如下所示,該包含文件在后面的程序中還要用到,。

;名稱:386SCD.INC
;功能:符號(hào)常量等的定義
;----------------------------------------------------------------------------
;IFNDEF __386SCD_INC
;__386SCD_INC EQU 1
;----------------------------------------------------------------------------
.386P
;----------------------------------------------------------------------------
;打開(kāi)A20地址線
;----------------------------------------------------------------------------
EnableA20 MACRO
push ax
in al,92h
or al,00000010b
out 92h,al
pop ax
ENDM
;----------------------------------------------------------------------------
;關(guān)閉A20地址線
;----------------------------------------------------------------------------
DisableA20 MACRO
push ax
in al,92h
and al,11111101b
out 92h,al
pop ax
ENDM
;----------------------------------------------------------------------------
;16位偏移的段間直接轉(zhuǎn)移指令的宏定義(在16位代碼段中使用)
;----------------------------------------------------------------------------
JUMP16 MACRO Selector,Offset
DB 0eah ;操作碼
DW Offset ;16位偏移量
DW Selector ;段值或段選擇子
ENDM
;----------------------------------------------------------------------------
;32位偏移的段間直接轉(zhuǎn)移指令的宏定義(在32位代碼段中使用)
;----------------------------------------------------------------------------
COMMENT <JUMP32>
JUMP32 MACRO Selector,Offset
DB 0eah ;操作碼
DD OFFSET
DW Selector ;段值或段選擇子
ENDM
<JUMP32>
;-------------------------------------------------
JUMP32 MACRO Selector,Offset
DB 0eah ;操作碼
DW OFFSET
DW 0
DW Selector ;段值或段選擇子
ENDM
;----------------------------------------------------------------------------
;16位偏移的段間調(diào)用指令的宏定義(在16位代碼段中使用)
;----------------------------------------------------------------------------
CALL16 MACRO Selector,Offset
DB 9ah ;操作碼
DW Offset ;16位偏移量
DW Selector ;段值或段選擇子
ENDM
;----------------------------------------------------------------------------
;32位偏移的段間調(diào)用指令的宏定義(在32位代碼段中使用)
;----------------------------------------------------------------------------
COMMENT <CALL32>
CALL32 MACRO Selector,Offset
DB 9ah ;操作碼
DD Offset
DW Selector ;段值或段選擇子
ENDM
<CALL32>
;-------------------------------------------------
CALL32 MACRO Selector,Offset
DB 9ah ;操作碼
DW Offset
DW 0
DW Selector ;段值或段選擇子
ENDM
;----------------------------------------------------------------------------
;存儲(chǔ)段描述符結(jié)構(gòu)類型定義
;----------------------------------------------------------------------------
Desc STRUC
LimitL DW 0 ;段界限(BIT0-15)
BaseL DW 0 ;段基地址(BIT0-15)
BaseM DB 0 ;段基地址(BIT16-23)
Attributes DB 0 ;段屬性
LimitH DB 0 ;段界限(BIT16-19)(含段屬性的高4位)
BaseH DB 0 ;段基地址(BIT24-31)
Desc ENDS
;----------------------------------------------------------------------------
;門描述符結(jié)構(gòu)類型定義
;----------------------------------------------------------------------------
Gate STRUC
OffsetL DW 0 ;32位偏移的低16位
Selector DW 0 ;選擇子
DCount DB 0 ;雙字計(jì)數(shù)
GType DB 0 ;類型
OffsetH DW 0 ;32位偏移的高16位
Gate ENDS
;----------------------------------------------------------------------------
;偽描述符結(jié)構(gòu)類型定義(用于裝入全局或中斷描述符表寄存器)
;----------------------------------------------------------------------------
PDesc STRUC
Limit DW 0 ;16位界限
Base DD 0 ;32位基地址
PDesc ENDS
;----------------------------------------------------------------------------
;任務(wù)狀態(tài)段結(jié)構(gòu)類型定義
;----------------------------------------------------------------------------
TSS STRUC
TRLink DW 0 ;鏈接字段
DW 0 ;不使用,置為0
TRESP0 DD 0 ;0級(jí)堆棧指針
TRSS0 DW 0 ;0級(jí)堆棧段寄存器
DW 0 ;不使用,置為0
TRESP1 DD 0 ;1級(jí)堆棧指針
TRSS1 DW 0 ;1級(jí)堆棧段寄存器
DW 0 ;不使用,置為0
TRESP2 DD 0 ;2級(jí)堆棧指針
TRSS2 DW 0 ;2級(jí)堆棧段寄存器
DW 0 ;不使用,置為0
TRCR3 DD 0 ;CR3
TREIP DD 0 ;EIP
TREFlag DD 0 ;EFLAGS
TREAX DD 0 ;EAX
TRECX DD 0 ;ECX
TREDX DD 0 ;EDX
TREBX DD 0 ;EBX
TRESP DD 0 ;ESP
TREBP DD 0 ;EBP
TRESI DD 0 ;ESI
TREDI DD 0 ;EDI
TRES DW 0 ;ES
DW 0 ;不使用,置為0
TRCS DW 0 ;CS
DW 0 ;不使用,置為0
TRSS DW 0 ;SS
DW 0 ;不使用,置為0
TRDS DW 0 ;DS
DW 0 ;不使用,置為0
TRFS DW 0 ;FS
DW 0 ;不使用,置為0
TRGS DW 0 ;GS
DW 0 ;不使用,置為0
TRLDTR DW 0 ;LDTR
DW 0 ;不使用,置為0
TRTrip DW 0 ;調(diào)試陷阱標(biāo)志(只用位0)
TRIOMap DW $+2 ;指向I/O許可位圖區(qū)的段內(nèi)偏移
TSS ENDS
;----------------------------------------------------------------------------
;存儲(chǔ)段描述符類型值說(shuō)明
;----------------------------------------------------------------------------
ATDR EQU 90h ;存在的只讀數(shù)據(jù)段類型值
ATDW EQU 92h ;存在的可讀寫數(shù)據(jù)段屬性值
ATDWA EQU 93h ;存在的已訪問(wèn)可讀寫數(shù)據(jù)段類型值
ATCE EQU 98h ;存在的只執(zhí)行代碼段屬性值
ATCER EQU 9ah ;存在的可執(zhí)行可讀代碼段屬性值
ATCCO EQU 9ch ;存在的只執(zhí)行一致代碼段屬性值
ATCCOR EQU 9eh ;存在的可執(zhí)行可讀一致代碼段屬性值
;----------------------------------------------------------------------------
;系統(tǒng)段描述符類型值說(shuō)明
;----------------------------------------------------------------------------
ATLDT EQU 82h ;局部描述符表段類型值
ATTaskGate EQU 85h ;任務(wù)門類型值
AT386TSS EQU 89h ;可用386任務(wù)狀態(tài)段類型值
AT386CGate EQU 8ch ;386調(diào)用門類型值
AT386IGate EQU 8eh ;386中斷門類型值
AT386TGate EQU 8fh ;386陷阱門類型值
;----------------------------------------------------------------------------
;DPL值說(shuō)明
;----------------------------------------------------------------------------
DPL0 EQU 00h ;DPL=0
DPL1 EQU 20h ;DPL=1
DPL2 EQU 40h ;DPL=2
DPL3 EQU 60h ;DPL=3
;----------------------------------------------------------------------------
;RPL值說(shuō)明
;----------------------------------------------------------------------------
RPL0 EQU 00h ;RPL=0
RPL1 EQU 01h ;RPL=1
RPL2 EQU 02h ;RPL=2
RPL3 EQU 03h ;RPL=3
;----------------------------------------------------------------------------
;IOPL值說(shuō)明
;----------------------------------------------------------------------------
IOPL0 EQU 0000h ;IOPL=0
IOPL1 EQU 1000h ;IOPL=1
IOPL2 EQU 2000h ;IOPL=2
IOPL3 EQU 3000h ;IOPL=3
;----------------------------------------------------------------------------
;其它常量值說(shuō)明
;----------------------------------------------------------------------------
D32 EQU 40h ;32位代碼段標(biāo)志
GL EQU 80h ;段界限以4K為單位標(biāo)志
TIL EQU 04h ;TI=1(局部描述符表標(biāo)志)
VMFL EQU 00020000h ;VMF=1
VMFLW EQU 0002h
IFL EQU 00000200h ;IF=1
RFL EQU 00010000h ;RF=1(重啟動(dòng)標(biāo)志,為1表示忽略調(diào)試故障)
RFLW EQU 0001h
NTL EQU 00004000h ;NT=1
;----------------------------------------------------------------------------
;分頁(yè)機(jī)制使用的常量說(shuō)明
;----------------------------------------------------------------------------
PL EQU 1 ;頁(yè)存在屬性位
RWR EQU 0 ;R/W屬性位值,讀/執(zhí)行
RWW EQU 2 ;R/W屬性位值,讀/寫/執(zhí)行
USS EQU 0 ;U/S屬性位值,系統(tǒng)級(jí)
USU EQU 4 ;U/S屬性位值,用戶級(jí)
;----------------------------------------------------------------------------
;ENDIF
2.實(shí)例源程序
   實(shí)例一的源程序如下所示:
;名稱:ASM1.ASM
;功能:演示實(shí)方式和保護(hù)方式切換(切換到16位代碼段)
;----------------------------------------------------------------------------
INCLUDE 386SCD.INC
;----------------------------------------------------------------------------
;字符顯示宏指令的定義
;----------------------------------------------------------------------------
EchoCh MACRO ascii
mov ah,2
mov dl,ascii
int 21h
ENDM
;----------------------------------------------------------------------------
DSEG SEGMENT USE16 ;16位數(shù)據(jù)段
;----------------------------------------------------------------------------
GDT LABEL BYTE ;全局描述符表
DUMMY Desc <> ;空描述符
Code Desc <0ffffh,,,ATCE,,> ;代碼段描述符
DataS Desc <0ffffh,0,11h,ATDW,,> ;源數(shù)據(jù)段描述符
DataD Desc <0ffffh,,,ATDW,,> ;目標(biāo)數(shù)據(jù)段描述符
;----------------------------------------------------------------------------
GDTLen = $-GDT ;全局描述符表長(zhǎng)度
VGDTR PDesc <GDTLen-1,> ;偽描述符
;----------------------------------------------------------------------------
Code_Sel = Code-GDT ;代碼段選擇子
DataS_Sel = Datas-GDT ;源數(shù)據(jù)段選擇子
DataD_Sel = DataD-GDT ;目標(biāo)數(shù)據(jù)段選擇子
;----------------------------------------------------------------------------
BufLen = 256 ;緩沖區(qū)字節(jié)長(zhǎng)度
Buffer DB BufLen DUP(0) ;緩沖區(qū)
;----------------------------------------------------------------------------
DSEG ENDS ;數(shù)據(jù)段定義結(jié)束
;----------------------------------------------------------------------------
CSEG SEGMENT USE16 ;16位代碼段
ASSUME CS:CSEG,DS:DSEG
;----------------------------------------------------------------------------
Start PROC
mov ax,DSEG
mov ds,ax
;準(zhǔn)備要加載到GDTR的偽描述符
mov bx,16
mul bx
add ax,OFFSET GDT ;計(jì)算并設(shè)置基地址
adc dx,0 ;界限已在定義時(shí)設(shè)置好
mov WORD PTR VGDTR.Base,ax
mov WORD PTR VGDTR.Base+2,dx
;設(shè)置代碼段描述符
mov ax,cs
mul bx
mov WORD PTR Code.BaseL,ax ;代碼段開(kāi)始偏移為0
mov BYTE PTR Code.BaseM,dl ;代碼段界限已在定義時(shí)設(shè)置好
mov BYTE PTR Code.BaseH,dh
;設(shè)置目標(biāo)數(shù)據(jù)段描述符
mov ax,ds
mul bx ;計(jì)算并設(shè)置目標(biāo)數(shù)據(jù)段基址
add ax,OFFSET Buffer
adc dx,0
mov WORD PTR DataD.BaseL,ax
mov BYTE PTR DataD.BaseM,dl
mov BYTE PTR DataD.BaseH,dh
;加載GDTR
lgdt QWORD PTR VGDTR
cli ;關(guān)中斷
EnableA20 ;打開(kāi)地址線A20
;切換到保護(hù)方式
mov eax,cr0
or eax,1
mov cr0,eax
;清指令預(yù)取隊(duì)列,并真正進(jìn)入保護(hù)方式
JUMP16 Code_Sel,<OFFSET Virtual>
Virtual: ;現(xiàn)在開(kāi)始在保護(hù)方式下運(yùn)行
mov ax,DataS_Sel
mov ds,ax ;加載源數(shù)據(jù)段描述符
mov ax,DataD_Sel
mov es,ax ;加載目標(biāo)數(shù)據(jù)段描述符
cld
xor si,si
xor di,di ;設(shè)置指針初值
mov cx,BufLen/4 ;設(shè)置4字節(jié)為單位的緩沖區(qū)長(zhǎng)度
repz movsd ;傳送
;切換回實(shí)模式
mov eax,cr0
and al,11111110b
mov cr0,eax
;清指令預(yù)取隊(duì)列,進(jìn)入實(shí)方式
JUMP16 <SEG Real>,<OFFSET Real>
Real: ;現(xiàn)在又回到實(shí)方式
DisableA20
sti
mov ax,DSEG
mov ds,ax
mov si,OFFSET Buffer
cld
mov bp,BufLen/16
NextLine: mov cx,16
NextCh: lodsb
push ax
shr al,1
call ToASCII
EchoCh al
pop ax
call ToASCII
EchoCh al
EchoCh ' '
loop NextCh
EchoCh 0dh
EchoCh 0ah
dec bp
jnz NextLine
mov ax,4c00h
int 21h
Start ENDP
;----------------------------------------------------------------------------
ToASCII PROC
and al,0fh
add al,90h
daa
adc al,40h
daa
ret
ToASCII ENDP
;----------------------------------------------------------------------------
CSEG ENDS ;代碼段定義結(jié)束
;----------------------------------------------------------------------------
END Start

3.關(guān)于實(shí)例步驟的注釋

在源程序的開(kāi)頭首先包含了文件“386SCD.INC”,,在此包含文件中定義了保護(hù)模式程序設(shè)計(jì)要用到的一些結(jié)構(gòu)、宏及常量,。下面對(duì)各實(shí)現(xiàn)步驟作些說(shuō)明,。

(1)切換到保護(hù)方式的準(zhǔn)備工作

在從實(shí)模式切換到保護(hù)模式之前,必須作必要的準(zhǔn)備,。準(zhǔn)備工作的內(nèi)容根據(jù)實(shí)際而定,。最起碼的準(zhǔn)備工作是建立合適的全局描述符表,并使用GDTR指向該GDT。因?yàn)樵谇袚Q到保護(hù)方式時(shí),,至少要把代碼段的選擇子裝載到CS,,所以GDT中至少含有代碼段的描述符。

從本實(shí)例源程序可見(jiàn),,全局描述符表GDT僅有四個(gè)描述符:第一個(gè)是空描述符,;第二個(gè)是代碼段描述符;第三個(gè)和第四個(gè)分別為源數(shù)據(jù)段及目標(biāo)數(shù)據(jù)段描述符,。本實(shí)例各描述符中的段界限是在定義時(shí)設(shè)置的,,并且除偽描述符VGDTR中的界限按GDT的實(shí)際長(zhǎng)度設(shè)置外,各使用的存儲(chǔ)段描述符的界限都規(guī)定為0FFFFH,。另外,,描述符中的段屬性也根據(jù)所描述段的類型被預(yù)置,各屬性的定義在包含文件386SCD.INC中均有說(shuō)明,。從屬性值可知,,這三個(gè)段都是16位段。

由于在切換到保護(hù)方式后就要引用GDT,,所以在切換到保護(hù)方式前必須裝載GDTR,。實(shí)例中使用如下指令裝載GDTR:

LGDT QWORD PTR VGDTR

該指令的功能是把存儲(chǔ)器中的偽描述符VGDTR裝入到全局描述符表寄存器GDTR中。偽描述符VGDTR的結(jié)構(gòu)如前所述結(jié)構(gòu)類型PDESC所示,,低字是以字節(jié)位單位的全局描述符表段的界限,,高雙字為描述符表段的線性基地址(本實(shí)例不啟用分頁(yè)機(jī)制,所以線性地址等同于物理地址),。本實(shí)例中未涉及到局部描述符表及中斷描述符表,,后面的文章將作詳細(xì)說(shuō)明。

(2)由實(shí)模式切換到保護(hù)模式

在做好準(zhǔn)備后,,從實(shí)模式切換到保護(hù)模式并不難,。原則上只要把控制寄存器CR0中的PE位置1即可。本實(shí)例采用如下三條指令設(shè)置PE位:

   mov eax,cr0
   or eax,1
   mov cr0,eax

實(shí)際情況要比這復(fù)雜些,。執(zhí)行上面的三條指令后,,處理器轉(zhuǎn)入保護(hù)模式,但CS中的內(nèi)容還是實(shí)模式下代碼段的段值,,而不是保護(hù)模式下代碼段的選擇子,,所以在取指令之前得把代碼段的選擇子裝入CS。為此,,緊接著這三條指令,,安排一條如下所示的段間轉(zhuǎn)移指令:

JUMP16 Code_Sel ,< OFFSET Virtual >

這條段間轉(zhuǎn)移指令 在實(shí)模式下被預(yù)取并在保護(hù)方式下被執(zhí)行 。利用這條段間轉(zhuǎn)移指令可把保護(hù)模式下代碼段的選擇子裝入CS,,同時(shí)也刷新指令預(yù)取隊(duì)列,。從此真正進(jìn)入保護(hù)模式,。

(3)由保護(hù)模式切換到實(shí)模式

在80386上,從保護(hù)模式切換到實(shí)模式的過(guò)程類似于從實(shí)模式切換到保護(hù)模式,。原則上只要把控制寄存器CR0中的PE位清0即可,。實(shí)際上,在此之后也要安排一條段間轉(zhuǎn)移指令,,一方面清指令預(yù)取隊(duì)列,,另一方面把實(shí)模式下代碼段的段值送CS。 這條段間轉(zhuǎn)移指令在保護(hù)方式下被預(yù)取并在實(shí)模式下被執(zhí)行 ,。

(4)保護(hù)模式下的數(shù)據(jù)傳送

首先,,把源數(shù)據(jù)段和目標(biāo)數(shù)據(jù)段的選擇子裝入DS和ES寄存器,這兩個(gè)描述符已在實(shí)模式下設(shè)置好,,把選擇子裝入段寄存器就意味著把包括基地址在內(nèi)的段信息裝入到了段描述符高速緩沖寄存器。然后設(shè)置指針寄存器SI和DI的初值,,也設(shè)置計(jì)數(shù)器CX的初值,。根據(jù)預(yù)置的段屬性,在保護(hù)方式下,,代碼段也僅是16位段,,串操作指令只使用16位的SI、DI和CX等寄存器,。最后利用串操作指令實(shí)施傳送,。

(5)顯示緩沖區(qū)中的內(nèi)容

由于緩沖區(qū)在常規(guī)內(nèi)存中,所以在實(shí)模式下根據(jù)要求按十六進(jìn)制顯示其內(nèi)容是很容易理解的,,這里就不再多說(shuō),。

4.內(nèi)存映象

在源程序中沒(méi)有把GDT作為一個(gè)單獨(dú)的段對(duì)待,但在進(jìn)入保護(hù)方式后,,它是一個(gè)獨(dú)立的段,。從對(duì)代碼段和源數(shù)據(jù)段描述符所賦的基地址和段界限值可見(jiàn),代碼段和數(shù)據(jù)段有部分覆蓋,。盡管這樣做不利于代碼和數(shù)據(jù)的安全,,但如果需要,這樣做是可行的,。本實(shí)例運(yùn)行時(shí)的內(nèi)存映象如下圖所示,。


5.特別說(shuō)明

作為第一個(gè)實(shí)模式和保護(hù)模式切換的例子,本實(shí)例作了大量的簡(jiǎn)化處理,。

通常,,由實(shí)模式切換到保護(hù)模式的準(zhǔn)備工作還應(yīng)包含建立中斷描述符表。但本實(shí)例沒(méi)有建立中斷描述符表,。為此,,要求整個(gè)過(guò)程在關(guān)中斷的情況下進(jìn)行;要求不使用軟中斷指令;假設(shè)不發(fā)生任何異常,。否則會(huì)導(dǎo)致系統(tǒng)崩潰,。

本實(shí)例未使用局部描述符表,所以在進(jìn)入保護(hù)模式后沒(méi)有設(shè)置局部描述符表寄存器LDTR,。為此,,在保護(hù)模式下使用的段選擇子都指定GDT中的描述符。

本實(shí)例未定義保護(hù)模式下的堆棧段,,GDT中沒(méi)有堆棧段描述符,,在保護(hù)模式下沒(méi)有設(shè)置SS,所以在保護(hù)方式下沒(méi)有涉及堆棧操作的指令,。

本實(shí)例各描述符特權(quán)級(jí)DPL和各選擇子的請(qǐng)求特權(quán)級(jí)RPL均為0,,在保護(hù)方式下運(yùn)行時(shí)的當(dāng)前特權(quán)級(jí)CPL也是0。

本實(shí)例沒(méi)有采用分頁(yè)管理機(jī)制,,也即CR0中的PG位為0,,線性地址就是存儲(chǔ)單元的物理地址。

6.打開(kāi)和關(guān)閉地址線A20

PC及其兼容機(jī)的第21根地址線(A20)較特殊,,計(jì)算機(jī)系統(tǒng)中一般安排一個(gè) “門”控制該地址線是否有效,。為了訪問(wèn)地址在1M以上的存儲(chǔ)單元,應(yīng)先打開(kāi)控制地址線A20的“門”,。這種設(shè)置與實(shí)模式下只使用最低端的1M字節(jié)存儲(chǔ)空間有關(guān),,與處理器是否工作在實(shí)模式或保護(hù)方式無(wú)關(guān),即使在關(guān)閉地址線A20時(shí),,也可進(jìn)入保護(hù)模式,。

如何打開(kāi)和關(guān)閉地址線A20與計(jì)算機(jī)系統(tǒng)的具體設(shè)置有關(guān)。在本文中介紹的包含文件386SCD.INC中定義了兩個(gè)宏,,打開(kāi)地址線A20的宏EnableA20和關(guān)閉地址線A20的宏DisableA20,,此兩個(gè)宏指令在一般的PC兼容機(jī)上都是可行的。

<二>演示32位代碼段和16位代碼段切換的實(shí)例(實(shí)例二)

實(shí)例二的邏輯功能是,,以十六進(jìn)制數(shù)和ASCII字符兩種形式顯示從內(nèi)存地址100000H開(kāi)始的16個(gè)字節(jié)的內(nèi)容,。

從功能上看,本實(shí)例類似于實(shí)例一,,但在實(shí)現(xiàn)方法上卻有了改變,,它更能反映出實(shí)模式和保護(hù)模式切換的情況。具體實(shí)現(xiàn)步驟是:

(1)作切換到保護(hù)方式的準(zhǔn)備,;

(2)切換到保護(hù)方式的一個(gè)32位代碼段,;

(3)把指定內(nèi)存區(qū)域的內(nèi)容以字節(jié)為單位,轉(zhuǎn)換成對(duì)應(yīng)的十六進(jìn)制數(shù)的ASCII碼,,并直接填入顯示緩沖區(qū)實(shí)現(xiàn)顯示,;

(4)再變換到保護(hù)方式下的一個(gè)16位代碼段,;

(5)把指定內(nèi)存區(qū)域的內(nèi)容直接作為ASCII碼填入顯示緩沖區(qū)中實(shí)現(xiàn)顯示;

(6)切換回實(shí)模式,。

1.實(shí)例二源程序

實(shí)例二的源程序如下所示:

;名稱:ASM2.ASM
;功能:演示實(shí)方式和保護(hù)方式切換(切換到32位代碼段)
;----------------------------------------------------------------------------
INCLUDE 386SCD.INC
;----------------------------------------------------------------------------
DSEG SEGMENT USE16 ;16位數(shù)據(jù)段
;----------------------------------------------------------------------------
GDT LABEL BYTE ;全局描述符表
DUMMY Desc <> ;空描述符
Normal Desc <0ffffh,,,ATDW,,> ;規(guī)范段描述符
Code32 Desc <C32Len-1,,,ATCE,D32,> ;32位代碼段描述符
Code16 Desc <0ffffh,,,ATCE,,> ;16位代碼段描述符
DataS Desc <DataLen-1,0,10h,ATDR,,> ;源數(shù)據(jù)段描述符
DataD Desc <3999,8000h,0bh,ATDW,,> ;顯示緩沖區(qū)描述符
Stacks Desc <StackLen-1,,,ATDW,,> ;堆棧段描述符
;----------------------------------------------------------------------------
GDTLen = $-GDT ;全局描述符表長(zhǎng)度
VGDTR PDesc <GDTLen-1,> ;偽描述符
;----------------------------------------------------------------------------
SaveSP DW ? ;用于保存SP寄存器
SaveSS DW ? ;用于保存SS寄存器
;----------------------------------------------------------------------------
Normal_Sel = Normal-GDT ;規(guī)范段描述符選擇子
Code32_Sel = Code32-GDT ;32位代碼段選擇子
Code16_Sel = Code16-GDT ;16位代碼段選擇子
DataS_Sel = Datas-GDT ;源數(shù)據(jù)段選擇子
DataD_Sel = DataD-GDT ;目標(biāo)數(shù)據(jù)段選擇子
Stacks_Sel = Stacks-GDT ;堆棧段描述符選擇子
;----------------------------------------------------------------------------
DataLen = 16
;----------------------------------------------------------------------------
DSEG ENDS ;數(shù)據(jù)段定義結(jié)束
;----------------------------------------------------------------------------
StackSeg SEGMENT PARA STACK USE16
StackLen = 256
DB StackLen DUP(0)
StackSeg ENDS
;----------------------------------------------------------------------------
CSEG1 SEGMENT USE16 'REAL' ;16位代碼段
ASSUME CS:CSEG1,DS:DSEG
;----------------------------------------------------------------------------
Start PROC
mov ax,DSEG
mov ds,ax
;準(zhǔn)備要加載到GDTR的偽描述符
mov bx,16
mul bx
add ax,OFFSET GDT ;計(jì)算并設(shè)置基地址
adc dx,0 ;界限已在定義時(shí)設(shè)置好
mov WORD PTR VGDTR.Base,ax
mov WORD PTR VGDTR.Base+2,dx
;設(shè)置32位代碼段描述符
mov ax,CSEG2
mul bx
mov WORD PTR Code32.BaseL,ax
mov BYTE PTR Code32.BaseM,dl
mov BYTE PTR Code32.BaseH,dh
;設(shè)置16位代碼段描述符
mov ax,CSEG3
mul bx
mov WORD PTR Code16.BaseL,ax ;代碼段開(kāi)始偏移為0
mov BYTE PTR Code16.BaseM,dl ;代碼段界限已在定義時(shí)設(shè)置好
mov BYTE PTR Code16.BaseH,dh
;設(shè)置堆棧段描述符
mov ax,ss
mov WORD PTR SaveSS,ax
mov WORD PTR SaveSP,sp
mov ax,StackSeg
mul bx
mov WORD PTR Stacks.BaseL,ax
mov BYTE PTR Stacks.BaseM,dl
mov BYTE PTR Stacks.BaseH,dh
;加載GDTR
lgdt QWORD PTR VGDTR
cli ;關(guān)中斷
EnableA20 ;打開(kāi)地址線A20
;切換到保護(hù)方式
mov eax,cr0
or al,1
mov cr0,eax
;清指令預(yù)取隊(duì)列,并真正進(jìn)入保護(hù)方式
JUMP16 Code32_Sel,<OFFSET SPM32>
ToReal: ;現(xiàn)在又回到實(shí)方式
mov ax,DSEG
mov ds,ax
mov sp,SaveSP
mov ss,SaveSS
DisableA20
sti
mov ax,4c00h
int 21h
Start ENDP
;----------------------------------------------------------------------------
CSEG1 ENDS ;代碼段定義結(jié)束
;----------------------------------------------------------------------------
CSEG2 SEGMENT USE32 'PM32'
ASSUME CS:CSEG2
;----------------------------------------------------------------------------
SPM32 PROC
mov ax,Stacks_Sel
mov ss,ax
mov esp,StackLen
mov ax,DataS_Sel
mov ds,ax
mov ax,DataD_Sel
mov es,ax
xor esi,esi
xor edi,edi
mov ecx,DataLen
cld
Next: lodsb
push ax
CALL ToASCII
mov ah,7
shl eax,16
pop ax
shr al,4
CALL ToASCII
mov ah,7
stosd
mov al,20h
stosw
loop Next
JUMP32 Code16_Sel,<OFFSET SPM16>
SPM32 ENDP
;----------------------------------------------------------------------------
ToASCII PROC
and al,00001111b
add al,30h
cmp al,39h
jbe Isdig
add al,7
IsDig: ret
ToASCII ENDP
;----------------------------------------------------------------------------
C32Len = $
;----------------------------------------------------------------------------
CSEG2 ENDS
;----------------------------------------------------------------------------
CSEG3 SEGMENT USE16 'PM16'
ASSUME CS:CSEG3
;----------------------------------------------------------------------------
SPM16 PROC
xor si,si
mov di,DataLen*3*2
mov ah,7
mov cx,DataLen
AGain: lodsb
stosw
loop AGain
mov ax,Normal_sel
mov ds,ax
mov es,ax
mov ss,ax
mov eax,cr0
and al,11111110b
mov cr0,eax
jmp FAR PTR ToReal
SPM16 ENDP
;----------------------------------------------------------------------------
CSEG3 ENDS
;----------------------------------------------------------------------------
END Start

2.關(guān)于實(shí)現(xiàn)步驟的注釋

(1)切換到保護(hù)模式的準(zhǔn)備工作

建立全局描述符表,,這里的全局描述符表含有兩個(gè)16位數(shù)據(jù)段的描述符、一個(gè)16位代碼段的描述符和一個(gè)16位的堆棧段描述符,。此外,,GDT中還有一個(gè)32位的代碼段描述符,描述32位代碼段,,該描述符的屬性字段中的D位為1,。

(2)由實(shí)模式切換到保護(hù)模式

由實(shí)模式切換到保護(hù)模式32位代碼段的方法與切換到16位代碼段的方法相同。由保護(hù)模式16位代碼段切換回實(shí)模式的方法與實(shí)例一相似,。

在保護(hù)模式下,,通過(guò)如下直接段間轉(zhuǎn)移指令從32位代碼段切換到16位代碼段:

JUMP32 Code16_Sel ,< OFFSET SPM16 >

從該宏指令的定義可知,該轉(zhuǎn)移指令含48位指針,,其高16位是16位代碼段的選擇子,,低32位是16位代碼段的入口偏移。 該指令在32位方式下預(yù)取并執(zhí)行 ,。由于在32位方式下執(zhí)行,所以要使用48位指針,。

(3)顯示指定內(nèi)存區(qū)域的內(nèi)容

在本實(shí)例中,,采用直接寫顯示緩沖區(qū)的方法實(shí)現(xiàn)顯示。假設(shè)顯示緩沖區(qū)的開(kāi)始物理地址是0B8000H,, 3號(hào)文本顯示模式,,在屏幕的第一行進(jìn)行顯示。

3.特別說(shuō)明

本實(shí)例在保護(hù)方式下使用了涉及堆棧操作的指令,,因此建立了一個(gè)16位的保護(hù)模式下的堆棧段,。

本實(shí)例仍作了大量的簡(jiǎn)化處理。如:沒(méi)有建立IDT和LDT等,,各特權(quán)級(jí)均是0,。也沒(méi)有采用分頁(yè)管理機(jī)制。

從本實(shí)例的GDT中可見(jiàn),,兩個(gè)數(shù)據(jù)段的界限都是根據(jù)實(shí)際大小而設(shè)置的,。從源程序代碼段CSEG3可見(jiàn),在切換到實(shí)模式之前,,把一個(gè)指向似乎沒(méi)有用的數(shù)據(jù)段的描述符Normal的選擇子裝載到DS和ES,。這是為什么呢?

實(shí)模
式下
段描
述符
高速
緩沖
寄存
器的
內(nèi)容    段寄存器    段基地址    段界限(固定)    段屬性(固定)    

存在性    特權(quán)級(jí)    已存取    粒度    擴(kuò)展方向    可讀性    可寫性    可執(zhí)行    堆棧大小    一致特權(quán)    

CS    當(dāng)前CS*16    0000FFFFH    Y    0    Y    B    U    Y    Y    Y    -    N    

SS    當(dāng)前SS*16    0000FFFFH    Y    0    Y    B    U    Y    Y    N    W    -    

DS    當(dāng)前DS*16    0000FFFFH    Y    0    Y    B    U    Y    Y    N    -    -    

ES    當(dāng)前ES*16    0000FFFFH    Y    0    Y    B    U    Y    Y    N    -    -    

FS    當(dāng)前FS*16    0000FFFFH    Y    0    Y    B    U    Y    Y    N    -    -    

GS    當(dāng)前GS*16    0000FFFFH    Y    0    Y    B    U    Y    Y    N    -    -    

在分段管理機(jī)制一文中已介紹過(guò),每個(gè)段寄存器都配有段描述符高速緩沖寄存器,,這些高速緩沖寄存器在實(shí)方式下仍發(fā)揮作用,,只是內(nèi)容上與保護(hù)模式下有所不同,。如上表所示,其中“Y”表示“是”,; “N”表示“否”,;“B”表示字節(jié);“U”表示向上擴(kuò)展,,“W”表示以字方式操作堆棧,。段基地址仍是 32位,其值是相應(yīng)段寄存器值(段值)乘以16,,在把段值裝載到段寄存器時(shí)刷新,。由于其值是16位段值乘上16,所以在實(shí)模式下基地址實(shí)際上有效位只有20位,。每個(gè)段的32位段界限都固定為0FFFFH,,段屬性的許多位也是固定的。所謂固定是指在實(shí)方式下不可設(shè)置這些屬性值,,只能繼續(xù)沿用保護(hù)方式下所設(shè)置的值,。因此,在準(zhǔn)備結(jié)束保護(hù)模式回到實(shí)模式之前,,要通過(guò)加載一個(gè)合適的描述符選擇子到有關(guān)段寄存器,,以使得對(duì)應(yīng)段描述符高速緩沖寄存器中含有合適的段界限和屬性。本實(shí)例GDT中的描述符Normal就是這樣一個(gè)描述符,,在返回實(shí)模式之前把對(duì)應(yīng)選擇子Normal_Sel加載到DS和ES就是此目的,。由于SS段描述符中的內(nèi)容已符合實(shí)模式的需要,所以盡管也改變了SS,,但不需要重新加載SS(本實(shí)例中重新加載了SS,,這除了稍增加運(yùn)行時(shí)間外,并沒(méi)有什么壞處),。16位代碼段描述符中的內(nèi)容也符合實(shí)模式的需要,,所以在通過(guò)16位代碼段返回實(shí)模式時(shí),CS段描述符中的內(nèi)容也符合實(shí)模式的要求,。需要注意的是,,不能從32位代碼段返回實(shí)模式,這是因?yàn)闊o(wú)法實(shí)現(xiàn)從32位代碼段返回時(shí)CS高速緩沖寄存器中的屬性符合實(shí)模式的要求(實(shí)模式不能改變段屬性),。順便說(shuō)以下,,實(shí)例一中的描述符都是符合實(shí)模式要求的。段描述符高速緩沖寄存器中含有合適的段界限

4.關(guān)于32位代碼段程序設(shè)計(jì)的說(shuō)明

在32位代碼段中,,缺省的操作數(shù)大小是32位,,缺省的存儲(chǔ)單元地址大小是32位。由于串操作指令使用的指針寄存器是ESI和EDI,,LOOP指令使用的計(jì)數(shù)器是ECX,,所以,,在代碼段CSEG2中,為了使用串操作指令,,對(duì)ESI和EDI等寄存器賦初值,。請(qǐng)比較代碼段CSEG3中的相關(guān)片段和實(shí)例一中的相關(guān)片段,它們是16位代碼段,。


本站內(nèi)容除特別聲明的原創(chuàng)文章之外,,轉(zhuǎn)載內(nèi)容只為傳遞更多信息,并不代表本網(wǎng)站贊同其觀點(diǎn),。轉(zhuǎn)載的所有的文章,、圖片、音/視頻文件等資料的版權(quán)歸版權(quán)所有權(quán)人所有,。本站采用的非本站原創(chuàng)文章及圖片等內(nèi)容無(wú)法一一聯(lián)系確認(rèn)版權(quán)者,。如涉及作品內(nèi)容、版權(quán)和其它問(wèn)題,,請(qǐng)及時(shí)通過(guò)電子郵件或電話通知我們,,以便迅速采取適當(dāng)措施,避免給雙方造成不必要的經(jīng)濟(jì)損失,。聯(lián)系電話:010-82306118,;郵箱:[email protected]