首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Linux C語言內聯匯編完全指南:AT&T語法、寄存器約束與實戰優化

     編輯:關於C語言

AT&T vs Intel 語法核心差異

特性AT&T (GCC默認)Intel (MSVC/NASM)
操作數順序源 → 目的 movl %ecx, %eax目的 ← 源 mov eax, ecx
寄存器前綴% %eax無 eax
立即數前綴$ $42無 42
內存操作數後綴b/w/l/q (1/2/4/8字節) movl (%ecx), %eaxbyte/word/dword/qword ptr mov eax, dword ptr [ecx]
間接寻址disp(base,index,scale) 8(%rbp,%rax,4)[base + index*scale + disp] [rbp + rax*4 + 8]

GCC 內聯匯編完整模板

asm (
    "汇编指令模板"           // 指令字符串,%0 %1 對應操作數
    : "=约束" (输出变量)     // 輸出操作數,= 表示只寫
    : "约束" (输入变量)      // 輸入操作數
    : "clobber列表"          // 被隱式修改的寄存器/內存/cc
);

實戰案例:循環左移優化

C語言版本 (編譯器可能優化為rol)

unsigned int rotl_c(unsigned int x, unsigned char n) {
    return (x << n) | (x >> (32 - n));
}

內聯匯編版本 (顯式控制)

unsigned int rotl_asm(unsigned int x, unsigned char n) {
    unsigned int res;
    __asm__ (
        "rolb %1, %0"          // 8位旋轉,cl隱含計數
        : "=a" (res)           // 輸出:eax → res
        : "0" (x), "c" (n)     // 輸入:eax←x, ecx←n ("0"綁定第0輸出)
        : "cc"                 // 修改標誌寄存器
    );
    return res;
}

關鍵約束解析

  • "=a":輸出到%eax,=表示覆蓋寫入
  • "0":輸入綁定第0個輸出操作數(這裡也是%eax)
  • "c":輸入放入%ecx (x86旋轉指令隱含計數器)
  • "cc":告知編譯器標誌位被修改,避免錯誤優化

常用約束字母速查表

進階技巧

1. 條件碼輸出

int cmp_asm(int a, int b) {
    int result;
    __asm__ (
        "cmpl %1, %2; setg %0"
        : "=q" (result)   // q: 可用al/bl/cl/dl (setg只寫低8位)
        : "r" (a), "r" (b)
        : "cc"
    );
    return result;
}

2. 內存屏障與volatile

// 防止編譯器重排/刪除
__asm__ __volatile__ ("" ::: "memory");  // 編譯器屏障
__asm__ __volatile__ ("mfence" ::: "memory"); // 硬件屏障

3. 輸出C源碼為匯編

# AT&T 語法
gcc -S -O2 -masm=att foo.c -o foo_att.s

# Intel 語法 (需源碼無AT&T內聯匯編)
gcc -S -O2 -masm=intel foo.c -o foo_intel.s

避坑指南

  1. 雙重百分號:模板中寄存器寫%%eax,輸出單個%
  2. clobber列表:漏寫導致編譯器假設寄存器不變,產生極難調試的錯誤
  3. 輸入輸出別名:用"0"綁定避免多餘mov指令
  4. 早期clobber:"=&r" 防止輸入輸出分配同一寄存器
  5. 64位調用約定:System V AMD64 ABI 前6參數用 RDI,RSI,RDX,RCX,R8,R9

總結

GCC內聯匯編是「高性能C」的終極武器。掌握AT&T語法、約束系統、clobber語義、調用約定,配合-O2 -march=native,能在關鍵熱點路徑榨乾CPU性能。但切記:優先相信編譯器優化,僅在SIMD、特權指令、精確時序、鎖自由算法等編譯器無能為力處手寫匯編,並用內建函數(__builtin_*)作為中間選擇。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
字母含義適用寄存器
a累加器eax/ax/al
b基址ebx/bx/bl
c計數器ecx/cx/cl
d數據edx/dx/dl
S源索引esi/si
D目的索引edi/di
r任意通用寄存器eax/ebx/ecx/edx/esi/edi
q任意低8位可寻址eax/ebx/ecx/edx
m內存操作數任意地址
g通用 (寄存器/內存/立即數)最靈活
I/J/K...特定範圍立即數架構相關