默认使用哪个段寄存器?

ash*_*ish 3 x86 assembly memory-segmentation

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

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

Pet*_*des 5

代码提取总是使用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指令读取[DS:ESI]和写入[ES:EDI],从而可以轻松地在没有段覆盖前缀的情况下在段之间进行复制。

使用存储器操作数espebp作为基址寄存器默认到SS,因此堆栈的指令等执行隐式访问push/ pop/ call/ ret

FS并且GS从来都不是默认值,因此它们可以在现代 32 位和 64 位操作系统等平面内存模型系统中用于特殊目的(如线程本地存储)。

维基百科在这里解释了同样的事情


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

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

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

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

另请参阅标记 wiki 以获取更多链接。

  • @ashish:在当前的 32 位操作系统中,所有段(除了 FS 和 GS)的 base=0,limit=4GiB,给出了一个平坦的内存空间,其中 `CS`、`DS`、`SS` 和 `ES`都是等价的。段转换发生在虚拟到物理地址转换之前。在实模式下,段寄存器不索引描述符,它们只是乘以 16 并添加到地址的偏移部分。 (2认同)