<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-Hans-CN">
	<id>http://wiki.foofun.cn//index.php?action=history&amp;feed=atom&amp;title=Virtual_8086_Mode</id>
	<title>Virtual 8086 Mode - 版本历史</title>
	<link rel="self" type="application/atom+xml" href="http://wiki.foofun.cn//index.php?action=history&amp;feed=atom&amp;title=Virtual_8086_Mode"/>
	<link rel="alternate" type="text/html" href="http://wiki.foofun.cn//index.php?title=Virtual_8086_Mode&amp;action=history"/>
	<updated>2026-04-04T01:33:06Z</updated>
	<subtitle>本wiki上该页面的版本历史</subtitle>
	<generator>MediaWiki 1.37.1</generator>
	<entry>
		<id>http://wiki.foofun.cn//index.php?title=Virtual_8086_Mode&amp;diff=1006&amp;oldid=prev</id>
		<title>Zhang3：创建页面，内容为“虚拟8086模式是保护模式的子模式。 简而言之，虚拟8086模式是在保护模式下运行的CPU“模拟（Emulated）”得到的16位实模式机器。  == 进入V86 ==  当在EFLAGS寄存器中设置VM位（位17）为1时，CPU在虚拟86模式下执行。 如果要进入虚拟86模式，则必须将此位设置为1。 修改EFLAG寄存器的一种方法是使用pushf和popf指令。 这些指令分别推送和弹出堆栈…”</title>
		<link rel="alternate" type="text/html" href="http://wiki.foofun.cn//index.php?title=Virtual_8086_Mode&amp;diff=1006&amp;oldid=prev"/>
		<updated>2022-03-24T01:48:28Z</updated>

		<summary type="html">&lt;p&gt;创建页面，内容为“虚拟8086模式是&lt;a href=&quot;/index.php?title=Protected_mode&quot; class=&quot;mw-redirect&quot; title=&quot;Protected mode&quot;&gt;保护模式&lt;/a&gt;的子模式。 简而言之，虚拟8086模式是在保护模式下运行的CPU“模拟（Emulated）”得到的16位实模式机器。  == 进入V86 ==  当在EFLAGS寄存器中设置VM位（位17）为1时，CPU在虚拟86模式下执行。 如果要进入虚拟86模式，则必须将此位设置为1。 修改EFLAG寄存器的一种方法是使用pushf和popf指令。 这些指令分别推送和弹出堆栈…”&lt;/p&gt;
&lt;p&gt;&lt;b&gt;新页面&lt;/b&gt;&lt;/p&gt;&lt;div&gt;虚拟8086模式是[[Protected mode|保护模式]]的子模式。 简而言之，虚拟8086模式是在保护模式下运行的CPU“模拟（Emulated）”得到的16位实模式机器。&lt;br /&gt;
&lt;br /&gt;
== 进入V86 ==&lt;br /&gt;
&lt;br /&gt;
当在EFLAGS寄存器中设置VM位（位17）为1时，CPU在虚拟86模式下执行。 如果要进入虚拟86模式，则必须将此位设置为1。&lt;br /&gt;
修改EFLAG寄存器的一种方法是使用pushf和popf指令。 这些指令分别推送和弹出堆栈上的eflags寄存器。 所以你可以向栈推入寄存器，在堆栈上修改它，然后弹出它。 但是popf指令不会修改eblags寄存器中的位16和17。&lt;br /&gt;
设置VM标志的唯一方法是使用iret指令。 此指令通常用于从中断返回。 执行iret时，CPU会从堆栈中弹出eip，cs，eflags，esp，ss，并在新的eip上继续执行。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
; 您应该将此函数声明为：&lt;br /&gt;
; extern void enter_v86(uint32_t ss, uint32_t esp, uint32_t cs, uint32_t eip);&lt;br /&gt;
enter_v86:&lt;br /&gt;
   mov ebp, esp               ; 保存堆栈指针&lt;br /&gt;
&lt;br /&gt;
   push dword  [ebp+4]        ; ss&lt;br /&gt;
   push dword  [ebp+8]        ; esp&lt;br /&gt;
   pushfd                     ; eflags&lt;br /&gt;
   or dword [esp], (1 &amp;lt;&amp;lt; 17)  ; 设置VM标志&lt;br /&gt;
   push dword [ebp+12]        ; cs&lt;br /&gt;
   push dword  [ebp+16]       ; eip&lt;br /&gt;
   iret&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==V86问题==&lt;br /&gt;
