香港編程學院 | Assembly Language課程

從零開始學會 Assembly Language

組合語言是最接近硬體的程式語言之一。透過它,你可以更理解 CPU、記憶體、暫存器、指令執行流程, 也能打下作業系統、編譯器、逆向工程與嵌入式開發的重要基礎。

6 大章節

完整入門路線

3 個範例

實用程式示範

5 題測驗

即時互動檢驗

; NASM x86 範例:將 5 + 3 的結果存入 eax
section .text
global _start

_start:
    mov eax, 5
    add eax, 3

    ; 結束程式
    mov ebx, 0
    mov eax, 1
    int 0x80

Assembly Language 是什麼?

先理解組合語言的定位,再開始學語法會更容易。

接近硬體

組合語言幾乎是一對一對應機器指令,能直接操作 CPU 暫存器、記憶體位址與中斷。

效能與控制力高

能精準控制程式執行流程,常用於驅動程式、作業系統核心、嵌入式系統與效能關鍵區塊。

學習門檻較高

因為沒有高階語言那麼多抽象化,必須理解 CPU 架構、暫存器、資料表示法與記憶體模型。

你會學到什麼?

第 1 步:基本語法

了解 section、label、mov、add、sub 等常見語法。

第 2 步:暫存器與記憶體

學會使用 eax、ebx、ecx、edx 等暫存器,以及位址存取。

第 3 步:流程控制

使用 cmp、jmp、je、jne 建立條件判斷與迴圈。

第 4 步:應用練習

透過字串輸出、加總運算、迴圈範例,把概念實際串起來。

語法教學

本教學採用 x86 NASM 常見寫法,先掌握基本骨架。

1. 程式結構

常見的組合語言程式會分成資料區與程式區:

section .data     ; 已初始化資料
section .bss      ; 未初始化資料
section .text     ; 程式碼區

global _start

_start:
    ; 程式從這裡開始執行
重點: .data 放字串與常數,.bss 放未初始化變數,.text 放指令。

2. 註解與標籤

註解使用分號 ;,標籤(Label)代表可跳躍的位置。

; 這是一行註解

start_loop:
    inc eax
    cmp eax, 10
    jne start_loop
用途: 標籤常與 jmpjejne 搭配,建立迴圈與分支流程。

3. 資料宣告

常見宣告型態如下:

  • db:定義 1 byte(位元組)
  • dw:定義 2 bytes
  • dd:定義 4 bytes
  • dq:定義 8 bytes
section .data
msg db "Hello", 0
num dw 100
value dd 123456

4. 常見資料表示

你可以用十進位、十六進位或字元表示資料:

mov eax, 10      ; 十進位
mov ebx, 0x1F    ; 十六進位
mov ecx, 'A'     ; 字元 A 的 ASCII 值

由於組合語言貼近硬體,理解數值表示非常重要。

暫存器與記憶體觀念

暫存器是 CPU 內部的小型高速儲存空間,組合語言大量使用它們。

暫存器 用途 常見說明
EAX 累加器 常用於運算結果、系統呼叫編號
EBX 基底暫存器 常用於儲存資料或系統呼叫參數
ECX 計數器 常見於迴圈、重複操作次數
EDX 資料暫存器 常與 EAX 搭配,或作為系統呼叫參數
ESP Stack Pointer 指向堆疊頂端
EBP Base Pointer 常用於函式呼叫框架
ESI / EDI 索引暫存器 常用於字串與陣列處理

直接值與位址

以下兩種寫法意義不同:

mov eax, 5        ; 把數值 5 放入 eax
mov eax, [num]    ; 讀取記憶體 num 的內容到 eax
方括號 [ ] 表示「存取記憶體位置中的資料」。

堆疊 Stack

堆疊遵循「後進先出」(LIFO)原則,常用於儲存返回位址、區域變數與暫存資料。

push eax   ; 將 eax 壓入堆疊
pop ebx    ; 從堆疊取出資料到 ebx

