【问题标题】:When are logical addresses created?什么时候创建逻辑地址?
【发布时间】:2018-10-02 21:04:19
【问题描述】:

我总是指 x86 (Linux)

  • 在生成二进制文件期间是否创建了逻辑地址?
  • 如果是,它们是否在二进制文件中?

谢谢

【问题讨论】:

    标签: compilation x86 operating-system virtual-memory


    【解决方案1】:

    在 x86 中,逻辑地址(也称为远指针)由 16 位段选择器和 16/32/64 位偏移量(也称为近指针)组成。偏移量的大小取决于操作模式、代码段描述符和地址大小前缀。然后段选择器用于获取段基地址(或者它是从段描述符缓存中获得的,除非在 64 位模式下运行,其中除了 FS 和 GS 之外的所有段的基地址都被认为为零)为添加到偏移量以形成虚拟地址。 x86 ISA 无法完全跳过该过程。所以任何 x86 指令都必须分别(隐式或显式)指定构成逻辑地址的两部分。

    在生成二进制文件期间是否创建了逻辑地址?

    x86 二进制文件包含 x86 指令。每条指令都指定使用哪个段寄存器以及如何计算偏移量(使用诸如基数、索引、比例和位移之类的东西)。在运行时,当一条指令正在执行时,会计算偏移量并确定段选择器值。因此,从技术上讲,x86 指令只告诉 CPU 从哪里获取段选择器以及如何计算偏移量,但生成逻辑地址的是 CPU。通常,编译器和操作系统确定偏移量的值,但只有操作系统控制段选择器的值。

    如果是,它们是否在二进制文件中?

    x86 指令可以将偏移量指定为立即值(常量)。段部分可以指定为立即值(远调用或 var 跳转),从段寄存器中获取,或从内存中获取(远返回)。所以偏移量的可能是使用它的指令编码的二进制,但是段选择器的可能不是。

    【讨论】:

    • 我认为 OP 只是指虚拟地址,而不是 x86 线性地址。此外,他们还询问了 Linux,它使用 base=0 的平面内存模型。无需使用 x86 分割使事情变得过于复杂。 所以任何 x86 指令都必须分别指定构成逻辑地址的两个部分。 有点误导,因为段部分通常是隐式的,与 ARM 或指令格式中的其他任何内容相比基本上没有开销。跨度>
    • 另外,段寄存器中的段选择器值仅在第一次写入时使用,以更新缓存的描述符信息。 The selector value is not re-checked for every instruction that uses the same segment, not even implicitly.。在更新它选择的 GDT / LDT 条目后,您必须重新加载 ds
    • @PeterCordes 我基本同意。我已经从字面上解释了这个问题。除了用于线程本地存储的 FS 和 GS 之外,内存模型是平坦的。当我说“x86 指令必须指定...”时,我的真正意思是明确地。我已经稍微改进了答案。
    【解决方案2】:

    LINKER 定义进程用户地址空间的初始布局。然后链接器定义逻辑地址的范围和它们的页面属性(读或读/写,执行或不执行)。

    逻辑地址空间的用户区在可执行文件运行时由程序加载器设置。

    你的问题的答案

    在生成二进制文件期间是否创建了逻辑地址?

    然后取决于您的意思是“创建”是在定义逻辑地址空间时(链接器)还是您的意思是在设置时(程序加载器)。

    【讨论】:

      猜你喜欢
      • 2015-06-25
      • 2011-06-30
      • 1970-01-01
      • 2018-07-06
      • 2017-05-23
      • 1970-01-01
      • 1970-01-01
      • 2015-01-22
      • 2012-03-25
      相关资源
      最近更新 更多