Beruflich Dokumente
Kultur Dokumente
22
Virtual-8086 Mode
E
CHAPTER 22
VIRTUAL-8086 MODE
The Pentium processor supports execution of one or more 8086 or 8088 programs in a
Pentium processor protected-mode environment. An 8086 program runs in this environment
as part of a virtual-8086 task. Virtual-8086 tasks take advantage of the hardware support for
multitasking offered by the protected mode. Not only can there be multiple virtual-8086
tasks, each one running an 8086 program, but virtual-8086 tasks can be multitasked with
other Pentium processor tasks.
The purpose of a virtual-8086 task is to form a "virtual machine" for running programs
written for the 8086 processor. A complete virtual machine consists of hardware and system
software. The emulation of an 8086 processor is the result of software using hardware in the
following ways:
• The hardware provides a virtual set of registers (through the TSS), a virtual memory
space (the first megabyte of the linear address space of the task), and virtual interrupt
support and directly executes all instructions which deal with these registers and with
this address space.
• The software controls the external interfaces of the virtual machine (I/O, interrupts, and
exceptions) in a manner consistent with the larger environment in which it runs.
Software can choose to emulate I/O and interrupt and exception handling or let the
hardware execute them directly without software intervention.
Software which supports virtual 8086 machines is called a virtual-8086 monitor. The
Pentium processor includes extensions to its virtual-8086 mode of operation that improve the
performance of applications by eliminating the overhead of faulting to a virtual-8086 monitor
for emulation of certain operations. For more information on the virtual mode extensions on
the Pentium processor, see Appendix H.
22-1
VIRTUAL-8086 MODE E
22.1.1. Registers and Instructions
The register set available in virtual-8086 mode includes all the registers defined for the 8086
processor plus new registers introduced after the 8086 processor (FS and GS). Instructions,
which explicitly operate on the segment registers FS and GS, are available. The segment-
override prefixes can be used to cause instructions to use the FS and GS registers for address
calculations. Instructions can take advantage of 32-bit operands through the use of the
operand size prefix.
Programs running as virtual-8086 tasks can take advantage of the new application-oriented
instructions added to the architecture by the introduction of the Intel 286, Intel386, Intel486,
and Pentium processors:
• New instructions introduced on the Intel 286 processors.
PUSH immediate data
Push all and pop all (PUSHA and POPA)
Multiply immediate data
Shift and rotate by immediate count
String I/O
ENTER and LEAVE instructions
BOUND instruction
• New instructions introduced on the Intel386 processors.
LSS, LFS, LGS instructions
Long-displacement conditional jumps
Single-bit instructions
Bit scan instructions
Double-shift instructions
Byte set on condition instruction
Move with sign/zero extension
Generalized multiply instruction
• New instructions introduced on the Intel486 processor.
BSWAP instruction
XADD instruction
CMPXCHG instruction
• New instructions introduced on the Pentium processor.
CMPXCHG8B instruction
CPUID instruction
22-2
E VIRTUAL-8086 MODE
19 3 0
+
19 15 0
=
20 0
LINEAR
X X X X X X X X X X X X X X X X X X X X X
ADDRESS
APM52
22-3
VIRTUAL-8086 MODE E
22.2. STRUCTURE OF A VIRTUAL-8086 TASK
A virtual-8086 task consists of the 8086 program to be run and the 32-bit "native mode" code
which serves as the virtual-machine monitor. The task must be represented by a 32-bit TSS
(not a 16-bit TSS). The processor enters virtual-8086 mode to run the 8086 program and
returns to protected mode to run the monitor or other 32-bit protected-mode tasks.
To run in virtual-8086 mode, an existing 8086 processor program needs the following:
• A virtual-8086 monitor.
• Operating-system services.
The virtual-8086 monitor is 32-bit protected-mode code which runs at privilege-level 0 (most
privileged). The monitor mostly consists of initialization, exception-handling procedures, and
I/O emulation in order to virtualize the PC platform. As with any other Pentium processor
program, code-segment descriptors for the monitor must exist in the GDT or in the task's
LDT. The linear addresses above 10FFEFH are available for the virtual-8086 monitor, the
operating system, and other system software. The monitor also may need data-segment
descriptors so it can examine the interrupt vector table or other parts of the 8086 program in
the first megabyte of the address space.
In general, there are two options for implementing the 8086 operating system:
1. The 8086 operating system may run as part of the 8086 program. This approach is
desirable for either of the following reasons:
The 8086 application code modifies the operating system.
There is not sufficient development time to reimplement the 8086 operating system
as a Pentium processor operating system.
2. The 8086 operating system may be implemented or emulated in the virtual-8086
monitor. This approach is desirable for any of the following reasons:
Operating system functions can be more easily coordinated among several virtual-
8086 tasks.
The functions of the 8086 operating system can be easily emulated by calls to the
Pentium processor operating system.
Note that the approach chosen for implementing the 8086 processor operating system may
have different virtual-8086 tasks using different 8086 operating systems.
22-4
E VIRTUAL-8086 MODE
• Emulating the address wraparound which occurs at 1 megabyte. With members of the
8086 family, it is possible to specify addresses larger than 1 megabyte. For example,
with a selector value of 0FFFFH and an offset of 0FFFFH, the effective address would
be 10FFEFH (1 megabyte plus 65519 bytes). The 8086 processor, which can form
addresses only up to 20 bits long, truncates the high-order bit, thereby "wrapping" this
address to 0FFEFH. The Pentium processor, however, does not truncate such an address.
If any 8086 processor programs depend on address wraparound, the same effect can be
achieved in a virtual-8086 task by mapping linear addresses between 100000H and
110000H and linear addresses between 0 and 10000H to the same physical addresses.
• Creating a virtual address space larger than the physical address space.
• Sharing 8086 operating system or ROM code which is common to several 8086
programs running in multitasking.
• Redirecting or trapping references to memory-mapped I/O devices.
22-5
VIRTUAL-8086 MODE E
8086 procedure. The CPL at the time the IRET instruction is executed must be 0,
otherwise the processor does not change the state of the VM flag.
MODE TRANSITION DIAGRAM
INTERRUPT, EXCEPTION
V86 MONITOR
8086 PROGRAM
(PROTECTED
(V86 MODE) IRET
MODE)
TASK TASK
SWITCH SWITCH
OTHER CPU TASKS
(PROTECTED MODE)
TASK SWITCH TASK SWITCH
APM53
When a task switch is used to enter virtual-8086 mode, the segment registers are loaded from
a TSS. When an IRET instruction is used to set the VM flag, however, the segment registers
are loaded from the segment registers on the PL0 stack (see Figure 22-3).
The processor leaves virtual-8086 mode when an interrupt or exception occurs. There are two
cases:
1. The interrupt or exception causes a task switch. A task switch from a virtual-8086 task to
any other task loads the EFLAGS register from the TSS of the new task. If the new TSS
is a 32-bit TSS and the VM flag in the new contents of the EFLAGS register is clear or if
the new TSS is a 16-bit TSS, the processor clears the VM flag of the EFLAGS register,
loads the segment registers from the new TSS using protected-mode address formation,
and begins executing the instructions of the new task in 32-bit protected mode.
2. The interrupt or exception calls a privilege-level 0 procedure (most privileged). The
processor stores the current contents of the EFLAGS register on the stack, then clears the
VM flag. The interrupt or exception handler, therefore, runs as "native" 32-bit protected-
mode code. If an interrupt or exception calls a procedure in a conforming segment or in a
segment at a privilege level other than 0 (most privileged), the processor generates a
general-protection exception; the error code is the selector of the code segment to which
a call was attempted.
22-6
E VIRTUAL-8086 MODE
OLD FS OLD FS
OLD DS OLD DS
OLD ES OLD ES
OLD SS OLD SS
OLD CS OLD CS
APM54
System software does not change the state of the VM flag directly, but instead changes states
in the image of the EFLAGS register stored on the stack or in the TSS. The virtual-8086
monitor sets the VM flag in the EFLAGS image on the stack or in the TSS when first
creating a virtual-8086 task. Exception and interrupt handlers can examine the VM flag on
the stack. If the interrupted procedure was running in virtual-8086 mode, the handler may
need to call the virtual-8086 monitor.
22-7
VIRTUAL-8086 MODE E
22.3.2. Transitions Through Trap Gates and Interrupt Gates
The processor may leave virtual-8086 mode as the result of an exception or interrupt which
calls a trap or interrupt gate. The exception or interrupt handler returns to the 8086 program
by executing an IRET instruction.
Exceptions and interrupts can be handled in one of three ways:
1. By the the virtual-8086 monitor.
2. The virtual-8086 monitor can pass control to the 8086 program's interrupt handler.
3. By a protected-mode interrupt service routine.
If the interrupt or exception is one which the monitor needs to handle and the VM flag is set
in the EFLAGS image stored on the stack, the interrupt handler passes control to the virtual-
8086 monitor. The virtual-8086 monitor may choose one of the first two methods listed
above. If the exception or interrupt is one which the monitor does not need to handle, the
IOPL can be set to 3 allowing the protected-mode interrupt handler to execute for all virtual-
mode interrupts.
Because it was designed to run on an 8086 processor, an 8086 program in a virtual-8086 task
has an 8086-style interrupt table, which starts at linear address 0. However, for exceptions
and interrupts requiring virtual-8086 monitor intervention and a transition into protected
mode, the processor does not use this table directly. Instead, the processor calls handlers
through the IDT. The IDT entry for an interrupt or exception in a virtual-8086 task must
contain either:
• A task gate.
• A 32-bit trap gate (descriptor type 14) or 32-bit interrupt gate (descriptor type 15), which
must point to a nonconforming, privilege-level 0 (most privileged), code segment.
Interrupts and exceptions which call 32-bit trap or interrupt gates use privilege-level 0. The
contents of the segment registers are stored on the stack for this privilege level. Figure 22-3
shows the format of this stack after an exception or interrupt which occurs while a virtual-
8086 task is running an 8086 program.
After the processor saves the 8086 segment registers on the stack for privilege level 0, it
clears the segment registers before running the handler procedure. This lets the interrupt
handler safely save and restore the DS, ES, FS, and GS registers as though they were
Pentium processor selectors. Interrupt handlers, which may be called in the context of either
a regular task or a virtual-8086 task, can use the same code sequences for saving and
restoring the registers for any task. Clearing these registers before execution of the IRET
instruction does not cause a trap in the interrupt handler. Interrupt procedures which expect
values in the segment registers or which return values in the segment registers must use the
register images saved on the stack for privilege level 0. Interrupt handlers which need to
know whether the interrupt occurred in virtual-8086 mode can examine the VM flag in the
stored contents of the EFLAGS register.
Sending an interrupt or exception back to the 8086 program involves the following steps:
1. Use the 8086 interrupt vector to locate the appropriate handler procedure.
22-8
E VIRTUAL-8086 MODE
2. Store the FLAGS, CS and IP values of the 8086 program on the privilege-level 3 stack
(least privileged).
3. Change the return link on the privilege-level 0 stack to point to the privilege-level 3
handler procedure.
4. Execute an IRET instruction to pass control to the handler.
5. When the IRET instruction from the privilege-level 3 handler again calls the virtual-
8086 monitor, restore the return link on the privilege-level 0 stack to point to the
original, interrupted, privilege-level 3 procedure.
6. Execute an IRET instruction to pass control back to the interrupted procedure.
If the IOPL is set to three and the DPL of the interrupt gate is set to three, INT n instructions
will trap with the given vector number n. Interrupt vectors that must have their IDT gates set
to three can examine the VM bit in the EFLAGS image on the stack to determine if the
interrupt needs to be redirected to the virtual-8086 monitor or passed to the 8086 program's
interrupt handler.
22-9
VIRTUAL-8086 MODE E
monitor for emulation on these processors. For more information on Pentium processor
support of a virtual interrupt flag, see Appendix H.
22-10
E VIRTUAL-8086 MODE
The processor provides I/O protection for creating I/O which is compatible with the
environment and transparent to 8086 programs. Designers may take any of several possible
approaches to protecting I/O ports:
• Protect the I/O address space and generate exceptions for all attempts to perform I/O
directly.
• Let the 8086 processor program perform I/O directly.
• Generate exceptions on attempts to access specific I/O ports.
• Generate exceptions on attempts to access specific memory-mapped I/O ports.
The method of controlling access to I/O ports depends upon whether they are I/O-mapped or
memory-mapped.
22-11
VIRTUAL-8086 MODE E
22.7.3. Special I/O Buffers
Buffers of intelligent controllers (for example, a bit-mapped frame buffer) also can be
emulated using page mapping. The linear space for the buffer can be mapped to a different
physical space for each virtual-8086 task. The virtual-8086 monitor then can control which
virtual buffer to copy onto the real buffer in the physical address space.
22-12
E VIRTUAL-8086 MODE
generated if the limit on instruction length is violated. The 8086 processor has no
instruction length limit.
7. Operand crossing offset 0 or 65,535.
On the 8086 processor, an attempt to access a memory operand which crosses offset
65,535 (e.g., MOV a word to offset 65,535) or offset 0 (e.g., PUSH a word when the
contents of the SP register are 1) causes the offset to wrap around modulo 65,536. The
Pentium processor generates an exception in these cases, a general-protection exception
if the segment is a data segment (i.e., if the CS, DS, ES, FS, or GS register is being used
to address the segment), or a stack exception if the segment is a stack segment (i.e., if the
SS register is being used).
8. Sequential execution across offset 65,535.
On the 8086 processor, if sequential execution of instructions proceeds past offset
65,535, the processor fetches the next instruction byte from offset 0 of the same segment.
On the Pentium processor, the processor generates a general-protection exception.
9. LOCK is restricted to certain instructions.
The LOCK prefix and its output signal should only be used to prevent other bus masters
from interrupting a data movement operation. The LOCK prefix only may be used with
the following Pentium processor instructions when they modify memory. An invalid-
opcode exception results from using LOCK before any other instruction, or with these
instructions when no write operation is made to memory.
Bit test and change: the BTS, BTR, and BTC instructions.
Exchange: the XCHG, XADD, CMPXCHG, and CMPXCH8B instructions (no
LOCK prefix is needed for the XCHG instruction).
One-operand arithmetic and logical: the INC, DEC, NOT, NEG instructions
Two-operand arithmetic and logical: the ADD, ADC, SUB, SBB, AND, OR, and
XOR instructions.
10. Single-stepping external interrupt handlers.
The priority of the Pentium processor single-step exception is different from that of the
8086 processor. This change prevents an external interrupt handler from being single-
stepped if the interrupt occurs while a program is being single-stepped. The Pentium
processor single-step exception has higher priority than any external interrupt. The
Pentium processor will still single-step through an interrupt handler called by the INT
instruction or by an exception.
11. IDIV exceptions for quotients of 80H or 8000H.
The Pentium processor can generate the largest negative number as a quotient from the
IDIV instruction. The 8086 processor generates a divide-error exception instead.
12. Flags in stack.
The contents of the EFLAGS register stored by the PUSHF instruction, by interrupts, and
by exceptions is different from that stored by the 8086 processor in bit positions 12
through 15. On the 8086 processor these bits are stored as though they were set, but in
virtual-8086 mode bit 15 is always clear, and bits 14 through 12 have the last value
loaded into them.
22-13
VIRTUAL-8086 MODE E
13. NMI interrupting NMI handlers.
After an NMI interrupt is accepted by the Pentium processor, the NMI interrupt is
masked until an IRET instruction is executed.
14. Floating-point errors call the floating-point error exception.
Floating-point exceptions on the Pentium processor call the floating-point error
exception handler. If an 8086 processor uses another exception for the 8087 interrupt,
both exception vectors should call the floating-point error exception handler. The
Pentium processor has signals which, with the addition of external logic, support user-
defined error reporting for emulation of the interrupt mechanism used in many personal
computers.
15. Numeric exception handlers should allow prefixes.
On the Pentium processor, the value of the CS and IP registers saved for floating-point
exceptions points at any prefixes which come before the ESC instruction. On the 8086
processor, the saved CS:IP points to the ESC instruction.
16. Floating-Point Unit does not use interrupt controller.
The floating-point error signal to the Pentium processor does not pass through an
interrupt controller (an INT signal from 8087 coprocessor does). Some instructions in a
coprocessor-error exception handler may need to be deleted if they use the interrupt
controller. The Pentium processor has signals which, with the addition of external logic,
support user-defined error reporting for emulation of the interrupt mechanism used in
many personal computers.
17. Response to bus hold.
Unlike the 8086 and Intel 286 processors, the Pentium processor responds to requests for
control of the bus from other potential bus masters, such as DMA controllers, between
transfers of parts of an unaligned operand, such as two words which form a doubleword.
18. CPL is 3 in virtual-8086 mode.
The 8086 processor does not support protection, so it has no CPL. Virtual-8086 mode
uses a CPL of 3, which prevents the execution of privileged instructions. These are:
LIDT instruction
LGDT instruction
LMSW instruction
Special forms of the MOV instruction for loading and storing the control registers
CLTS instruction
HLT instruction
INVD instruction
WBINVD instruction
INVLPG instruction
RDMSR instruction
WRMSR instruction
22-14
E VIRTUAL-8086 MODE
RSM instruction
These instructions may be executed while the processor is in real-address mode
following reset initialization. They allow system data structures, such as descriptor
tables, to be set up before entering protected mode. Since virtual-8086 mode is entered
from protected mode, these structures will already be set up.
19. Denormal exception handling is different. See Chapter 23 for details on exception
handling differences.
22-15
VIRTUAL-8086 MODE E
22.9.2. Bus Lock
The Intel 286 processor implements the bus lock function differently than the Intel386,
Intel486, and Pentium processors. This fact may or may not be apparent to 8086 programs,
depending on how the virtual-8086 monitor handles the LOCK prefix. Instructions with the
LOCK prefix are sensitive to the IOPL; software designers can choose to emulate its
function. If, however, 8086 programs are allowed to execute LOCK directly, programs which
use forms of memory locking specific to the 8086 processor may not run properly when run
on the Pentium and other 32-bit processors.
The LOCK prefix and its bus signal only should be used to prevent other bus masters from
interrupting a data movement operation. The LOCK prefix only may be used with the
following Pentium CPU instructions when they modify memory. An invalid-opcode
exception results from using the LOCK prefix before any other instruction, or with these
instructions when no write operation is made to memory (i.e., when the destination operand
is in a register).
• Bit test and change: the BTS, BTR, and BTC instructions.
• Exchange: the XCHG, XADD, and CMPXCHG instructions (no LOCK prefix is needed
for the XCHG instruction).
• One-operand arithmetic and logical: the INC, DEC, NOT, NEG instructions.
• Two-operand arithmetic and logical: the ADD, ADC, SUB, SBB, AND, OR, and XOR
instructions.
A locked instruction is guaranteed to lock only the area of memory defined by the destination
operand, but may lock a larger memory area. For example, typical 8086 and Intel 286
configurations lock the entire physical memory space.
Unlike the 8086 and Intel 286 processors, the Intel386, Intel486 and Pentium processors
respond to requests for control of the bus from other potential bus masters, such as DMA
controllers, between transfers of parts of an unaligned operand, such as two words which
form a doubleword.
22-16