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

Linux 組合語言開發完全指南:語法、工具、系統呼叫與 GCC 內嵌組語

     編輯:組合語言

前言

本文系統介紹 Linux 平台下組合語言開發的核心知識:AT&T 與 Intel 語法差異、開發工具鏈 (GAS/NASM, ld, GDB/ALD)、系統呼叫慣例 (int 0x80)、命令列參數存取、GCC 內嵌組語完整語法。配合 Hello World、參數處理、內嵌組語範例,是 Linux 組合語言入門與進階的綜合參考。

語法格式:AT&T vs Intel

特性AT&T (GAS 預設)Intel (NASM/MASM)
暫存器前綴%eaxeax
立即數前綴$11
操作數順序來源, 目的 (addl $1, %eax)目的, 來源 (add eax, 1)
運算長度後綴b/w/l (movb)前綴 byte/word/dword ptr
間接跳轉/呼叫jmp *%eaxjmp eax
遠跳轉/呼叫ljump $seg, $offjmp far seg:off
記憶體定址disp(base,index,scale)[base+index*scale+disp]

Linux 保護模式下採用 32 位元線性定址,段基址通常為 0,有效位址 = disp + base + index*scale。

Hello World 範例 (兩種語法)

AT&T 語法

# hello.s
.data
msg: .string "Hello, world!\n"
len = . - msg
.text
.global _start
_start:
 movl $len, %edx
 movl $msg, %ecx
 movl $1, %ebx
 movl $4, %eax
 int $0x80
 movl $0, %ebx
 movl $1, %eax
 int $0x80

Intel 語法 (NASM)

; hello.asm
section .data
msg db "Hello, world!", 0xA
len equ $ - msg
section .text
global _start
_start:
 mov edx, len
 mov ecx, msg
 mov ebx, 1
 mov eax, 4
 int 0x80
 mov ebx, 0
 mov eax, 1
 int 0x80

兩者皆直接呼叫核心 sys_write (4) 和 sys_exit (1),無需 libc,體積極小、速度極快。

開發工具鏈

工具指令範例說明
GASas --gstabs -o hello.o hello.sGCC 後端組譯器,支援 AT&T,--gstabs 產生符號表供 GDB
NASMnasm -f elf hello.asmIntel 語法,快速、支援多格式 (ELF/COFF/Mach-O)
ldld -o hello hello.o標準連結器,-s 會剝離符號表
GDB/DDDgdb hello源碼級除錯,需符號表
ALDald hello專用組合語言除錯器,指令集disassemble, break, run, next, register

系統呼叫慣例 (int 0x80)

  • 呼叫號:EAX (定義於 /usr/include/bits/syscall.h,SYS_write, SYS_exit 等)
  • 參數傳遞:EBX, ECX, EDX, ESI, EDI (最多 5 個)
  • 返回值:EAX
  • 參數 >5 時:記憶體連續區塊,EBX 指向該區塊 (類似堆疊呼叫慣例,參數右至左入棧,EBX=ESP)

範例:write(fd, buf, len) → EAX=SYS_write, EBX=fd, ECX=buf, EDX=len

命令列參數存取

程式啟動時棧佈局:

ESP → argc
     argv[0] (程式名)
     argv[1] ...
     argv[argc-1]
     0 (NULL 結束)
     envp[0] ...
     envp[envc-1]
     0 (NULL 結束)

組合語言存取範例:

_start:
 popl %ecx        # argc
vnext:
 popl %ecx        # argv[i]
 test %ecx,%ecx; jz exit
 movl %ecx,%ebx; xorl %edx,%edx
strlen: movb (%ebx),%al; inc %edx; inc %ebx; test %al,%al; jnz strlen
 movb $10,-1(%ebx)      # 換行
 movl $4,%eax; movl $1,%ebx; int $0x80
 jmp vnext
exit: movl $1,%eax; xorl %ebx,%ebx; int $0x80

GCC 內嵌組語完整語法

__asm__("asm statements" : outputs : inputs : clobbers);
  • 指令部:組合語言指令,操作數用 %0, %1... 代表輸出/輸入變數,實體暫存器寫 %%eax
  • 輸出部:"=r"(var),= 表示輸出,r 限定暫存器
  • 輸入部:"r"(var),無 =
  • 損壞部:"%eax",告知 GCC 此暫存器被修改

範例:變數複製

int a=10, b=0;
__asm__ __volatile__(
 "movl %1, %%eax\n\t"
 "movl %%eax, %0"
 : "=r"(b)   /* 輸出 %0 */
 : "r"(a)    /* 輸入 %1 */
 : "%eax"    /* 損壞 eax */
);
printf("Result: %d, %d\n", a, b);

常用約束字母

約束含義
r任意通用暫存器
qeax/ebx/ecx/edx
a/b/c/d指定 eax/ebx/ecx/edx
S/Desi/edi
I常數 0-31
m/v/o記憶體單元
i/h立即數
g任意 (暫存器/記憶體/立即數)

結語

Linux 組合語言開發雖不如 Windows (MASM32) 擁有統一 IDE,但工具鏈 (GAS/NASM, ld, GDB/ALD) 成熟完整,且直接對接核心系統呼叫,無 libc 依賴可產生極小極快執行檔。AT&T 與 Intel 雙語法共存滿足不同背景開發者。GCC 內嵌組語以強大的約束系統完美解決暫存器分配與 C 變數綁定難題,是效能關鍵路徑優化的利器。掌握本文核心知識點,即可在 Linux 系統程式開發、嵌入式優化、逆向工程、編譯器後端等領域自如運用組合語言威力。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved