我需要保留寄存器的值([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-64与x86相比有许多额外的寄存器。但是如果我需要在x86上使用它,这可能会影响性能,因为那里的寄存器数量更加有限。
将其保存到变量可能是最佳选择。而且由于编译器可能会将变量保存在堆栈上并且&&即使分配一个寄存器,也可能不那么慢。但它确实使代码看起来很奇怪,还有一个额外的变量,可能会让其他人挠头。
所以问题是:哪种解决方案是最好的解决方案,即什么是Right Thing™?或者可能有更多的方法来保存它,我没有想到 - 那些会更好?
注意:该函数不接受变量,如果重要,则不返回任何内容;寄存器中的值不能简单地通过一些“更高级”的解决方案来保留,因此内联asm;它必须是具体的呃;我还没有测试过第三种解决方案,所以它可能有点不准确。
答案 0 :(得分:0)
在解决方案2中,认为寄存器不会被破坏是大胆的,特别是在优化时。解决方案1的唯一缺点是您将无法展开堆栈(如果您需要调试函数调用堆栈),因为堆栈帧之间的唯一链接是推送[er] bp,在这种情况下它不再是与[er] sp一致我肯定会选择解决方案3,这更清晰。当然它为一些混淆的目的添加了一个局部变量,但至少它不会欺骗ABI!
答案 1 :(得分:0)
你的方法都不正确,你不能安全地将某些东西保存在asm语句之外的寄存器中。如果你想在asm语句之间传递一个值,你必须将它存储在一个变量中,GCC会将它保存在寄存器中,如果不能,它会将它保存在某个地方。