保护模式(摘来的)

1.实模式下通常只能寻址1M内存空间,且只能是单任务。

2.保护模式就是对程序运行加以保护,对实模式的增强主要体现在多任务的支持,

3.8086/8088有20根地址线,80286有24根,80386有32根,puntium有36根地址线分辨可寻址1M,16M,4G,64G的内存空间。纯DOS下运行的Puntium4也只是一个快速的8086.

4.描述符表:若干描述符组成,每个描述符占用8B的内存空间,每个描述表最多有8129个描述符。 

描述符:描述一个段的大小,地址及各种状态的。

5.GDT:全局描述符表,系统中只有一个,且可以被每一个任务共享。可以放任何描述符,但中断门和陷阱门放在GDT中不起作用。能被多任务共享的内存区就是通过GDT完成的。可以放在内存的任何位置,单CPU必须知道GDT的入口,也就是基址放在哪里,intel专门有一个寄存器GDTR用来存放GDT的入口地址,程序员将GDT设定在内存中某个位置后,可以通过LGDT指令将GDT的入口地址装入此寄存器。之后,CPU就根据此寄存器中的内容作为GDt的入口来访问GDT了。GDTR中存放的是GDT在内存中的基地址和其表长界限。32位基地址+16位表界限。

6.LDT:局部描述符表,可以有多个,通常与任务的数量对等,但任务可以没有LDT。任务间不相干的部分也是通过LDT实现的。中断门和陷阱门放在LDT中也不起作用。LDT和GDT从本质上说是相同的,只是LDT嵌套在GDT之中。LDTR记录局部描述符表的起始位置,与GDTR不同LDTR的内容是一个段选择子。由 于LDT本身同样是一段内存,也是一个段,所以它也有个描述符描述它,这个描述符就存储在GDT中,对应这个表述符也会有一个选择子,LDTR装载的就是 这样一个选择子。LDTR可以在程序中随时改变,通过使用lldt指令。

7.IDT:中断描述符表在系统最多只能有一个,可以放256个描述符,分别对应256个中断。每个描述符占8B,故IDT长度可达2K.可以有任务门,中断门,陷阱门三个门描述符。其他的描述符在IDT中无意义。

8.段选择子:在保护模式下,段寄存器的内容已不是段值,而称为选择子。该选择子指示描述符在上面这三个表中的位置。选择子即是索引值。

9.描述符
 前面已经提到,描述符是描述一个段的大小,地址及各种状态的8个字节的结构,在编程时它可以定义它.
 如图2所示,根据描述符所描述对象的不同,描述符可分为存储段描述符、系统段描述符、门描述符三种,而门描述符又可分为调用门、任务门、中断门和陷阱门四类。下面将分别介绍各描述符作用及其各位的意义:
 一、存储段描述符
 存储段描述符是描述程序中的代码段和数据段的,这其中也包括堆栈段,在保护模式下,应该把堆栈段理解为特殊的数据段。
 分析存储段描述符时应该把它分成4个域来理解:
