【问题标题】:Should I push on the stack, use a register, or a variable?我应该压栈,使用寄存器还是变量?
【发布时间】:2012-06-12 21:27:38
【问题描述】:

我需要保存一个寄存器的值(即[ar]ax)。它在函数调用后被修改,但该值需要稍后使用。 我想到了三种方法(示例是 64 位):

1.入栈:

__asm__ ("pushq %rax\n\t"
         "call function\n\t"
         "popq %rax");

2.保存在寄存器中:

__asm__ ("movq %%rax, %%some_register\n\t"
         "call function\n\t"
         "movq %%some_register, %%rax"
         : : : "%some_register");

3.将其保存在变量中:

unsigned long var;
__asm__ ("movq %%rax, %0" : "=m" (var) : : );
function();
__asm__ ("movq %0, %%rax" : : "m" (var) : );

目前,我正在使用#1。它在我的特定情况下按预期工作,但我担心将它推入堆栈可能是一件坏事™。我最担心的是:编译器不“知道”它被推送。由于它似乎占用了堆栈帧的一些空间,而这相当有限,这通常会导致麻烦。

将它保存在寄存器中可以防止编译器根据自己的需要使用它。这在 x86-64 上可能不是什么大问题,与 x86 相比,这里有许多额外的寄存器。但如果我需要在 x86 上使用它,那可能会影响性能,因为那里的寄存器数量要有限得多。

将其保存到变量可能是最佳选择。而且由于编译器可能会将变量保存在堆栈上 && 甚至分配一个寄存器,所以它可能不会那么慢。但这确实让代码看起来很奇怪,而且还有一个额外的变量可能会让其他人摸不着头脑。

所以问题是:哪种解决方案是最好的,即 Right Thing™ 应该做什么?或者也许还有一些我没有想到的方法来保存它 - 那些会更好?

注意:如果重要的话,该函数不接受变量并且不返回任何内容;寄存器中的值不能简单地通过一些“更高级别”的解决方案来保存,因此是内联汇编;它必须是 [er]ax ;我还没有测试第三种解决方案,所以它可能有点不准确。

【问题讨论】:

  • 为什么不能用内联此代码的编程语言创建局部变量。然后将寄存器保存到其中。您的语言范围将保留 var,直到您的函数返回。
  • 另一种可能性是使用 r12-r15,它们是被调用者保存的寄存器。一般来说,在任何情况下检查生成的组件是明智的。内联汇编可以以非常隐蔽的方式抑制编译器优化。
  • @kingchris 那将是解决方案#3。问题是我需要该值在使用时专门位于 [er]ax 寄存器中。如果没有我所知道的 inline-asm,就无法可靠地确保寄存器保持该值。我不能用 c++ 写它(这就是我使用的)。
  • @horsh 我想到了这一点并写了这篇文章(在我写了我对使用寄存器的担忧的部分。但我没有明确命名 r12-r15)。正如我所写,我担心的是——在 x86(32 位)上,这些寄存器不存在,因此我必须使用极少数可用的寄存器之一。以及阻止编译器使用它。
  • 好吧,如果你解释一下为什么我必须在 [er]ax 也许我们可以想到可能的副作用。它必须在函数调用之前在 [er]ax 中,还是在函数调用之后使用它。

标签: x86 stack x86-64 inline-assembly cpu-registers


【解决方案1】:

在解决方案 2 中,认为寄存器不会被破坏是大胆的,尤其是在优化时。解决方案 1 的唯一缺点是您将无法展开堆栈(如果您需要调试函数调用堆栈),因为堆栈帧之间的唯一链接是推送的 [er]bp,在这种情况下它不再是与 [er] sp 一致。我肯定会选择更清晰的解决方案 3。当然,它为某些混淆目的添加了一个局部变量,但至少它不会欺骗 ABI!

【讨论】:

    【解决方案2】:

    您的方法都不正确,您无法安全地将某些内容保存在 asm 语句之外的寄存器中。如果你想在 asm 语句之间传递一个值,你必须将它存储在一个变量中,如果可以的话,GCC 会将它保存在寄存器中,如果不能,它会将它保存在某个地方。

    【讨论】:

      猜你喜欢
      • 2012-03-31
      • 1970-01-01
      • 2013-01-02
      • 1970-01-01
      • 2012-04-27
      • 1970-01-01
      • 2010-10-21
      • 2017-06-10
      • 2017-01-03
      相关资源
      最近更新 更多