GCC 支援在 C 代碼中嵌入彙編指令,適用於:硬體端口訪問(in/out)、特權指令、極致優化、裸機開發。本文詳解基本格式、完整約束語法、輸入輸出操作數綁定、寄存器保護列表。
__asm__("nop"); // 單條指令
__asm__("movl $1, %eax\n\t" // 多條指令用 \n\t 分隔
"movl $4, %ebx\n\t"
"int $0x80");
__asm__( assembler_template
: output_operands /* 可選 */
: input_operands /* 可選 */
: clobbered_regs /* 可選 */
);
%0, %1… 佔位,對應輸出/輸入列表順序。"=r" (var),= 表示寫入,r 表示通用寄存器約束,var 為 C 左值表達式。"r" (expr),r 表示讀取,expr 為 C 表達式。"cc", "memory", "%eax",告知編譯器哪些寄存器/狀態旗標/內存被修改,編譯器避開分配或重新加載。xchg)static inline int atomic_xchg(volatile int *ptr, int newval) {
int result;
__asm__ __volatile__(
"xchgl %0, %1"
: "=r" (result), "+m" (*ptr)
: "0" (newval)
: "memory"
);
return result;
}
__volatile__ 防止編譯器優化調整順序/刪除。"+m" (*ptr):輸出輸入同用一個操作數(讀修寫),m 表示內存操作數。"0" (newval):輸入操作數綁定到輸出操作數 0 的寄存器(%0)。"memory":告知編譯器內存被修改,禁止重排內存訪問。| 字母 | 含義 |
|---|---|
r | 通用寄存器 |
q | 低 8 位寄存器 (al,bl,cl,dl) |
a/b/c/d/S/D | 特定寄存器 (eax/ebx/ecx/edx/esi/edi) |
m | 內存操作數 |
g | 寄存器/內存/立即數任意 |
i/n | 立即數 |
=:純輸出(寫入前值無關)。+:輸入輸出(讀取舊值,寫入新值)。&:早期剋制(該操作數在指令前被寫入,防止與其他輸入共用寄存器)。static inline unsigned char inb(unsigned short port) {
unsigned char data;
__asm__ __volatile__("inb %w1, %0" : "=a" (data) : "Nd" (port) : "memory");
return data;
}
static inline void outb(unsigned short port, unsigned char data) {
__asm__ __volatile__("outb %0, %w1" : : "a" (data), "Nd" (port) : "memory");
}
%w1 表示操作數 1 的字大小(16 位端口號),Nd 約束允許立即數或 dx 寄存器。
"a" 等)。clobber 列表務必完整,否則編譯器可能誤以為寄存器值未變,導致難以調試的錯誤。.S 文件,用 extern 調用,保持 C 代碼整潔。