第 一个域为描述符的第0至1字节,该字是段界线的低16位,段界线是描述段的大小共20位,高4位在第六字节的低4位中;第二个域为描述符的第2至4字节, 这三个字节是段基址的低24位;第三个域是描述符的第5、6字节,该字存放的是段的一些属性;第四个域是最后一个字节,该字节存放的是段基址的高8位。下 面对属性字的每一位进行描述:
 如图2所示:
 P位说明所描述的段是否存在,P=1表示描述符所描述的段存在于内存中,P=0表示描述符所描述的段不在内存中。
 DPL为描述符所描述段的特权级,只有有效特权级EPL大于等于DPL时,才能对段进行访问。
 DT位必有为1以区别于系统段描述符。
 TYPE字段:
 位0表示被描述的段是否被访问过,该位为0表示未被访问过,为1则表示该段先前已经被访问过。
 位1的定义在于描述符所描述段的类型。当所描述的是代码段时,该位指示所描述的代码段是否可读,为1则可读,为0则不可读;当所描述的是数据段时,该位指示所描述的数据段是否可写,为1则可写,为0则不可写。
 位 2的定义也在于描述符所描述段的类型。当所描述的是代码段时,该位指示所描述的代码段是否是一至代码段,为1表示该代码段是一至代码段,为0表示该代码段 不是一至代码段,即是普通的代码段。当所描述的是数据段时,该位指示该段的扩展方向,为1时表示该段向低地址扩展,为0时表示该段向高地址扩展。
 位3指示所描述的段类型,为1表示所描述的段是代码段,是可以被执行的,为0表示所描述的段是数据段,是不能被执行的。前面已经说了,在保护模式下应该把堆栈段理解为特殊的数据段,为0时也包括堆栈段。
 G位表示段界限的计数单位,该位为0时表示段界限以字节为单位,为1时表示以4K为单位。这样计算下来,20位的段界限就可以描述大小为64K或4G的段了,
 D 位说明描述符所描述的段是32位环境还是16位的环境。该决定了指令所使用的操作数以及地址的默认大小,为1时说明是32位地址和32位操作数,即32位 段;为0时说明是16位地址和16位操作数,即是16位段。但这时仍可使用操作数及地址大小前缀来改变这种默认设置。该位还决定了系统是使用IP还是 EIP,使用SP还是ESP,
 二、系统段描述符
 系统段描述符是描述两个特殊的段,它们分别为局部描述符表LDT段和任务状态段TSS。
 从图2中可见,系统段描述符与存储段描述符的区别只在于DT位,DT=1则为存储段描述符,DT=0则为系统段描述符,两种描述符就靠此位区分.但系统段描述符的TYPE字段与存储段描述符的TYPE却截然不同.描述如下:
 TYPE字段:
 0、 1两位的定义取决于位2。当位2为1时,说明是门描述符,为0时说明是非门描述符。当位2为1时,0、1两位确定门描述符的类型,因为两位可有4种状态, 所以正好描述4个描述符,为0时则是调用门,为1时则是任务门,为2时则是中断门,为3时则是陷阱门;当位2为0时,低两位0位、1位为0时未定义,为1 时则是可用的286的TSS,为2时则是LDT,为3时则是忙的286的TSS。
 位4为0时,如其它位也为0或低两位为2或3时则也是未定义,否则该位提示是386还是286描述符,关于段基地址和段界限为何都安排在两个分开的域中的原因也与此有关,请读者自己想想!
 三、门描述符
 从 系统段描述符的说明中可以看出门描述符是靠TYPE字段与系统段描述符区分的,但从图2中可见门描述符却与系统段描述符在结构上也不一至,其实这才是区分 二者关键。门描述符的第四字节的低4位为双字计数字段,该字段是说是在发生特权级变换时,把外层堆栈中的参数拷贝到内层堆栈中的数量,计数以双字为单位。

 

10.内核空间和用户空间:每个用户进程都可以访问4GB的线性虚拟内存空间。其中0~3G的虚存地址是用户空间,用户进程可以直接访问。从3GB~4GB的虚存地址为内核空间,存放公内核访问的代码和数据。用户态进程不能访问。所有进程从3GB~4GB的虚拟空间都是一样的,linux以此方式让内核态进程共享代码段和数据段。

11.线性地址。在保护模式下,逻辑地址并不是直接转换为物理地址,而是将逻辑地址首先转换为线性地址,再将线性地址转换为物理地址。虽然沿用了逻辑地址的格式,seg:offset的形式。线性地址是个新概念,简单的说就是0000000h~fffffffh(即0~4G)的线性结构,是32个bite位能表示的一段连续地址。是个抽象的地址。主要为分页机制而产生,通过分页转换为物理地址。

12.在保护模式中seg:offset,seg有个新名字叫段选择子,seg selector。段选择子,GDT,LDT构成了保护膜是的存储结构。描述符十一个线性表(数组),表中存放的是描述符。

