对pmtest2中两段代码的理解(转载)

转载于:http://wenku.baidu.com/view/57a589d249649b6648d74727.html

注意一.在由保护模式切换到实模式之前,用normal选择子对段寄存器进行填充。

 原因:

在切换到实模式之前,把一个指向似乎没有用的数据段的描述符Normal的选择子装载到DS和ES。这是为什么呢?

 实模式下段描述符高速缓冲寄存器的内容

段寄存器 段基地址     段界限(固定)     段属性(固定) 存在性 特权级 已存取 粒度 扩展方向 可读性 可写性 可执行 堆栈大小 一致特权

CS 当前CS*16 0000FFFFH

 Y 0 Y B U Y Y Y - N

SS 当前SS*16 0000FFFFH

 Y 0 Y B U Y Y N W -

 DS 当前DS*16 0000FFFFH Y 0 Y B U Y Y N - -

 ES 当前ES*16 0000FFFFH Y 0 Y B U Y Y N - -

 FS 当前FS*16 0000FFFFH Y 0 Y B U Y Y N - -

GS 当前GS*16 0000FFFFH Y 0 Y B U Y Y N - -

在分段管理机制中,每个段寄存器都配有段描述符高速缓冲寄存器,这些高速缓冲寄存器在实方式下仍发挥作用,只是内容上与保护模式下有所不同。

如上表所示,其中“Y”表示“是”; “N”表示“否”;“B”表示字节;“U”表示向上扩展,“W”表示以字方式操作堆栈。

段基地址仍是 32位,其值是相应段寄存器值(段值)乘以16,在把段值装载到段寄存器时刷新。

由于其值是16位段值乘上16,所以在实模式下基地址实际上有效位只有20位。每个段的32位段界限都固定为0FFFFH,段属性的许多位也是固定的。[bit 16起的作用]

所谓固定是指在实方式下不可设置这些属性值,只能继续沿用保护方式下所设置的值。

因此,在准备结束保护模式回到实模式之前,要通过加载一个合适的描述符选择子(如实例代码中的Normal选择子)到有关段寄存器,以使得对应段描述符高速缓冲寄存器中含有合适的段界限和属性。

 也就是说,在实模式下装载段寄存器并不会影响段告诉缓冲寄存器的值,比如段界限(其实在实模式也没有必要改变,应为段界限一直都是0ffffh),这也就是为甚麽所有讲保护模式的树在讲到有保护模式切换到实模式时都要加载一个normal选择子的原因了。

因为必须在保护模式下设置好段高速缓冲寄存器的值,因为一旦到了实模式下就不能在改变了。

经我试验,对于normal的描述符,其最重要是段界限一定要设置为0ffffh,如果不是这样,那莫在由保护模式跳转到实模式后会发生错误(对于上述代码如果把normal描述符的段界限改为别的的话,在跳转后会产生死循环的现象,具体是什么原因现在还不明确,哪位高人知道一定要告诉我啊~~)。

其次就是属性的设置一定要设置为可读可写的,否则也会发生错误.

注意二:不能从32位代码段返回实模式,而只能从16位代码段返回

 原因:(书中说的)因为无法实现从32位代码段返回时CS高速缓冲寄存器中的属性符合实模式的要求(实模式不能改变段属性) 对于这个解释还是不太明确,如果哪位高人明白其中的来龙去脉的话,请一定在下面留个言,给我解释一下,不胜感激.

补充: 关于为什么不能从32位的保护模式直接跳转到实模式,而要先跳转到16位的保护模式,再从16位的保护模式跳转到实模式的理解 ;[三种状态]

****************注意在此用normal选择子对段寄存器进行填充******************************

mov ax,SelectorNormal

317 mov ds, ax

318 mov es, ax

319 mov fs, ax

 320 mov gs, ax

321 mov ss, ax

从上述代码可以看出:ds,es,fs,gs,ss这些段寄存器对应的高速缓冲寄存器中的内容可以通过加载normal选择子而得到更新,

当向这几个段寄存器中装入normal选择子时,会自动地将normal对应的描述符装载到描述符高速缓冲寄存器中。

因normal选择子所对应的描述符的属性符合实模式下的要求,即:段界限为ffffh,段属性也是固定的。

但是:CS寄存器是不可以通过装载normal来更新CS对应的高速缓冲寄存器的,为什么:你能写出这样的指令吗:MOV CS,SelectorNormal

汇编中没有这样的指令。 即然这样,那怎么可以让CS对应的高速缓冲寄存器中的内容符合实模式的要求呢?

方法是这样的:因为CS的值只能通过jmp,call这样的指令去改变。

所以定义一个16位的代码段,这个代码段的描述符定义为:段界限0ffffh,段属性:存在的只执行代码段

假设这个代码段的选择子为:select32,偏移地址为:offsetaddr 用一条转移指令向这段代码跳转:jmp select32:offsetaddr 因现在处于保护模式,所以jmp指令执行的结果是将select32对应的描述符装入cs对应的描述符高速缓冲寄存器中,这个描述符就是符合实模式要求的。

这样,CS段寄存器对应的高速缓冲寄存器中的内容终于达到实模式的要求了,所以现在可以进行从保护模式到实模式跳转了,再用一条jmp语句就可以从保护模式跳转到实模式了。

posted on 2011-04-21 23:31  wanghj_dz  阅读(958)  评论(1编辑  收藏  举报

导航