如何在GCC中通过asm获取类成员函数的地址?

时间:2016-09-20 09:06:19

标签: gcc assembly inline-assembly

家伙!我有个问题。如何在GCC中通过asm获取类成员函数的地址?

在VS2012中,我们可以在下面的代码中获取地址。

asm {mov eax, offset TEST::foo}

但是,在GCC?

__asm__ __volatile__(
                     "movq offset %1, %%rdi"
                     "movq %%rdi, %0"
                     :"=r"(addr)
                     :"r"(&TEST::foo)
);

失败了......

1 个答案:

答案 0 :(得分:1)

AT& T语法不使用offset关键字。此外,您已经要求编译器将&TEST::foo放入寄存器中。

__asm__ (
                 "mov %1, %0"
                 :"=r"(addr)
                 :"r"(&TEST::foo)
);

或更好:

__asm__ ( ""                // no instructions
          :"=r"(addr)
          :"0"(&TEST::foo)  // same register as operand 0
);

甚至更好:addr = &TEST::foo; https://gcc.gnu.org/wiki/DontUseInlineAsm为此,因为它阻止编译器知道发生了什么。

但是如果 要使用内联asm,请确保让编译器为您尽可能多地执行操作。使用约束来告诉它您想要输入的位置以及输出的位置。如果inline-asm语句的第一个或最后一个指令是mov,通常这意味着你做错了。 (请参阅 tag wiki以获取指向如何编写GNU C inline asm的指南的链接。

你原来的错误:你没有在RDI上声明一个clobber,所以编译器仍然假设你没有修改它。

如果在asm语句中运行代码的唯一原因是生成输出操作数,而不是副作用,则不需要volatile。退出volatile可让编译器围绕它进行优化,如果输出未使用,甚至可以完全删除它。