13.描述表中记录的段基址加上逻辑地址转换为线性地址。

14.描述符主要包括三部分:段基址base,段限制Limit,段属性Attr。一个任务会涉及多个段,每个段需要一个描述符来描述。为了便于组织管理,80386就将描述符组织成表。

15.段选择子(Selector)由GDTR访问全局描述符表是通过“段选择子”(实模式下的段寄存器)来完成的,如图三①步。段选择子是一个16位的寄存器(同实模式下的段寄存器相同)如图四
 

段选择子包括三部分:描述符索引(index)、TI、请求特权级(RPL)。他的index(描述符索引)部分表示所需要的段的描述符在描述符表的位 置,由这个位置再根据在GDTR中存储的描述符表基址就可以找到相应的描述符(如图三①步)。然后用描述符表中的段基址加上逻辑地址 (SEL:OFFSET)的OFFSET就可以转换成线性地址(如图三②步),段选择子中的TI值只有一位0或1,0代表选择子是在GDT选择,1代表选 择子是在LDT选择。请求特权级(RPL)则代表选择子的特权级,共有4个特权级(0级、1级、2级、3级)。例如给出逻辑地 址:21h:12345678h转换为线性地址
      a. 选择子SEL=21h=0000000000100 0 01b 他代表的意思是:选择子的index=4即100b选择GDT中的第4个描述符;TI=0代表选择子是在GDT选择;左后的01b代表特权级RPL=1
      b. OFFSET=12345678h若此时GDT第四个描述符中描述的段基址(Base)为11111111h,则线性地址=11111111h+12345678h=23456789h

(3)局部描述符表LDT(Local Descriptor Table)局部描述符表可以有若干张,每个任务可以有一张。我们可以这样理解GDT和LDT:GDT为一级描述符表,LDT为二级描述符表。如图五


  LDT和GDT从本质上说是相同的,只是LDT嵌套在GDT之中。LDTR记录局部描述符表的起始位置,与GDTR不同LDTR的内容是一个段选择子。由 于LDT本身同样是一段内存,也是一个段,所以它也有个描述符描述它,这个描述符就存储在GDT中,对应这个表述符也会有一个选择子,LDTR装载的就是 这样一个选择子。LDTR可以在程序中随时改变,通过使用lldt指令。如图五,如果装载的是Selector 2则LDTR指向的是表LDT2。举个例子:如果我们想在表LDT2中选择第三个描述符所描述的段的地址12345678h。
        1. 首先需要装载LDTR使它指向LDT2 使用指令lldt将Select2装载到LDTR
        2. 通 过逻辑地址(SEL:OFFSET)访问时SEL的index=3代表选择第三个描述符;TI=1代表选择子是在LDT选择,此时LDTR指向的是 LDT2,所以是在LDT2中选择,此时的SEL值为1Ch(二进制为11 1 00b)。OFFSET=12345678h。逻辑地址为1C:12345678h
        3. 由SEL选择出描述符,由描述符中的基址(Base)加上OFFSET可得到线性地址,例如基址是11111111h,则线性地址=11111111h+12345678h=23456789h
        4. 此时若再想访问LDT1中的第三个描述符,只要使用lldt指令将选择子Selector 1装入再执行2、3两步就可以了(因为此时LDTR又指向了LDT1)
    由于每个进程都有自己的一套程序段、数据段、堆栈段,有了局部描述符表则可以将每个进程的程序段、数据段、堆栈段封装在一起,只要改变LDTR就可以实现对不同进程的段进行访问。
    存储方式是保护模式的基础,学习他主要注意与实模式下的存储模式的对比,总的思想就是首先通过段选择子在描述符表中找到相应段的描述符,根据描述符中的段基址首先确定段的位置,再通过OFFSET加上段基址计算出线性地址。

posted @ 2012-03-29 13:44  FollylloF  阅读(257)  评论(0编辑  收藏  举报