S.l.e!ep.¢%

像打了激速一样,以四倍的速度运转,开心的工作
简单、开放、平等的公司文化;尊重个性、自由与个人价值;
posts - 1098, comments - 335, trackbacks - 0, articles - 1
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

实模式、保护模式

Posted on 2009-10-17 00:13 S.l.e!ep.¢% 阅读(1388) 评论(0)  编辑 收藏 引用 所属分类: 系统低层
实模式、保护模式
2009-06-07 17:18

参考了百度百科中关于实模式的讨论:http://baike.baidu.com/view/404433.htm
http://hi.baidu.com/toening/blog/item/d8d927d403bdfdc350da4b6d.html
http://hi.baidu.com/trueailei/blog/item/b8faa413a22c57d7f7039e4d.html

实模式、保护模式、虚拟模式都是X86中的概念。
从寻址方式来说,CPU中的IP(EIP)中存放虚地址,把虚地址转换到物理地址,各个模式有各自的转换方式。
实模式下,虚地址到实地址转换:DS段寄存器左移4位与偏移地址相加,得到物理地址,寻址1M。
保护模式下,虚地址到实地址转换经过MMU(内存管理单元),也就是分段与分页机制,寻址4G。

保护有两层含义:
1、任务间保护:多任务操作系统中,一个任务不能破坏另一个任务的代码,这是通过内存分页以及不同任务的内存页映射到不同物理内存上来实现的。
2、 任务内保护:系统代码与应用程序代码虽处于同一地址空间,但系统代码具有高优先级,应用程序代码处于低优先级,规定只能高优先级代码访问低优先级代码,这 样杜绝用户代码破坏系统代码。这是通过段式管理来实现,4G虚拟内存中,代码数据和堆栈各占有一个段,段是一个独立有意义的内存单元,有基地址和边界以及 本段的优先级,windows系统有两个优先级,Ring0(高优先级)或Ring3(低优先级),系统代码段和数据段属于Ring0,不能被用户代码 (Ring3)访问。

实模式:
16bit的8086处理器标志着IntelX86王朝的开始,并且引入了一个重要概念——段。8086处理器地址总线扩展到 20位,但算术逻辑运算单元(ALU)宽度即数据总线却只有16位,也就是直接运算的指针长度是16位的。为支持1M寻址空间,引入分段的方法。为支持分 段8086CPU设置四个16bit段寄存器:CS、DS、SS、ES,对应于地址总线中的高16位。寻址时,段寄存器*0x10+偏移地址=物理地址。 这样实现16位内存地址到20位物理地址的转换,叫“映射”。
(之前在想:为什么每个段最大不超过64K,其实很简单,因为16位CPU数据线是16位的,所以最多只能用一个16bit数来标识一个偏移量,也就说一个段最大长度是64K)

保护模式:
80286处理器地址总线位数增加到24位,可以访问16M地址空间。并引入一个新概念——保护模式。这种模式下,内存段的访 问受到了限制。访问内存时不能直接从段寄存器获得段起始地址了,而要经过额外转换和检查(从其不能随意存取数据段)。为与过去兼容,80286内存寻址有 两种方式:保护模式和实模式。系统启动时处理器处于实模式,只能访问1M内存空间,经过处理可以进入保护模式,可访问16M内存空间,但要从保护模式回到 实模式必须重启机器。它有个致命缺陷就是80286虽然扩大了寻址空间,但是每个段大小还是64K(因为数据线还是16位的),程序规模仍然受到限制,因 此很快就被80386代替了。

80386是一个32位的CPU。它的地址总线和ALU数据总线都是32位的。寻址能力达到4G。理论上说当数据总线和地址总线宽度一致 时,CPU结构应该简洁明了,但80386不能做到这点,作为80X86产品系列的一员,80386必须维持那些16位段寄存器的存在,必须支持实模式, 同时还要支持保护模式。Intel选择在段寄存器基础上构筑保护模式,保留16位段寄存器。在保护模式下,段范围达到4G。从80386以后Intel的 CPU经历了80486、Pentium、Pentium2、Pentium3等型号,但都属于同一种系统结构的改进与加强,所以把80386以后的处理 器统称为IA32(32 Bit Intel Architecture)。


