实模式和保护模式(附i386/x86的由来)
实模式: (即实地址访问模式)它是 Intel公司 80286及以后的 x86(80386,80486和 80586等 )兼容处理器( CPU)的一种操作模式。实模式被特殊定义为 20位地址内存可访问空间上,这就意味着它的容量是 2的 20次幂( 1M)的可访问内存空间(物理内存和 BIOS-ROM),软件可通过这些地址直接访问 BIOS程序和外围硬件。实模式下处理器没有硬件级的内存保护概念和多道任务的工作模式。但是为了向下兼容,所以 80286及以后的 x86系列兼容处理器仍然是开机启动时工作在实模式下。 80186和早期的处理器仅有一种操作模式,就是后来我们所定义的实模式。实模式虽然能访问到 1M的地址空间,但是由于 BIOS的映射作用(即 BIOS占用了部分空间地址资源),所以真正能使用的物理内存空间(内存条),也就是在 640k到 924k之间。 1M 地址空间组成是由 16位的段地址和 16位的段内偏移地址组成的。用公式表示为:物理地址 =左移 4位的段地址 +偏移地址。
286处理器体系结构引入了地址保护模式的概念,处理器能够对内存及一些其他外围设备做硬件级的保护设置(保护设置实质上就是屏蔽一些地址的访问)。使用这些新的特性,然而必不可少一些额外的在 80186及以前处理器没有的操作规程。自从最初的 x86微处理器规格以后,它对程序开发完全向下兼容,80286芯片被制作成启动时继承了以前版本芯片的特性,工作在实模式下,在这种模式下实际上是关闭了新的保护功能特性,因此能使以往的软件继续工作在新的芯片下。直到今天,甚至最新的 x86处理器都是在计算机加电启动时都是工作在实模式下,它能运行为以前处理器芯片写的程序.
DOS操作系统(例如 MS-DOS,DR-DOS)工作在实模式下,微软 Windows早期的版本(它本质上是运行在 DOS上的图形用户界面应用程序,实际上本身并不是一个操作系统)也是运行在实模式下,直到 Windows3.0,它运行期间既有实模式又有保护模式,所以说它是一种混合模式工作。它的保护模式运行有两种不同意义 (因为 80286并没有完全地实现 80386及以后的保护模式功能 ):
1〉“标准保护模式”:这就是程序运行在保护模式下;
2〉“虚拟保护模式(实质上还是实模式,是实模式上模拟的保护模式)”:它也使用 32位地址寻址方式。 Windows3.1彻底删除了对实模式的支持。在80286处理器芯片以后, Windows3.1成为主流操作系统( Windows/80286不是主流产品)。目前差不多所有的 X86系列处理器操作系统( Linux, Windows95 and later, OS/2等)都是在启动时进行处理器设置而进入保护模式的。
实模式工作机理:
1> 对于 8086/8088来说计算实际地址是用绝对地址对 1M求模。 8086的地址线的物理结构: 20根,也就是它可以物理寻址的内存范围为 2^20个字节,即 1 M空间,但由于 8086/8088所使用的寄存器都是 16位,能够表示的地址范围只有 0-64K,这和 1M地址空间来比较也太小了,所以为了在 8086/8088下能够访问 1M内存, Intel采取了分段寻址的模式: 16位段基地址 :16位偏移 EA。其绝对地址计算方法为: 16位基地址左移 4位 +16位偏移 =20位地址。 比如:DS=1000H EA=FFFFH 那么绝对地址就为: 10000H + 0FFFFH = 1FFFFH 地址单元 。通过这种方法来实现使用 16位寄存器访问 1M的地址空间,这种技术是处理器内部实现的,通过上述分段技术模式,能够表示的最大内存为: FFFFh: FFFFh=FFFF0h+FFFFh=10FFEFh=1M+64K-16Bytes( 1M多余出来的部分被称做高端内存区 HMA)。但 8086/8088只有 20位地址线,只能够访问 1M地址范围的数据,所以如果访问 100000h~10FFEFh之间的内存(大于 1M空间),则必须有第 21根地址线来参与寻址( 8086/8088没有)。因此,当程序员给出超过 1M( 100000H-10FFEFH)的地址时,因为逻辑上正常,系统并不认为其访问越界而产生异常,而是自动从 0开始计算,也就是说系统计算实际地址的时候是按照对 1M求模的方式进行的,这种技术被称为 wrap-around。
2> 对于 80286或以上的 CPU通过 A20 GATE来控制 A20地址线 。 技术发展到了 80286,虽然系统的地址总线由原来的 20根发展为 24根,这样能够访问的内存可以达到 2^24=16M,但是 Intel在设计 80286时提出的目标是向下兼容 ,所以在实模式下,系统所表现的行为应该和 8086/8088所表现的完全一样,也就是说,在实模式下, 80386以及后续系列应该和 8086/8088完全兼容仍然使用 A20地址线。所以说 80286芯片存在一个 BUG:它开设 A20地址线。如果程序员访问 100000H-10FFEFH之间的内存,系统将实际访问这块内存(没有 wrap-around技术),而不是象 8086/8088一样从 0开始。我们来看一副图:
为了解决上述兼容性问题, IBM使用键盘控制器上剩余的一些输出线来管理第 21根地址线(从 0开始数是第 20根) 的有效性,被称为 A20 Gate:
1> 如果 A20 Gate被打开,则当程序员给出 100000H-10FFEFH之间的地址的时候,系统将真正访问这块内存区域;
2 如果 A20 Gate被禁止,则当程序员给出 100000H-10FFEFH之间的地址的时候,系统仍然使用 8086/8088的方式即取模方式( 8086仿真)。绝大多数IBM PC兼容机默认的 A20 Gate是被禁止的。现在许多新型 PC上存在直接通过 BIOS功能调用来控制 A20 Gate的功能。
上面所述的内存访问模式都是实模式,在 80286以及更高系列的 PC中,即使 A20 Gate被打开,在实模式下所能够访问的内存最大也只能为 10FFEFH,尽管它们的地址总线所能够访问的能力都大大超过这个限制。为了能够访问 10FFEFH以上的内存,则必须进入保护模式。
保护模式: 经常缩写为 p-mode,在 Intel iAPX 286程序员参考手册中( iAPX 286是 Intel 80286的另一种叫法) 它又被称作为虚拟地址保护模式。经管在 Intel 80286手册中已经提出了虚地址保护模式,但实际上它只是一个指引,真正的 32位地址出现在 Intel 80386上。保护模式本身是 80286及以后兼容处理器序列之后产成的一种操作模式,它具有许多特性设计为提高系统的多道任务和系统的稳定性。例如内存的保护,分页机制和硬件虚拟存储的支持。现代多数的 x86处理器操作系统都运行在保护模式下,包括 Linux, Free BSD, 和 Windows 3.0(它也运行在实模式下,为了和 Windows 2.x应用程序兼容)及以后的版本。
80286及以后的处理器另一种工作模式是实模式(仅当系统启动的一瞬间),本着向下兼容的原则屏蔽保护模式特性,从而容许老的软件能够运行在新的芯片上。作为一个设计规范,所有的 x86系列处理器,除嵌入式 Intel80387之外,都是系统启动工作在实模式下,确保遗留下的操作系统向下兼容。它们都必须被启动程序(操作系统程序最初运行代码)重新设置而相应进入保护模式的,在这之前任何的保护模式特性都是无效的。在现代计算机中,这种匹配进入保护模式是操作系统启动时最前沿的动作之一。
在被调停的多道任务程序中,它可以从新工作在实模式下是相当可能的。保护模式的特性是阻止被其他任务或系统内核破坏已经不健全的程序的运行,保护模式也有对硬件的支持,例如中断运行程序,移动运行进程文档到另一个进程和置空多任务的保护功能。
386及以后系列处理器不仅具有保护模式又具有 32位寄存器,结果导致了处理功能的混乱,因为 80286虽然支持保护模式,但是它的寄存器都是 16位的,它是通过自身程序设定而模拟出的 32位,并非 32位寄存器处理。归咎于这种混乱现象,它促使Windows/386 及以后的版本彻底抛弃 80286的虚拟保护模式,以后保护模式的操作系统都是运行在 80386以上,不再运行在 80286(尽管 80286模式支持保护模式),所以说 80286是一个过渡芯片,它是一个过渡产品。
尽管 286和 386处理器能够实现保护模式和兼容以前的版本,但是内存的 1M以上空间还是不易存取,由于内存地址的回绕, IBM PC XT (现以废弃)设计一种模拟系统,它能过欺骗手段访问到 1M以上的地址空间,就是开通了 A20地址线。在保护模式里,前 32个中断为处理器异常预留,例如,中断 0D(十进制 13)常规保护故障和中断 00是除数为零异常。
如果要访问更多的内存,则必须进入保护模式,那么,在保护模式下, A20 Gate对于内存访问有什么影响呢?
为了搞清楚这一点,我们先来看一看 A20的工作原理。 A20,从它的名字就可以看出来,其实它就是对于 A20(从 0开始数)的特殊处理 (也就是对第 21根地址线的处理 )。如果 A20 Gate被禁止,对于 80286来说,其地址为 24根地址线,其地址表示为 EFFFFF;对于 80386极其随后的 32根地址线芯片来说,其地址表示为 FFEFFFFF。这种表示的意思是:
1> 如果 A20 Gate被禁止。则其第 A20在 CPU做地址访问的时候是无效的,永远只能被作为 0。所以,在保护模式下,如果 A20 Gate被禁止,则可以访问的内存只能是奇数 1M段,即 1M,3M,5M…,也就是 00000-FFFFF, 200000-2FFFFF,300000-3FFFFF…
2如果 A20 Gate被打开。则其第 20-bit是有效的,其值既可以是 0,又可以是 1。那么就可以使 A20线传递实际的地址信号。如果 A20 Gate被打开,则可以访问的内存则是连续的。
实模式和保护模式的区别: 从表面上看,保护模式和实模式并没有太大的区别,二者都使用了内存段、中断和设备驱动来处理硬件,但二者有很多不同之处。我们知道,在实模式中内存被划分成段,每个段的大小为 64KB ,而这样的段地址可以用 16 位来表示。内存段的处理是通过和段寄存器相关联的内部机制来处理的,这些段寄存器( CS 、 DS 、 SS 和 ES )的内容形成了物理地址的一部分。具体来说,最终的物理地址是由 16 位的段地址和 16 位的段内偏移地址组成的。用公式表示为:物理地址 = 左移 4 位的段地址 + 偏移地址。
在保护模式下,段是通过一系列被称之为 “ 描述符表 ” 的表所定义的。段寄存器存储的是指向这些表的指针。用于定义内存段的表有两种:全局描述符表 (GDT)和局部描述符表 (LDT) 。 GDT 是一个段描述符数组,其中包含所有应用程序都可以使用的基本描述符。在实模式中,段长是固定的 ( 为 64KB) ,而在保护模式中,段长是可变的,其最大可达 4GB 。 LDT 也是段描述符的一个数组。与 GDT 不同, LDT 是一个段,其中存放的是局部的、不需要全局共享的段描述符。每一个操作系统都必须定义一个 GDT ,而每一个正在运行的任务都会有一个相应的 LDT 。每一个描述符的长度是 8 个字节,格式如图 3 所示。当段寄存器被加载的时候,段基地址就会从相应的表入口获得。描述符的内容会被存储在一个程序员不可见的影像寄存器 (shadow register) 之中,以便下一次同一个段可以使用该信息而不用每次都到表中提取。物理地址由 16 位或者 32 位的偏移加上影像寄存器中的基址组成。实模式和保护模式的不同可以从下图很清楚地看出来。
实模式下寻址方式
保护模式下寻址方式
PS:
计算机刚启动的时候,CPU首先以实模式的方式工作,直到启动操作系统后才会切换到保护模式下工作;
从8086到80386,虽然位数从16位扩展成了32位,但CPU的体系结构却发生了质的改变。其中,寻址方式从实模式到保护模式的转变对CPU的计算能力起到了至关重要的作用。80386的后续型号(如80486,奔腾,奔腾4等)虽然计算速度在飞速提高,但最核心的体系结构基本上没有多大变化。所以人们把80386及其后续型号统称为“x86”或“i386”。