組合語言

組合語言，又有叫匯編語言，係一類低級程式語言，特徵係機械語言同佢有一對一嘅對應，但係用咗羅馬字母嘅 ｢記憶語法｣將本來係數字嘅命令符號化，令佢易睇啲。

舉返個例說明：喺 Zilog Z80 嘅處理器嗰度，「00000101」呢段機械碼會令到粒 CPU 做「將 B 處理器暫存器入面嗰個數值下降 1」嘅運算，而同一個命令用組合語言寫嘅話會係「DEC B」－喺組合語言嗰串命令當中見到有「DEC」呢三個羅馬字母，代表咗英文字「decrement」。組合語言對羅馬字母嘅使用令到用呢啲語言寫成嘅碼易睇過機械語言碼好多。

話雖如此，組合語言都有「兩頭唔到岸」嘅缺點：喺一般嘅應用當中，電腦內部處理嘅係機械語言，電腦係唔曉直接讀組合語言嘅，所以喺用親組合語言寫程式嗰陣，個用家梗要有個組合器將段組合語言碼轉化做電腦識直接睇嘅機械語言，即係唔似得機械語言碼噉，可以直接攞嚟俾電腦行；另一方面，組合語言又唔似得高級語言噉有普遍性－每一款組合語言都係要喺某啲特定嘅電腦系統架構同作業系統上先會行到，而相比之下，好似係 Java 或者 Python 等嘅高級語言一般都可以用落去多個平台上面，淨係需要有啱用嘅編譯器將佢哋翻譯俾部電腦睇就得。

基礎

機械語言 

機械語言係電腦內部直接處理嗰種語言。機械語言係最低級嘅程式語言－淨係用數字表達嗮所有嘢，而組成一段機械碼嘅數字會包含嗮「要用啲乜嘢數據」同「要做啲乜嘢作業」等嘅資訊。舉個例說明：假想而家有款機械語言，
款語言嘅每段命令都由 18 個數字組成，呢 18 個數字每一個都一係 1 一係 0，
最頭嗰 7 個數字用二進制表達數據 A，
跟住嗰 7 個數字用二進制表達數據 B，
最尾嗰 4 個數字就表達要做乜－0000 代表加，0001 代表減等等。
於是喺用呢種語言寫成嘅源碼入面，「0000011 0000100 0000」呢段碼係叫電腦計 3加 4嘅結果出嚟。有關機械語言嘅物理實現，可以睇吓電子工程同邏輯門等嘅電腦硬件技術。

組合句法 
組合語言大致上就係用羅馬字母嘅機械語言，用咗記憶術表達想部電腦行嘅指示：組合語言會用羅馬字母串表達機械語言當中嘅每一個命令或者行動碼，通常亦會用同樣嘅手法表達埋要用嘅資訊喺邊個暫存器同位元欄等嘅資訊，並且好多時會掕埋一個或者多個運算數。

舉個例說明，例如家吓個用家想叫部電腦計「3 + 2」嘅結果，「加」就係要做嗰個命令，喺部電腦嘅機械碼會有個相應嘅行動碼，而 3 同 2 就係運算數。多數嘅組合器都容許用家運用有名嘅常數、暫存器同埋記憶嘅位置等嘅資訊，所以個用家唔使用人手噉做一啲重複性嘅作業，亦都唔使睇淨係用 1 同 0 寫成嘅機械碼。

以下係一啲典型嘅用組合語言寫嘅語句：
INC COUNT        ; 將而家喺記憶入面嗰個變數嘅數值「提高」，而 count 係要提高幾多。

ADD AH, BH       ; 將 BH 暫存器入面嗰個數值加落去 AH 暫存器入面嗰個度。

AND MASK1, 128   ; 同變數「MASK1」以及「128」呢個數字做 AND 嘅作業。

ADD MARKS, 10    ; 加 10 落去變數「MARKS」嗰度。

MOV AL, 10       ; 「搬」10 呢個數字去 AL 暫存器嗰度。
視乎系統結構，呢啲元素可以結合埋一齊嚟整更加複雜嘅命令。

