来自《编程高手箴言》

    我们知道,CPU上电后,从ROM 中的BIOS开始运行,而Intel 文档却说80x86 CPU上电总是从最高内存下16字节开始执行,那么,BIOS是处在内存的最顶端64KBFFFF0000H),还是1MB之下的64KBF0000H)处呢?事实上,BIOS在这两个地方都同时出现(可用后面存取4GB 内存的程序验证)。

   为了弄清楚以上问题,首先要了解CPU 是如何处理物理地址的。真的是在实模式下用段寄存器左移4位与偏移量相加,还是在保护模式下用段描述符中的基地址加偏移量,难道两者是毫无关联的吗? 

    答案是两者其实是一样的。当Intel80286推出时,其地址空间变成了24位,则从808620位到24位,十分自然地要加大段寄存器才行。实际上,段寄存器和指针都被加大了,只是由于保护的原因,加大的部分没有被程序看见,到了80386之后,地址又从24位加大到32位(80386 SX24位)。

    8086中,CPU只有看得见部分,但在80286之后,在看不见部分中已经包含了地址值,看得见部分”就退化为只是一个标号,再也不用参与地址形成运算了。地址的形成总是从“不可看见部分”取出基址值与偏移相加形成地址。也就是说,在实模式下,当一个段寄存器被装入一个值时,看不见部分的界限被设成FFFFH,基址部分将装入值左移4位,属性部分设成160特权级。这个过程与保护模式时装入一个段寄存器是同理的,只是保护模式的不可见部分是从描述表中取值,而实模式是一套固定的过程。 

    对于CPU在形成地址时,是没有实模式与保护模式之分的,它只管用基址(“不可见部分”)去加上偏移量。实模式与保护模式的差别实际上只是保护处理部件是否工作得更精确而已,比如不允许代码段的写入。实模式下的段寄存装入有固定的形成办法,从而也就不需要保护模式的描述符了,因此,保持了与8086/8088的兼容性。而描述符也只是为了装入段寄存器的不可见部分而设的。 

     从上面的整个段寄存器可见,CPU的地址形成与“看得见部分”的当前值毫无关系。这也解释了为什么在刚进入保护模式时,后面的代码依然被正确地运行,而这时代码段寄存器CS的值却还是进入保护模式前的实模式值,或者从保护模式回到实模式时,代码段CS被改变之前程序是正常地工作,而不会“突变”到CS左移4位的地址上去。比如在保护模式时,CS08H的选择子,到了实模式时,CS还是08H,但地址不会突然变成80H加上偏移量。因为地址的形成不理会段寄存器“看得见部分”的当前值,这一个值只是在被装入时对CPU有用

     地址的形成与CPU的工作模式无关,也就是说,实模式与0特权级保护模式不分页时是一模一样的。明白了这一机理后,在实模式下一样可以处理通常被认为只有在保护模式才能做的事,比如访问整个机器的内存。不必理会保护模式下的众多术语或许会更易于理解,如选择子就是“看得见部分”,描述符是为了装入“不可见部分”而设的。

    有一些书籍也介绍有同样功能的汇编程序,但它们都错误地认为是利用80386芯片的设计疏漏。实际上,Intel本身就在使用这种办法,使得CPU上电时能从FFFFFFF0H处开始第一条指令,这种技术在286之后的每一台机器每一次冷启动时都使用,只是我们不知道罢了。

 

其中应该去理解的是:在386后段寄存器其实是32bit的。在实模式的时候,它是直接把给的段基地址左移4位然后装入的,而在保护模式下是在段描述表中取得段描述符后计算出基地址存入段寄存器中的。

 

阅读全文
类别:保护模式详解 查看评论
posted on 2010-12-28 23:39  sinbad_li  阅读(933)  评论(0编辑  收藏  举报