正在加载图片...
问4GB大的内存。段地址加偏移地址的计算方法显然无法覆盖这么大的范围。但计算一下 就可以发现,实际上和8086同样的限制己经不复存在,因为80386所有的通用寄存器都是 32位的,2的32次方相当于4G,所以用任何一个通用寄存器来间接寻址,不必分段就已经 可以访问到所有的内存地址 这是不是说,在保护模式下,段寄存器就不再有用了呢?答案是否定的。实际上段寄存 器更有用了,虽然在寻址上不再有分段的限制问题,但在保护模式下,一个地址空间是否可 以被写入,可以被多少优先级的代码写入,是不是允许执行等涉及保护的问题就出来了。要 解决这些问题,必须对一个地址空间定义一些安全上的属性。段寄存器这时就派上了用途 但是涉及属性和保护模式下段的其他参数,要表示的信息太多了,要用64位长的数据才能表 示。我们把这64位的属性数据叫做段描述符( Segment Descriptor) 80386的段寄存器是16位的,无法放下保护模式下64位的段描述符。如何解决这个新 的问题呢?解决办法是把所有段的段描述符顺序放在内存中的指定位置,组成一个段描述符 表( Descriptor Table);而段寄存器中的16位用来做索引信息,指定这个段的属性用段描述 符表中的第几个描述符来表示。这时,段寄存器中的信息不再是段地址了,而是段选择器 ( Segment Selector)。可以通过它在段描述符表中选择一个项目以得到段的全部信息。 既然这样,段描述符表放在那里呢?80386中引入了两个新的寄存器来管理段描述符表 个是48位的全局描述符表寄存器GDTR,一个是16位的局部描述符表寄存器LDIR。那 么,为什么有两个描述符表寄存器呢? GDIR指向的描述符表为全局描述符表GDT( Global Descriptor Table)。它包含系统中所 有任务都可用的段描述符,通常包含描述操作系统所使用的代码段、数据段和堆栈段的描述 符及各任务的LDT段等:全局描述符表只有一个。 LDTR则指向局部描述符表LDT( Local Descriptor Table)。80386处理器设计成每个任务 都有一个独立的LDT。它包含有每个任务私有的代码段、数据段和堆栈段的描述符,也包含 该任务所使用的一些门描述符,如任务门和调用门描述符等。 不同任务的局部描述符表分别组成不同的内存段,描述这些内存段的描述符当做系统描 述符放在全局描述符表中。和GDTR直接指向内存地址不同,LDTR和CS,DS等段选择器 样只存放索引值,指向局部描述符表内存段对应的描述符在全局描述符表中的位置。随着 任务的切换,只要改变LDTR的值,系统当前的局部描述符表LDT也随之切换,这样便于 各任务之间数据的隔离。但GDT并不随着任务的切换而切换。 看到这里,读者可能会提出一个问题,既然有全局描述符表和局部描述符表两个表,那 么段选择器中的索引值对应哪个表中的描述符呢。实际上,16位的段选择器中只有高13位 表示索引值。剩下的3个数据位中,第0,1位表示程序的当前优先级RPL:第2位T位用 来表示在段描述符的位置:T=0表示在GDT中,T1=1表示在LDT中 以图1.3为例,在保护模式下,同样以 xxxX. yyyyyyyy格式表示一个虚拟地址。单单凭 段选择器中的数值xxx根本无法反映出段的基址在哪里。对于这个地址,首先要看xxx的 TI位是否为0,如果是的话,则先从GDTR寄存器中获取GDT的基址(图中的步骤①),然 后在GDT中以段选择器xw的高13位当做位置索引得到段描述符(步骤②)。段描述符包 含段的基址、限长、优先级等各种属性,这就得到了段的起始地址(步骤③);如果xx的 ∏I位为1的话就更复杂了,这表示段描述符在LDT中,这时第一步的操作还是从GDTR寄 存器中获取GDT的基址(步骤①),并且要从LDTR中获取LDT所在段的位置索引(步骤问 4 GB 大的内存。段地址加偏移地址的计算方法显然无法覆盖这么大的范围。但计算一下 就可以发现,实际上和 8086 同样的限制已经不复存在,因为 80386 所有的通用寄存器都是 32 位的,2 的 32 次方相当于 4G,所以用任何一个通用寄存器来间接寻址,不必分段就已经 可以访问到所有的内存地址。 这是不是说,在保护模式下,段寄存器就不再有用了呢?答案是否定的。实际上段寄存 器更有用了,虽然在寻址上不再有分段的限制问题,但在保护模式下,一个地址空间是否可 以被写入,可以被多少优先级的代码写入,是不是允许执行等涉及保护的问题就出来了。要 解决这些问题,必须对一个地址空间定义一些安全上的属性。段寄存器这时就派上了用途。 但是涉及属性和保护模式下段的其他参数,要表示的信息太多了,要用 64 位长的数据才能表 示。我们把这 64 位的属性数据叫做段描述符(Segment Descriptor)。 80386 的段寄存器是 16 位的,无法放下保护模式下 64 位的段描述符。如何解决这个新 的问题呢?解决办法是把所有段的段描述符顺序放在内存中的指定位置,组成一个段描述符 表(Descriptor Table);而段寄存器中的 16 位用来做索引信息,指定这个段的属性用段描述 符表中的第几个描述符来表示。这时,段寄存器中的信息不再是段地址了,而是段选择器 (Segment Selector)。可以通过它在段描述符表中 选择 一个项目以得到段的全部信息。 既然这样,段描述符表放在那里呢?80386 中引入了两个新的寄存器来管理段描述符表。 一个是 48 位的全局描述符表寄存器 GDTR,一个是 16 位的局部描述符表寄存器 LDTR。那 么,为什么有两个描述符表寄存器呢? GDTR 指向的描述符表为全局描述符表 GDT(Global Descriptor Table)。它包含系统中所 有任务都可用的段描述符,通常包含描述操作系统所使用的代码段、数据段和堆栈段的描述 符及各任务的 LDT 段等;全局描述符表只有一个。 LDTR 则指向局部描述符表 LDT(Local Descriptor Table)。80386 处理器设计成每个任务 都有一个独立的 LDT。它包含有每个任务私有的代码段、数据段和堆栈段的描述符,也包含 该任务所使用的一些门描述符,如任务门和调用门描述符等。 不同任务的局部描述符表分别组成不同的内存段,描述这些内存段的描述符当做系统描 述符放在全局描述符表中。和 GDTR 直接指向内存地址不同,LDTR 和 CS,DS 等段选择器 一样只存放索引值,指向局部描述符表内存段对应的描述符在全局描述符表中的位置。随着 任务的切换,只要改变 LDTR 的值,系统当前的局部描述符表 LDT 也随之切换,这样便于 各任务之间数据的隔离。但 GDT 并不随着任务的切换而切换。 看到这里,读者可能会提出一个问题,既然有全局描述符表和局部描述符表两个表,那 么段选择器中的索引值对应哪个表中的描述符呢。实际上,16 位的段选择器中只有高 13 位 表示索引值。剩下的 3 个数据位中,第 0,1 位表示程序的当前优先级 RPL;第 2 位 TI 位用 来表示在段描述符的位置;TI=0 表示在 GDT 中,TI=1 表示在 LDT 中。 以图 1.3 为例,在保护模式下,同样以 xxxx:yyyyyyyy 格式表示一个虚拟地址。单单凭 段选择器中的数值 xxxx 根本无法反映出段的基址在哪里。对于这个地址,首先要看 xxxx 的 TI 位是否为 0,如果是的话,则先从 GDTR 寄存器中获取 GDT 的基址(图中的步骤①),然 后在 GDT 中以段选择器 xxxx 的高 13 位当做位置索引得到段描述符(步骤②)。段描述符包 含段的基址、限长、优先级等各种属性,这就得到了段的起始地址(步骤③);如果 xxxx 的 TI 位为 1 的话就更复杂了,这表示段描述符在 LDT 中,这时第一步的操作还是从 GDTR 寄 存器中获取 GDT 的基址(步骤○1' ),并且要从 LDTR 中获取 LDT 所在段的位置索引(步骤
<<向上翻页向下翻页>>
©2008-现在 cucdc.com 高等教育资讯网 版权所有