例子 1
舉個具體例子說明，以下呢段碼會叫一個 X86 或者 IA-32 處理器去將一個 8 bit 咁長嘅數值搬去個暫存器嗰度。呢個命令用二進制嘅機械語言寫嘅話係「10110」，而呢個命令跟住仲要掕住第段數字表示要用邊一個暫存器嚟做，例如 AL 暫存器嘅碼係「000」，所以跟住呢段機械碼會叫部電腦將數據 0110001 入落去 AL 暫存器嗰度：

10110000 01100001

呢段碼有得用十六進制嚟表示，等段嘢對一般人嚟講易睇啲：

B0 61

喺呢段碼入面，「B0」代表咗行動碼，叫部電腦做「將跟住嗰個數值複製，再擺落去 AL 嗰度」，而「61」係用十六進制寫嘅「0110001」。8086 系列嘅組合語言仲會俾用家用「MOV」嚟表達呢個命令，等段碼對於人類嚟講更加易睇，即係好似以下噉樣：

MOV AL, 61h       ; 將「97」嘅數值嘅二進制版本入落去 AL 嗰度。

喺第啲組合語言入面，同一段字可能會有唔同－但類似－嘅意思，好似係「將某某數據搬去某個暫存器嗰度」呀噉。又有啲可能會將個命令分開或者合拼，例如係用「MOV」代表嗮所有數據嘅移動，又或者用唔同嘅命令代表「由記憶體去暫存器」同「由暫存器去記憶體」... 等等。

例子 2
「1011000」係 X86 當中嘅一段行動碼，會將一個 8 bit 長嘅數值搬去 AL 暫存器嗰度，「1011001」會將個數值搬去 CL 暫存器，而「1011010」會將個數值搬去 DL 暫存器，即係好似以下呢段碼噉：

MOV AL, 1h        ; 將「1」嘅數值嘅二進制版本入落去 AL 嗰度。
MOV CL, 2h        ; 將「2」嘅數值嘅二進制版本入落去 CL 嗰度。
MOV DL, 3h        ; 將「3」嘅數值嘅二進制版本入落去 DL 嗰度。

例子 3
「MOV」呢個命令可以做得再複雜啲，好似以下嘅碼噉：

MOV EAX, [EBX]	  ; 記憶體之間嘅數據移動，將「EBX」嗰個位置入面嗰 4 位元組嘅數據搬去「EAX」嗰個位置度。
MOV [ESI+EAX], CL ; 將 CL 嘅內容搬去「ESI+EAX」嗰個位置度。

語言設計

三大元素 
整組合器嘅人响將命令分類同埋所用嘅命名法等方面好多樣化。不過，無論係邊款組合語言邊個設計師，一款典型嘅組合語言喺句法上都會有三款命令用嚟定義個程式要乜：
用羅馬字代表嘅行動碼、
類行動碼、
數據定義：數據定義會定義要處理嘅數據嘅種類同埋長度等嘅資訊。呢啲命令亦都可以用嚟定義啲數據係咪可以由外來嘅程式處理，定係淨係可以喺嗰個程式入面用。運算數。
INC COUNT        ; 將而家喺記憶入面嗰個變數嘅數值「提高」；
行動碼：INC；
數據定義：COUNT；

ADD AH, BH       ; 將 BH 暫存器入面嗰個數值加落去 AH 暫存器入面嗰個度；
行動碼：ADD；
數據定義：AH 同 BH；

MOV AL, 10       ; 搬10 呢個數字去 AL 暫存器嗰度；
行動碼：MOV；
數據定義：AL 同 10；

行動碼 

行動碼係指段命令當中教部電腦「要做乜運算」嗰橛。組合語言入面嗰啲命令一般都係好簡單嘅，唔似得高級語言入面嗰啲噉。普遍嚟講，喺程式編寫上，記憶術係指某個電腦識執行嘅機械碼用符號表達嘅名，例如係正話提咗嘅例子 1 入面嘅 X86 命令「將跟住嗰個數值複製，再擺落去 AL 嗰度」噉，
段嘢本身係一個部電腦識得執行嘅命令；
喺機械語言當中嘅行動碼係「10110」；
喺嗰款組合語言當中嘅記憶術係「MOV」；
是但搵款組合語言嚟睇，同款語言對應嘅機械語言嘅每款命令都會有個記憶術。多數嘅命令都會掕住若干個運算數，運算數可以代表要計嘅數值又得、代表儲住要用嘅數值嘅暫存器嘅位置又得、或者要用嘅數值喺部電腦嘅記憶嘅位置都得。

