在C中嵌入汇编程序,编译器为您查找寄存器

时间:2009-05-31 00:16:16

标签: c assembly inline-assembly cpu-registers

将汇编代码嵌入到C / C ++程序中时,可以通过使用push指令保存寄存器(或指定编译器的clobber列表支持它)来避免破坏寄存器。

如果你包括汇编内联并希望避免推送和弹出破坏寄存器的开销,有没有办法让gcc为你选择寄存器(例如它知道它们没有有用的信息)。

3 个答案:

答案 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”),但我现在认为将它们列为输出可能更好,以便允许编译器选择它们。我不知道有任何消息来源明确地解决了这个问题。