第十课 实模式到保护模式 上

  远古时期的程序开发是直接操作物理内存的,CPU指令的操作数直接使用实地址(实际内存地址),程序员拥有绝对的权利,可以随意访问内存的任意一个地址,可以说是指哪打哪。

  使用绝对的物理地址会带来很多问题,例如:

1、难以重定位,程序每次都需要同样地址的内存来运行。

2、给多道程序设计带来了障碍,也就是说,不管内存多大,但凡一个字节被其他程序占用都无法执行。

  为了解决以上的问题,英特尔开发出了8086 CPU处理器,其引入了如下特性:

1、地址线宽度为20位,可访问1M内存空间

2、引入[段地址:偏移地址] 的内存访问方式

  8086的段寄存器和通用寄存器为16位

  单个寄存器寻址最多访问64K的内存空间

  需要两个寄存器配合,完成所有内存空间的访问

下面我们来研究一下  段地址:偏移地址  的访问方式,其中硬件会做如下工作:

  段地址左移4位,构成20位的基地址,也就是起始地址,这正好和20根地址线对应上

  基地址 + 偏移地址 = 实地址

段地址 :偏移地址的访问方式对开发者具有很大的意义:

  更有效的划分内存的功能(数据段、代码段等)

  当出现程序地址冲突时,通过修改段地址解决冲突,给重定位带来了方便

段地址:偏移地址的示例如下:

  默认情况下,数据访问的段地址存在ds寄存器中,我们也可以显式的给出,例如把段地址放到es寄存器中。

   段地址:偏移地址的访问方式会产生一点小问题,例如,[段地址:偏移地址]能访问的最大地址为0xFFFF:0xFFFF,按照求实地址的方法得到最终的地址为10FFEF,这已经超过了1MB的空间,那么CPU如何进行处理呢?

看下面的推导:

  0xFFFF:0xFFFF

    ->0xFFFF0 + 0xFFFF

      ->0xFFFF0 + (0xF + 0xFFF0)

        ->(0xFFFF0 + 0xF) + 0xFFF0

上面的0xFFFF0 + 0xF已经是1MB内存的最大地址了,再加上0xFFF0已经超出了物理内存大小,这超出的部分在8086中称为高端地址区(HMA)。

   上面的地址已经超过了20位,8086怎么处理呢?由于8086只有20位地址线,因此最高位被丢弃(溢出),如下所示:

  8086是一款非常成功的产品,因此,拥有一大批的开发者和应用程序,各种基于8086程序设计的技术得到了发展,同时,各种奇淫技巧也应运而生,虽然8086解决了程序重定位的问题,但还是存在很多其他的问题:

1、1MB的内存完全不够用

2、开发者在程序中大量使用内存回卷技术(HMA地址被使用)

3、应用程序之间没有界限,相互之间随意干扰

  A程序可以随意访问B程序中的数据

  C程序可以修改系统调度程序的指令

 为了解决以上问题,英特尔的第二代CPU被开发出来,也即80286,8086已经有很多程序在运行了,因此,80286必须兼容8086,而且80286地址线的数量增加到了24位,[段地址:偏移地址]的访问方式也得到了强化:

  1、为每一个段提供了更多的属性(如范围、特权级等)

  2、为每个段的定义提供固定方式

默认情况下80286是完全兼容8086的运行方式(实模式),例如,默认可以访问1MB的内存空间、通过特殊的方式可以访问1MB+的内存空间。

这个特殊的方式就是使80286运行在保护模式下,实模式和保护模式有如下不同:

保护模式:

  1、每一段内存拥有一个属性定义(描述符Descriptor)

  2、所有段的属性定义构成一张表(描述符表Descriptor Table)

  3、段寄存器保存的是段属性定义在表中的索引(选择子Selector)

描述符的内存结构如下:

描述符表如下:

选择子的结构如下:

80286进入保护模式的方式如下:

1、定义描述符表

2、打开A20地址线,使CPU支持24位地址

3、加载描述符表

4、通知CPU进入保护模式(通过设置CPU中的某个寄存器实现)

猜你喜欢

转载自www.cnblogs.com/wanmeishenghuo/p/9331088.html