很好的一片有关分段和分页解释的

http://bbs.chinaunix.net/thread-3586493-1-1.html
首先实模式和保护模式是CPU的两种工作模式。一开始PC启动时CPU是工作在实模式下的,经过某种机制后,CPU跳转到保护模式。

Intel 8086是16位CPU,它只有16位寄存器、16位数据总线和20位地址总线,它只能运行在实模式
在实模式,
物理地址=段值*16+偏移 
段值和偏移都是16位的 具有1MB(2^16 * 2^4 + offset)的寻址能力。
而从80386开始CPU有32位地址线,所以寻址空间可以达到4GB。单从寻址这方面说,使用16位寄存器的方法已经不够用了,必须要开发一种新方法。在保护模式下,虽然CPU还是使用原来16位的cs、ds寄存器表示内存地址的段值,不过保护模式下的段值只是一个索引,这个索引指向一个数据结构的一个表项就是GDT(or LDT)。
在保护模式下,CPU有着巨大的寻址能力,并为强大的32位操作系统提供了更好的硬件保障。

所以实模式和保护模式其实就是随着CPU性能不断增强后为了前后能够兼容而设计出来的一套模式。是一个历史遗留产物。
--------------------------------------
为什么要分段?
当x86 CPU 工作在保护模式时,可以使用全部32根地址线访问4GB的内存,因为80386的所有通用寄存器都是32位的,所以用任何一个通用寄存器来间接寻址,不用分段就可以访问4G空间中任意的内存地址。但这并不意味着,此时段寄存器就不再有用了。实际上,段寄存器更加有用了,虽然再寻址上没有分段的限制了,但在保护模式下,一个地址空间是否可以被写入,可以被多少优先级的代码写入,是不是允许执行等等涉及保护的问题就出来了。要解决这些问题,必须对一个地址空间定义一些安全上的属性。段寄存器这时就派上了用场。但是设计属性和保护模式下段的参数,要表示的信息太多了,要用64位长的数据才能表示。我们把着64位的属性数据叫做段描述符,上面说过,它包含3个变量:段物理首地址、段界限、段属性 80386的段寄存器是16位(注意:通用寄存器在保护模式下都是32位,但段寄存器没有被改变)的,无法放下保护模式下64位的段描述符。如何解决这个问题呢?方法是把所有段的段描述符顺序存放在内存中的指定位置,组成一个段描述符表(Descriptor Table);而段寄存器中的16位用来做索引信息,这时,段寄存器中的信息不再是段地址了,而是段选择子(Selector)。可以通过它在段描述符表中“选择”一个项目已得到段的全部信息。那么段描述符表存放在哪里呢?80386引入了两个新的寄存器来管理段描述符,就是GDT和LDT。这样,用以下几步来总体体验下保护模式下寻址的机制
1、段寄存器中存放段选择子Selector 
2、GDT中存放着段描述符表的首地址 
3、通过选择子根据GDT中的首地址,就能找到对应的段描述符 
4、段描述符中有段的物理首地址,就得到段在内存中的首地址 
5、加上偏移量,就找到在这个段中存放的数据的线性地址(只有分段机制情况下,就是真实物理地址)。 

接上面所述,GDT的作用就是用来提供段式存储机制,这种机制是通过段寄存器和GDT中的描述符共同提供的。
因为要能够访问4GB内存,所以在32位模式下
物理地址不能等于 段值*16+偏移 (这种方法寻址1MB)
于是,设计者让
段值*16指向一个数据结构的一个表项就是GDT(or LDT),表项中详细定义了段的起始地址,界限和属性等内容 
于是原先“段:偏移”形式的逻辑地址经过段机制转化成线性地址
如果只有分段机制,那么这个地址就是对应的真实内存的物理地址。

--------------------------------------
为什么要分页?
其实它的主要目的在于实现虚拟存储器。

接上面所述,刚刚说到线性地址,并且说如果只有分段机制,线性地址就是物理地址
如果打开了分页机制后:
逻辑地址-》分段机制-》线性地址-》分页机制-》物理地址
是这样一套转化机制。

另外,如果你写完一个程序后,复制了一份,然后同时调试。你会发现,从变量地址到寄存器的值,这两个程序几乎全部是都是一样的,而这些一样的地址之间完全不会被混淆,而是各自完成自己的职责,这也是分页机制的功劳。
另外,因为分页机制的存在,程序使用的都是线性地址空间,而不再直接是物理地址。这好像是操作系统位应用程序提供了一个不依赖于硬件(物理内存)的平台,应用程序不必关心实际上有多少物理内存,也不必关心正在使用的是哪一段内存,甚至不必关心某一个地址是在物理内存里面还是在硬盘中。只要像操作系统申请就行,而操作系统全权负责了这其中的转换工作。
--------------------------------------

你可能感兴趣的:(技术探秘)