通行证│用户名: 密码: 验证码: 验证码,看不清楚?请点击刷新验证码 电信网通铁通移动   在线
资源搜索:
热门搜索:Linux VB C语言 PhotoShop Flash TCP/IP
   首页 | 文章 | 软件 | 动画 | 资源 | 励志 | 骗术 | 论坛 | 邮箱 | 会员中心 | 军事 | 科技 | 博客 | 图片 | 商城 | 最新更新 | 800g资源 | 爱心黑客
您现在的位置: 爱国者黑客 >> 资源 >> 程序设计 >> 汇编语言 >> 基础教程 >> 文章正文
虚拟8086模式
责任编辑:admin   更新日期:2005-8-6
    继推出80386之后,Intel又推出了80386、Pentium和Pentium PRO。这些处理器都具有 实模式和保护模式两种工作方式。前面已介绍过,实模式与8086兼容,可以运行DOS及 以其为平台的几乎所有软件;但在实模式下,处理器不能发挥自身的优越性能,不能支 持多用户、多任务操作系统的运行。为了充分发挥处理器的功能,同时使DOS及以其为 平台的软件继续有效地运行,从80386开始增加了虚拟8086模式。本文将介绍虚拟8086模式。

<一>V86模式

1.V86模式

    虚拟8086模式是保护模式下的一种工作方式,也称为V8086模式,或者简称为V86模式。在 虚拟8086模式下,处理器类似于8086。寻址的地址空间是1M字节;段寄存器的内容作为段 值解释;20位存储单元地址由段值乘以16加偏移构成。在V86模式下,代码段总是可写的, 这与实模式相同,同理,数据段也是可执行的,只不过可能会发生异常。所以,在虚 拟8086模式下,可以运行DOS及以其为平台的软件。但V86模式毕竟是虚拟8086的一种方 式,所以不完全等同于8086。
    当标志寄存器中的VM位为1时,处理器就处于V86模式。此时,其当前特权级由处理器自动 设置为3。

2.V86任务

    8086程序可以直接在V86模式下运行,而V86模式受到称为V86监控程序的控制。V86监控程 序和在V86模式下的8086程序构成的任务称为虚拟8086任务,或者简称为V86任务。V86任务 形成一个由处理器硬件和属于系统软件的监控程序组成的“虚拟8086机”。V86监控程序控 制V86外部界面、中断和I/O。硬件提供该任务最低端1M字节线性地址空间的虚拟存储空间, 包含虚拟寄存器的TSS,并执行处理这些寄存器和地址空间的指令。
    80386把V86任务作为与其它任务具有同等地位的一个任务。它可以支持多个V86任务,每 个V86任务是相对独立的。所以,通过V86模式这种形式,运行8086程序可充分发挥处理器 的能力和充分利用系统资源。

<二>进入和离开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程序中执行“INT 0FFH”指令,开始第二 阶段。第二阶段的演示步骤如下:
    (1)进入INTFF任务后,显示提示信息,切换到临时任务;
    (2)在临时任务内切换到实模式;
    (3)在实模式下中止发出“INT 0FFH”的程序
    源程序由如下几部分组成:
    (1)全局描述符表GDT;
    (2)中断描述符表IDT(只适用于V86任务);
    (3)INTFF任务的TSS段、LDT段、0级堆栈段和代码段;
    (4)V86任务的TSS段、LDT段、0级堆栈段、3级堆栈段及数据段,通用保护异常处理程序 段和其它中断/异常处理程序段,V86模式下的8086程序段;
    (5)临时任务的TSS段和代码段;
    (6)实模式下的初始化代码段及有关过程。
源程序清单如下:

;名称:ASM11.ASM

;功能:演示进入和离开V86方式

;编译:TASM ASM11.ASM

;连接:TLINK ASM11.OBJ

;============================================================================

INCLUDE         386SCD.INC

;============================================================================

GDTSeg          SEGMENT PARA USE16                ;全局描述符表数据段(16位)

;----------------------------------------------------------------------------

                ;全局描述符表

GDT             LABEL   BYTE

                ;空描述符

DUMMY           Desc    <>

                ;规范段描述符及选择子

Normal          Desc    <0ffffh,,,ATDW,,>

Normal_Sel      =       Normal-GDT

                ;显示缓冲区数据段描述符及选择子

Video           Desc    <07fffh,8000h,0bh,ATDW,,>

Video_Sel       =       Video-GDT

;----------------------------------------------------------------------------

EFFGDT          LABEL   BYTE

                ;V86任务TSS段描述符及选择子

V86TSS          Desc    <V86TSSLen-1,V86TSSSeg,,AT386TSS,,>

V86TSS_Sel      =       V86TSS-GDT

                ;V86任务局部描述符表的描述符及选择子

[1] [2] [3] [4] [5] [6] 下一页

  • 上一篇文章:
  • 下一篇文章:
  • 热门文章
    Olldbg常见问题
    汇编语言的艺术(组合语言的艺术)--观
    汇编语言的艺术(组合语言的艺术)--准
    汇编语言的艺术(组合语言的艺术)--基
    汇编语言的艺术(组合语言的艺术)--基
    汇编语言---程式设计 (4)
    虚拟8086模式
    SYS命令使用说明
    javascript + CSS 实现动态菜单显
    推荐文章
    自制Windows XP SP2自动安装光盘
    SQLServer注入工具改进版 v1.02
    使用photoshop CS进行自然美肤
    Photoshop绘制诺基亚手机
    PHOTOSHOP制作秋日之梦
    PHOTOSHOP鼠绘名模王爱萍
    Photoshop制作晶莹飞溅的水珠
    教你用PHOTOSHOP做放大镜
    鼠绘美女及服装修画全过程