我正在学习英特尔手册中的计算机体系结构。据我了解,我们给出的指令是逻辑地址,由段选择器和偏移量组成。
它基本上是 CS register<<4 + offset
. Segment Selector
映射到 TI
中给出的 GDT 或 LDT段选择器的位。 GDT 由 Segment Descriptors
组成其中有 BASE
, LIMIT
和 RPL
输出是基地址。这base address
+ offset
提供 logical address
.
决定哪个段寄存器(SS
、DS
等)适用于不同的内存操作的规则是什么?例如是什么决定了哪个段用于mov eax, [edi]
?
最佳答案
代码获取始终使用 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]
,从而可以轻松地在没有段覆盖前缀的段之间进行复制。
使用 esp
或 ebp
作为基址寄存器的内存操作数默认为 SS
,堆栈指令的隐式访问也是如此,例如 push
/pop
/call
/ret
.
FS
和 GS
从来都不是默认值,因此它们可以在平面内存模型系统(如现代 32 和64 位操作系统。
wikipedia explains the same thing here 。
这也在 Intel's ISA manuals 中正式记录。例如在第 2 卷(指令集引用)中,表 2-1。带有 ModR/M 字节的 16 位寻址形式 有一个脚注说:
The default segment register is SS for the effective addresses containing a BP index, DS for other effective addresses.
(注意 SP 不是 16 位寻址模式的有效基地址。
另请注意,当他们说“索引”时,这意味着完全使用 BP,即使是 [bp + si]
或 [bp+di]
。在32位和64位寻址方式下,base和index的区别比较明显,[symbol + ebp*4]
仍然隐含DS为段,因为EBP是作为index使用的,不是基地。)
对于 32 位或 64 位寻址模式没有等效的脚注,因此详细信息必须在手册的另一卷中。
另请参阅 x86 标签 wiki 以获得更多链接。
关于assembly - 默认使用哪个段寄存器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38843403/