Virtual 8086 Mode: Difference between revisions

m
Bot: Replace deprecated source tag with syntaxhighlight
[unchecked revision][unchecked revision]
m (Improved grammar and spelling.)
m (Bot: Replace deprecated source tag with syntaxhighlight)
 
(4 intermediate revisions by 4 users not shown)
Line 3:
==Entering V86==
 
The CPU is executing in virtual 86 mode when the VM bit (bit 17) is set in the ''EFLAGS'' register. If you want to enter virtual 86 mode you must set this bit to 1.
A way of modifying the EFLAGEFLAGS register is to use the pushf''PUSHF'' and popf''POPF'' instructions., but Thesethese instructions respectivelyare pushfor user space and popcannot modify supervisor flags. The only way to set the eflagsVM registerflag onis to use the stackiret instruction. SoThis youinstruction couldis pushnormally theused register,to modifyreturn itfrom onan interrupt. When ''IRET'' is called with the VM=1 in the stack and''EFLAGS'' pop(the it.context Butbeing returned to is V86), the popfinterrupt instructionstack doesn'tframe modifywill bitscontain 16segments ''ES'', ''DS'', ''FS'', and 17''GS'', inso thethat eflagsthey registercan be set before entry.
The only way to set the VM flag is to use the iret instruction. This instruction is normally used to return from an interrupt. When executing an iret, the CPU pops eip, cs, eflags, esp, ss from the stack and continues executing at the new eip.
 
A task gate can also be used to enter V86. This allows setting the segment registers. It is probably not necessary to do it this way unless the OS is using hardware multitasking.
<pre>
; you should declare this function as :
; extern void enter_v86(uint32_t ss, uint32_t esp, uint32_t cs, uint32_t eip);
enter_v86:
mov ebp, esp ; save stack pointer
 
[[File:Fig15-3.gif]]
push dword [ebp+4] ; ss
push dword [ebp+8] ; esp
pushfd ; eflags
or dword [esp], (1 << 17) ; set VM flags
push dword [ebp+12] ; cs
push dword [ebp+16] ; eip
iret
</pre>
 
==V86 Problem==
Line 32 ⟶ 20:
EFLAGS.VM is NEVER pushed onto the stack if the V86 task uses PUSHFD. You should check if CR0.PE=1 and then assume it's V86 if that bit is set.
 
<syntaxhighlight lang="asm">
<pre>
detect_v86:
smsw ax
and eax,1 ;CR0.PE bit
ret
</syntaxhighlight>
</pre>
 
VM mode detection is mainly useful when writing DOS extenders or other programs that could be started either in plain real mode or in virtual mode from a protected mode system. An 'ordinary' bootloader shouldn't worry about this since the BIOS will not set up VM86 to read the bootsector ;)