DJGPP、GCC 內聯組合語言、Linux 核心開發均採用 AT&T 語法。它與主流的 Intel 語法(MASM/TASM/NASM)有顯著差異。本文系統整理核心差異,附對照表與實例,幫助開發者快速轉換。
| 項目 | Intel 語法 | AT&T 語法 |
|---|---|---|
| 運算元順序 | 目的, 來源 | 來源, 目的 (顛倒) |
| 暫存器前綴 | 無 | % (如 %eax) |
| 立即數前綴 | 無 | $ (如 $1) |
| 記憶體運算元大小 | BYTE PTR, WORD PTR, DWORD PTR | 指令尾碼 b(8-bit), w(16-bit), l(32-bit) |
| 記憶體定址 | [base + index*scale + disp] | disp(base, index, scale) |
| 段暫存器 | seg:[offset] | seg:offset 或 %seg:offset |
Intel AT&T
mov ax, bx movw %bx, %ax
xor eax, eax xorl %eax, %eax
mov ax, 1 movw $1, %ax
mov ah, byte ptr X movb X, %ah
mov ax, word ptr X movw X, %ax
mov eax, X movl X, %eax
註:movw = 16-bit, movl = 32-bit, movb = 8-bit。
Intel AT&T
movsx movsSD (S=來源大小, D=目的大小, 如 movswl %ax, %ecx)
movzx movzSD
cbw cbtw
cwde cwtl
cwd cwtd
cdq cltd
call far S:O lcall $S, $O
jmp far S:O ljmp $S, $O
ret far V lret $V
Intel AT&T
mov eax, [ebp+4] movl 4(%ebp), %eax
add ecx, [eax+eax*4] addl (%eax,%eax,4), %ecx
mov fs:eax, 4 movb $4, %fs:(%eax)
mov eax, [4*eax+array] movl _array(,%eax,4), %eax
mov cx, [ebx+4*eax+array]movw _array(%ebx,%eax,4), %cx
jcxz, jecxz, loop, loopz, loope, loopnz, loopne 僅支援短跳轉(-128~+127)。長跳轉需展開:
jcxz foo → jcxz cx_zero
jmp cx_nonzero
cx_zero:
jmp foo
cx_nonzero:
AT&T 單運算元 imul %ebx 為擴展乘法(結果在 EDX:EAX)。雙運算元 imul %ebx, %eax 為非擴展乘法(結果在 EAX),對應 Intel imul eax, ebx。
__asm__( "asm statements" : outputs : inputs : clobbers );
\n 或 ;"=constraint" (c_var),= 表示唯寫"constraint" (c_var)"eax", "memory"int i = 0;
__asm__(
"pushl %%eax\n"
"movl %0, %%eax\n"
"addl $1, %%eax\n"
"movl %%eax, %0\n"
"popl %%eax"
: /* 無輸出 */
: "g" (i) /* 輸入:i,g=任意位置 */
: "eax" /* 修改 eax(雖然 push/pop 保護,但建議宣告)*/
); // i++
int i=0, j=1, k=0;
__asm__ __volatile__(
"pushl %%eax\n"
"movl %1, %%eax\n"
"addl %2, %%eax\n"
"movl %%eax, %0\n"
"popl %%eax"
: "=g" (k) /* %0 = k (輸出) */
: "g" (i), "g" (j) /* %1 = i, %2 = j (輸入) */
: "eax", "memory"
); // k = i + j
編號規則:輸出優先編號 %0..%K-1,輸入接著 %K..%N-1。
內聯組合語言標號需加 b(向後)或 f(向前)後綴:
__asm__(
"0:\n"
"...\n"
"jmp 0b\n" /* 跳回標號 0 */
"...\n"
"jmp 1f\n" /* 跳往標號 1 */
"...\n"
"1:\n"
);
.file "myasm.S"
.data
somedata: .word 0
.text
.globl __myasmfunc
__myasmfunc:
...
ret
使用 gcc -S file.c 產生 .S 參考編譯器輸出慣例。
包含 libc/asmdefs.h 使用巨集:
#include
.file "myasm.S"
.data
.align 2
somedata: .word 0
.text
.align 4
FUNC(__MyExternalAsmFunc)
ENTER
movl ARG1, %eax
...
jmp mylabel
...
mylabel:
...
LEAVE
FUNC/ENTER/LEAVE/ARG1 等巨集處理函數序言/結語、參數存取,提高可移植性。