有陣時，一款組合語言會有延伸嘅行動碼嚟表達一啲結合咗多個命令嘅複雜命令。舉個例說明，有好多 CPU 都係冇 NOP 命令－呢個命令叫部電腦唔好做任何嘢，好多時俾人攞嚟控制第啲命令喺乜嘢時間行；但有一啲細啲、可以結合埋一齊做 NOP 嘅命令；喺 8086 系列嘅 CPU 當中， 呢行命令俾人用嚟做 ，而  呢段嘢嚴格嚟講唔算係呢啲 CPU 入面嘅命令。某啲反組合器識得認呢段碼，會將  解碼做 。呢啲唔淨只代表一個命令，而係代表咗多個命令嘅組合嘅記憶術就係所謂嘅延伸記憶術，SPARC 架構嗌呢啲記憶術做合成命令。

類行動碼 

類行動碼係指一啲由個用家俾去個組合器嘅命令，叫個組合器做一啲「翻譯組合碼」以外嘅作業。呢啲指示會影響到個組合器嘅運作，控制個組合器內部嘅參數，例如係個組合器「用乜訊號代表邊個邊個組合碼命令」呀噉。類行動碼嘅名通常都係以一個點做開頭嘅－呢樣嘢幫手令啲用家一睇就知呢啲碼同機械碼命令唔同。

類行動碼可以好有用。呢啲碼可以令一個程式嘅組合受制於程式員俾嘅參數，即係叫個組合器「喺呢個情況噉樣組合，而喺第個情況用第個方法組合」，令到有陣時同一個程式可以用唔同方法組合，增加組合器嘅用途；另一方面，類行動碼又可以用嚟操控一個程式點樣呈現，令個程式對於人類嚟講易睇啲；類行動碼嘅仲可以用嚟保留空間去儲起個組合器嘅執行期等嘅資訊，等個程式員有得做有關「個組合器用咗幾耐時間做一次翻譯」方面嘅分析。

同大多數嘅電腦語言一樣，組合語言俾用家喺個程式嘅源碼嗰度加啲注釋落去－即係喺啲命令後面有啲用人類語言寫、個組合器喺組合段碼嗰陣會忽略嘅句子。呢啲句子幫到程式員手令到佢哋寫嘅源碼更加易讀，例如一個程式員可以喺一行命令後面加個注釋，用淺白嘅語言講清楚嗰行命令處理嗰個變數有乜嘢重要性。呢啲注釋會令到下一手處理呢段源碼嘅程式員能夠一睇就明嗰行命令係做乜嘢目的嘅。
MOV CL, 34h       ; 呢段灰色嘅字係注釋－個組合器係設計好咗會忽略「;」後面嘅碼，所以呢段灰字部電腦唔會處理，但係程式員可以用佢嚟解釋俾下一手程式員知呢段碼有乜嘢作用。

組譯風格比較 
x86/amd64 組譯命令嘅兩大風格分別係 Intel 組譯同 AT&T 組譯，分別由 Microsoft Windows/Visual C++ 同 GNU/Gas 用：

組合器 

組合器係用組合語言寫程式實要用嘅嘢，組合器係一啲特別嘅程式，負責將用組合語言寫成嘅源碼轉化做電腦識睇嘅機械碼：一段電腦會識行嘅機械碼會完全用 1 同 0 表達嗮所有資訊－包括行動碼、運算數同埋啲運算數嘅位置；個組合器會將組合碼入面嗰啲羅馬字母轉化做相應嘅機械碼，亦都會計返好啲常數表達同埋解決記憶體嘅位置以及其他嘢嘅名。組合器會用某啲名代表個程式入面嘅物體，唔似得機械語言噉，等個用家唔使吓吓都計同人手噉更新啲嘢嘅位置。例：
入落組合器嘅輸入：MOV R3, #15；
組合器俾出嘅輸出：1100 1010 1011 0011；

