【问题标题】:Segment Selector in IA-32IA-32 中的段选择器
【发布时间】:2023-03-05 03:57:01
【问题描述】:

段选择器何时出现。英特尔指南中的行说:

"每个段描述符都有一个关联的段选择器。一个段 选择器为使用它的软件提供 GDT 的索引 或 LDT(其关联的段描述符的偏移量), 全局/本地标志(确定选择器是否指向 GDT 或 LDT),以及访问权限信息。”

我不太明白。

是否有单独的段选择器寄存器? 它是如何计算的? 为什么我们需要它?

【问题讨论】:

    标签: assembly operating-system x86


    【解决方案1】:

    GDT 代表 全局描述符表
    这里重要的是 table 这个词,Intel 所说的 table 是指数组。

    作为一个表一个数组,它有元素,每个元素被称为Descriptor。当然每个元素都可以被索引,即它有一个唯一的索引

    段选择器寄存器保存描述符的索引。进入段选择器寄存器的值称为 selector

    但是事情要复杂一些。
    索引 不是 选择器

    除了index之外,一个段选择器寄存器,还有两个东西:

    1. 程序员想要用于访问描述符的权限。对于每个寄存器,这称为 RPL(请求特权级别),但 CS 称为 CPL(当前特权级别)。 RPLCPL 在使用段选择器寄存器中所起的作用在 Intel 手册中有定义,这里就不多解释了。

    2. 用于查看的表。一个表是GDT,另一个是LDT。英特尔手册中再次说明了差异和用途。

    所以非正式的规则是:

    选择器 = 索引 + table_to_use + 权限
    table_to_use + 索引 = 描述符 = 关于要使用的内存段的所有信息

    当然,+ 根本不意味着算术加法。段选择器寄存器的实际位域是

    15                                                 3    2        0
    +--------------------------------------------------+----+--------+
    |          Index                                   | TI |   RPL  |
    +--------------------------------------------------+----+--------+
    
    TI = Table Indicator: 0 = GDT, 1 = LDT
    

    因此,例如值 05h 选择索引为 0 的描述符(在 LDT 中使用 RPL=1),这是无效的,因为英特尔明确要求不这样做使用描述符 0。
    第一个可用的 descriptor 可通过 selector 08h 访问,它选择 GDT 作为表,RPL=0 . 08h-0bh的值都选择GDT中索引为1的descriptor,只是RPL不同。

    这是术语的完整 ASCII 艺术

    <---- Selector ---->    +----- Segment Selector Register
    +-------+----+-----+    v
    | Index | TI | RPL | = DS
    +-------+----+-----+            GDT                        LDT
       |      |             +---------------------+   +---------------------+
       |      +------------>| Null Descriptor     |   | Null Descriptor     |
       |                    +---------------------+   +---------------------+
       |                    | Descriptor 1        |   | Descriptor 1        |
       |                    +---------------------+   +---------------------+
       |                    |                     |   |                     |
       |                    ...     ...    ...   ...  ...     ...    ...   ...
       |                    |                     |
       |                    +---------------------+
       +------------------->| Descriptor K        |
                            +---------------------+
                            |                     |
                            ...     ...    ...   ...
    

    关于它的计算方式以及我们为什么需要它

    简答:阅读英特尔手册,因为它是完整的参考。

    长答案:我们,用户模式程序员,不计算它。由于所有这些与段有关的事情归结为限制程序的权限,并且因为它是操作系统而不是我们发出命令,所以我们只需使用操作系统给我们的值(基本上通过加载我们的程序)作为 GDTLDT 是由 OS 建立的,现在它愿意在任何方面与我们合作。

    我们需要分段,因为在 真实模式 中有分段(Google 了解更多信息),因为它们可以避免在没有分页的情况下重新定位和聚集隔离(Google 了解更多信息)并且因为分段现在包含比简单的基本偏移和限制更多的信息。其中之一是:Descriptor Privilege Level,它限制了用户模式程序的权限。

    【讨论】:

    • LDT 与 GDT 不同,没有 NULL 描述符条目,因此第一个条目有效
    • 您在哪里找到“段选择器寄存器”,您认为段选择器是哪个处理器架构的寄存器?
    • @RaGa__M on 80286+ 实模式下的所有段寄存器在保护模式和兼容模式下都成为选择器。我相信当他们说段选择器寄存器时,他们指的是 CS、DS、ES、FS、GS 和 SS。
    【解决方案2】:

    那么会发生什么:

    每当加载程序时,链接加载程序都会使用适当的选择器加载“段寄存器”。
    段寄存器(例如 CS、DS、SS 等)分为两部分:可见和隐藏。
    它是加载器以适当的值加载的可见部分。
    此值是 GDT 或 LDT 中的索引,具体取决于选择器的 TI 标志。
    处理器自己加载隐藏部分。隐藏部分的信息是线性地址空间中的段基地址、段限制、访问信息。

    【讨论】:

      【解决方案3】:

      在实模式下,对内存的访问是分段的,即通过指定段位置和段偏移来访问。然后通过将偏移量添加到左移段位置来计算物理地址。段位置段和段偏移都是16位。

      由于 Intel 的设计选择显然非常注重向后兼容性,因此他们选择保留 16 位大小的段寄存器。当保护模式出现时,这会导致问题。在保护模式下,GDT(全局描述符表)和 LDT(本地描述符表)保存在内存中的某个位置。这些描述符包含有关处理器使用的段的所有必要数据。为了访问这些描述符,您需要一个段选择器,它本质上是段描述符数组(即 LDT 或 GDT)的索引。

      本质上,将 5 指定为段选择器的值会导致 CPU 使用本地/全局描述符表中的第 5 个(索引从零开始)描述符。

      【讨论】:

      • 那么,如何获取段选择器呢?
      • 获取不到,是你根据应用中要使用的段描述符设置的值。
      • 所以我们需要知道段选择器来选择段描述符。现在,当上下文切换发生时,选择器是从哪里获取的?
      • 您使用LGDT/LLDT/LIDT 指令来加载描述符表。然后,您分配给选择器的任何值都将成为描述符表的索引。例如,将 3 分配给 ES 意味着您之前加载的描述符表中的第 3 个条目的值。并且任何使用 ES: 前缀的访问都将导致使用该条目的内容访问内存。
      猜你喜欢
      • 2011-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-27
      • 1970-01-01
      • 2010-11-22
      • 2014-01-03
      相关资源
      最近更新 更多