在x86架构的实模式下,如何将段基址与偏移地址结合来计算物理地址,取决于正在执行的指令以及这些指令引用的寄存器。下面是一些常见情况:
默认段寄存器和偏移寄存器的使用:
- 代码段(CS):当执行跳转和调用指令时,默认使用
CS
寄存器作为基址。指令指针IP
(或在某些指令中使用的偏移量)提供偏移地址。 - 数据段(DS):大多数数据相关的指令(如
MOV
、ADD
等操作内存的指令)默认使用DS
寄存器作为段基址。通用寄存器(如AX
、BX
、CX
、DX
、SI
、DI
等)中的值通常用作偏移地址。 - 堆栈段(SS):与堆栈操作相关的指令(如
PUSH
、POP
、CALL
、RET
等)默认使用SS
寄存器作为段基址,而堆栈指针SP
或基指针BP
用作偏移地址。 - 附加段(ES):某些指令允许或要求使用
ES
作为额外的段寄存器,通常与字符串操作指令(如MOVSB
、MOVSW
)结合使用。在这些操作中,ES
用于目标地址的段基址,而DI
通常用作目标的偏移地址。
显式指定段寄存器:
在某些指令中,可以显式指定使用哪个段寄存器,这是通过在指令中包含段寄存器的前缀来实现的。例如:
code
mov ax, ds:[bx] ; 使用DS作为段基址,BX作为偏移地址
mov ax, es:[di] ; 使用ES作为段基址,DI作为偏移地址
在保护模式下,段寄存器(CS
、DS
、ES
、SS
、FS
、GS
)的工作原理有所不同。它们存储的不再是段基址,而是指向段描述符的选择子(Selector)。这些选择子与全局描述符表(GDT)或局部描述符表(LDT)中的条目相关联,每个条目定义了段的基址、大小和访问权限。在这种模式下,段寄存器和偏移寄存器的组合仍然用于内存访问,但实际的物理地址计算涉及到段描述符中定义的段基址。