深入讨论下保护模式:
保护模式与实模式中程序运行的实质是一样的,都是“CPU执行指令,操作相关数据”。最大的变化是“地址转换方式”的变化。

这里可以看下两种模式下地址转换方式的区别: 在ES存入0x1000,DI存入0xFFFF
实模式:ES:DI = 0x1000 * 0x10 + 0xFFFF = 0x1FFFF,这就是“段基址左移4位加偏移地址”。
保护模式:(注意:0x1000 = 10 0000 0000 0 00 B)ES:DI = GDT全局描述符表中第0x200项描述符给出的段基址 + 0xFFFF。为什么是第0x200项?请看下边段选择子(即段值)的结构。
这里ES在两种模式下都不是真正段地址(实模式下称"段寄存器",保护模式下称"选择子"),都是一种映射,不过映射规则不同而已。


保护模式的基本组成:(围绕“地址转换方式”的变化增设了相应机构)
1、数据段
   实模式下的各种代码段、数据段、堆栈段、中断服务程序仍然存在,这里统称为“数据段”。
2、描述符
   保护模式引入描述符类描述各种数据段,描述符为8个字节(0-7),第5个字节说明描述符类型,类型不同,描述符的结构也不同。
   若干描述符集中组成描述符表,描述符表本身也是一种数据段,也使用描述符进行描述。描述符表是一张地址转换函数表。
3、选择子
   保护模式下,逻辑地址由段选择子和段内偏移两部分组成。与实模式相比,保护模式下的段选择子代替了段值。
   段 选择子有2个BYTE。高13位是描述符索引,第2位TI(Table Indicator)是描述符表指示位,TI=0指示从GTD(全局描述符表)中读取描述符,TI=1指示从LTD(局部描述符表)中读取描述符。低2位 是RPL(Request Privilege Level),即进程对段访问的请求权限,具体可以查阅有关资料。


这里80X86系列引入新的寄存器GDTR和LDTR。
GDTR表示GDT在内存中的段地址和段界限,GDTR是一个48位寄 存器,其中32位表示段地址,16位表示段界限(段最大64K,之前提过描述符表也使用描述符进行描述,因此描述符表最大长度也是64K,里面最多可存放 64K/8Byte=8K个描述符[每个描述符8Byte]。这也是段选择子中描述符索引占13bit的原因[13b=8192])。
   因为GDT不能由GDT本身之内的描述符进行描述定义,所以采用GDTR为GDT这一特殊系统段提供一个伪描述符。

LDTR表示LDT在内存中的位置。因为LDT本身也是一种数据段,它必须有一个描述符存放于GDT中。因此LDTR使用与DS、ES、CS等相同机制,只存放一个“选择子”,通过查GDT获得LDT内存地址。
   LDTR 类似于段寄存器,由程序员可见的16bit寄存器和程序员不可见的高速缓冲寄存器组成。在初始化或切换任务过程中,把描述符对应任务LDT的描述符的选择 子装入LDTR,处理器根据LDTR可见部分的选择子从GDT中取出对应描述符,并把LDT的基地址、界限和属性等信息保存在LDTR的不可见高速缓冲寄 存器中。随后对LDT的访问可根据保存在高速缓冲寄存器中的有关信息进行合法性检查。
   LDTR包含当前任务的LDT选择子。所以装入到LDTR的选择子必须确定一个位于GDT中类型为LDT的系统段描述符,即选择子中的TI=0,且描述符类型字段所表示的类型必须为LDT。

一个多任务操作系统必须有一个GDT,而每一个正在运行的任务(进程)都有一个LDT。可以说保护模式的引进才使得80286以后处理器实现了对 多任务的硬件支持。多任务系统运行中在进程间切换时需要“环境”保护(比如各寄存器值等)。这些“环境”数据构成了一类新的数据段TSS(任务状态段)。 给TSS段设置描述符(TSS描述符),并把该类描述符放在GDT中(自然不能放在LDT中,80x86也不允许),再加个TR寄存器用于查表。TR(任 务寄存器)是一个起“选择子”作用的16bit寄存器。任务切换的工作就是将原任务“环境”存入TSS,更新TR,系统将自动查GDT表获得并装载新任务 的“环境”,然后找到该任务执行。


