如何将类变量加载(mov)到cpu寄存器中

时间:2011-04-18 07:29:20

标签: c++ assembly

我想将定义为类成员的int值加载到eax cpu寄存器。像这样:“

class x
{
    int a;

    x() { a=5; }

    do_stuff()
    {
        __asm
        {
            mov eax, a; // mov a varbiale content into register
        };
    }
};

如何在任何类中使用任何变量?感谢...

3 个答案:

答案 0 :(得分:1)

将类变量加载到寄存器中的最佳方法是让编译器为您完成。

由于编译器总是必须假设最坏的情况,当涉及从内存中读取内容时,可能会被迫多次从类成员中读取值,尽管事实上知道该值没有改变。

例如,在函数do_stuff的下面的代码中,编译器不能假定mX的值在foo()的调用中保持不变。因此,不允许将其放在处理器寄存器中。

int glob;
int glob2;
void foo();

class Test
{
public:
  Test(int x) : mX(x) { }
  void do_stuff();
private:
  int mX;
};


void Test::do_stuff()
{
  glob = mX;
  foo();
  glob2 = mX;
}

另一方面,在下面的例子中,编写源代码使tmp不能改变函数调用,因此编译器可以安全地将它放在寄存器中。

void Test::do_stuff()
{
  int tmp = mX;
  glob = tmp;
  foo();
  glob2 = tmp;
}

对于内联汇编程序,我强烈反对您不使用它。在引入C ++时情况更糟,因为类对象的底层表示不像C结构那样直接(必须在内存中完全按照声明的方式布局)。这意味着类中的轻微更改或迁移到较新的编译器可能会破坏您的代码。

答案 1 :(得分:1)

如果您正在使用gcc或icc,这完全符合您的要求:

class x
{
    int a;

    x() { a=5; }

    do_stuff()
    {
        asm("mov %0, %%eax; // mov a varbiale content into register \n"
            :
            : "r" (a)
            : "%eax"
           );


    }
};

如果您仍感兴趣,则对{rgister约束和clobber列表的解释位于http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html。在MS VC上,我不建议使用内联汇编,因为MS编译器不擅长内联混合并且生成很多开销。

答案 2 :(得分:0)

您需要获取正在使用的类“x”的实例的地址(mov eax,this),以及“a”相对于“x”(offsetof macro)的开头的偏移量。

如果你只是添加“a”或“& a”作为do_stuff()函数的参数,那就容易多了。