【问题标题】:GCC inline asm: constraint for direct memory referenceGCC inline asm:直接内存引用的约束
【发布时间】:2014-06-12 18:02:36
【问题描述】:

我需要 GCC 为内联 asm 生成一组一致的指令,但我使用的其中一条指令有时会以两种不同的方式编译:

__asm__ ("mov %1,%%rax;" \
         : \
         : "m"(ref) \
         : "%rax");

编译#1:

mov 0x200894(%rip),%rax

编译#2:

mov 0x200894(%rip),%rdx
mov (%rdx),%rax

我不确定第二个版本的原因是什么,但我不想要它。是否有限制指定内存引用只能是直接的,即不能通过寄存器?


更新:

这种变化总是产生完全相同的指令:

    __asm__ ("mov ref@GOTPCREL(%rip),%rax");

编译为:

mov 0x200910(%rip),%rax

【问题讨论】:

  • 这两个指令序列是不等价的。在第一个0x200894(%rip) 中直接包含结果,在第二个0x200894(%rip) 中包含指向结果的指针。 ref 是什么?它在两种情况下都具有相同的类型吗?它是指向从 DLL 导出的函数或对象的指针(有时可能必须是通过“GOT”的间接引用)?
  • 它是extern const char *ref,第二个版本只出现在共享库中——因此即使变量是在库中定义的,它也必须具有 GOT 引用。我能以某种方式避免这种情况吗?
  • 我不确定。这里对 GOT 机制有很好的描述:eli.thegreenplace.net/2011/11/03/… 如果有办法做你想做的事,那篇文章可能会给你一个线索(或起点)。
  • @MichaelBurr:谢谢,我找到了方法(见更新)。
  • 拜伦,您应该发布您的解决方案作为您自己问题的答案。这很有趣。

标签: c gcc inline-assembly


【解决方案1】:

回答我自己的问题:

这种变化总是产生完全相同的指令:

__asm__ ("mov ref@GOTPCREL(%rip),%rax");

编译为:

mov 0x200910(%rip),%rax

对于 RIP-relative 不可用的 x86,需要两条指令:

__asm__ ("mov $_GLOBAL_OFFSET_TABLE_,%%eax; \
          add ref@GOT,%%eax;");

编译为:

mov $0x2ff7,%eax
add 0xfffffff0,%eax

要使%eax RIP-relative,还需要两条指令,但我正在使用二进制翻译器,在内部更容易做到这一点。

【讨论】:

    猜你喜欢
    • 2016-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-07
    • 2011-04-23
    相关资源
    最近更新 更多