将汇编代码嵌入到C / C ++程序中时,可以通过使用push指令保存寄存器(或指定编译器的clobber列表支持它)来避免破坏寄存器。
如果你包括汇编内联并希望避免推送和弹出破坏寄存器的开销,有没有办法让gcc为你选择寄存器(例如它知道它们没有有用的信息)。
答案 0 :(得分:9)
是。您可以指定希望将特定变量(输入或输出)存储在寄存器中,但不必指定寄存器。有关详细说明,请参阅this document。本质上,内联汇编看起来像这样:
asm("your assembly instructions"
: output1("=a"), // I want output1 in the eax register
output2("=r"), // output2 can be in any general-purpose register
output3("=q"), // output3 can be in eax, ebx, ecx, or edx
output4("=A") // output4 can be in eax or edx
: /* inputs */
: /* clobbered registers */
);
答案 1 :(得分:0)
Compiler intrinsics是一种非常有用的混合程序集和C / C ++代码的方法。它们的声明看起来像函数,但实际上直接编译为单独的本机指令(通过编译器内部的特殊情况)。这为您提供了对汇编工作的大部分控制,但是将寄存器着色和调度留给了编译器。
一个优点是,您可以将普通的C变量传递给内部函数,让编译器负责将其加载到寄存器中并调度其周围的其他操作。例如,
struct TwoVectors
{
__m128 a; __m128b;
}
// adds two vectors A += B using the native SSE opcode
inline void SimdADD( TwoVectors *v )
{
v->a = _mm_add_ps( v->a , v->b ); // compiles directly to ADDSS opcode
}
答案 2 :(得分:0)
好的,所以我不能在上面留下评论,但我很确定正确的语法(与上面显示的不同)是:
asm ( "your assembly instructions"
: "=a"(output1),
"=r"(output2),
"=q"(output3),
"=A"(output4)
: /* inputs */
: /* clobbered registers */
);
虽然您可以将输入和输出寄存器的分配留给编译器,但是没有明显的方法可以将临时/临时寄存器(即用于中间值而不是输入或输出)分配给编译器。从历史上看,我只是在clobber列表中明确列出它们(例如“%xmm1”,“%rcx”),但我现在认为将它们列为输出可能更好,以便允许编译器选择它们。我不知道有任何消息来源明确地解决了这个问题。