,4c00h
int 21h
Start ENDP
;---------------------------------------
Text ENDS
END Start
2.说明
(1)对IDT表的初始化
为了方便地书写IDT表,采用了重复汇编。从采用重复汇编方式定义的IDT表可见,除对应通用
保护异常的13号陷阱门描述符和255号任务门描述符外,其它中断门描述符内的偏移均未设定。
为此,在实模式下初始化时,把相应的入口偏移填入这些门描述符。从源程序可见,这些处理
程序的入口偏移也用重复汇编书写,并且字节数相同,所以间隔等长。
(2)任务切换方式进入V86模式
实例从临时任务切换到V86任务时进入V86模式。在V86任务的TSS中,EFLAGS字段内的VM=1,所
以伴随着任务切换,就进入了V86模式。为此,TSS中对应各段寄存器字段内的初始值都是V86模
式下要执行的8086程序各段的段值,而非选择子。由于在发生中断/异常时要进入V86任务的特
权级0,所以初始化了0级堆栈指针。V86任务使用局部描述符表LDT,所以TSS中对应字段填有相
应的选择子。
(3)V86模式下对中断的处理
实例对V86模式下响应中断和执行软中断指令“INT n”的处理方法是,转实模式下的对应中断
处理程序。具体步骤如下:
1)在V86模式堆栈(V86任务的3级堆栈)顶形成返回点的现场;
2)用实模式下对应的中断向量值代替返回地址;
3)从保护模式返回V86模式。由于堆栈中保存的EFLAGS内的VM=1,所以在保护模式下执
行IRET指令时,返回V86模式;由于在0级堆栈中保存的返回地址(段值和偏移)已被修改成实模
式下的中断向量,所以这时的返回也就是转入实模式下的对应中断处理程序;由于在V86堆栈顶
已安排了返回地址,所以在执行实模式下对应中断处理程序时,遇到IRET指令就返回到V86任务
的被中断处。这种处理方法似乎绕了个弯。但就是利用这个方法有效地调用了DOS功能,方便地
显示了提示信息“V86 is OK.”,顺利地实现了驻留退出。
这种处理方法没有充分考虑异常,更没有考虑异常时的出错码。
(4)V86任务的通用保护异常处理
在演示的第一阶段和第二阶段,不会发生任何异常。但在这两个阶段之间,由于允许执行其它
程序,可能引起异常。为了简单,实例只考虑了通用保护异常,而未考虑其它异常。该可能发
生异常的阶段是在V86模式下。如果发生通用保护异常,那么就转入V86任务的通用保护异常处
理程序。通用保护异常处理程序在保护模式下显示提示信息
“......General Protection Error......”,然后再转21H号中断处理程序,通过设置入口
参数AX=4C01H,中止引起通用保护异常的程序。
(5)INTFF任务
为了演示以任务切换方式离开V86模式,在实例中安排了这一任务,并称之为INTFF任务。由于
中断描述符表IDT中的255(0FFH)号描述符是任务门描述符,所以当在V86模式下执行软中断指
令“INT 0FFH”时便从V86模式切换到INTFF任务。INTFF任务的TSS是初始化好的,在INTFF任
务下不发生特权级变换,不使用局部描述符表LDT。INTFF任务先显示提示信息
“Return to real mode.”,然后再切换到临时任务。
<四>V86模式下的敏感指令
在V86模式下,CPL=3,执行特权指令时,或者要引起出错码为0的通用保护故障,或者要引起
非法操作码故障。
在V86模式下,输入/输出指令的敏感条件有所变化。指令CLI和STI的敏感条件不变,由于CPL=3,
所以如果IOPL<3,那么执行CLI或STI指令将引起通用保护故障。输入/输出指令IN、INS、OUT或OUTS的
敏感条件仅仅是当前V86任务TSS内的I/O许可位图,而忽略EFLAGS中的IOPL。输入/输出指
令IN、INS、OUT或OUTS是否可以执行与CPL是否小于IOPL无关,而直接由I/O许可位图对应位决
定,如果输入/输出指令所使用I/O地址对应的I/O许可位图内的各位都位0,则输入输出指令可
正常执行,否则引起通用保护故障。
此外,在V86模式下,指令PUSHF、POPF、INT n和IRET却对IOPL敏感。也就是说,在V86模式下,
当IOPL<3时,执行指令PUSHF、POPF、INT n及IRET会引起出错码为0的通用保护故障。
采取上述措施的目的是使操作系统软件可以支持一个“虚拟EFLAGS”寄存器。
|