曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 4720|回复: 3
打印 上一主题 下一主题

[X86] 分段机制

[复制链接]

4917

主题

5879

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34382
跳转到指定楼层
楼主
发表于 2011-1-2 22:30:42 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
一、虚拟地址(逻辑地址)到线性地址的转换


虚拟地址(逻辑地址)空间最多可包含 16K (16384)个段,每个段最长可达 4GB,因此虚拟地址空间的容量高达 64TB (2^32^14=2^46)。在 16K 个段中,平均分成两部分,一半(2^13=8192)是由 GDT 映射的全局虚拟地址空间;另一半是由 LDT 映射的局部虚拟地址空间。如下图所示:

4917

主题

5879

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34382
沙发
 楼主| 发表于 2011-1-2 22:47:36 | 只看该作者

逻辑地址到线性地址的转换

二、逻辑地址(虚拟地址)转换为线性地址


过程描述
1. 首先,在 GDT (全局描述符表)或 LDT (局部描述符表)中会存放有段描述符(段描述符就是一些描述我们要寻址的段的属性的数据)。段描述符就是通过段选择符中的偏移值(段索引)获取得来的。

2. 利用段描述符检验检验段的访问权限和范围,以确保该段是可以访问的并且偏移量在段界限内。

3. 把段描述符中的段基址和偏移量相加,最后形成一个线性地址。

如果没有开启分页机制,那么这个线性地址就会被映射到物理地址上。如果开启了分页机制,那么就会用二级地址转换再映射到物理地址上。

4917

主题

5879

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34382
板凳
 楼主| 发表于 2011-1-3 15:01:31 | 只看该作者

段选择符和段寄存器

段描述符存放在段描述符表中,利用段选择符可以从段描述符表中取出段描述符。

段选择符(Segment Selector)是 16 位长结构,如下图所示:

RPL (0-1) 是请求者特权,它提供了段的保护信息。其组合 00,01,10,11 分别代表了0级,1级,2级,3级 4 个特权级。

TI (2-3) 是描述符指示器,TI=0 时表示段描述符在 GDT 中,TI=1 时表示段描述符在 LDT 中。

描述符索引(3-15) 共 13 位,它是放在 GDT 或 LDT 中相应的段描述符的入口。

一个段描述符是 8 字节长,所以段描述符在 GDT 或 LDT 内的相对地址是通过 "index * 8" 得到的。比如,如果 GDT 所在地址为 0x00020000 (这个值保存在 gdtr 寄存器中),而且段选择符的索引值为 2,那么相应的段描述符的地址就是:0x00020000 + (2 x 8) ,即 0x00020010 。

但是,GDT 的第一项总是为 0。这么做,就确保了空段选择符的逻辑地址会被认为是无效的,如果遇到无效的逻辑地址,那么会引起一个处理器异常。因此,能够保存在 GDT 中的段描述符的最大数目是 8191 个,即 2^13 - 1 。

通过段选择符定位到段描述符原理如下图所示:



那么段选择符是放在哪里的呢?

答案是段寄存器,也就是我们常见的 CS, DS, SS, ES, FS 和 GS 。实际上,段寄存器的唯一目的也就是存放这些段选择符。

可能会问,有这么段,但只有这 6 个段寄存器,它们够用吗?不用担心,做法是如果你要访问其它段时,可以先将原先的段寄存器中的内容保存到内存中,等用完之后再恢复就好了。

上面 6 个寄存器中,其中 3 个寄存器有特定的用途:

CS:代码段寄存器,它指向包含指令的段。
SS:堆栈段寄存器,它指向包含当前程序栈的段。
DS:数据段寄存器,它指向包含静态数据或者全局数据段。

其它 3 个辅助段寄存器用作一般用途,可以指向任意的数据段。

实际上,段寄存器并不是只有 16 位,它还有隐藏的一部分,如下图所示:

这个隐藏部分即所谓的“影子寄存器”,它的作用就是对段描述符进行缓冲,而缓冲就是为了加速访问。

