【问题标题】:Which segment register is used by default?默认使用哪个段寄存器?
【发布时间】:2024-01-21 04:24:01
【问题描述】:

我正在学习英特尔手册中的计算机体系结构。我的理解是,我们给出的指令是逻辑地址,由段选择器和偏移量组成。 基本上是CS register<<4 + offsetSegment Selector 映射到 GDTLDT,如段选择器的 TI 位中所给。 GDT 由Segment Descriptors 组成,其中有BASELIMITRPL,输出是基地址。这个base address + offset 提供了logical address

决定哪个段寄存器(SSDS 等)适用于不同内存操作的规则是什么?例如是什么决定了哪个段用于mov eax, [edi]

【问题讨论】:

  • 你的问题我不清楚,你能解释一下吗?
  • 基本上我想知道那个数据段,堆栈段是如何被分配给一个过程的。
  • 这可能对*.com/questions/29785991/…有帮助
  • 说明segment为64kb,在线性地址空间中可以重叠但不说明过程!
  • 我编辑了您的问题,以清楚地问我认为您想问什么,但我可能猜错了。如有必要,请编辑。

标签: assembly x86 memory-segmentation


【解决方案1】:

代码提取始终使用CS

在“正常”寻址模式下,数据寻址模式默认为DS(或SS,当EBP 或ESP 是基址寄存器时)。 (例如mov eax, [edi] 等价于[ds:edi]mov eax, [ebp+edi*4] 等价于mov eax, [ss: ebp + edi*4])。

(某些反汇编程序即使在默认情况下也会显式显示段,因此您会看到很多 DS: 混淆了反汇编输出。(您可以使用段覆盖前缀来选择哪个段将应用于内存操作数一条指令。)在 NASM 语法中,显式使用 [ds:edi] 寻址模式将导致机器代码中出现冗余的 ds 前缀。)

一些带有隐式内存操作数的指令有不同的默认值:

一些字符串指令隐式使用ES:EDI。例如movs instruction[DS:ESI] 读取并写入[ES:EDI],使得在没有段覆盖前缀的段之间进行复制变得容易。

使用espebp作为基址寄存器的内存操作数默认为SS,对于堆栈指令的隐式访问也是如此,如push/pop/call/ret

wikipedia explains the same thing here.


这也正式记录在Intel's ISA manuals 中。例如在第 2 卷(指令集参考)中,表 2-1。带有 ModR/M 字节的 16 位寻址表格有一个脚注说:

对于包含 BP 索引的有效地址,默认段寄存器是 SS,对于其他有效地址,默认是 DS。

(请注意,对于 16 位寻址模式,SP 不是有效的基地址。
另请注意,当他们说“索引”时,这意味着完全使用 BP,即使是 [bp + si][bp+di]。在 32 位和 64 位寻址模式中,基址和索引之间有更清晰的区别,[symbol + ebp*4] 仍然暗示 DS 作为段,因为 EBP 用作索引,不是基址。)

对于 32 位或 64 位寻址模式没有等效的脚注,因此详细信息必须在手册的另一卷中。

有关更多链接,另请参阅 标签 wiki。

【讨论】:

  • 这些段在内存中的什么位置?线性地址?实际地址?
  • @ashish:在当前的 32 位操作系统中,所有段(FS 和 GS 除外)的 base=0,limit=4GiB,提供平坦的内存空间,其中 CSDSSSES 都是等价的。段转换发生在虚拟到物理地址转换之前。在实模式下,段寄存器不索引描述符,它们只是乘以 16 并添加到地址的偏移部分。
  • 在长模式下,即 x86_64 模式?
  • @ashish:IIRC,除了 FS 和 GS 以外的段在长模式下甚至不能有非零碱基。 AMD 为 AMD64 简化/中和了很多,因为 32 位操作系统没有使用该功能。只有 Multics 粉丝感到失望:*.com/a/10810340/224132
  • 该链接回答了我的问题。谢谢!