段描述符高速缓冲寄存器:
   为避免每次存储器访问时,都要访问描述符表获得对应段描述符,从80286开始每个段寄存器都配有一个高速缓冲寄存器,称为“描述符高速缓冲寄存器”或“描述符投影寄存器”(shadow register),对于程序员不可见。
   每 当一个选择子装入某个段寄存器,处理器自动从描述符表中取出相应描述符,把描述符中的信息保存到对应高速缓冲寄存器中。此后对该段访问时,处理器都使用对 应高速缓冲寄存器中的描述符信息。段描述符高速缓冲寄存器内保存的描述符信息将一直保存到重新把选择子装入段寄存器时再更新。程序员尽管不可见段描述符高 速缓冲寄存器,但必须注意到它的存在和它的上述更新时机。例如,在改变了描述符表中的某个当前段的描述符后,也要更新对应的段描述符高速缓冲寄存器的内 容,即使段选择子未作改变,这可通过重新装载段寄存器实现。


分页:
   不同程序由不同用户编写,而所有这些程序完全可能使用相同地址空间,而程序切换过程一般不包括内存数据的刷新,因为这么做太浪费。因此引入分页机制才能有效完成对多任务的支持。
   分 页引入的主要目标就是解决不同进程之间发生地址冲突问题。分页实质就是实现程序内地址到物理地址的映射。用类似GDT的做法:先建立页表这种数据 段,80x86中使用二级页表方案,增设一个CR3寄存器用于存放一级页表(页目录)在内存中的地址,CR3共32位,低12位总为零,高20位指示页目 录的内存地址,因此页目录总是按页对齐的。CR3作为进程“环境”的一部分在进程切换时被存入TSS数据段中。还有一个相应的缺页中断机制及其相关寄存器 CR2(页故障线性地址寄存器)。


中断:
   80x86(保护模式)与8086(实模式)的中断机制不一样。80x86系列为中断服务提供中断/陷阱描述符,这些 描述符构成中断描述符表IDT,并引入一个48bit寄存器IDTR存放IDT的内存地址。理论上IDT表同样可以有8K项,可是因为80x86只支持 256个中断,因此IDT实际上最大只能有256项(2K大小,因为所有描述符都是8BYTE)。


总结可得出,保护模式下增加了:
   1、寄存器:GDTR、LDTR、IDTR、TR、CR3、CR2
   2、数据段:描述符表(GDT、LDT、IDT)、任务数据段(TSS)、页表(页目录、二级页表)
   3、机制:权限检测(利用选择子/描述符/页表项的属性位)、线性地址到物理地址的映射

=========================================================

实模式:(即实地址访问模式)它是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开始。我们来看一副图:

<!--[if !vml]-->      

      为了解决上述兼容性问题,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 286Intel 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是一个过渡芯片,它是一个过渡产品。

尽管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位来表示。内存段的处理是通过和段寄存器相关联的内部机制来处理的,这些段寄存器(CSDS SSES)的内容形成了物理地址的一部分。具体来说,最终的物理地址是由16位的段地址和16位的段内偏移地址组成的。用公式表示为:物理地址=左移4位的段地址+偏移地址。

在保护模式下,段是通过一系列被称之为描述符表的表所定义的。段寄存器存储的是指向这些表的指针。用于定义内存段的表有两种:全局描述符表(GDT) 和局部描述符表(LDT)GDT是一个段描述符数组,其中包含所有应用程序都可以使用的基本描述符。在实模式中,段长是固定的(64KB),而在保护模式中,段长是可变的,其最大可达4GBLDT也是段描述符的一个数组。与GDT不同,LDT是一个段,其中存放的是局部的、不需要全局共享的段描述符。每一个操作系统都必须定义一个GDT,而每一个正在运行的任务都会有一个相应的LDT。每一个描述符的长度是8个字节,格式如图3所示。当段寄存器被加载的时候,段基地址就会从相应的表入口获得。描述符的内容会被存储在一个程序员不可见的影像寄存器(shadow register)之中,以便下一次同一个段可以使用该信息而不用每次都到表中提取。物理地址由16位或者32位的偏移加上影像寄存器中的基址组成。实模式和保护模式的不同可以从下图很清楚地看出来。

                实模式下寻址方式

    <!--[if !vml]-->

                     保护模式下寻址方式

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理