何时在扩展GCC内联汇编中使用特定操作数约束?

Vil*_*ray 2 c x86 assembly gcc inline-assembly

我很难理解何时在扩展GCC内联汇编中使用特定输入操作数约束而不是另一个.

例如:

int x = 42;
asm("movl %0, %%eax;"
    : /* no outputs */
    : "r"(x)
    : "%eax");
Run Code Online (Sandbox Code Playgroud)

我知道"r"告诉编译器使用寄存器保持的值x,但什么时候使用"g"或更合适"m"呢?"m"因为我正在使用寄存器目的地,所以会使用破坏此代码; 并且"g"对操作数约束过于"模糊"?

Eri*_*hil 7

您使用的约束的很大一部分是它描述的类型是否适用于您的说明.在mov %0, %%eax,您可以放置​​寄存器,内存引用或立即操作数代替%0,汇编器将接受它.所以你可以使用g约束.

如果你有mov %0, 4(%%esp),那么你不能允许%0成为内存引用,因为它4(%%esp)是一个内存引用,并且没有任何形式的mov指令接受两个内存引用.因此,您需要使用约束,例如r要求%0成为寄存器.

(请注意,这段代码本身是没用的.一旦asm完成,编译器就可以自由地使用%eax它所希望的任何东西,所以没有理由期望它x会保留在寄存器中.移动东西%eax只能用于%eax在允许编译器再次控制之前使用的一系列指令.)

  • @VilhelmGray:它为编译器提供了灵活性。如果您使用 `m` 但该值位于最近计算的寄存器中,则编译器必须将其存储到内存中。或者,如果它是一个编译时常量,但您使用了 `r`,那么编译器必须将该值放入一个寄存器中,而 `g` 将让它使用立即数操作数。 (2认同)