我可以告诉你这在 x86 上是如何工作的。
所有非 64 位模式的程序都使用由以下两项组合而成的地址:segment selector(为简洁起见,“选择器”通常在文本中被省略,这可能会造成混淆)和offset。这对selector:offset 称为logical address。
选择器部分并不总是在代码中明确指定或操作,因为 CPU 具有段寄存器的“默认”关联,其中包含具有特定指令或特定指令编码的选择器。在 32 位模式下操作选择器也不常见,但在 16 位代码中却经常需要。
virtual address 由“直接”(real 或 8086 virtual 模式)或“间接”(protected 模式)逻辑地址构成。
"Direct" virtual address = selector * 16 + offset。
"Indirect" virtual address = SegmentDescriptorTable[selector].Base + offset。
SegmentDescriptorTable 是 Global Descriptor Table (AKA GDT) 或本地描述符表 (AKA LDT)。它由操作系统设置,描述了各个内存段的位置和大小。 selector 用于在表格中选择一个段。表的Base 条目告诉段的开始(虚拟地址)。 Limit 条目告诉分段大小(通常;细节稍微复杂一些)。
当程序尝试使用偏移量访问内存时,导致访问超出段末尾(CPU 比较 offset 和 Limit),CPU 生成一个 exception 并且操作系统通过通常终止来处理它程序。
顺便说一句,在real/v86 模式下,即使虚拟地址是直接从selector:offset 形成的,仍然有一个16 位Limit 施加在偏移量上,这就是为什么您需要使用不同的选择器来访问更多超过 64KB 的内存。
段描述符中的Base 条目可用于将段与内存的其余部分隔离(Limit 在此处提供帮助)或将整个段放置或移动到任意虚拟地址而无需修改它所属的程序中的任何东西(或很多东西)(如果我们正在移动一个段,显然必须在内存中移动数据)。基本上,它可以用于重定位目的。在 real/v86 模式下,为了重定位,selector 已更改。
如果 CPU 在protected mode 中运行并已设置page tables,则virtual address 可以进一步转换为physical address。如果没有页表,则物理地址与虚拟地址相同。转换是在称为pages(通常为 4KB)的物理内存块和地址范围中完成的。
x86 CPU 上没有专用的重定位寄存器。搬迁可以通过调整来实现:
- CPU 寄存器或程序代码中的段选择器
- GDT/LDT 中的段基地址
- 程序代码中的偏移量
- 页表中的物理地址
至于virtual address : reside in the hard disk , as a pages,我不确定你到底想说什么,但仅仅因为有虚拟到物理地址的转换,并不意味着也有虚拟磁盘内存。除了虚拟磁盘内存之外,翻译还有其他用途。这些地址驻留在 CPU 中以及您(和操作系统)代码将它们写入的任何位置,不一定在磁盘上。