【问题标题】:X86_64 - assembly - Why displacement not 64 bits?X86_64 - 装配 - 为什么位移不是 64 位?
【发布时间】:2015-10-29 10:47:52
【问题描述】:

我正在阅读 Intel x86_64 指南 vol.1 以刷新内存寻址的工作原理。

还是,

3.7.5 指定偏移量

内存地址的偏移部分可以直接指定为静态值(称为位移),也可以通过由以下一个或多个组件组成的地址计算来指定:

• 位移 — 8、16 或 32 位值。

我在 Agner Fog 的汇编指南中读到,当与 (r/e)ax 寄存器一起使用时,64 位绝对寻址是可能的。

所以..

是否可以使用 64 位地址的绝对寻址来 jmp、mov 和调用(使用所有寄存器),还是我必须继续使用 Base + 位移组合 ?

【问题讨论】:

  • 既然你在看手册..为什么不查一下呢?
  • @harold:我没有用于该拱门的多个 CPU/品牌。我需要一个普遍而可靠的答案。这就是为什么:)

标签: assembly x86-64 memory-address


【解决方案1】:

请注意,mov absolute_addr64, %raxrax 为目标可用。
mov $imm64, %reg 可用于任何寄存器。
Load from a 64-bit address into other register than raxwhy we can't move a 64-bit immediate value to memory?

AMD 设计 AMD64 架构时,他们基本上说 2GB 的 代码 应该足够每个人使用。 (每个可执行文件和每个共享库;非静态链接在一起的事物之间的调用通常需要通过完整的 64 位地址进行间接调用。)

https://gitlab.com/x86-psABIs/x86-64-ABI 描述了 x86-64 System V ABI 的小型、中型和大型代码模型(用于所有非 Windows 系统。)

  • small:每次跳转、调用和内存位移的正常 32 位相对位移。 (已知所有符号都位于02^31 - 2^24 - 1 之间)。

  • medium:小代码,但数据部分分为两部分:常规和大(.ldatalrodata.lbss)。

此模型需要编译器使用movabs指令 访问大型静态数据并将地址加载到寄存器中,但是 保留了小代码模型的优势,用于操作 在小数据和文本部分的地址(特别需要 分支)

默认情况下,只有大于 65535 字节的数据才会放在大数据段中

  • 大:

编译器需要使用movabs 指令,如 中等代码模型,甚至用于处理文本内的地址 部分。另外,分支时需要间接分支 到与当前指令指针的偏移量为的地址 未知。

可以避免对文字的限制 中小机型通过拆分方案 到多个共享库,所以这个模型是严格只 如果单个函数的文本变得大于 中型允许。

Medium PIC 需要movabs / lea / add 生成大于 32 位位移的 RIP 相对地址。

大型 PIC 也需要它来处理全局偏移表和过程链接表。

【讨论】:

    【解决方案2】:

    只有进出累加器的移动具有 64 位绝对地址变量。
    所有其他移动仅限使用 32 位位移方法。

    【讨论】:

      【解决方案3】:

      我认为 x86 架构没有 64 位位移或偏移量。

      原因很简单:这些提供的编程“轻松”并不经常发生,并不重要。从统计上讲,您需要的大多数偏移量都非常小。当您需要 64 位偏移量(很少)时,您始终可以使用 ADD 指令进行模拟,而几乎不会降低性能。做 64 位偏移的晶体管,最好花在做其他事情上。

      【讨论】:

      • 添加指令?有趣,你会怎么做?我怀疑我会这样做,因为它会产生另一条指令,甚至是 1 个 cpu 周期的指令,这是一种浪费。
      • 如果要进行64位位移的索引操作,则必须将位移添加到基数。因此,以寄存器为基数,添加 64 位常量,然后间接加载或存储目标地址。在 64 位值是直接地址的更特殊情况下,您可以简单地将其加载到寄存器中,然后进行间接寻址。是的,执行 ADD 需要额外的指令。实际上,您不会经常这样做,所以没关系。
      • 好的,非常感谢您的精确
      • 我不认为您可以添加 64 位立即数,但您可以添加存储在内存中的 64 位值,或者将 64 位立即数移动到寄存器中,然后将该寄存器用作地址的一部分。我想知道使用段时的偏移量,例如用于访问“每个线程”变量的 FS 或 GS​​。 rand 的种子值就是其中之一。
      • @rcgldr: 没错,即使add $immediate, %rax 也只能通过符号扩展imm32 使用。如果你希望你的常量内联在指令流中,而不是作为数据加载,你可以movabs $imm64, %rax。 (stackoverflow.com/questions/19415184/…)。最佳计划:将您的 64b 位移保存在一个寄存器中,在另一个寄存器中计算一个索引,并将该索引用作 add 的 dest / 1st src。
      猜你喜欢
      • 2021-07-20
      • 1970-01-01
      • 2011-03-02
      • 1970-01-01
      • 1970-01-01
      • 2021-01-06
      • 2010-12-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多