双线百分号(%%)在gcc内联汇编中有什么作用?

我遇到了一个看起来像这样的代码:

asm volatile ( # [...] "movl $1200, %%ecx;" # [...] ); 

我知道什么是movl $1200, %ecx在x86中做了什么。 但我很困惑为什么有两个百分号。

GCC内联汇编使用%0,%1,%2等来表示输入和输出操作数。 这意味着你需要使用两个%%来实现真正的寄存器。

查看此howto以获取重要信息。

这取决于

  • 如果有一个冒号:在字符串之后,那么它是一个扩展的asm ,并且%%逃脱卡尔所提到的具有特殊含义的百分比。 例:

     uint32_t in = 1; uint32_t out = 0; asm volatile ( "movl %1, %%eax;" "inc %%eax;" "movl %%eax, %0" : "=m" (out) /* Outputs. '=' means written to. */ : "m" (in) /* Inputs. No '='. */ : "%eax" ); assert(out == in + 1); 
  • 否则,它将是一个编译时错误,因为没有冒号它是一个基本的asm ,它不支持变量约束,不需要或支持转义%1 。 例如:

     asm volatile ("movl $1200, %ecx;"); 

    工作得很好。

扩展的asm更常用,因为它更强大。

这有助于GCC区分操作数和寄存器。 操作数具有单个%作为前缀。 ‘%%’总是与寄存器一起使用。