組合語言

組合語言（粵拼：zou2hap6jyu5jin4；英文：assembly language，又叫assembler language，簡寫asm），又有叫匯編語言，係一類低級（low-level）程式語言，特徵係機械語言（machine language）同佢有一對一嘅對應，但係用咗羅馬字母嘅 ｢記憶語法｣（mnemonics）將本來係數字嘅命令符號化，令佢易睇啲。
舉返個例說明：喺Zilog Z80嘅處理器嗰度，「00000101」呢段機械碼會令到粒CPU做 ｢將 B 處理器暫存器入面嗰個數值下降 1｣ 嘅運算，而同一個命令用組合語言寫嘅話會係 ｢DEC B｣​——​喺組合語言嗰串命令當中見到有「DEC」呢三個羅馬字母，代表咗英文字 ｢decrement｣（指「令某樣嘢數值下降」噉解）。組合語言對羅馬字母嘅使用令到用呢啲語言寫成嘅碼（對一般人嚟講）易睇過機械語言碼好多。
話雖如此，組合語言都有「兩頭唔到岸」嘅缺點：喺一般嘅應用當中，電腦內部處理嘅係機械語言，電腦係唔曉直接讀組合語言嘅，所以喺用親組合語言寫程式嗰陣，個用家梗要有個組合器（assembler）將段組合語言碼轉化做電腦識直接睇嘅機械語言，即係唔似得機械語言碼噉，可以直接攞嚟俾電腦行；另一方面，組合語言又唔似得高級語言（high-level programming language）噉有普遍性​——​每一款組合語言都係要喺某啲特定嘅電腦系統架構同作業系統（operating system）上先會行到，而相比之下，好似係Java或者Python等嘅高級語言一般都可以用落去多個平台上面，淨係需要有啱用嘅編譯器（compiler）將佢哋翻譯俾部電腦睇就得。
機械語言（machine lanaguage）係電腦內部直接處理嗰種語言。機械語言係最低級（low-level）嘅程式語言​——​淨係用數字表達嗮所有嘢，而組成一段機械碼嘅數字會包含嗮「要用啲乜嘢數據」同「要做啲乜嘢作業」等嘅資訊。舉個例說明：假想而家有款機械語言，
於是喺用呢種語言寫成嘅源碼入面，「0000011 0000100 0000」呢段碼係叫電腦計 3（用二進制寫係 11）加 4（用二進制寫係 100）嘅結果出嚟。有關機械語言嘅物理實現，可以睇吓電子工程同邏輯門等嘅電腦硬件技術。
組合語言大致上就係用羅馬字母嘅機械語言，用咗記憶術表達想部電腦行嘅指示，等唔使睇淨係用數字寫成嘅機械碼：組合語言會用羅馬字母串表達機械語言當中嘅每一個命令或者行動碼，通常亦會用同樣嘅手法表達埋要用嘅資訊喺邊個暫存器（register）同位元欄（bit field）等嘅資訊，並且好多時會掕埋一個或者多個運算數（operand；指要運算嗰啲數值）。
舉個例說明，例如家吓個用家想叫部電腦計「3+2」嘅結果，「加」就係要做嗰個命令，喺部電腦嘅機械碼會有個相應嘅行動碼，而 3 同 2 就係運算數。多數嘅組合器（assembler；將段組合語言碼轉化做電腦識睇嘅機械語言）都容許用家運用有名嘅常數、暫存器同埋記憶嘅位置等嘅資訊，所以個用家唔使用人手噉做一啲重複性嘅作業。
以下係一啲典型嘅用組合語言寫嘅語句：
視乎系統結構，呢啲元素可以結合埋一齊嚟整更加複雜嘅命令。
舉個具體例子說明，以下呢段碼會叫一個X86或者IA-32處理器去將一個 8bit咁長嘅數值搬去個暫存器嗰度。呢個命令用二進制嘅機械語言寫嘅話係「10110」，而呢個命令跟住仲要掕住第段數字表示要用邊一個暫存器嚟做，例如 AL 暫存器嘅碼係「000」，所以跟住呢段機械碼會叫部電腦將數據 0110001 入落去 AL 暫存器嗰度：
實際做編程嗰陣，呢段碼通常係用十六進制嚟表示，等段嘢對一般人嚟講易睇啲：
喺呢段碼入面，「B0」代表咗行動碼，叫部電腦做「將跟住嗰個數值複製，再擺落去 AL 嗰度」，而「61」係用十六進制寫嘅「0110001」（呢個數用十進制寫係「97」）。8086 系列嘅組合語言仲會俾用家用「MOV」（英文字「move」嘅簡寫）嚟表達呢個命令，等段碼對於人類嚟講更加易睇，即係好似以下噉樣：
喺第啲組合語言入面，同一個動作可能會有唔同但類似嘅字眼表示，又有啲可能會將個命令分開或者合併，又或者用唔同嘅命令代表唔同嘅情況。以 MOV ｢搬｣（其實係 ｢抄｣）做例，有啲組合語言用「MOV」代表嗮所有抄數據嘅動作，第啲組合語言可能唔叫 ｢搬｣，再第啲又可能用唔同嘅命令代表「由記憶體抄去暫存器」同「由暫存器抄去記憶體」等等嘅唔同情況；例如Z80叫 ｢載入｣（load，LD）唔叫 ｢搬｣；但係6502就分 ｢載入｣（load，LD，記憶體抄去暫存器）、｢儲存｣（store，ST，暫存器抄去記憶體）同 ｢轉移｣（transfer，T，暫存器互抄），而且係命令掕埋暫存器名（LDA、STX、TYA 等等）。
「10110000」（十六進制：B0）係 X86 當中嘅一個行動碼，會將一個 8 位元嘅數值抄去 AL 暫存器嗰度，「10110001」（十六進制：B1）會將個數值抄去 CL 暫存器，而「10110010」（十六進制：B2）會將個數值抄去 DL 暫存器，即係好似以下呢段碼噉：
「MOV」呢個命令可以做得再複雜啲，好似以下嘅碼噉：
最後呢個例嘅 ESI 暫存器係所謂索引暫存器；概念上，EAX 嘅內容係陣列位址，ESI 嘅內容係對應陣列索引嘅位元組偏移量（byte offset）。
整組合器嘅人响將命令分類同埋所用嘅命名法等方面好多樣化。不過，無論係邊款組合語言邊個設計師，一款典型嘅組合語言喺句法（syntax）上都會有三款命令用嚟定義個程式要乜：
行動碼（opcode）係指段命令當中教部電腦「要做乜運算」嗰橛。組合語言入面嗰啲命令一般都係好簡單嘅，唔似得高級語言入面嗰啲噉。普遍嚟講，喺程式編寫上，記憶術（mnemonic）係指某個電腦識執行嘅機械碼用符號（而唔係 0 同 1）表達嘅名，例如係正話提咗嘅例子 1 入面嘅 X86 命令「將跟住嗰個數值複製，再擺落去 AL 嗰度」噉，
是但搵款組合語言嚟睇，同款語言對應嘅機械語言嘅每款命令都會有個記憶術。多數嘅命令都會掕住若干個運算數，運算數可以代表要計嘅數值又得、代表儲住要用嘅數值嘅暫存器嘅位置又得、或者要用嘅數值喺部電腦嘅記憶嘅位置都得。
有陣時，一款組合語言會有延伸嘅行動碼嚟表達一啲結合咗多個命令嘅複雜命令。舉個例說明，有好多 CPU 都係冇NOP命令​——​呢個命令叫部電腦唔好做任何嘢，好多時俾人攞嚟控制第啲命令喺乜嘢時間行；但有一啲細啲、可以結合埋一齊做 NOP 嘅命令；喺 8086 系列嘅 CPU 當中，xchgax,ax呢行命令俾人用嚟做nop，而nop呢段嘢嚴格嚟講唔算係呢啲 CPU 入面嘅命令。某啲反組合器識得認呢段碼，會將xchgax,ax解碼做nop。呢啲唔淨只代表一個命令，而係代表咗多個命令嘅組合嘅記憶術就係所謂嘅延伸記憶術（extended mnemonics），SPARC 架構嗌呢啲記憶術做合成命令（synthetic instrcution）。
類行動碼（pseudo-opcode）係指一啲由個用家俾去個組合器嘅命令，叫個組合器做一啲「翻譯組合碼」以外嘅作業。呢啲指示會影響到個組合器嘅運作，控制個組合器內部嘅參數，例如係個組合器「用乜訊號代表邊個邊個組合碼命令」呀噉。類行動碼嘅名通常都係以一個點（.）做開頭嘅​——​呢樣嘢幫手令啲用家一睇就知呢啲碼同機械碼命令唔同。
類行動碼可以好有用。呢啲碼可以令一個程式嘅組合受制於程式員俾嘅參數，即係叫個組合器「喺呢個情況噉樣組合，而喺第個情況用第個方法組合」，令到有陣時同一個程式可以用唔同方法組合，增加組合器嘅用途；另一方面，類行動碼又可以用嚟操控一個程式點樣呈現，令個程式對於人類嚟講易睇啲；類行動碼嘅仲可以用嚟保留空間去儲起個組合器嘅執行時間（run time）等嘅資訊，等個程式員有得做有關「個組合器用咗幾耐時間做一次翻譯」方面嘅分析。
同大多數嘅電腦語言一樣，組合語言俾用家喺個程式嘅源碼嗰度加啲注釋（comment）落去​——​即係喺啲命令後面有啲用人類語言寫、個組合器喺組合段碼嗰陣會忽略嘅句子（即係好似下面嗰段碼入面嗰啲灰字）。呢啲句子幫到程式員手令到佢哋寫嘅源碼更加易讀，例如一個程式員可以喺一行命令後面加個注釋，用淺白嘅語言講清楚嗰行命令處理嗰個變數有乜嘢重要性。呢啲注釋會令到下一手處理呢段源碼嘅程式員能夠一睇就明嗰行命令係做乜嘢目的嘅。
x86/amd64組譯命令嘅兩大格式分別係Intel式同AT&T式，分別由微軟產品用（包括Microsoft Windows/Visual C++）同GNU軟件用（包括GAS，不過 GAS 亦可以用 Intel 組譯格式）：
組合器（assembler）係用組合語言寫程式實要用嘅嘢，組合器係一啲特別嘅程式，負責將用組合語言寫成嘅源碼轉化做電腦識睇嘅機械碼：一段電腦會識行嘅機械碼會完全用 1 同 0 表達嗮所有資訊​——​包括行動碼、運算數同埋啲運算數嘅位置；個組合器會將組合碼入面嗰啲羅馬字母轉化做相應嘅機械碼，亦都會計返好啲常數表達同埋解決記憶體嘅位置以及其他嘢嘅名。組合器會用某啲名代表個程式入面嘅物體，唔似得機械語言噉，等個用家唔使吓吓都計同人手噉更新啲嘢嘅位置。例：
組合器呢家嘢早喺 1950 年代，有字嘅電腦介面啱啱出現嗰陣時經已開始有，同Fortran、COBOL、同埋LISP呢啲早期程式語言同期，而且喺嗰時因為易寫過高級語言嘅編譯器而頗受歡迎​——​正如頭先提到，組合語言喺結構上好似機械語言，好多時組合語言啲命令都只不過係用咗羅馬字母表達嘅機械語言命令，組合語言入面嗰啲命令好多都同某啲機械語言嘅命令有 1 對 1 嘅關係，所以要將組合碼翻譯做機械碼好容易。
組合器大致上可以按「行嗰陣要睇段源碼幾多次」嚟分做兩大類：
傳統上用睇一次組合器嘅原因係因為呢啲組合器唔使同一段源碼睇幾次，所以做起嘢上嚟好快，組合時間（assembly time；評估組合器效率嘅重要指標之一）短​——​睇第二次就要重新讀過段源碼一次，呢樣嘢要用舊式嘅電腦（靠讀一段寫咗喺帶上面嘅源碼嘅電腦）做可以撈絞得好交關。但由廿一世紀初開始，電腦經已有龐大嘅記憶體，能夠有足夠嘅空間做嗮所有必需嘅處理而唔使讀帶，所以更加穩陣同埋做起某啲作業上嚟快啲嘅睇多次組合器開始受到重視。
喺以下呢段組合碼當中，一個睇一次組合器喺處理S2嗰行命令嗰陣已經能夠知道BKWD嘅位置，但喺處理S1嗰行命令嗰時唔會知道FWD嘅位置，所以要靠估嚟決定要預留幾多記憶體嘅位置。相比之下，一個睇兩次嘅組合器會喺第一次睇段碼嗰陣知道兩個物件嘅位置，並且喺第二次讀碼嗰陣處理。
... 等等。
高級語言入面常見、用嚟做結構化編程（structured programming）嘅流程控制多數都可以用簡單嘅組合語言命令砌出嚟，呢啲命令主要包括 ｢比較｣（compare，其實即係減，但係唔儲存計出嚟嘅差）同 ｢跳｣（jump或者branch，即係goto）。例如：
條件運算式（conditional statement）係高級語言常用嘅流程控制之一。一個條件運算式會指明一個條件同埋包含一柞命令，而如果個條件成立，噉佢就會叫部電腦做佢包含嗰柞命令，好似係以下呢段C嘅碼噉：
喺組合語言入面，同一段命令望落大致上會係噉樣嘅：
要注意嘅係，喺某嘅處理器嘅架構，跳幾遠可能有限制（例如，喺 6502，跳幾遠係以位元組偏移量計，向前向後跳嘅距離都淨得 7 位元）；如果唔可以跳得遠，但係中間要做好多嘢，就可能要將中間部分變成子程式。
For 迴圈（For loop）係高級語言實會有嘅一種流程控制。一個 for 迴圈會指定一個變數，部電腦每行個迴圈一次就會將個變數嘅數值改變，直至個變數嘅數值去到某個位為止。例如係 C 程式語言，就有噉樣嘅句法：
以下呢段 8086 嘅組合碼會達到同呢個 for 迴圈一樣嘅效果：
同條件運算式一樣，喺某嘅處理器嘅架構，跳幾遠可能有限制。如果用意只係要內容行 4 次，而唔使用到例入面 CX 暫存器嘅數值，喺實際編程通常會係掉轉由 4 數到 1（數到 0 就停），而唔係由 0 數到 3，理由係慳位同慳執行時間（唔使做 cmp）。
喺某啲架構，呢種廻圈可能會入面冇嘢或者得某個數量嘅 NOP，齋用嚟計時。
Do-while 迴圈（Do-while loop）係另一種高級語言幾乎實會有嘅一種流程控制，每個 do-while 迴圈通常都會包含一行或者多行嘅命令，而個迴圈會令到部電腦係噉不停做個迴圈入面嗰啲命令，一路做到某個條件唔再成立為止。例如 C 程式語言就有噉樣嘅句法：
喺 8086 嘅組合語言當中，呢個 do-while 迴圈係噉嘅：
同條件運算式一樣，喺某嘅處理器嘅架構，跳幾遠可能有限制。
到咗廿一世紀初，無論係專業嘅程式設計員定係得閒玩寫程式嘅人，都係多數偏向鍾意用高級語言，所以「組合語言仲係咪有用」係一個有相當爭議性嘅課題：截至 2017 年 7 月為止，TIOBE 指數嘅評級顯示，如果將主要程式語言按人氣排嘅話，組合語言屬第 11 名​——​個名次仲高過Visual Basic；事實係，就算係同高級語言比，組合語言都仲係有一啲優勢​——​例如係有研究一再噉證明咗，雖然相關領域嘅科學家同工程師嘗試令到高級語言用嘅編譯器快啲，但好多時將組合語言翻譯做機械碼都仲係快一截；不過事實又係，現代嘅CPU快得好交關，所以喺部電腦運行嘅大多數時間，粒 CPU 都係處理閒置嘅狀態，所以「一段源碼能夠以幾快嘅速度翻做電腦識行嘅機械碼」呢家嘢對整體運算速度造成嘅影響理應會愈嚟愈唔明顯。
廿一世紀初嘅電腦科學同電子工程課程普遍都會教組合語言：雖然專業嘅程式設計員已經好少可會定時定候用組合語言做嘢，但組合語言所教嘅嗰啲概念都仲係好緊要。好似係二進制算術、記憶體嘅管理、堆疊嘅處理同埋編譯器嘅設計等嘅課題實要識少少有關電腦喺硬件層面嘅運作先至會學得明，而一部電腦嘅行為係本質上由佢嘅命令集（instruction set）話事嘅，所以要學電腦點喺硬件層面運作，就要學電腦所屬嘅組合語言（同埋機械語言）。現代電腦一般彼此之間都有相似嘅命令集，所以學一隻組合語言好多時經已夠個學生了解嗮呢啲基本概念。