組合器呢家嘢早喺 1950 年代，有字嘅電腦介面啱啱出現嗰陣時經已開始有，同 Fortran、COBOL、同埋 LISP 呢啲早期程式語言同期，而且喺嗰時因為易寫過高級語言嘅編譯器而頗受歡迎－正如頭先提到，組合語言喺結構上好似機械語言，好多時組合語言啲命令都只不過係用咗羅馬字母表達嘅機械語言命令，組合語言入面嗰啲命令好多都同某啲機械語言嘅命令有 1 對 1 嘅關係，所以要將組合碼翻譯做機械碼好容易。
功能
有陣時，同一個 CPU 或者命令集會有好幾個命令句法嚟應付唔同嘅組合器。舉個例說明，喺 X86 型嘅處理器當中，一條「叫部電腦將記憶數據加落去個暫存器嗰度」嘅命令用 Intel 嘅句法寫可能係 add eax,[ebx]，而用 GNU 組合器用嘅 AT&T 嘅句法寫就係 addl (%ebx),%eax。雖然呢啲唔同句法寫嘅命令望落唔同，但佢哋轉化咗做機械碼嗰陣好多時都係一樣樣嘅。有陣時同一個組合器可能會有幾個唔同模式嚟幫手翻譯唔同嘅句法嘅組合碼。
有啲組合器仲有能力做一啲簡單嘅命令集特定嘅編譯器最佳化－最佳化係指將個編譯器嘅某啲特徵最大化或者最小化，例如係某啲組合器曉將個編譯器行嗰陣霸嘅記憶體量最小化，等部機行起上嚟順暢啲。周圍都搵得到嘅 X86 組合器就係一個具體嘅例子，呢啲組合器多數都曉喺俾用家要求嗰陣時跳過若干行嘅指示，有啲仲曉做簡單嘅重新排序或者插入新指示。

要睇幾多次 
組合器大致上可以按「行嗰陣要睇段源碼幾多次」嚟分做兩大類：
睇一次組合器會將段源碼睇一次，跟手就可以出到佢要出嘅輸出。喺段源碼行過之前用咗嘅符號都需要改返啱，話俾部機聽要覆蓋一個之前用過嘅位，並且將呢個位攞嚟儲嗰個新嘅變數。
睇多次組合器會整個表出嚟，列嗮所有嘅符號同埋佢哋喺第一次睇段碼嗰陣嘅數值出嚟，再用個表嚟整碼。
傳統上用睇一次組合器嘅原因係因為呢啲組合器唔使同一段源碼睇幾次，所以做起嘢上嚟好快，組合時間短－睇第二次就要重新讀過段源碼一次，呢樣嘢要用舊式嘅電腦做可以撈絞得好交關。但由廿一世紀初開始，電腦經已有龐大嘅記憶體，能夠有足夠嘅空間做嗮所有必需嘅處理而唔使讀帶，所以更加穩陣同埋做起某啲作業上嚟快啲嘅睇多次組合器開始受到重視。
例子說明
喺以下呢段組合碼當中，一個睇一次組合器喺處理 S2 嗰行命令嗰陣已經能夠知道 BKWD 嘅位置，但喺處理 S1 嗰行命令嗰時唔會知道 FWD 嘅位置，所以要靠估嚟決定要預留幾多記憶體嘅位置。相比之下，一個睇兩次嘅組合器會喺第一次睇段碼嗰陣知道兩個物件嘅位置，並且喺第二次讀碼嗰陣處理。
S1   B   FWD
...
FWD   EQU *
...
BKWD   EQU *
...
S2   B   BKWD

組合器類別 
宏組合器：係任何可以用 ｢巨集｣嘅組合器。即係你可以定義一啲特定嘅名嚟表達某啲特定嘅組合語言命令，例如，如果你話「swap」代表一組令某兩個變數數值互換嘅命令，你就可以打「swap」就可以直接將嗰串命令入落去第段碼嗰度，唔使下下都成串命令打一次。好多組合器亦都係宏組合器。
微組合器：係用嚟準備微程式嘅組合器，呢啲微程式嘅作用係要控制部中央處理器等等嘅內部作業，例如機械碼嘅內部運作。
交叉組合器：負責令一段組合碼喺另一個電腦或者作業系統上面行；交叉組合器令到用家有得為一啲本身冇能力支援軟件發展嘅系統寫程式。喺呢個情況下，個用家可以將要行嗰段碼用某啲方法搬去個目標系統嗰度。
高級組合器：會提供類似高階程式語言嘅命令，俾個用家用一啲進級嘅控制結構命令同埋一啲進級嘅數據類。
反組合器： 係組合器嘅相反，負責將用機械語言嘗試翻譯做組合語言。
... 等等。

