虚拟8086模式Word格式文档下载.docx
- 文档编号:19774394
- 上传时间:2023-01-10
- 格式:DOCX
- 页数:23
- 大小:26.73KB
虚拟8086模式Word格式文档下载.docx
《虚拟8086模式Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《虚拟8086模式Word格式文档下载.docx(23页珍藏版)》请在冰豆网上搜索。
二>
进入和离开V86模式
保护模式和V86模式之间的切换情形如下图所示。
图中左面部分为V86任务。
从图中可见,V86模式与保护模式的切换可发生在V86任务之内,这种切换是V86模式下的8086程序与保护模式下的监控程序之间的转换;
V86模式与保护模式的切换可发生在任务之间,这种切换是V86任务与其它任务的切换。
此外,V86监控程序与其它任务之间的切换是普通的任务切换。
由于80386没有提供直接改变VM标志的指令,并且只有当前特权级CPL=0时,对VM的改变才有效,所以V86模式与保护模式的切换不能简单地通过改变VM位而进行。
下面介绍V86模式与保护模式之间的切换,也就是如何进入和离开V86模式。
为了方便,先介绍如何离开V86模式。
1.离开V86模式
在V86模式下,如果处理器响应中断/异常,那么就会退出当前V86任务的V86模式。
在V86模式下,处理器对中断/异常的响应处理不同于真正的8086,而仍然采用保护模式下对中断/异常响应处理的方法。
所以,在V86模式下,不是根据位于线性地址空间最低端的中断向量表内的对应中断向量转入处理程序,而是根据中断描述符表IDT内的对应门描述符的指示转入处理程序。
(1)在V86任务内离开V86模式
如果对应的门描述符是386中断门或386陷阱门,那么就发生在当前V86任务内从V86模式到保护模式的转换。
80386要求执行这种中断/异常处理程序时的CPL必须等于0。
由于V86模式下的CPL=3,而转换到保护模式后的CPL=0,所以这种转换包含了特权级的变换。
在转入处理程序之前,处理器先将V86模式下的段寄存器GS、FS、DS及ES压入0级堆栈,并在进入保护模式下的处理程序之前装入空选择子。
为保持使堆栈对齐,把段寄存器压入堆栈时一律按32位值压入,低16位是段寄存器的值,高16位为空。
于是,转换后的0级堆栈如下图所示。
其中,段寄存器SS和CS的值也是V86模式下的段值。
图(a)是没有出错码的情形;
图(b)是有出错码的情形。
在这种V86任务内从V86模式转换到保护模式的过程中,为了保证中断/异常处理程序工作于特权级0,对目标代码段描述符特权级进行检查,如果由目标代码段描述符特权级决定的CPL不等于0,将引起通用保护异常。
此外,标志寄存器EFLAGS中的VM位被清0,从而使得中断/异常处理在保护模式下进行,也即离开V86模式。
这种情况下,相应的中断/异常处理在当前V86任务之内进行。
中断异常处理程序可以检查保存在堆栈中的EFLAGS映象,根据VM位的值来确定被中断程序的工作模式。
如果VM=1,那么被中断的程序工作于V86模式,是8086程序;
否则,被中断的程序工作于保护模式,是V86监控程序。
(2)任务切换离开V86模式
如果对应的门描述符是任务门,那么就发生从当前V86任务到其它任务的切换,也就离开了当前V86任务的V86方式。
象普通任务切换一样,V86模式的各通用寄存器、段寄存器、指令指针和标志寄存器EFLAGS等保存到原V86任务的386TSS中。
被保存的段寄存器的内容是V86模式下的段值。
被保存的EFLAGS内的VM=1。
这种情况下,相应的中断异常处理在另一个任务内进行。
目标任务可以是普通任务,也可以是另一个V86任务。
如果目标任务TSS内的EFLAGS字段内的VM=1,那么就转入另一个V86任务的V86模式。
2.进入V86模式
与离开V86模式的两条途径相对应,有两条进入V86模式的途径。
(1)通过IRET指令进入V86模式
通过在中断/异常处理结束时使用IRET指令返回被中断的程序继续执行。
指令IRET的执行步骤如下所示:
(1)若NT=1,则进行任务切换,然后转步骤6;
(2)否则从堆栈中弹出EIP、CS和EFLAGS;
(3)若VM=1且CPL=0,则恢复外层堆栈及其它段寄存器,然后转步骤6;
(4)若无特权级变换则转步骤6;
(5)否则恢复外层堆栈;
(6)结束
尽管上述步骤不够细致和没包括异常情况,但还是体现了指令IRET执行时所处理的三种情形。
第一种情形是当前EFLAGS中的NT=1,也即嵌套任务返回,那么就进行任务切换,指向目标任务TSS的选择子在当前任务TSS的连接字段。
NT=0表示当前中断/异常处理程序与被中断程序属于同一任务,于是就从堆栈弹出EIP、CS和EFLAGS。
第二和第三中情形是NT=0的条件下产生的。
第二种情形是弹出的EFLAGS中VM=0,表示被中断的程序是普通保护模式程序,那么就考虑特权级变换,如果向外层返回,那么就恢复外层堆栈指针。
不允许向内层返回,否则将会引起通用保护异常。
前文中介绍的IRET指令的动作只考虑了情形一和情形二,并不是IRET指令的完整动作。
第三种情形是弹出的EFLAGS中VM=1且当前正运行程序的CPL=0,表示被中断的程序是V86模式下的8086程序,当前是从同一V86任务下的中断/异常处理程序返回。
由于V86模式的特权级是3,所以要进行堆栈切换,也即从堆栈中弹出3级堆栈的指针(ESP和SS)。
此外,还从堆栈中弹出段寄存器ES、DS、FS和GS。
在这种情形下,弹到各段寄存器(包括CS和SS)的内容都作为段值,而非选择子。
这种处理动作对应于上述第一种离开V86模式的情形,有关堆栈操作与上图所示的堆栈内容相符。
当然,如果产生异常时提供出错码,那么异常处理程序在利用IRET指令返回时,必须确保堆栈指针指向如上图所示保存EIP的单元。
简单的实现方法是,异常处理程序在执行IRET前,先从堆栈中弹出出错码。
利用指令IRET处理的这第三种情形,可以方便地从V86任务下的中断/异常处理程序返回到V86模式下的8086程序。
利用这条途径还可以直接进入V86模式。
为此,先在0级堆栈中形成如上图(a)所示的栈顶。
对应EIP值是V86模式下要执行的8086程序入口点的16位偏移;
对应CS值是V86模式下要执行的8086程序入口点的段值;
对应EFLAGS值中的VM位必须是1;
对应SS和ESP的值是要执行的8086程序的堆栈指针;
对应ES、DS、FS和GS的值是相应的段值。
然后,在CPL=0和NT=0的情况下,执行IRET指令。
实际上,这种进入V86模式的途径是,先建立一个V86模式下执行的8086程序被中断而离开V86模式的环境,然后再返回。
需要注意的是,若当前正执行程序的CPL不为0,则再执行IRET指令时不会进入V86模式,但也不产生异常,EFLAGS中的VM位被处理器自动清0。
不能通过RET指令进入V86模式,因为它不改变EFLAGS的内容。
任何不能修改EFLAGS中VM位的指令均不能切换到V86模式。
(2)通过任务切换进入V86模式
通过任务切换的途径,可以从其它任务进入V86任务内的V86模式。
利用在前文介绍的任务切换的方法可以进行任务切换。
如果目标任务由386TSS描述,并且其中EFLAGS字段内的VM位为1,那么在切换到目标任务时,也就进入了V86模式。
在切换到V86模式时,CPL被规定为3。
目标任务TSS中的各段寄存器字段被解释为8086可以接受的段值,而不是选择子。
任务切换时也将装载LDTR和CR3。
程序在V86模式下执行时,EFLAGS寄存器中的NT位被忽略,所以,不能在V86模式下用IRET指令完成一个任务切换,并使其工作于V86以外的工作模式。
在V86模式下执行IRET指令时,将弹出IP、CS及FLAGS寄存器,以恢复被中断的程序,而不考虑NT位的值。
如果利用这条途径建立V86任务并进入V86模式,那么主要是把对应386TSS中EFLAGS字段内的VM位置1,把8086程序的有关段值填入对应386TSS中的相应段寄存器字段。
此外,如果V86监控程序需要用到LDT,那么还要填写LDTR字段;
如果需要采用分页机制,那么还要填写CR3字段(当新任务为V86模式的任务时,只装入段寄存器,而没有装入描述符投影寄存器的动作)。
三>
演示进入和离开V86模式的实例(实例十一)
下面给出一个用于演示进入和离开V86模式的实例。
该实例的逻辑功能是,以驻留方式结束程序,退出时已处于V86模式。
该实例演示内容包括:
两种方式进入V86模式和两种方式离开V86模式;
V86模式下的8086程序如何调用实模式下的软中断处理程序。
1.演示步骤和源程序清单
为了便于演示,本实例含有三个任务:
临时任务,V86任务和INTFF任务。
在实模式下做必要的初始化工作后切换到保护模式,也即进入临时任务,开始演示。
演示分两个阶段:
第一阶段进入V86任务的V86模式,并驻留退出;
第二阶段进入INTFF任务,切换到临时任务,并返回实模式。
第一阶段的演示步骤如下:
(1)开始临时任务后,作切换到V86任务的准备;
(2)切换到V86任务,由于V86任务TSS中的EFLAGS字段内的VM=1,所以伴随着任务切换就进入了V86模式。
(3)进入V86任务的V86模式后,显示提示信息,驻留结束,出现DOS提示符,第一阶段至此结束。
在V86模式下,可进行各种操作,运行其它8086程序。
如果8086程序引起通用保护异常,那么在屏幕上显示提示信息,并中止该8086程序。
如果在8086程序中执行“INT0FFH”指令,开始第二阶段。
第二阶段的演示步骤如下:
(1)进入INTFF任务后,显示提示信息,切换到临时任务;
(2)在临时任务内切换到实模式;
(3)在实模式下中止发出“INT0FFH”的程序
源程序由如下几部分组成:
(1)全局描述符表GDT;
(2)中断描述符表IDT(只适用于V86任务);
(3)INTFF任务的TSS段、LDT段、0级堆栈段和代码段;
(4)V86任务的TSS段、LDT段、0级堆栈段、3级堆栈段及数据段,通用保护异常处理程序段和其它中断/异常处理程序段,V86模式下的8086程序段;
(5)临时任务的TSS段和代码段;
(6)实模式下的初始化代码段及有关过程。
源程序清单如下:
;
名称:
ASM11.ASM
功能:
演示进入和离开V86方式
编译:
TASMASM11.ASM
连接:
TLINKASM11.OBJ
============================================================================
INCLUDE386SCD.INC
GDTSegSEGMENTPARAUSE16;
全局描述符表数据段(16位)
----------------------------------------------------------------------------
;
全局描述符表
GDTLABELBYTE
空描述符
DUMMYDesc<
>
规范段描述符及选择子
NormalDesc<
0ffffh,,,ATDW,,>
Normal_Sel=Normal-GDT
显示缓冲区数据段描述符及选择子
VideoDesc<
07fffh,8000h,0bh,ATDW,,>
Video_Sel=Video-GDT
EFFGDTLABELBYTE
V86任务TSS段描述符及选择子
V86TSSDesc<
V86TSSLen-1,V86TSSSeg,,AT386TSS,,>
V86TSS_Sel=V86TSS-GDT
V86任务局部描述符表的描述符及选择子
V86LDTDesc<
V86LDTLen-1,V86LDTSeg,,ATLDT,,>
V86LDT_Sel=V86LDT-GDT
IntFF任务TSS段描述符及选择子
IntFFTSSDesc<
IntFFTSSLen-1,IntFFTSSSeg,,AT386TSS,,>
IntFFTSS_Sel=IntFFTSS-GDT
IntFF任务局部描述符表的描述符及选择子
IntFFLDTDesc<
IntFFLDTLen-1,IntFFLDTSeg,,ATLDT,,>
IntFFLDT_Sel=IntFFLDT-GDT
临时任务的任务状态段描述符及选择子
TempTSSDesc<
TempTSSLen-1,TempTSSSeg,,AT386TSS,,>
TempTSS_Sel=TempTSS-GDT
临时任务代码段描述符及选择子
TempCodeDesc<
0ffffh,TempCodeSeg,,ATCE,,>
TempCode_Sel=TempCode-GDT
GDNum=($-EFFGDT)/(SIZEDesc);
需特殊处理的描述符数
GDTLen=$-GDT;
全局描述符表长度
GDTSegENDS;
全局描述符表段定义结束
IDTSegSEGMENTPARAUSE16;
V86任务使用的中断描述符表
IDTLABELBYTE
对应0--12号中断/异常的中断门描述符
REPT13
Gate<
TPCode_Sel,,AT386IGate+DPL3,>
ENDM
通用保护故障处理程序门描述符
GPBegin,GPCode_Sel,,AT386TGate+DPL3,>
对应14--254号中断/异常的中断门描述符
REPT241
对应255号中断的任务门描述符
IntFFTSS_Sel,,ATTaskGate+DPL3,>
IDTLen=$-IDT
IDTSegENDS;
中断描述符表段定义结束
IntFF任务的TSS段
IntFFTSSSegSEGMENTPARAUSE16
DD0;
链接字
0级堆栈指针(实例不使用)
DW0,0;
0级堆栈选择子(实例不使用)
1级堆栈指针(实例不使用)
1级堆栈选择子(实例不使用)
2级堆栈指针(实例不使用)
2级堆栈选择子(实例不使用)
CR3
DWIntFFBegin,0;
EIP
EFLAGS
EAX
ECX
EDX
EBX
DDIntFFStackLen;
ESP
EBP
ESI
EDI
DWNormal_Sel,0;
ES
DWIntFFCode_Sel,0;
CS
DWIntFFStack_Sel,0;
SS
DS
FS
GS
DWIntFFLDT_Sel,0;
LDTR
DW0;
调试陷阱标志
DW$+2;
指向I/O许可位图
DB0ffh;
I/O许可位图结束标志
IntFFTSSLen=$
IntFFTSSSegENDS
IntFF任务的LDT段
IntFFLDTSegSEGMENTPARAUSE16
FLDTLABELBYTE
0级堆栈段描述符及选择子
IntFFStackDesc<
IntFFStackLen-1,IntFFStackSeg,,ATDWA,,>
IntFFStack_Sel=IntFFStack-FLDT+TIL
代码段描述符及选择子
IntFFCodeDesc<
IntFFCodeLen-1,IntFFCodeSeg,,ATCER,,>
IntFFCode_Sel=IntFFCode-FLDT+TIL
IntFFLDNum=($-FLDT)/(SIZEDesc)
IntFFLDTLen=$
IntFFLDTSegENDS
IntFF任务的堆栈
IntFFStackSegSEGMENTPARAUSE16
IntFFStackLen=512
DBIntFFStackLenDUP(0)
IntFFStackSegENDS
IntFF任务的代码段
IntFFCodeSegSEGMENTPARAUSE16
ASSUMECS:
IntFFCodeSeg
IntFFMessDB'
Returntorealmode.'
IntFFMessLen=$-IntFFMess
IntFFBeginPROCFAR
movsi,OFFSETIntFFMess
movax,Video_Sel
moves,ax
movdi,0
movah,17h
movcx,IntFFMessLen
cld
INext:
moval,BYTEPTRcs:
[si]
incsi
stosw
loopINext
JUMP16TempTSS_Sel,0
IntFFBeginENDP
IntFFCodeLen=$
IntFFCodeSegENDS
V86任务的TSS段
V86TSSSegSEGMENTPARAUSE16
DDV86Stack0Len;
0级堆栈指针
DWV86Stack0_Sel,0;
0级堆栈选择子
DWV86Begin,0;
DDIOPL3ORVMFL;
EFLAGS(IO特权级为3,VM=1)
DDV86Stack3Len;
DWV86CodeSeg,0;
DWV86Stack3Seg,0;
DWV86LDT_Sel,0;
DB4000h/8DUP(0);
I/O许可位图
-------------------
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 虚拟 8086 模式