【问题标题】:Accessing C++ class member in inline assembly在内联汇编中访问 C++ 类成员
【发布时间】:2011-01-03 09:18:16
【问题描述】:

问题:如何从非 POD 类中访问程序集中的成员变量?


阐述:

我已经为类成员函数编写了一些内联汇编代码,但我不知道如何访问类成员变量。我试过 offsetof 宏,但这是一个非 POD 类。

我正在使用的当前解决方案是将全局范围的指针分配给成员变量,但这是一个混乱的解决方案,我希望有更好的东西我不知道。

注意:我使用的是 G++ 编译器。使用 Intel 语法 Asm 的解决方案会很好,但我会采取任何措施。

我想做的例子(intel语法):

class SomeClass
{
  int* var_j;
  void set4(void)
  {
    asm("mov var_j, 4"); // sets pointer SomeClass::var_j to address "4"
  }
};

当前的黑客解决方案:

int* global_j;
class SomeClass
{
  int* var_j;
  void set4(void)
  {
    asm("mov global_j, 4"); // sets pointer global_j to address "4"
    var_j = global_j;       // copy it back to member variable :(
  }
};

这些都是粗略的例子,但我认为他们明白了重点。

【问题讨论】:

  • 您是否尝试过使用代码 var_j = 4; 或类似的代码查看 G++ 编译器输出的反汇编?
  • 使用全局指针不是线程安全的,因为它的值可能在重新分配保存的值之前被覆盖

标签: c++ assembly g++ inline-assembly


【解决方案1】:

这就是你所需要的:

__asm__ __volatile__ ("movl $4,%[v]" : [v] "+m" (var_j)) ;

编辑添加: 汇编器确实接受 Intel 语法,但编译器不知道它,所以这个技巧在使用 Intel 语法时不起作用(无论如何,不​​适用于 g++ 4.4.0) .

【讨论】:

  • 这很有趣。此语法不是标准 GCC 内联汇编 HOWTO 的一部分。您是从哪里了解到的?
  • “使用 GNU 编译器集合”(对于 gcc 版本 4.5.1),第 6.39 节“带有 C 表达式操作数的汇编器指令”。可在gcc.gnu.org/onlinedocs/gcc 获取。 (实际上我似乎无法在网络上找到我的版本——在本文档中是第 6.41 节。)
  • 您可以使用-masm=intel 编译以在内联asm 中使用Intel 语法。但一般不会;附加到助记符而不是操作数的 AT&T 语法对于内联汇编通常更容易。
【解决方案2】:
class SomeClass
{
  int* var_j;
  void set4(void)
  {
    __asm__ __volatile__("movl $4, (%0,%1)"
:
: "r"(this), "r"((char*)&var_j-(char*)this)
:
);
  }
};

这也可能有效,为您节省一个寄存器:

    __asm__ __volatile__("movl $4, %1(%0)"
:
: "r"(this), "i"((char*)&var_j-(char*)this)
:
);

其实,由于var_j wrt的偏移量。 this 应该在编译时知道,第二个选项是要走的路,即使它需要一些调整才能使其工作。 (我现在无法访问 g++ 系统,所以我会留给您调查。)

永远不要低估__volatile__ 的重要性。我花了更多的时间来追踪出现的错误,因为我错过了 volatile 关键字,编译器自行对我的程序集做一些奇怪的事情。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-31
    • 2012-04-22
    • 1970-01-01
    相关资源
    最近更新 更多