支援結構化編程 

高級語言入面常見、用嚟做結構化編程嘅命令多數都可以用簡單嘅組合語言命令砌出嚟。例如：

條件運算式 

條件運算式係高級語言常用嘅命令之一。一個條件運算式會指明一個條件同埋包含一柞命令，而如果個條件成立，噉佢就會叫部電腦做佢包含嗰柞命令，好似係以下呢段 C 嘅碼噉：

if (ax < bx) { // 如果 ax 細過 bx...
    x = -1; // 將 x 設做 -1。
} else { // 如果唔係...
    x = 1; // 就將 x 設做 1。
}

喺組合語言入面，同一段命令望落大致上會係噉樣嘅：

cmp 	ax, bx  	; 「cmp」係英文「compare」嘅簡寫，呢個命令叫部電腦比較 ax 同 bx。
	jl  	axLess          ; 如果比較結果係 ax 細啲，跳去「axless」嗰命令。
	mov 	word [X], 1     ; 將 x 設做 1，如果 ax 細過 bx，部電腦會跳過呢行命令。
	jmp 	Both            ; 做咗「將 x 設做 1」喇，所以要跳去 Both 嗰度。
axLess: 
	mov 	word [X], -1    ; 將 x 設做 -1。
Both:

For 迴圈 

For 迴圈係高級語言實會有嘅一種命令。一個 for 迴圈會指定一個變數，部電腦每行個迴圈一次就會將個變數嘅數值改變，直至個變數嘅數值去到某個位為止。例如係 C 程式語言，就有噉樣嘅句法：

for (int x = 0; x <= 3; x++)
{
    // x 開頭係 0，呢個 for 迴圈每重複一次，x 就會提升 1，而只要 x ≤ 3，呢個迴圈會係噉重複行。
}

以下呢段 8086 嘅組合碼會達到同呢個 for 迴圈一樣嘅效果：

xor cx,cx   ; cx 暫存器攞嚟做 counter，設佢數值做 0。
loop1   nop         ; 個迴圈嘅內容喺度。
        inc cx      ; 將 cx 暫存器入面嗰個數值升 1。
        cmp cx,3    ; 叫部電腦比較 cx 暫存器嗰個數值同「3」。
        jle loop1   ; 「如果比較結果係兩個數一樣咁大或者 cx 暫存器嗰個數值細啲，返返去 loop1」。

Do-while 迴圈 

Do-while 迴圈係另一種高級語言幾乎實會有嘅一種命令，每個 do-while 迴圈都會包含咗一行或者多行嘅命令，而個迴圈會令到部電腦係噉不停做個迴圈入面嗰啲命令，一路做到某個條件唔再成立為止。例如 C 程式語言就有噉樣嘅句法：

int x = 1;
do {
    // 只要 x = 1，個程式就會係噉重複做 do {} 入面嗰柞命令。
}
while(x == 1)

喺 8086 嘅組合語言當中，呢個 do-while 迴圈係噉嘅：

mov ax,1    ;  將 ax 暫存器嘅數值設做 1。
loop1   nop         ;　個迴圈嘅內容喺度。
        cmp ax,1    ; 叫部電腦比較 ax 暫存器嗰個數值同「1」。
        je loop1    ; 「如果比較結果係兩個數一樣嘅話，返返去 loop1 嗰行命令度」。

廿一世紀初應用 
到咗廿一世紀初，無論係專業嘅程式設計員定係得閒玩寫程式嘅人，都係多數偏向鍾意用高級語言，所以「組合語言仲係咪有用」係一個有相當爭議性嘅課題：截至 2017 年 7 月為止，TIOBE 指數嘅評級顯示，如果將主要程式語言按人氣排嘅話，組合語言屬第 11 名－個名次仲高過 Visual Basic ；事實係，就算係同高級語言比，組合語言都仲係有一啲優勢－例如係有研究一再噉證明咗，雖然相關領域嘅科學家同工程師嘗試令到高級語言用嘅編譯器快啲，但好多時將組合語言翻譯做機械碼都仲係快一截；不過事實又係，現代嘅 CPU 快得好交關，所以喺部電腦運行嘅大多數時間，粒 CPU 都係處理閒置嘅狀態，所以「一段源碼能夠以幾快嘅速度翻做電腦識行嘅機械碼」呢家嘢對整體運算速度造成嘅影響理應會愈嚟愈唔明顯。

