本文主要记录内嵌汇编学习笔记。

1. 扩展内联汇编 (Extended Asm)语法

1
2
3
4
5
asm ( assembler template
: output operands /* optional */
: input operands /* optional */
: list of clobbered registers /* optional */
);

2. constraints

2.1 寄存器操作数constraints: r

如果操作数指定了这个constraints,操作数将被存储在通用寄存器中。看下面的例子:
asm ( "movl %%eax, %0" : "=r" (myval));

上面变量myval会被被保存在一个由GCC自己选择的寄存器中,eax中的值被拷贝到这个寄存器中去,并且在内存中的myval的值也会按这个寄存器值被更新。当constraints ”r” 被指定时,GCC可能会在任何一个可用的通用寄存器中保存这个值。当然,你也可以指定具体使用那个寄存器,用下表所列出的constraints:

2.2 Numbers in constraints

Only input operands may use numbers in constraints, and they must each refer to an output operand. Only a number (or the symbolic assembler name) in the constraint can guarantee that one operand is in the same place as another.

1
2
3
4
5
void asm_cpuid(uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
{
/* Execute CPUID instruction and save results */
asm volatile("cpuid" : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx) : "0"(*eax), "2"(*ecx) : "memory");
}

2.3 Output constraints

Output constraints must begin with either = (a variable overwriting an existing value) or+ (when reading and writing).

2.4 constraint:m

m: 使用一个内存操作数。

2.5 asmSymbolicName

Specifies a symbolic name for the operand. Reference the name in the assembler template by enclosing it in square brackets (i.e. %[Value]). The scope of the name is the asm statement that contains the definition. Any valid C variable name is acceptable, including names already defined in the surrounding code.

When not using an asmSymbolicName, use the (zero-based) position of the operand in the list of operands in the assembler template. For example if there are three output operands, use %0 in the template to refer to the first, %1 for the second, and %2 for the third.

2.6 constraint:i

“i” : An immediate integer operand (one with constant value) is allowed. This includes symbolic constants whose values will be known only at assembly time.

3 Clobber List

Some instructions clobber some hardware registers. We have to list those registers in the clobber-list. This is to inform gcc that we will use and modify them ourselves. So gcc will not assume that the values it loads into these registers will be valid. We shoudn’t list the input and output registers in this list. Because, gcc knows that asm uses them (because they are specified explicitly as constraints). If the instructions use any other registers, implicitly or explicitly (and the registers are not present either in input or in the output constraint list), then those registers have to be specified in the clobbered list.

3.1 cc clobber

If our instruction can alter the condition code register, we have to add cc to the list of clobbered registers.

3.2 memory clobber

If our instruction modifies memory in an unpredictable fashion, add “memory” to the list of clobbered registers. This will cause GCC to not keep memory values cached in registers across the assembler instruction. We also have to add the volatile keyword if the memory affected is not listed in the inputs or outputs of the asm.


参考资料:

  1. GCC内联汇编基础
  2. GCC-Inline-Assembly-HOWTO
  3. 内嵌汇编学习
  4. Extended Asm - Assembler Instructions with C Expression Operands