gcc 扩展了 asm 支持

gcc 中的扩展 asm 支持具有以下语法:

asm [volatile] ( AssemblerTemplate
                  : OutputOperands
                  [ : InputOperands
                  [ : Clobbers ] ])
 
 asm [volatile] goto ( AssemblerTemplate
                       :
                       : InputOperands
                       : Clobbers
                       : GotoLabels)

其中 AssemblerTemplate 是汇编程序指令的模板,OutputOperands 是可以通过汇编代码修改的任何 C 变量,InputOperands 是用作输入参数的任何 C 变量,Clobbers 是由汇编代码修改的列表或寄存器,GotoLabels 是可以在汇编代码中使用的任何 goto 语句标签。

扩展格式在 C 函数中使用,是内联汇编的更典型用法。下面是 Linux 内核中用于 ARM 处理器的字节交换 16 位和 32 位数字的示例:

/* From arch/arm/include/asm/swab.h in Linux kernel version 4.6.4 */
#if __LINUX_ARM_ARCH__ >= 6

static inline __attribute_const__ __u32 __arch_swahb32(__u32 x)
{
    __asm__ ("rev16 %0, %1" : "=r" (x) : "r" (x));
    return x;
}
#define __arch_swahb32 __arch_swahb32
#define __arch_swab16(x) ((__u16)__arch_swahb32(x))

static inline __attribute_const__ __u32 __arch_swab32(__u32 x)
{
    __asm__ ("rev %0, %1" : "=r" (x) : "r" (x));
    return x;
}
#define __arch_swab32 __arch_swab32

#endif

每个 asm 部分使用变量 x 作为其输入和输出参数。然后 C 函数返回操作结果。

使用扩展的 asm 格式,gcc 可以按照用于优化 C 代码的相同规则优化 asm 块中的汇编指令。如果你希望自己的 asm 部分保持不变,请使用 volatile 关键字作为 asm 部分。