保护模式--段式存储

我们都知道,现在我们用计算机时操作系统都傲游在她的保护模式上,而一开始计算机是运行在保护模式上的。那么之间是如何转换得呢?

首先温习一下实模式下的物理地址和寄存器代表得(逻辑地址)之间得关系
物理地址=段值*16+偏移地址。

但是在保护模式下(段式管理),寄存器中得值并不是物理地址得段值,而是段值得索引。这个索引指向一个数据结构得一个表项。
这个数据结构就是GDT(Global Descriptor Table) LDT(Local Descriptor Table) 以及 IDT(Interrput Descriptor Table),这结构中得表项就是Descriptor描述符。

首先看下段的描述符结构


从上面得结构看起来,这个结构在内存中被安排得非常杂乱。所以我们需要一个函数或是宏来合理安排,由于用得很频繁且代码不长,考虑效率所以选择宏定义。nasm宏:
;宏描述符  
;usage:  Descriptor Base,Limit,Attr  
;        Base  %1 :  dd   双字(基址有32位)  
;        Limit %2 :  dd   双字,但是只有低20位有效,段界限只有20位  
;        Attr  %3 :  dw   字,高字节得低四位永远是0(在赋值时注意),因为它描述的在段界限中。即与属性相关得只有12位  
所以该宏得具体做法如下。  
%macro  Descriptor 3  
        dw  %2 & 0ffffh                      ;段界限(15..0)  
        dw  %1 & 0ffffh                      ;段基址(15..0)  
        db  (%1>>16) & 0ffh                  ;段基址(23..16)  
        dw  ((%2>>8) & 0f00h)|(%3 & 0f0ffh)  ;段界限(19..16) + 属性(这里好好分析,如果没搞明白就分成两个字节分别赋值,这样更直白)  
        db  (%1>>24) & 0ffh                  ;段基址(31..24)  
%endmacro  ;以上共8个字节。 

既然现在结构已经被管理好了(即现在用得时候很直观就能给其赋值了),那么他们具体怎么和CS,ds等实模式下段寄存器相关联的呢?

此时通过段的选择子来实现保护模式下寻址。此时CS,DS等


下面介绍选择子结构(其共有16位)它就是保护模式下段寄存器中的内容


其中TI是引用描述中得表示位。TI=1时表示从LDT中读取描述符。TI=0则表示从GDT中读取描述符。
RPL则是表示请求特权级。用于特权检查。其用法如下:每当一个程序访问一个段时,要把当前特权级与所访问段的特权级进行检查,以确定该程序是否允许访问该段。

现在我觉得我们应该详细了解下GDT中每个位的含义了:

首先对于基址,和段界限我觉得没什么可说得,这两者就确定一段物理地址范围。
所以主要解说下GDT属性。
对于BYTE5


1、P位称为存在位,P=1表示描述符对地址的转换有效的,即该段地址在内存中。P=0则表示段在内存中不存在
2、DPL是该描述符得特权级(Decriptor Privilege Level),特权级可以是0 ,1 , 2 ,3。数字越小特权越大。
3、S位指明描述符是代码段/数据段(S=1)还是系统段/门描述(S=0).
4、至于TYPE[3..0](当S=1时)
    1)、TYPE[0]表示该描述符是否被访问过,用A(Accessed)表示。A=1表示被访问过,A=0未被访问。当把描述符相应得选择子装入段寄存器时A=1。
2)、TYPE[3]表示该段是数据段还是代码段,用E表示。E=0表示为数据段,则数据可读,不可执行,E=1时表示为代码段,则数据可执行,不可写。
3)、当E=0时,即该描述符指的是数据段,所以数据可读,此时TYPE[1]表示数据是否可写用W表示。W=1表示可写,否则不可写。TYPE[2]表示数据段扩展方向ED表示,ED=1表示向下扩展,否则向上扩展。
4)、E=1是,表明该描述符指代码段,所以数据可执行。此时TYPE[1]用R标记表示代码是否可读,R=1则可读,否则不可读。TYPE[2]用C表示,指明代码是否一致代码段,C=0表示不是一致代码段(普通代码段),C=1表示是一致代码段。

下面综合归纳一下TYPE属性



看到这里,一定很迷惑这个“一致”是什么意思:它的意思是当转移的目标是一个特权级更高得一致代码段,当前特权会被延续下去,而向特权级更高得非一致性代码段转移就会引起常规得特权保护,无论是不是一致性代码,如果目标代码特权级低都不能通过jmp call转移进去。
   总之通过call 和 jmp转移遵循规则


好了BYTE5就这样了
下面讲下BYTE6中得属性了


1、G就是段的界限粒度(Granularity)。G=0表示段界限粒度是字节;G=1表示段界限粒度4K字节。段的界限粒度只对段界限有效,对基址无效(一直以字节位单位)
  2、D/B大致分为以下三种情况
     1)、在可执行代码段中此位D。D=1时,在默认情况下指令使用32位地址及32位或8位操作数。D=0时默认指令使用16位地址和16位或8位操作数。
2)、在向下扩展数据段中,此位B。B=1,段得上部界限4GB,B=0段得上部界限64KB
3)、在描述堆栈段时,此位B,B=1隐式堆栈访问指令(PUSH POP Call) 使用32位堆栈指针寄存器esp。当B=0时使用16位堆栈指针寄存器sp。
  3、AVL,是软件可利用位。80386对该位未作规定。
  4、位5必须值为0,也许为以后处理器预留。

猜你喜欢

转载自tviker.iteye.com/blog/1464479
今日推荐