我需要保留一个寄存器的值([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 ;我还没有测试第三种解决方案,所以它可能有点不准确。