标签:固定 兼容 span 成功 范围 使用 属性 cto spl
远古时期的程序开发是直接操作物理内存的,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中的某个寄存器实现)
标签:固定 兼容 span 成功 范围 使用 属性 cto spl
原文地址:https://www.cnblogs.com/wanmeishenghuo/p/9331088.html