当一个段选择符被加载到一个段寄存器的可见部分时,处理器同时也会把段选择符指向的段描述符中的段地址、段限长以及相关的访问控制信息也加载到段寄存器中的隐藏部分中。这样,内存中的段描述符信息就被缓冲到寄存器中来,从而使在地址转换时就无需花费时间再从段描述符(段描述放在内存中)中读取相应信息。相比内存,CPU 访问寄存器的速度要快得多!

4917

主题

5879

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34382
地板
 楼主| 发表于 2011-1-3 21:11:36 | 只看该作者

段描述符

顾名思义,段描述符就是描述一个段属性(位置,大小,访问控制等)的数据结构,它存放在段描述符表中,每个段描述符为 8 个字节,其中三个主要字段为:
      段基地址
      段限长
      段属性
通用段描述符格式如下图所示:


描述符字段说明

1. 基地址字段 BASE :
BASE 一共有 32 位,该字段定义在 4GB 线性地址空间中的首字节的线性地址。

2. 颗粒度标志 G (Granularity) :
粒度标志。如果 G=0,则段大小以字节为单位;如果 G=1,则段大小以 4096 字节(4K)的倍数计。

3. 段限长 Limit :
存放段中最后一个内存单元的偏移量,从而决定段的长度。段的长度还需要配合上面的 G 位一起判断:
如果 G=0,那么段的长度从 1 字节到 1MB 字节之间变化;
如果 G=1,那么段的长度从 4KB 到 4GB 之间变化。

4. 描述符类型标志 S :
S=0 时表示这是一个系统段;
S=1 时表示这个这是一个普通的代码段或数据段。

5. 段类型 Type :
指定段或门(Gate)的类型、说明段的访问种类以及段的扩展方向。TYPE 字段的编码对代码段、数据段或系统段的描述符都不同,如下图所示:

上图中,当第 S=0 时,表示该段是系统段描述符;当 S=1 时,表示该段是代码段或数据段描述符。区分到底是数据段还是代码段,要看 TYPE 域中的最高位是 1 还是 0。如果为 0,则表示是数据段;如果为 0,则表示是代码段。

如果是代码段,那么 TYPE 域中的低 3 位分别是:
      A  (Accessed),已访问位,如果 A=1 表示已访问,如果 A=0 则表示还未访问。
      W (Write-enable),可写位,如果 W=1 表示可读写,如果 W=0 表示只读。
      E (Expansion-direction),扩展方向位,E=1 表示向下扩展,E=0 表示无扩展。
已访问位表示自从上次系统复位后一个段是否被访问过。当一个段的段选择符被加载时,该位就会被置位,表明此段已被访问。该位需要明确清除,否者一直保持置位状态。该位可用于虚拟内存管理和调试。

堆栈段必须是可读可写的数据段,如果是堆栈段的话,则 W=1。假如将不可写的数据段的段选择符加载到 SS 寄存器中,将导致一个一般保护异常。如果堆栈段的长度需要动态的改变,那么堆栈段可以是一个向下扩展的数据段(E=1)。

如果是代码段,类型字段的低 3 位要被解释成:
      A (Accessed) : 同数据段的 A 。
      R (Read-enable) : R=1 时,该代码段可执行、可读;R=0 时,该代码段仅能执行,但不可读。
      C (Conforming) : C=1 时,表示为一致性代码段;C=0 时,表示非一致性代码段。
代码段可以是是一种仅能执行的段,也可以是一种既可以执行又可读的代码段。对于可读可执行的代码段,举一个例子来说,例如当常数随着指令码都被放到 RAM 中时,可执行的是指令代码,可读的是则是那些常数。在这种情况下,可以通过使用一条带 CS 前缀的指令来读取数据;还可以代码段选择符加载进一个数据寄存器(DS,ES,FS 或 GS),这样也能读取代码段中的数据。在保护模式下,代码段是不可写的。




6. 描述符特权级 DPL (Descripor privilege level):
特权级范围从 0 到 3。0 级特权级最高,3 级最低。这个字段用于限制对这个段的存取,它指明描述符的特权级。例如,DPL 设为 0 的段只能当 CPL (当前特权级) 为 0 时 (即在内核态)才可以访问,而 DPL 为 3 时,则对任何 CPL 的值都是可以访问的。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2024-5-15 12:49 , Processed in 0.067924 second(s), 21 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表