x86 实模式与保护模式

2019-04-13 21:12发布

0386开始,CPU有三种工作方式:实模式保护模式虚拟8086模式。只有在刚刚启动的时候是real-mode,等到操作系统运行起来以后就切换到protected-mode。实模式只能访问地址在1M以下的内存称为常规内存,我们把地址在1M 以上的内存称为扩展内存。在保护模式下,全部32条地址线有效,可寻址高达4G字节的物理地址空间; 扩充的存储器分段管理机制和可选的存储器分页管理机制,不仅为存储器共享和保护提供了硬件支持,而且为实现虚拟存储器提供了硬件支持; 支持多任务,能够快速地进行任务切换(switch)保护任务环境(context); 4个特权级和完善的特权检查机制,既能实现资源共享又能保证代码和数据的安全和保密及任务的隔离; 支持虚拟8086方式,便于执行8086程序。
实模式(Real Mode) 它是 Intel公司80286及以后的x86(80386,8048680586)兼容处理器CPU)的一种操作模式。实模式被特殊定义为20位地址内存可访问空间上,这就意味着它的容量是220次幂(1M)的可访问内存空间(物理内存和BIOS-ROM),软件可通过这些地址直接访问BIOS程序和外围硬件。实模式下处理器没有硬件级内存保护概念和多道任务的工作模式。但是为了向下兼容,所以80286及以后的x86系列兼容处理器仍然是开机启动时工作在实模式下80186和早期的处理器仅有一种操作模式,就是后来我们所定义的实模式。实模式虽然能访问到1M的地址空间,但是由于BIOS的映射作用(即BIOS占用了部分空间地址资源),所以真正能使用的物理内存空间(内存条),也就是在640k924k之间。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系列处理器操作系统(LinuxWindows95 and laterOS/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-16Bytes1M多余出来的部分被称做高端内存区HMA。但8086/8088只有20位地址线,只能够访问1M地址范围的数据,所以如果访问100000h~10FFEFh之间的内存(大于1M空间),则必须有第21根地址线来参与寻址(8086/8088没有)。因此,当程序员给出超过1M100000H-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之间的地址的时候,系统将真正访问这块内存区域; 如果A20 Gate被禁止,则当程序员给出100000H-10FFEFH之间的地址的时候,系统仍然使用8086/8088的方式即取模方式(8086仿真)。绝大多数IBM PC兼容机默认的A20 Gate是被禁止的。现在许多新型PC上存在直接通过BIOS功能调用来控制A20 Gate的功能。

保护模式(Protected Mode)

上面所述的内存访问模式都是实模式,在80286以及更高系列的PC中,即使A20 Gate被打开,在实模式下所能够访问的内存最大也只能为10FFEFH,尽管它们的地址总线所能够访问的能力都大大超过这个限制。为了能够访问10FFEFH以上的内存,则必须进入保护模式。 (286Intel 80286的另一种叫法) 它又被称作为虚拟地址保护模式。尽管在Intel 80286手册中已经提出了虚地址保护模式,但实际上它只是一个指引,真正的32位地址出现在Intel 80386上。保护模式本身是80286及以后兼容处理器序列之后产成的一种操作模式,它具有许多特性设计为提高系统的多道任务系统的稳定性。例如内存的保护分页机制硬件虚拟存储的支持。现代多数的x86处理器操作系统都运行在保护模式下,包括Linux, Free BSD, Windows3.0(它也运行在实模式下,为了和Windows 2.x应用程序兼容)及以后的版本。   80286及以后的处理器另一种工作模式是实模式(仅当系统启动的一瞬间),本着向下兼容的原则屏蔽保护模式特性,从而容许老的软件能够运行在新的芯片上。作为一个设计规范,所有的x86系列处理器,除嵌入式Intel80387之外,都是系统启动工作在实模式下,确保遗留下的操作系统向下兼容。它们都必须被启动程序(操作系统程序最初运行代码)重新设置而相应进入保护模式的,在这之前任何的保护模式特性都是无效的。在现代计算机中,这种匹配进入保护模式是操作系统启动时最前沿的动作之一。   在被调停的多道任务程序中,它可以从新工作在实模式下是相当可能的。保护模式的特性是阻止被其他任务或系统内核破坏已经不健全的程序的运行,保护模式也有对硬件的支持,例如中断运行程序,移动运行进程文档到另一个进程和置空多任务的保护功能。   386及以后系列处理器不仅具有保护模式又具有32位寄存器,结果导致了处理功能的混乱,因为80286虽然支持保护模式,但是它的寄存器都是16位的,它是通过自身程序设定而模拟出的32位,并非32位寄存器处理。归咎于这种混乱现象,它促使Windows/386 及以后的版本彻底抛弃80286的虚拟保护模式,以后保护模式的操作系统都是运行在80386以上,不再运行在80286(尽管80286模式支持保护模式),所以说80286是一个过渡芯片,它是一个过渡产品   尽管 286386处理器能够实现保护模式和兼容以前的版本,但是内存的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被禁止。则其第A20CPU做地址访问的时候是无效的,永远只能被作为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 位的偏移加上影像寄存器中的基址组成。实模式和保护模式的不同可以从下图很清楚地看出来。
实模式地址

保护模式地址

总结

保护模式同实模式的根本区别是进程内存受保护与否。可寻址空间的区别只是这一原因的果。实模式将整个物理内存看成分段的区域,程序代码和数据位于不同区域,系统程序和用户程序没有区别对待,而且每一个指针都是指向"实在"的物理地址。这样一来,用户程序的一个指针如果指向了系统程序区域或其他用户程序 区域,并改变了值,那么对于这个被修改的系统程序或用户程序,其后果就很可能是灾难性的。为了克服这种低劣的内存管理方式,处理器厂商开发出保护模式。这 样,物理内存地址不能直接被程序访问,程序内部的地址(虚拟地址)要由操作系统转化为物理地址去访问,程序对此一无所知。

至此,进程有了严格的边界,任何其他进程根本没有办法访问不属于自己的物理内存区域,甚至在自己的虚拟地址范围内也不是可以任意访问的,因为有一些虚拟区域已经被放进一些公共系统运行库。这些区域也不能随便修改,若修改就会有: SIGSEGV(linux 段错误);非法内存访问对话框(windows 对话框)。

CPU启动环境为16位实模式,之后可以切换到保护模式。但从保护模式无法切换回实模式 。

对于80X86处理器来说,从80386处理器开始,除了以前的实模式外,还增添了 
保护模式和V86模式。实模式和V86模式都是为了和8086兼容而设置的。 
  
实模式: 
      内存寻址方式为:段式寻址,即物理地址=段地址*16   +   段内偏移地址 
      可寻址任意地址,所有指令都相当于工作在特权级。 
      dos工作在实模式下 
保护模式: 
      内存寻址方式为:支持内存分页和虚拟内存 
      支持多任务,可依靠硬件用一条指令即可实现任务切换,不同任务可工作在 不同的优先级下,操作系统工作在最高优先级0上,应用程序则运行       在较低优先级 上。从实模式到保护模式,需要建立GDT、IDT等数据表,然后通过修改控制寄存 器CR0的控制位(位0)来实现。 
      Windows工作在保护模式下。 
虚拟8086模式: 
        内存寻址方式:段式寻址,与实模式一样 
        支持多任务和内存分页 
        v86模式主要是为了在保护模式下兼容以前的实模式应用,即可支持多任务, 
        但每个任务都是实模式的工作方式。 

另外,中断和异常等的处理对于不同的工作模式都是不同的,具体的可以去 参看一些相关书籍。 

以上转自:http://blog.csdn.net/kennyrose/article/details/7563649 以下转自:http://ahhqlrg.lofter.com/post/1ccdac85_7882945  Intel的实模式和保护模式,必须要知道的... 一、Intel手册如是说 
        Intel的IA-32架构支持三种基本操作模式:保护模式、实地址模式和系统管理模式。操作模式决定了哪些指令和架构相关的特性是可用的:
  • 保护模式(protected mode)——是处理器的根本模式,在保护模式下,可以为直接运行的实地址模式程序提供保护的、多任务的环境,这种特性被称作“虚拟8086模式(virtual 8086 mode)”,尽管“虚拟8086”模式并不是一种真正的处理器模式;virtual 8086 mode实际上是保护模式的一种属性,在保护模式下,可以向任何任务提供这种属性。
  • 实地址模式(real-addess mode)——该模式以扩展的方式实现了8086CPU的程序运行环境(就像切换到保护模式和系统管理模式一样)。处理器在刚刚上电或者重启后的时候,处于实地址模式。
  • 系统管理模式(system manangement mode,SMM)——该模式提供操作系统或者执行程序一种透明的机制去实现平台相关的特性,例如电源管理和系统安全。当来自外部的或者APIC控制器的SMM中断pin脚被触发时,处理器在下列情况进入SMM。在SMM下,处理器切换到一个独立的地址空间,同时保存当前运行的程序或任务的上下文。SMM相关的代码可透明的执行。当SMM模式返回时,处理器返回SMI(system manangement interrupt)前的工作模式。SMM模式在Intel 386 SL和Intel 486 SL处理器时被引入,在Pentium家族时成为标准的IA-32架构的特性。
        Intel 64 架构增加了IA-32e模式,IA-32e模式又包含两种子模式:
  • 兼容模式(Compatibility mode)——兼容模式允许绝大部分16-bit/32-bit的应用可以无需重新编译就能直接在64bits的操作系统下运行。简单的,在IA-32架构下将“兼容子模式”称为“兼容模式”。兼容模式的可执行环境与Section 3.2定义的一致。兼容模式也支持所有的特权级别,在64-bit和保护模式下。运行在虚拟8086模式下的或用到硬件任务管理的程序,在此模式下无法工作。兼容模式做代码段基础被操作系统所启动,这意味着单独的64-bit操作系统可以通过64-bit模式支持64-bit应用,也可以通过兼容模式支持32-bit程序(无需再编译)。兼容模式类似于32-bit的保护模式,应用程序只能访问前4G的线性地址空间。兼容模式使用16-bit和32-bit的地址以及操作数长度。类似于保护模式,该模式允许应用程序通过PAE(物理地址扩展,Physical Address Extention)访问超过4G的物理内存。
  • 64-bit模式(64-bit  mode)——该模式使操作系统在64-bit线性地址空间上运行应用程序,在IA-32架构下,64-bit子模式被简称为64-bit模式。64-bit模式将通用寄存器和SIMD寄存器从8个扩展到16个。通用寄存器被增加到64bits宽。该模式还引入了新的操作数前缀(REX)来访问寄存器扩展。64-bit模式作为代码段基础被操作系统激活,该模式默认地址长度是64bits,但默认操作数长度为32bits,默认的操作数长度可以在指令级别被覆盖,通过使用REX操作数前缀结合操作数大小覆盖前缀。REX前缀被用来在64-bit模式下指定一个64-bit的操作数,通过这种机制,很多已经存在的指令代码可以被直接升级到访问64-bit地址空间和64-bit寄存器。        
二、实模式的历史原因 
        早在1978年,Intel研制了8086处理器,8086处理有16-bit寄存器和16-bit的外部数据总线,但是却能够访问20-bit的地址(包含1MByte的地址空间)。8086通过引入“分段(segmentation)机制”来解决这个问题。在分段机制下,一个16bits的段寄存器包含了一个长度是64KBytes的“段”空间的起始指针。通过1次时可用一个段寄存器,8086处理器可以无需在段间切换就能寻址高达256KBytes。因此,通过段寄存器+16bits的指针就能访问20bits的地址空间,共1Mbytes。         虽然8086/8088处理器采用的地址空间大小与外部总线位宽不一致,但是这显得很“别扭”,并且在1985年80386时被统一,地址空间和外部总线位宽均为32bits。         为了兼容8086,这种分段管理内存的方式一直被保留下来。当然,实模式不仅仅是分段内存管理,而是“程序的运行环境”,所为的运行环境,还包括寄存器的长度。 三、实模式和保护模式的区别 
        个人理解,因为x86的CPU在启动时首先处于实模式,也就8086的16位模式,主要特点有:
  • 内存管理采用段+偏移的方式进行;
  • 最大寻指位2的20次方,即1Mbyte;
  • 没有安全级别,直接操作CPU的各种功能;
  • 没有分页功能,没有虚拟地址的概念,只有物理地址;
  • 各种寄存器的位宽基本上是16位的(段寄存器为20位);
        实模式就是一种比较原始的模式,能看到CPU设计的初始过程。         保护模式是32位模式,但是可以兼容16位的实模式,保护模式的特点有:
  • 内存管理采用段式+页式的方式;
  • 最大寻指位2的32次方,即4G,还可以通过PAE模式访问超过4G的部分。
  • 有4个安全级别,内存操作时有安全检查;
  • 因为有了分页功能,因此有虚拟地址和物理地址的区别;
  • 各种寄存器的位宽基本上都是32位的,但是可以兼容同名的16位寄存器;
  • 可以兼容实地址模式,也即实地址模式的程序无需再编译即可跑在保护模式下。
        对于64位CPU来说,兼容模式和64位模式也基本上一个道理,兼容模式为了兼容32位,也就兼容了16位,而64位模式本身不去兼容32位,是纯净的64位。 四、实模式对OS的意义 
        仅从Linux操作系统考虑。因为32位CPU一上电后,首先处于实模式下,所以实模式是OS必须经历的一种模式。既然保护模式可以兼容实模式,那么CPU为什么还要提供专门的实模式呢?是否OS可以直接从实模式跳转到保护模式呢?         实话说,这两个问题我也不太好回答。为了钱?对Linux系统来说,从实模式到保护模式的过程,实际上主要就是为了初始化保护