将汇编代码嵌入到 C/C++ 程序中时,您可以通过使用 push 指令保存寄存器来避免破坏寄存器(或指定编译器支持它的 clobber 列表)。
如果您包含汇编内联并希望避免推送和弹出破坏寄存器的开销,有没有办法让 gcc 为您选择寄存器(例如,它知道其中没有有用信息的寄存器)。
将汇编代码嵌入到 C/C++ 程序中时,您可以通过使用 push 指令保存寄存器来避免破坏寄存器(或指定编译器支持它的 clobber 列表)。
如果您包含汇编内联并希望避免推送和弹出破坏寄存器的开销,有没有办法让 gcc 为您选择寄存器(例如,它知道其中没有有用信息的寄存器)。
是的。您可以指定要将特定变量(输入或输出)存储在寄存器中,但不必指定寄存器。有关详细说明,请参阅此文档。本质上,内联程序集如下所示:
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 */
);
编译器内在函数是混合汇编和 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
}
好的,所以我不能在上面发表评论,但我很确定正确的语法(与上面显示的不同)是:
asm ( "your assembly instructions"
: "=a"(output1),
"=r"(output2),
"=q"(output3),
"=A"(output4)
: /* inputs */
: /* clobbered registers */
);
尽管您可以将输入和输出寄存器的分配留给编译器,但没有明显的方法可以将暂存/临时寄存器(即用于中间值但不用于输入或输出)的分配留给编译器。从历史上看,我只是在 clobber 列表中明确列出它们(例如“%xmm1”、“%rcx”),但我现在认为最好将它们列为输出以便让编译器选择它们。我不知道有任何来源可以明确解决这个问题。