呼叫函式時,堆疊的使用尤其重要。

常用指令總整理

先掌握這些基本指令,就能寫出許多入門程式。

指令 功能 範例
mov 資料搬移 mov eax, 10
add 加法 add eax, 5
sub 減法 sub eax, 2
inc 加一 inc ecx
dec 減一 dec ecx
cmp 比較 cmp eax, ebx
jmp 無條件跳躍 jmp loop
je 相等時跳躍 je equal_label
jne 不相等時跳躍 jne retry
push / pop 堆疊操作 push eax / pop eax
call / ret 函式呼叫與返回 call func

條件跳躍範例

mov eax, 10
mov ebx, 10
cmp eax, ebx
je equal_label

mov ecx, 0
jmp end_program

equal_label:
mov ecx, 1

end_program:

eaxebx 相等時,程式會跳到 equal_label

迴圈範例

mov ecx, 5

loop_start:
    ; 這裡可放入重複執行的程式
    dec ecx
    cmp ecx, 0
    jne loop_start

這段程式會重複執行直到 ecx 變成 0。

範例應用例子

透過實際程式碼,理解組合語言如何運作。

範例 1:基本加法運算

將 15 與 27 相加,結果存入 eax

section .text
global _start

_start:
    mov eax, 15
    add eax, 27

    ; 結束程式
    mov ebx, 0
    mov eax, 1
    int 0x80
說明: mov eax, 15 先把 15 放進 eax, add eax, 27 再把 27 加進去,因此 eax 最後為 42。

範例 2:輸出 Hello, World!(Linux x86 / int 0x80)

這是經典入門範例,展示如何呼叫系統服務輸出字串。

section .data
msg db "Hello, World!", 10
len equ $ - msg

section .text
global _start

_start:
    mov eax, 4      ; sys_write
    mov ebx, 1      ; stdout
    mov ecx, msg    ; 字串位址
    mov edx, len    ; 字串長度
    int 0x80

    mov eax, 1      ; sys_exit
    mov ebx, 0
    int 0x80
說明: 這裡使用 Linux 的舊式系統呼叫方式 int 0x80eax 放系統呼叫編號,ebxecxedx 放參數。

範例 3:1 到 5 的總和

利用迴圈把 1+2+3+4+5 算出來。

section .text
global _start

_start:
    mov eax, 0      ; sum = 0
    mov ecx, 1      ; i = 1

sum_loop:
    add eax, ecx
    inc ecx
    cmp ecx, 6
    jne sum_loop

    ; 結束程式
    mov ebx, 0
    mov eax, 1
    int 0x80
結果: 最後 eax 會等於 15。

學習建議

  • 先熟悉資料搬移與加減法。
  • 再理解比較、跳躍與迴圈。
  • 接著學堆疊、函式呼叫與記憶體位址。
  • 最後再延伸到系統呼叫、檔案操作與中斷。

常見初學錯誤

  • 把記憶體值與位址混淆,例如忘記使用 [ ]
  • 不知道某個系統呼叫需要哪些參數暫存器。
  • 比較完之後不了解旗標(Flags)如何影響跳躍。
  • 堆疊 push / pop 次數不對稱,造成錯誤。

小測驗

測試你是否掌握了基本組合語言概念。

1. 哪個指令是用來搬移資料?
2. 在 Assembly 中,[num] 通常表示什麼?
3. 哪個暫存器常用來當作計數器?
4. 若 cmp eax, ebx 後兩者相等,通常可用哪個跳躍指令?
5. 下列哪一組指令與堆疊操作有關?

延伸學習方向

位元運算 函式呼叫慣例 中斷與系統呼叫 記憶體配置 逆向工程 作業系統核心 x86-64 架構 NASM / MASM 語法差異

如果你已經看懂這個教學網站,下一步可以繼續學習: 位元運算、旗標暫存器、函式堆疊框架、64 位元組合語言,以及與 C 語言互相呼叫的技巧。