保护模式下的编程<一>
保护模式下的编程<一>
本文介绍如何在保护模式下编程.虽然这种技术在现在的环境中很难用到,但是如果你想写操作系统,那还是要熟悉的.因为内存管理是操作系统的基础.
保护模式下的编程我也是刚才学的,算个新人.写这遍文章是为了和大家讨论保护模式下编程的心得,如有不妥请指出来.谢谢
从386系列开始出现了保护模式,这就为支持多任务,能够快速地进行任务切换和保护任务环境提供了硬气支持. 真是一伟大的发明呀.呵呵.在保护模式下提供对不同任务的保护和同一个任务不同段的保护.我想象我拥有一个很大的内存,而程序中的代码和数据是分段存储,因此每个段就应该有个段的起始地址和段界限.,每个段应该有自己的属性.这样计算机才能控制那些操作能访问那些段,那些不能访问.所以每个段就应该有段起始地址 段界限 段属性.每一个任务都是有许多不同的段构成的.有些任务有共同的数据段或者代码段,为了节约内存空间.就需要将共同的代码段或者数据段共享.使得多个任务都能访问共享数据..这就要求系统决定那些段是共享的,那些段是私有的.所以每个段就一个特权级数,i386给段分4个级别,0 1 2 3,最常用的是0级,他代表内核模式,3代表用户模式.1和2通常是不用的.
因为可以同时运行多个任务,每个任务又有很多段,这样就给计算机对存取段的操作带来了麻烦,也不利后面的分页机制.因此用一个局部描述表(LDT)来描述一个任务,一个局部描述表,有许多段的描述符构成,所谓段的描述符:是一个占8个字节的空间,他用来一个存储段的起始地址,段界限和段属性。我门可以想象有个叫LDT这样表,他有许多描述符够成,每个描述符指向他对应的段。一个LDT可以构成一个段.每个系统还存在一个全局描述表(GDT),他是由共享段的描述符和许多指向局部描述表段的描述符构成的.(还有中断描述符,这里不做介绍)这样我门可以把内存中的所有段抽象出来,用几张表来表示.如图
我们已经把内存中的段用一个表给抽象出来了,那怎么从表中找到我想要的段呢,这就要通过一个叫段选择子家伙来帮忙了,他长16位,底两位是用来表示特权级的,第3位是用来确定是从GDT,还是从LDT中找我们需要的段,我们用TI来表示这位,TI=0指示从全局描述表GDT中读取描述符;TI=1指示从局部描述表LDT中读取描述符.段选择子的高13位就是描述符索引了.所谓描述符索引是指描述符在描述符表中的序号.这样我门通过段选择子来查找我们想要的段.是不是跟我们找书有点相同呀。呵呵.
学过汇编的人都知道,CPU中包含有许多段寄存器,而每个段寄存器后面都有一个高速缓冲器,但我们把段的选择子存入段寄存器时,系统自动将对应的段描述符存入高速缓冲器.
然后系统根据描述符的信息去访问对应的段.这和实模式下的编程不同,在实模式下,段寄存器装的是段的地址,而在保护模式下,段寄存器中装的是段的选择子.
系统地址寄存器:
系统地址寄存器包括:全局描述符表寄存器GDTR,局部描述符表寄存器LDTR,中断描述符表寄存器IDTR,任务状态段寄存器TR.,后两者这里不做介绍.全局描述表自己构成了一个段,我们用一个伪描述符描述他.他被装如GDTR中,我门用一个结构描述他,如下.
pdesc struc
limit dw 0
base dd 0
pdesc ends
‘局部描述符表寄存器LDTR规定当前任务使用的局部描述符表LDT。LDTR类似于段寄存器,由程序员可见的16位的寄存器和程序员不可见的高速缓冲寄存器组成。在初始化或任务切换过程中,把描述符对应任务LDT的描述符的选择子装入LDTR,处理器根据装入LDTR可见部分的选择子,从GDT中取出对应的描述符,并把LDT的基地址、界限和属性等信息保存到LDTR的不可见的高速缓冲寄存器中。随后对LDT的访问,就可根据保存在高速缓冲寄存器中的有关信息进行合法性检查。
LDTR寄存器包含当前任务的LDT的选择子。所以,装入到LDTR的选择子必须确定一个位于GDT中的类型为LDT的系统段描述符,也即选择子中的TI位必须是0,而且描述符中的类型字段所表示的类型必须为LDT’(杨季文主编的<<80X86汇编语言程序设计教材>> (待续....)