forandom 发表于 2007-10-23 13:15

从保护模式到实模式的问题

在《自己动手写操作系统》一书上看到一段代码,从实模式跳到保护模式,再从保护模式跳回实模式。
从保护模式跳回实模式这一块不是很明白。

书中提到“在准备结束保护模式回到实模式前,需要加载一个合适的描述符选择子到有关的段寄存器,以使对应段描述符高速缓冲寄存器中案有合适的段界限和属性。”
(1)请问:实模式下还要用到描述符吗?实模式下寻址直接用CS*4+IP不就完事了吗?为什么还得使“描述符高速缓冲寄存器中案有合适的段界限和属性”?

书中还提到“不能从32位代码段返回实模式,只能从16位代码段中返回。这是因为无法实现从32为位代码段返回时CS高速缓冲寄存器中的属性符合实模式的要求(实模式不能改变段属性)”
(1)这句话又是什么意思?16位代码段返回就符合要求了??16位,32位代码段除了操作数宽度还有什么区别?


返回实模式的一段代码:
最后有一跳指令:jmp 0:LABEL_REAL_ENTRY
最开始在实模式下时,修改了这条指令,将实模式下CS的值保存在“0”的位置


; 16 位代码段. 由 32 位代码段跳入, 跳出后到实模式

ALIGN        32


LABEL_SEG_CODE16:
        ; 跳回实模式:
        mov        ax, SelectorNormal
        mov        ds, ax
        mov        es, ax
        mov        fs, ax
        mov        gs, ax
        mov        ss, ax

        mov        eax, cr0
        and        al, 11111110b
        mov        cr0, eax

LABEL_GO_BACK_TO_REAL:
        jmp        0:LABEL_REAL_ENTRY;


请各位帮我解惑...
谢谢!

mik 发表于 2007-10-24 22:58

原帖由 forandom 于 2007-10-23 13:15 发表 http://linux.chinaunix.net/bbs/images/common/back.gif
书中提到“在准备结束保护模式回到实模式前,需要加载一个合适的描述符选择子到有关的段寄存器,以使对应段描述符高速缓冲寄存器中案有合适的段界限和属性。”
(1)请问:实模式下还要用到描述符吗?实模式下寻址直接用CS*4+IP不就完事了吗?为什么还得使“描述符高速缓冲寄存器中案有合适的段界限和属性”?

答:此本说得的确不错,在返回实模式之前确实要加载合适 segment descriptor 进入各个 segment 寄存器。
    是必须要这么做,因为,在进入实模式后,segment 寄存器的 limit 及 attributes 就不能改变了。
    例如:在现代的 OS中,保护模式下 CS/DS 等的 limit 一般都为 0xFFFFFFFF,attribute 中 D 位是 1,也就是 32 位代码的。
    实模式下 limit 必须为 0xFFFF, D 须清 0 ,即 16 位。



原帖由 forandom 于 2007-10-23 13:15 发表 http://linux.chinaunix.net/bbs/images/common/back.gif
书中还提到“不能从32位代码段返回实模式,只能从16位代码段中返回。这是因为无法实现从32为位代码段返回时CS高速缓冲寄存器中的属性符合实模式的要求(实模式不能改变段属性)”
(1)这句话又是什么意思?16位代码段返回就符合要求了??16位,32位代码段除了操作数宽度还有什么区别?
答:这一点上,此书说错了。当然可以从 32 位代码返回实模式了。在 descriptor 中可以设定目标代码段是 32 bit 还是 16 bit 。
    descriptor 中的 D 位,就是用于这一目的。descriptor 的 G 位清0,limit 设为 FFFF,就符合了实模式代码的要求。


原帖由 forandom 于 2007-10-23 13:15 发表 http://linux.chinaunix.net/bbs/images/common/back.gif
返回实模式的一段代码:
最后有一跳指令:jmp 0:LABEL_REAL_ENTRY
最开始在实模式下时,修改了这条指令,将实模式下CS的值保存在“0”的位置

答:在各方面条件都准备好之后,最后一跳就返回到实模式下
下面这段代码:

ALIGN      32


LABEL_SEG_CODE16:
      ; 跳回实模式:
      mov      ax, SelectorNormal
      mov      ds, ax
      mov      es, ax
      mov      fs, ax
      mov      gs, ax
      mov      ss, ax

      mov      eax, cr0
      and      al, 11111110b
      mov      cr0, eax

LABEL_GO_BACK_TO_REAL:
      jmp      0:LABEL_REAL_ENTRY;

这段代码无须搞成 16 位模式,和 32 位下一样。
在还没 jmp 之前,可以说此时在保护摸式的残骸之中,此时 CR0.PG 已经被清 0,属于在实模式与保护摸式的混沌之中。
执行 jmp 后,就脱离了残骸,回到了实模式之中
页: [1]
查看完整版本: 从保护模式到实模式的问题