&lt;br /&gt;
v86模式最常见的问题是无法从v86任务内部进入保护模式。 换句话说，如果您正在运行Windows或内存中有emm386，则不能将“原始(raw)”切换到保护模式(这会导致异常)。 DOS extenders使用VCPI或DPMI接口切换到pmode来解决这个问题 (实际上，将其V86任务提升为 “常规” 用户任务)。 对于操作系统程序员来说，这样的接口毫无用处，因为它们是DOS操作系统的一部分。&lt;br /&gt;
&lt;br /&gt;
人们在使用v86模式时还有一些其他的“技术”问题，主要是因为v86有一些指令是由v86监控程序（v86-monitor program）“模拟”产生的，因为CPU处于保护模式，有些指令在安全/保护级别上很高，直接运行这些指令会给操作系统带来无穷无尽的麻烦。&lt;br /&gt;
&lt;br /&gt;
== 检测V8086 ==&lt;br /&gt;
&lt;br /&gt;
EFLAGS.在V86任务中使用PUSHFD，VM永远不会被推到栈上。 您需要首先检查CR0。PE=1，如果该位被设置1，才假定它是V86。（译者注：CR0的PE位是保护模式启用位）&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
detect_v86:&lt;br /&gt;
   smsw    ax&lt;br /&gt;
   and     eax,1           ;CR0.PE bit&lt;br /&gt;
   ret&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
VM模式检测主要用于编写DOS extenders或其他程序，这些程序可以从受保护模式系统以纯实模式或虚拟模式启动。 “普通的”bootloader不应该担心这一点，因为BIOS不会设置VM86来读取引导扇区。  ;)&lt;br /&gt;
&lt;br /&gt;
== 用法 ==&lt;br /&gt;
如果需要在保护模式下访问BIOS功能，VM86非常有用。 实际上，例如设置视频模式（video mode）时是必要的，因为许多现代的视频卡卡/芯片组缺乏对VBE3保护模式接口的支持， 因此，设置一个VM86任务来执行“设置视频模式”调用是首选方法。&lt;br /&gt;
&lt;br /&gt;
== 1MB以下的内核 ==&lt;br /&gt;
建议将内核映射到“高”逻辑地址（例如0xC0000000），以避免VM86任务干扰它。 对于1MB以下没有空间容纳VM86代码的大型内核，或者当更大的程序预计将在VM86机器中运行时，这一点尤其重要。&lt;br /&gt;
&lt;br /&gt;
如果进入VM86模式，所需要的只是BIOS中断包装器，则应执行以下操作:&lt;br /&gt;
# 确保16位代码与任何32位代码位于单独的页面上&lt;br /&gt;
# 启用分页&lt;br /&gt;
# 使DPL3的内核页面不可写 (也不可读？)，并仅允许用户访问包含16位代码的页面和包含BIOS代码或数据的页面。&lt;br /&gt;
&lt;br /&gt;
== 使用VM86访问磁盘 ==&lt;br /&gt;
虽然理论上是可能的，但这可能不是一个好主意。大多数BIOS磁盘访问将包括IRQ处理程序、DMA传输(无法从VM monitor中进行控制)、 并且可能会在BIOS等待中断响应时停留在VM86任务中，而 “好的” 驱动程序应使CPU可以用于其他进程。&lt;br /&gt;
&lt;br /&gt;
Windows 9x在访问磁盘时遭遇系统冻结。 通常是由于INT13-through-VM86问题导致的。&lt;br /&gt;
&lt;br /&gt;
== 另见 ==&lt;br /&gt;
===文章===&lt;br /&gt;
*[[Virtual Monitor]]&lt;br /&gt;
=== 论坛主题 ===&lt;br /&gt;
*[[Topic:8437|Creating vm86 task]]&lt;br /&gt;
*[[Topic:8477|VM86 and INT10h]]&lt;br /&gt;
*[[Topic:8949|kernel location &amp;amp; VM86]]&lt;br /&gt;
===外部链接===&lt;br /&gt;
*{{IntelManualLink|15}}&lt;br /&gt;
*http://osdev.berlios.de/v86.html - by Tim Robinson ([https://web.archive.org/web/20140111115023/http://osdev.berlios.de/v86.html Wayback Machine Link])&lt;br /&gt;
*[http://my.execpc.com/~geezer/osd/pmode/v86mm.zip A virtual-8086 mode monitor] - by Chris Giese&lt;br /&gt;
*[http://126.sytes.net/tmp/x86emu.zip x86emu] - a BSD style licensed vitual-8086 mode ''emulator'' - very different from a ''monitor''.&lt;br /&gt;
*[http://gitorious.org/x86emu/] - x86emu and several other projects. See mdt for code getting VBE modes.&lt;br /&gt;
*[http://www.rohitab.com/discuss/topic/35103-switch-between-real-mode-and-protected-mode/ Protected Mode BIOS Call Functionailty v2.0] - by Napalm&lt;br /&gt;
[[Category:X86 CPU]]&lt;br /&gt;
[[Category:Operating Modes]]&lt;br /&gt;
[[de:Virtual_8086_Mode]]&lt;/div&gt;</summary>
		<author><name>Zhang3</name></author>
	</entry>
</feed>