实模式与保护模式切换实例.docx
- 文档编号:9490423
- 上传时间:2023-05-19
- 格式:DOCX
- 页数:27
- 大小:25.57KB
实模式与保护模式切换实例.docx
《实模式与保护模式切换实例.docx》由会员分享,可在线阅读,更多相关《实模式与保护模式切换实例.docx(27页珍藏版)》请在冰点文库上搜索。
实模式与保护模式切换实例
四.实模式与保护模式切换实例
本文介绍两个实现实模式与保护模式切换的实例,通过他们说明如何实现实模式与保护模式的切换,也说明保护模式下的80386及其编程。
<一>演示实模式和保护模式切换的实例(实例一)
实例一的逻辑功能是,以十六进制数的形式显示从内存地址110000H开始的256个字节的值。
本实例指定该内存区域的目的仅仅是想说明切换到保护模式的必要性,因为在实模式下不能访问该指定内存区域,只有在保护模式下才能访问到该指定区域。
本实例的具体实现步骤是:
(1)作切换到保护方式的准备;
(2)切换到保护方式;(3)把指定内存区域的内容传送到位于常规内存的缓冲区中;(4)切换回实模式;(5)显示缓冲区内容。
1.包含文件
386保护模式汇编语言程序用到的包含文件如下所示,该包含文件在后面的程序中还要用到。
;名称:
386SCD.INC
;功能:
符号常量等的定义
;----------------------------------------------------------------------------
;IFNDEF__386SCD_INC
;__386SCD_INCEQU1
;----------------------------------------------------------------------------
.386P
;----------------------------------------------------------------------------
;打开A20地址线
;----------------------------------------------------------------------------
EnableA20MACRO
pushax
inal,92h
oral,00000010b
out92h,al
popax
ENDM
;----------------------------------------------------------------------------
;关闭A20地址线
;----------------------------------------------------------------------------
DisableA20MACRO
pushax
inal,92h
andal,11111101b
out92h,al
popax
ENDM
;----------------------------------------------------------------------------
;16位偏移的段间直接转移指令的宏定义(在16位代码段中使用)
;----------------------------------------------------------------------------
JUMP16MACROSelector,Offset
DB0eah;操作码
DWOffset;16位偏移量
DWSelector;段值或段选择子
ENDM
;----------------------------------------------------------------------------
;32位偏移的段间直接转移指令的宏定义(在32位代码段中使用)
;----------------------------------------------------------------------------
COMMENT
JUMP32MACROSelector,Offset
DB0eah;操作码
DDOFFSET
DWSelector;段值或段选择子
ENDM
;-------------------------------------------------
JUMP32MACROSelector,Offset
DB0eah;操作码
DWOFFSET
DW0
DWSelector;段值或段选择子
ENDM
;----------------------------------------------------------------------------
;16位偏移的段间调用指令的宏定义(在16位代码段中使用)
;----------------------------------------------------------------------------
CALL16MACROSelector,Offset
DB9ah;操作码
DWOffset;16位偏移量
DWSelector;段值或段选择子
ENDM
;----------------------------------------------------------------------------
;32位偏移的段间调用指令的宏定义(在32位代码段中使用)
;----------------------------------------------------------------------------
COMMENT
CALL32MACROSelector,Offset
DB9ah;操作码
DDOffset
DWSelector;段值或段选择子
ENDM
;-------------------------------------------------
CALL32MACROSelector,Offset
DB9ah;操作码
DWOffset
DW0
DWSelector;段值或段选择子
ENDM
;----------------------------------------------------------------------------
;存储段描述符结构类型定义
;----------------------------------------------------------------------------
DescSTRUC
LimitLDW0;段界限(BIT0-15)
BaseLDW0;段基地址(BIT0-15)
BaseMDB0;段基地址(BIT16-23)
AttributesDB0;段属性
LimitHDB0;段界限(BIT16-19)(含段属性的高4位)
BaseHDB0;段基地址(BIT24-31)
DescENDS
;----------------------------------------------------------------------------
;门描述符结构类型定义
;----------------------------------------------------------------------------
GateSTRUC
OffsetLDW0;32位偏移的低16位
SelectorDW0;选择子
DCountDB0;双字计数
GTypeDB0;类型
OffsetHDW0;32位偏移的高16位
GateENDS
;----------------------------------------------------------------------------
;伪描述符结构类型定义(用于装入全局或中断描述符表寄存器)
;----------------------------------------------------------------------------
PDescSTRUC
LimitDW0;16位界限
BaseDD0;32位基地址
PDescENDS
;----------------------------------------------------------------------------
;任务状态段结构类型定义
;----------------------------------------------------------------------------
TSSSTRUC
TRLinkDW0;链接字段
DW0;不使用,置为0
TRESP0DD0;0级堆栈指针
TRSS0DW0;0级堆栈段寄存器
DW0;不使用,置为0
TRESP1DD0;1级堆栈指针
TRSS1DW0;1级堆栈段寄存器
DW0;不使用,置为0
TRESP2DD0;2级堆栈指针
TRSS2DW0;2级堆栈段寄存器
DW0;不使用,置为0
TRCR3DD0;CR3
TREIPDD0;EIP
TREFlagDD0;EFLAGS
TREAXDD0;EAX
TRECXDD0;ECX
TREDXDD0;EDX
TREBXDD0;EBX
TRESPDD0;ESP
TREBPDD0;EBP
TRESIDD0;ESI
TREDIDD0;EDI
TRESDW0;ES
DW0;不使用,置为0
TRCSDW0;CS
DW0;不使用,置为0
TRSSDW0;SS
DW0;不使用,置为0
TRDSDW0;DS
DW0;不使用,置为0
TRFSDW0;FS
DW0;不使用,置为0
TRGSDW0;GS
DW0;不使用,置为0
TRLDTRDW0;LDTR
DW0;不使用,置为0
TRTripDW0;调试陷阱标志(只用位0)
TRIOMapDW$+2;指向I/O许可位图区的段内偏移
TSSENDS
;----------------------------------------------------------------------------
;存储段描述符类型值说明
;----------------------------------------------------------------------------
ATDREQU90h;存在的只读数据段类型值
ATDWEQU92h;存在的可读写数据段属性值
ATDWAEQU93h;存在的已访问可读写数据段类型值
ATCEEQU98h;存在的只执行代码段属性值
ATCEREQU9ah;存在的可执行可读代码段属性值
ATCCOEQU9ch;存在的只执行一致代码段属性值
ATCCOREQU9eh;存在的可执行可读一致代码段属性值
;----------------------------------------------------------------------------
;系统段描述符类型值说明
;----------------------------------------------------------------------------
ATLDTEQU82h;局部描述符表段类型值
ATTaskGateEQU85h;任务门类型值
AT386TSSEQU89h;可用386任务状态段类型值
AT386CGateEQU8ch;386调用门类型值
AT386IGateEQU8eh;386中断门类型值
AT386TGateEQU8fh;386陷阱门类型值
;----------------------------------------------------------------------------
;DPL值说明
;----------------------------------------------------------------------------
DPL0EQU00h;DPL=0
DPL1EQU20h;DPL=1
DPL2EQU40h;DPL=2
DPL3EQU60h;DPL=3
;----------------------------------------------------------------------------
;RPL值说明
;----------------------------------------------------------------------------
RPL0EQU00h;RPL=0
RPL1EQU01h;RPL=1
RPL2EQU02h;RPL=2
RPL3EQU03h;RPL=3
;----------------------------------------------------------------------------
;IOPL值说明
;----------------------------------------------------------------------------
IOPL0EQU0000h;IOPL=0
IOPL1EQU1000h;IOPL=1
IOPL2EQU2000h;IOPL=2
IOPL3EQU3000h;IOPL=3
;----------------------------------------------------------------------------
;其它常量值说明
;----------------------------------------------------------------------------
D32EQU40h;32位代码段标志
GLEQU80h;段界限以4K为单位标志
TILEQU04h;TI=1(局部描述符表标志)
VMFLEQU00020000h;VMF=1
VMFLWEQU0002h
IFLEQU00000200h;IF=1
RFLEQU00010000h;RF=1(重启动标志,为1表示忽略调试故障)
RFLWEQU0001h
NTLEQU00004000h;NT=1
;----------------------------------------------------------------------------
;分页机制使用的常量说明
;----------------------------------------------------------------------------
PLEQU1;页存在属性位
RWREQU0;R/W属性位值,读/执行
RWWEQU2;R/W属性位值,读/写/执行
USSEQU0;U/S属性位值,系统级
USUEQU4;U/S属性位值,用户级
;----------------------------------------------------------------------------
;ENDIF
2.实例源程序
实例一的源程序如下所示:
;名称:
ASM1.ASM
;功能:
演示实方式和保护方式切换(切换到16位代码段)
;----------------------------------------------------------------------------
INCLUDE386SCD.INC
;----------------------------------------------------------------------------
;字符显示宏指令的定义
;----------------------------------------------------------------------------
EchoChMACROascii
movah,2
movdl,ascii
int21h
ENDM
;----------------------------------------------------------------------------
DSEGSEGMENTUSE16;16位数据段
;----------------------------------------------------------------------------
GDTLABELBYTE;全局描述符表
DUMMYDesc<>;空描述符
CodeDesc<0ffffh,,,ATCE,,>;代码段描述符
DataSDesc<0ffffh,0,11h,ATDW,,>;源数据段描述符
DataDDesc<0ffffh,,,ATDW,,>;目标数据段描述符
;----------------------------------------------------------------------------
GDTLen=$-GDT;全局描述符表长度
VGDTRPDesc
;----------------------------------------------------------------------------
Code_Sel=Code-GDT;代码段选择子
DataS_Sel=Datas-GDT;源数据段选择子
DataD_Sel=DataD-GDT;目标数据段选择子
;----------------------------------------------------------------------------
BufLen=256;缓冲区字节长度
BufferDBBufLenDUP(0);缓冲区
;----------------------------------------------------------------------------
DSEGENDS;数据段定义结束
;----------------------------------------------------------------------------
CSEGSEGMENTUSE16;16位代码段
ASSUMECS:
CSEG,DS:
DSEG
;----------------------------------------------------------------------------
StartPROC
movax,DSEG
movds,ax
;准备要加载到GDTR的伪描述符
movbx,16
mulbx
addax,OFFSETGDT;计算并设置基地址
adcdx,0;界限已在定义时设置好
movWORDPTRVGDTR.Base,ax
movWORDPTRVGDTR.Base+2,dx
;设置代码段描述符
movax,cs
mulbx
movWORDPTRCode.BaseL,ax;代码段开始偏移为0
movBYTEPTRCode.BaseM,dl;代码段界限已在定义时设置好
movBYTEPTRCode.BaseH,dh
;设置目标数据段描述符
movax,ds
mulbx;计算并设置目标数据段基址
addax,OFFSETBuffer
adcdx,0
movWORDPTRDataD.BaseL,ax
movBYTEPTRDataD.BaseM,dl
movBYTEPTRDataD.BaseH,dh
;加载GDTR
lgdtQWORDPTRVGDTR
cli;关中断
EnableA20;打开地址线A20
;切换到保护方式
moveax,cr0
oreax,1
movcr0,eax
;清指令预取队列,并真正进入保护方式
JUMP16Code_Sel,
Virtual:
;现在开始在保护方式下运行
movax,DataS_Sel
movds,ax;加载源数据段描述符
movax,DataD_Sel
moves,ax;加载目标数据段描述符
cld
xorsi,si
xordi,di;设置指针初值
movcx,BufLen/4;设置4字节为单位的缓冲区长度
repzmovsd;传送
;切换回实模式
moveax,cr0
andal,11111110b
movcr0,eax
;清指令预取队列,进入实方式
JUMP16
Real:
;现在又回到实方式
DisableA20
sti
movax,DSEG
movds,ax
movsi,OFFSETBuffer
cld
movbp,BufLen/16
NextLine:
movcx,16
NextCh:
lodsb
pushax
shral,1
callToASCII
EchoChal
popax
callToASCII
EchoChal
EchoCh''
loopNextCh
EchoCh0dh
EchoCh0ah
decbp
jnzNextLine
movax,4c00h
int21h
StartENDP
;----------------------------------------------------------------------------
ToASCIIPROC
andal,0fh
addal,90h
daa
adcal,40h
daa
ret
ToASCIIENDP
;----------------------------------------------------------------------------
CSEGENDS;代码段定义结束
;----------------------------------------------------------------------------
ENDStart
3.关于实例步骤的注释
在源程序的开头首先包含了文件“386SCD.INC”,在此包含文件中定义了保护模式程序设计要用到的一些结构、宏及常量。
下面对各实现步骤作些说明。
(1)切换到保护方式的准备工作
在从实模式切换到保护模式之前,必须作必要的准备。
准备工作
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 模式 保护 切换 实例