廿一世紀初嘅電腦科學同電子工程課程普遍都會教組合語言：雖然專業嘅程式設計員已經好少可會定時定候用組合語言做嘢，但組合語言所教嘅嗰啲概念都仲係好緊要。好似係二進制算術、記憶體嘅管理、堆疊嘅處理同埋編譯器嘅設計等嘅課題實要識少少有關電腦喺硬件層面嘅運作先至會學得明，而一部電腦嘅行為係本質上由佢嘅命令集話事嘅，所以要學電腦點喺硬件層面運作，就要學電腦所屬嘅組合語言。現代電腦一般彼此之間都有相似嘅命令集，所以學一隻組合語言好多時經已夠個學生了解嗮呢啲基本概念。
應用例子
電腦系統嘅起動程式多數會用組合語言嚟將個系統初始化同埋喺起動個作業系統嗰時測試吓個系統嘅硬件先。例子有同 IBM 相容嘅個人電腦系統同埋 CP/M 嘅 BIOS。
某啲相對低級啲嘅程式語言－好似係 Pascal 或者 C－會俾個用家將組合語言直接噉嵌入去源碼嗰度。呢啲程式好多時仲有能力喺唔同嘅硬件平台嗰度搵返相應嘅組合碼出嚟。
有啲編譯器喺將啲高級語言嘅源碼完全編譯之前會首先將佢翻做組合碼先，等個用家有得用啲組合碼嚟做除錯或者最佳化。
喺處理能力同 RAM 比較有限嘅個人電腦嗰度，組合語言可以用嚟提高執行程式嘅速度。
組合語言喺還原工程上好有用。因為同專利相關嘅問題，好多時啲人都唔鍾意俾第啲人知道佢哋嗰啲程式嘅源碼，就算一間公司肯將佢哋個新軟件嘅源碼俾人知，好多時都淨係會以機械碼嘅形式發放。機械碼要譯做組合碼好易，但係要譯做高級語言就撈絞好多。好似係 IDA Pro 等嘅架生會因為呢個原因而好深入噉使用反組合嘅過程，而黑客等嘅人物會運用呢啲噉嘅架生嚟解開商業軟件嘅源碼－再將呢啲源碼賣俾出嗰個軟件間公司嘅同行競爭者。

指令集架構
十六進制
馮紐曼架構
編譯器
高級組合語言
麵條式程式碼
《人力資源機械》，一隻要玩家用組合語言噉嘅程式語言解難嘅 2015 年電子遊戲。

文獻 

ASM Community Book, "An online book full of helpful ASM info, tutorials and code examples" by the ASM Community, archived at the internet archive.
Jonathan Bartlett: Programming from the Ground Up. Bartlett Publishing, 2004. Also available online as PDF.
Robert Britton: MIPS Assembly Language Programming. Prentice Hall, 2003. 
Jeff Duntemann: Assembly Language Step-by-Step. Wiley, 2000. 
Randall Hyde: The Art of Assembly Language. No Starch Press, 2003. Draft versions available online as PDF and HTML.
Charles W. Kann: Introduction to MIPS Assembly Language Programming. 2015.
Peter Norton, John Socha, Peter Norton's Assembly Language Book for the IBM PC, Brady Books, NY: 1986.
Michael Singer, PDP-11. Assembler Language Programming and Machine Organization, John Wiley & Sons, NY: 1980.
Dominic Sweetman: See MIPS Run. Morgan Kaufmann Publishers, 1999. 
John Waldron: Introduction to RISC Assembly Language Programming. Addison Wesley, 1998.

攷

拎 

NASM 編譯器
Linux Assembly
Unix Assembly Language Programming
PPR: Learning Assembly Language
NASM – The Netwide Assembler (a popular assembly language)
Assembly Language Programming Examples
Authoring Windows Applications In Assembly Language
Assembly Optimization Tips by Mark Larson 
The Art of Assembly Language  by Randall Hyde
The table for assembly language to machine code
AoGo 彙编小站

程式語言