Windows XP Windows 7 Windows 2003 Windows Vista Windows 綜合教學 Linux 系統教學
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟體教學
您现在的位置: Windows教程網 >> Windows教程 >  >> Linux 系統教學 >> Linux 教學

Linux AT&T (GNU as) 匯編語法入門教學

編輯:Linux 教學

前言

GCC 工具鏈預設使用 AT&T 語法 (源自 AT&T Bell Labs),與 Intel 語法 (MSVC、NASM) 差異極大。閱讀編譯器輸出 (gcc -S) 或編寫內聯匯編時,掌握 AT&T 語法至關重要。

核心語法差異速查

項目AT&T (GNU as)Intel (NASM/MSVC)
立即數$1234 (前綴 $)1234
暫存器%eax (前綴 %)eax
操作數順序來源, 目的 (movl %eax, %ebx = eax → ebx)目的, 來源 (mov ebx, eax)
運算元大小後綴b/w/l/q (byte/word/long/quad)
movl = 32-bit
指令隱含或用 ptr (mov eax, dword ptr [mem])
記憶體寻址disp(base, index, scale)
-4(%rbp), (%rax,%rcx,4)
[base + index*scale + disp]
[rbp-4], [rax+rcx*4]
註解# comment; comment

暫存器總覽 (x86-64)

類別暫存器 (64/32/16/8-bit)慣用用途
通用%rax/%eax/%ax/%al, %rbx/%ebx/%bx/%bl, %rcx/%ecx/%cx/%cl, %rdx/%edx/%dx/%dl運算、返回值 (%rax)、計數器 (%rcx)
索引/基址%rsi/%esi/%si/%sil, %rdi/%edi/%di/%dil字串操作來源/目的、函數前 2 參數
棧/幀指針%rsp/%esp/%sp/%spl, %rbp/%ebp/%bp/%bpl棧頂、幀基址
擴展通用%r8~%r15 (及 d/w/b 子暫存器)額外參數 (第 3~6)、暫存
指令指針%rip/%eip/%ip下一條指令地址 (不可直接修改)
旗標%rflags/%eflags條件碼 (ZF, CF, SF, OF...)

常用指令範例

# 資料傳送 (大小後綴 b/w/l/q)
movb  $0x41, %al          # 立即數 → 8-bit 暫存器
movw  %ax, (%rdi)         # 16-bit → 記憶體
movl  %eax, -4(%rbp)      # 32-bit → 記憶體 (區域變數)
movq  %rax, %rbx          # 64-bit 暫存器間傳送

# 算術/邏輯 (同樣有大小後綴)
addl  %ecx, %eax          # eax += ecx
subl  $10, %esp           # esp -= 10 (分配棧空間)
imull %edx                # 有號乘法: edx:eax = eax * edx
idivq %rcx                # 有號除法: rax=商, rdx=餘數

# 控制流
cmpl  %eax, %ebx          # 比較 ebx - eax (設置旗標)
je    label               # 相等跳轉 (ZF=1)
jl    label               # 有號小於跳轉 (SF!=OF)
jmp   *%rax               # 間接跳轉

# 棧操作
pushq %rax
popq  %rbx

# 函數調用 (System V AMD64 ABI)
# 參數: %rdi, %rsi, %rdx, %rcx, %r8, %r9, 其餘壓棧
# 返回值: %rax (整數/指標), %xmm0 (浮點)
call  printf
# 調用者清理棧 (若有棧參數)

記憶體寻址模式詳解

通用形式:DISP(BASE, INDEX, SCALE) → 有效位址 = BASE + INDEX*SCALE + DISP

  • DISP:位移常數 (可為符號名)。
  • BASE:基址暫存器 (可省略)。
  • INDEX:索引暫存器 (可省略)。
  • SCALE:1, 2, 4, 8 (可省略,預設 1)。

範例:

(%rax)           # 間接寻址
8(%rax)          # 基址 + 位移
(%rax,%rcx,4)    # 基址 + 索引*4 (陣列索引)
-4(%rbp)         # 幀相對 (區域變數)
array(,%rcx,8)   # 純索引陣列 (64-bit 元素)

實戰:C 對應匯編

// C 代碼
void dummy() {
    int a = 1234;
    int b = a;
}

// gcc -S -O0 dummy.c 輸出 (精簡)
dummy:
    pushq %rbp
    movq  %rsp, %rbp
    movl  $1234, -4(%rbp)    # a = 1234
    movl  -4(%rbp), %eax     # 載入 a
    movl  %eax, -8(%rbp)     # b = a
    popq  %rbp
    ret

內聯匯編 (GCC Extended Asm)

int foo(int a, int b) {
    int sum;
    asm volatile (
        "addl %%ebx, %%eax\n\t"
        : "=a" (sum)        // 輸出: %eax → sum
        : "a" (a), "b" (b)  // 輸入: a→%eax, b→%ebx
        : "cc"              // 破壞: 條件碼
    );
    return sum;
}

結語

  • AT&T 語法「來源→目的」與「大小後綴」是最大適應障礙,多寫多看 gcc -S 輸出即可熟練。
  • x86-64 System V ABI 呼叫慣例 (參數暫存器、棧對齊、紅區) 是編寫高效內聯匯編/裸機代碼的基石。
  • 工具鏈:objdump -d -M intel 可輸出 Intel 語法反組譯,對照學習極佳。
Copyright © Windows教程網 All Rights Reserved