3

我一直在实模式下编写 x86 asm 程序(引导加载程序),并且我知道如何使用段、寄存器和类似的东西。

我从 OllyDbg 之类的调试器和类似的调试器中看到 DS 寄存器、SS 等……显然被使用了……但是普通的“类似 Windows”的进程如何使用它们呢?我知道分段被部分使用(只是为了将 ring0 与 ring3 分开)并且它们的条目在 GDT 中,我知道这涉及到分页,这会完全混淆 PDE 和 PTE 的地址,但我不能完全“链接” 将所有内容放在一起并了解数据堆栈额外段的全部内容。每个进程是否有不同的 DS/SS/ES?

4

2 回答 2

2

来自 1986 年英特尔 80386 程序员参考手册:

Figure 5-1.  Address Translation Overview

             15           0      31                           0
    LOGICAL ╔═══════════════╗   ╔══════════════════════════════╗
    ADDRESS ║    SELECTOR   ║   ║            OFFSET            ║
            ╚═══════════╤═══╝   ╚═══╤══════════════════════════╝
                        v           v
                     ╔══════════════════════════════╗
                     ║     SEGMENT TRANSLATION      ║
                     ╚══════════════╤═══════════════╝
                                 ╔══╧═╗       PAGING ENABLED
                                 ║PG ?╟────────────────────┐
                                 ╚══╤═╝                    │
                   31        PAGING v DISABLED       0     │
          LINEAR  ╔═══════════╦═══════════╦═══════════╗    │
          ADDRESS ║    DIR    ║   PAGE    ║  OFFSET   ║    │
                  ╚═══════════╩═════╤═════╩═══════════╝    │
                                    v                      │
                     ╔══════════════════════════════╗      │
                     ║       PAGE TRANSLATION       ║      │
                     ╚══════════════╤═══════════════╝      │
                                    │<─────────────────────┘
                      31            v              0
            PHYSICAL ╔══════════════════════════════╗
            ADDRESS  ║                              ║
                     ╚══════════════════════════════╝


Figure 5-2.  Segment Translation

           15              0    31                                   0
  LOGICAL ╔════════════════╗   ╔═════════════════════════════════════╗
  ADDRESS ║    SELECTOR    ║   ║                OFFSET               ║
          ╚═══╤═════════╤══╝   ╚═══════════════════╤═════════════════╝
       ┌──────┘         v                          │
       │ DESCRIPTOR TABLE                          │
       │  ╔════════════╗                           │
       │  ║            ║                           │
       │  ║            ║                           │
       │  ║            ║                           │
       │  ║            ║                           │
       │  ╠════════════╣                           │
       │  ║  SEGMENT   ║ BASE          ╔═══╗       │
       └─>║ DESCRIPTOR ╟──────────────>║ + ║<──────┘
          ╠════════════╣ ADDRESS       ╚═╤═╝
          ║            ║                 │
          ╚════════════╝                 │
                                         v
              LINEAR  ╔════════════╦═══════════╦══════════════╗
              ADDRESS ║    DIR     ║   PAGE    ║    OFFSET    ║
                      ╚════════════╩═══════════╩══════════════╝

在 Windows 中,大多数时间在大多数进程中 DS=ES=SS,并且 CS 和 DS 的值在所有进程之间共享。进程可能会更改它们的段寄存器,但它很少需要,因此大多数时候您会看到相同的 CS 和 DS/ES/SS 值集。内核使用自己的 CS 和 DS。

于 2012-10-06T18:43:28.670 回答
2

通常,在 x86 保护模式和 x86-64 长模式下,实际上不使用分段(平面内存模型)。有四个主要的段描述符,每个都允许访问整个地址空间:ring0 代码、ring0 数据、ring3 代码、ring3 数据。使用分页来强制执行内存保护。因此,通常所有进程都被赋予相同的 CS、DS、SS、ES 值。

请注意,某些操作系统在寻址本地数据时使用 FS 和 GS 段,例如Windows 中的 TIB

还值得一提的是,虽然在 x86 保护模式下这种行为是可选的,内核可以自由使用多个段来保护内存,但在 x86-64 长模式下,分段通常被禁用,操作系统被迫使用平面内存模型(尽管它仍然可以使用 FS 和 GS 来寻址本地数据和操作系统结构)。

您可能还想查看有关 x86 和 x86-64 架构的宝贵信息来源:Intel Manual 3A(第 3.2 节应该澄清您对分段的所有疑问)

于 2012-10-06T18:41:35.513 回答