跳去內容

組合語言

呢篇文係一篇好文。想知更多,請撳呢個掣。
出自維基百科,自由嘅百科全書
(由組合器跳轉過嚟)

摩托羅拉 MC6800 組合語言碼喺組合過程中得出嘅列表,右便係源碼(組合語言),左便係譯出來嘅目標碼(機械語言)。

組合語言粵拼zou2 hap6 jyu5 jin4英文assembly language,又叫 assembler language,簡寫 asm),又有叫匯編語言,係一類低級(low-level)程式語言,特徵係機械語言(machine language)同佢有一對一嘅對應,但係用咗羅馬字母嘅 「記憶語法」(mnemonics)將本來係數字嘅命令符號化,令佢易睇啲[1][2][3][4]

舉返個例說明:喺 Zilog Z80處理器嗰度,「00000101」呢段機械碼會令到粒 CPU 做 「將 B 處理器暫存器入面嗰個數值下降 1」 嘅運算,而同一個命令用組合語言寫嘅話會係 「DEC B」​​喺組合語言嗰串命令當中見到有「DEC」呢三個羅馬字母,代表咗英文字 「decrement」(指「令某樣嘢數值下降」噉解)。組合語言對羅馬字母嘅使用令到用呢啲語言寫成嘅碼(對一般人嚟講)易睇過機械語言碼好多[5][6]

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

基礎

[編輯]

機械語言

[編輯]
内文:機械語言

機械語言(machine lanaguage)係電腦內部直接處理嗰種語言。機械語言係最低級(low-level)[註 1]程式語言​淨係用數字表達嗮所有嘢,而組成一段機械碼嘅數字會包含嗮「要用啲乜嘢數據」同「要做啲乜嘢作業」等嘅資訊。舉個例說明:假想而家有款機械語言,

  • 款語言嘅每段命令都由 18 個數字組成,呢 18 個數字每一個都一係 1 一係 0(每一個呢啲數字成一個 bit),
    • 最頭嗰 7 個數字用二進制表達數據 A
    • 跟住嗰 7 個數字用二進制表達數據 B
    • 最尾嗰 4 個數字就表達要做乜(呢段就係所謂嘅行動碼;opcode)​​0000 代表,0001 代表等等。

於是喺用呢種語言寫成嘅源碼入面,「0000011 0000100 0000」呢段碼係叫電腦計 3(用二進制寫係 11)加 4(用二進制寫係 100)嘅結果出嚟[9][10]。有關機械語言嘅物理實現,可以睇吓電子工程邏輯門等嘅電腦硬件技術。

組合句法

[編輯]

組合語言大致上就係用羅馬字母嘅機械語言,用咗記憶術表達想部電腦行嘅指示,等唔使睇淨係用數字寫成嘅機械碼:組合語言會用羅馬字母串表達機械語言當中嘅每一個命令或者行動碼,通常亦會用同樣嘅手法表達埋要用嘅資訊喺邊個暫存器(register)同位元欄(bit field)等嘅資訊,並且好多時會掕埋一個或者多個運算數(operand;指要運算嗰啲數值)[6]

舉個例說明,例如家吓個用家想叫部電腦計「3 + 2」嘅結果,「加」就係要做嗰個命令,喺部電腦嘅機械碼會有個相應嘅行動碼,而 3 同 2 就係運算數。多數嘅組合器(assembler;將段組合語言碼轉化做電腦識睇嘅機械語言)都容許用家運用有名嘅常數、暫存器同埋記憶嘅位置等嘅資訊,所以個用家唔使用人手噉做一啲重複性嘅作業[6][7]

以下係一啲典型嘅用組合語言寫嘅語句[11]

INC COUNT        ; 將變數 「count」 嘅數值加一(increment),所謂變數係指之前有定義位元組數量嘅一個位址。

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

AND MASK1, 128   ; 將變數「mask1」嘅數值同「128」呢個數值做邏輯與(結果喺返 mask1),即係保留位元 7,其他位元設做 0。

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

MOV AL, 10       ; AL 暫存器載入數值 「10」。

視乎系統結構,呢啲元素可以結合埋一齊嚟整更加複雜嘅命令。

例子 1

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

10110000 01100001

實際做編程嗰陣,呢段碼通常係用十六進制嚟表示,等段嘢對一般人嚟講易睇啲:

B0 61

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

MOV AL, 61h       ; AL 暫存器(AX 暫存器嘅低位元組)載入(單位元組嘅)十進制數值 97 。

喺第啲組合語言入面,同一個動作可能會有唔同但類似嘅字眼表示,又有啲可能會將個命令分開或者合併,又或者用唔同嘅命令代表唔同嘅情況。以 MOV 「搬」(其實係 「抄」)做例,有啲組合語言用「MOV」代表嗮所有抄數據嘅動作,第啲組合語言可能唔叫 「搬」,再第啲又可能用唔同嘅命令代表「由記憶體抄去暫存器」同「由暫存器抄去記憶體」等等嘅唔同情況;例如 Z80 叫 「載入」(load,LD)唔叫 「搬」;但係 6502 就分 「載入」(load,LD,記憶體抄去暫存器)、「儲存」(store,ST,暫存器抄去記憶體)同 「轉移」(transfer,T,暫存器互抄),而且係命令掕埋暫存器名(LDA、STX、TYA 等等)。

例子 2

「10110000」(十六進制:B0)係 X86 當中嘅一個行動碼,會將一個 8 位元嘅數值抄去 AL 暫存器嗰度,「10110001」(十六進制:B1)會將個數值抄去 CL 暫存器,而「10110010」(十六進制:B2)會將個數值抄去 DL 暫存器,即係好似以下呢段碼噉[12]

MOV AL, 1h        ; AL 暫存器載入(單位元組)數值 「1」。
MOV CL, 2h        ; CL 暫存器載入數值 「2」。
MOV DL, 3h        ; DL 暫存器載入數值 「3」。
例子 3

「MOV」呢個命令可以做得再複雜啲,好似以下嘅碼噉[13]

MOV EAX, [EBX]	  ; EAX 暫存器載入 EBX 暫存器所指嘅位置嘅(頭 4 個位元組嘅)內容。
MOV [ESI+EAX], CL ; EAX 同 ESI 暫存器嘅內容嘅和所指嘅位置(嘅嗰個位元組)載入 CL 暫存器嘅內容。

最後呢個例嘅 ESI 暫存器係所謂索引暫存器;概念上,EAX 嘅內容係陣列位址,ESI 嘅內容係對應陣列索引嘅位元組偏移量(byte offset)。

語言設計

[編輯]

三大元素

[編輯]

組合器嘅人响將命令分類同埋所用嘅命名法等方面好多樣化。不過,無論係邊款組合語言邊個設計師,一款典型嘅組合語言喺句法(syntax)上都會有三款命令用嚟定義個程式要乜[6][14][15]

  • 用羅馬字代表嘅行動碼(opcode)、
  • 類行動碼(pseudo-opcode)、
  • 數據定義(data definitions):數據定義會定義要處理嘅數據嘅種類(例如係「數值」同「字母」等嘅種類)同埋長度(等部電腦知要預留幾多記憶體空間嚟儲件數據)等嘅資訊。呢啲命令亦都可以用嚟定義啲數據係咪可以由外來嘅程式(指分開噉組合嘅程式)處理,定係淨係可以喺嗰個程式入面用。睇埋運算數
INC COUNT        ; 將而家喺記憶入面嗰個變數嘅數值加一;
;行動碼:INC;
;數據定義:COUNT;

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

MOV AL, 10       ; AL 暫存器載入數值 10;
;行動碼:MOV;
;數據定義:AL 同 10;

行動碼

[編輯]
内文:行動碼

行動碼(opcode)係指段命令當中教部電腦「要做乜運算」嗰橛。組合語言入面嗰啲命令一般都係好簡單嘅,唔似得高級語言入面嗰啲噉。普遍嚟講,喺程式編寫上,記憶術(mnemonic)係指某個電腦識執行嘅機械碼用符號(而唔係 0 同 1)表達嘅名,例如係正話提咗嘅例子 1 入面嘅 X86 命令「將跟住嗰個數值複製,再擺落去 AL 嗰度」噉,

  • 段嘢本身係一個部電腦識得執行嘅命令;
  • 機械語言當中嘅行動碼係「10110」;
  • 喺嗰款組合語言當中嘅記憶術係「MOV」(英文「move」嘅簡寫,意思係「搬」,不過其實係 「抄」);

是但搵款組合語言嚟睇,同款語言對應嘅機械語言嘅每款命令都會有個記憶術[註 3][16]。多數嘅命令都會掕住若干個運算數,運算數可以代表要計嘅數值又得、代表儲住要用嘅數值嘅暫存器嘅位置又得、或者要用嘅數值喺部電腦嘅記憶嘅位置都得[17]

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

類行動碼

[編輯]
内文:類行動碼

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

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

同大多數嘅電腦語言一樣,組合語言俾用家喺個程式嘅源碼嗰度加啲注釋(comment)落去​​即係喺啲命令後面有啲用人類語言寫、個組合器喺組合段碼嗰陣會忽略嘅句子(即係好似下面嗰段碼入面嗰啲灰字)。呢啲句子幫到程式員手令到佢哋寫嘅源碼更加易讀,例如一個程式員可以喺一行命令後面加個注釋,用淺白嘅語言講清楚嗰行命令處理嗰個變數有乜嘢重要性。呢啲注釋會令到下一手處理呢段源碼嘅程式員能夠一睇就明嗰行命令係做乜嘢目的嘅[20]

MOV CL, 34h       ; 呢段灰色嘅字係注釋⸺個組合器係設計好咗會忽略「;」後面嘅碼,所以呢段灰字部電腦唔會處理,但係程式員可以用佢嚟解釋俾下一手程式員知呢段碼有乜嘢作用。

組譯風格比較

[編輯]

x86/amd64 組譯命令嘅兩大格式分別係 Intel 式同 AT&T 式,分別由微軟產品用(包括 Microsoft Windows/Visual C++)同 GNU 軟件用(包括 GAS,不過 GAS 亦可以用 Intel 組譯格式):

項目 Intel 格式 AT&T 格式
運算元(operand)順序 目標運算元行先 源運算元行先
暫存器嘅名 原樣 加「%」前綴
立即數 原樣 加「$」前綴
立即數嘅進位制 二進制 數值加「b」後綴 數值加 「0b」 前綴[23]
八進制 未知 數值加「0」前綴[23]
十六進制 數值加「h」後綴,但係數值如果字母開頭,要加「0」前綴 數值加「0x」前綴
存取記憶體長度 單位元組 如果需要[註 5],運算元前面加「byte ptr」關鍵字 行動碼加 b 後綴
雙位元組 如果需要,運算元前面加「word ptr」關鍵字 行動碼加 w 後綴
四位元組 如果需要,運算元前面加「dword ptr」關鍵字 行動碼加 l 後綴
八位元組[註 6] 如果需要,運算元前面加「qword ptr」關鍵字[24] 行動碼加 q 後綴
參照全局或者靜態 var 嘅值 [_var] _var
參照全局或者靜態變數 var 嘅位址 _var $_var
參照局部變數 需要基於堆叠指標(ESP)
記憶體直接尋址 seg_reg: [base + index * scale + immed32] seg_reg: immed32 (base, index, scale)
暫存器間址 [reg] (%reg)
暫存器變址尋址 [reg + _x] _x(%reg)
立即數變址尋址 [reg + 1] 1(%reg)
整數陣列尋址 [eax*4 + array] _array (,%eax, 4)

組合器

[編輯]
内文:組合器

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

  • 入落組合器嘅輸入:MOV R3, #15
  • 組合器俾出嘅輸出:1100 1010 1011 0011

組合器呢家嘢早喺 1950 年代,有字嘅電腦介面啱啱出現嗰陣時經已開始有,同 FortranCOBOL、同埋 LISP 呢啲早期程式語言同期,而且喺嗰時因為易寫過高級語言嘅編譯器而頗受歡迎​​正如頭先提到,組合語言喺結構上好似機械語言,好多時組合語言啲命令都只不過係用咗羅馬字母表達嘅機械語言命令,組合語言入面嗰啲命令好多都同某啲機械語言嘅命令有 1 對 1 嘅關係,所以要將組合碼翻譯做機械碼好容易[20]

功能
  • 有陣時,同一個 CPU 或者命令集會有好幾個命令句法嚟應付唔同嘅組合器。舉個例說明,喺 X86 型嘅處理器當中,一條「叫部電腦將記憶數據加落去個暫存器嗰度」嘅命令用 Intel 嘅句法寫可能係 add eax,[ebx],而用 GNU 組合器用嘅 AT&T 嘅句法寫就係 addl (%ebx),%eax。雖然呢啲唔同句法寫嘅命令望落唔同,但佢哋轉化咗做機械碼嗰陣好多時都係一樣樣嘅。有陣時同一個組合器可能會有幾個唔同模式嚟幫手翻譯唔同嘅句法嘅組合碼[20]
  • 有啲組合器仲有能力做一啲簡單嘅命令集特定嘅編譯器最佳化(optimization)​​最佳化係指將個編譯器嘅某啲特徵最大化或者最小化,例如係某啲組合器曉將個編譯器行嗰陣霸嘅記憶體量最小化,等部機行起上嚟順暢啲。周圍都搵得到嘅 X86 組合器就係一個具體嘅例子,呢啲組合器多數都曉喺俾用家要求嗰陣時跳過若干行嘅指示,有啲仲曉做簡單嘅重新排序或者插入新指示。

要睇幾多次

[編輯]

組合器大致上可以按「行嗰陣要睇段源碼幾多次」嚟分做兩大類[25]

  • 睇一次組合器(one-pass assembler)會將段源碼睇一次,跟手就可以出到佢要出嘅輸出。喺段源碼行過之前用咗嘅符號都需要改返啱,話俾部機聽要覆蓋(overwrite)一個之前用過嘅(記憶體入面嘅)位,並且將呢個位攞嚟儲嗰個新嘅變數。
  • 睇多次組合器(multi-pass assembler)會整個表出嚟,列嗮所有嘅符號同埋佢哋喺第一次睇段碼嗰陣嘅數值出嚟,再用個表嚟整碼。

傳統上用睇一次組合器嘅原因係因為呢啲組合器唔使同一段源碼睇幾次,所以做起嘢上嚟好快,組合時間(assembly time;評估組合器效率嘅重要指標之一)短​​睇第二次就要重新讀過段源碼一次,呢樣嘢要用舊式嘅電腦(靠讀一段寫咗喺帶上面嘅源碼嘅電腦)做可以撈絞得好交關。但由廿一世紀初開始,電腦經已有龐大嘅記憶體,能夠有足夠嘅空間做嗮所有必需嘅處理而唔使讀帶,所以更加穩陣同埋做起某啲作業上嚟快啲嘅睇多次組合器開始受到重視[25]

例子說明

喺以下呢段組合碼當中,一個睇一次組合器喺處理 S2 嗰行命令嗰陣已經能夠知道 BKWD 嘅位置,但喺處理 S1 嗰行命令嗰時唔會知道 FWD 嘅位置,所以要靠估嚟決定要預留幾多記憶體嘅位置。相比之下,一個睇兩次嘅組合器會喺第一次睇段碼嗰陣知道兩個物件嘅位置,並且喺第二次讀碼嗰陣處理。

S1   B   FWD
...
FWD   EQU *
...
BKWD   EQU *
...
S2   B   BKWD

組合器類別

[編輯]
  • 宏組合器(macro assembler):係任何可以用 「巨集」(macro)嘅組合器。即係你可以定義一啲特定嘅名嚟表達某啲特定嘅組合語言命令,例如,如果你話「swap」(英文「交換」噉解)代表一組令某兩個變數數值互換嘅命令,你就可以打「swap」就可以直接將嗰串命令入落去第段碼嗰度,唔使下下都成串命令打一次。好多組合器亦都係宏組合器。
  • 微組合器(micro assembler):係用嚟準備微程式(韌體)嘅組合器,呢啲微程式嘅作用係要控制部中央處理器等等嘅內部作業,例如機械碼嘅內部運作。
  • 交叉組合器(cross assembler):負責令一段組合碼喺另一個(同嗰段組合碼所屬嗰個系統唔同嘅)電腦或者作業系統上面行;交叉組合器令到用家有得為一啲本身冇能力支援軟件發展嘅系統寫程式。喺呢個情況下,個用家可以將要行嗰段碼(目的碼)用某啲方法(例如燒入唯讀記憶體)搬去個目標系統嗰度。
  • 高級組合器(high-level assembler):會提供類似高階程式語言嘅命令,俾個用家用一啲進級嘅控制結構命令(例如係 IF/THEN/ELSE)同埋一啲進級嘅數據類[26]
  • 反組合器(disassembler): 係組合器嘅相反,負責將用機械語言嘗試翻譯做組合語言[27]

... 等等。

支援結構化編程

[編輯]

高級語言入面常見、用嚟做結構化編程(structured programming)嘅流程控制多數都可以用簡單嘅組合語言命令砌出嚟[28],呢啲命令主要包括 「比較」(compare,其實即係減,但係唔儲存計出嚟嘅)同 「跳」(jump 或者 branch,即係 goto)。例如:

條件運算式

[編輯]

條件運算式(conditional statement)係高級語言常用嘅流程控制之一。一個條件運算式會指明一個條件同埋包含一柞命令,而如果個條件成立,噉佢就會叫部電腦做佢包含嗰柞命令,好似係以下呢段 C 嘅碼噉[29]

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 設做16位元嘅數值 1(如果 ax 細過 bx,上一行已經令部電腦跳過呢行命令)。
	jmp 	Both            ; 做咗「將 x 設做 1」喇,所以要跳去 Both 嗰度(如果冇呢行命令,部電腦就會將已經設做 1 嘅 x 重新設做 -1)。
axLess: 
	mov 	word [X], -1    ; 將 x 設做16位元嘅數值 -1。
Both:

要注意嘅係,喺某嘅處理器嘅架構,跳幾遠可能有限制(例如,喺 6502,跳幾遠係以位元組偏移量計,向前向後跳嘅距離都淨得 7 位元);如果唔可以跳得遠,但係中間要做好多嘢,就可能要將中間部分變成子程式

For 迴圈

[編輯]
睇埋:For 迴圈

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

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

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

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

同條件運算式一樣,喺某嘅處理器嘅架構,跳幾遠可能有限制。如果用意只係要內容行 4 次,而唔使用到例入面 CX 暫存器嘅數值,喺實際編程通常會係掉轉由 4 數到 1(數到 0 就停),而唔係由 0 數到 3,理由係慳位同慳執行時間(唔使做 cmp)。

喺某啲架構,呢種廻圈可能會入面冇嘢或者得某個數量嘅 NOP,齋用嚟計時。

Do-while 迴圈

[編輯]

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

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

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

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

同條件運算式一樣,喺某嘅處理器嘅架構,跳幾遠可能有限制。

廿一世紀初應用

[編輯]

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

廿一世紀初嘅電腦科學電子工程課程普遍都會教組合語言:雖然專業嘅程式設計員已經好少可會定時定候用組合語言做嘢,但組合語言所教嘅嗰啲概念都仲係好緊要。好似係二進制算術、記憶體嘅管理、堆疊嘅處理同埋編譯器嘅設計等嘅課題實要識少少有關電腦喺硬件層面嘅運作先至會學得明,而一部電腦嘅行為係本質上由佢嘅命令集(instruction set)話事嘅,所以要學電腦點喺硬件層面運作,就要學電腦所屬嘅組合語言(同埋機械語言)。現代電腦一般彼此之間都有相似嘅命令集,所以學一隻組合語言好多時經已夠個學生了解嗮呢啲基本概念[36]

應用例子
  • 電腦系統嘅起動程式(booting program)多數會用組合語言嚟將個系統初始化同埋喺起動個作業系統嗰時測試吓個系統嘅硬件先。例子有同 IBM 相容嘅個人電腦系統同埋 CP/MBIOS
  • 某啲相對低級啲嘅程式語言​​好似係 Pascal 或者 C​​會俾個用家將組合語言直接噉嵌入去源碼嗰度。呢啲程式好多時仲有能力喺唔同嘅硬件平台嗰度搵返相應嘅組合碼出嚟。
  • 有啲編譯器喺將啲高級語言嘅源碼完全編譯(做機械碼)之前會首先將佢翻做組合碼先,等個用家有得用啲組合碼嚟做除錯或者最佳化。
  • 喺處理能力同 RAM 比較有限嘅個人電腦嗰度,組合語言可以用嚟提高執行程式嘅速度。
  • 組合語言喺還原工程(reverse engineering)上好有用。因為同專利相關嘅問題,好多時啲人都唔鍾意俾第啲人知道佢哋嗰啲程式嘅源碼,就算一間公司肯將佢哋個新軟件嘅源碼俾人知,好多時都淨係會以機械碼嘅形式發放。機械碼要譯做組合碼好易,但係要譯做高級語言就撈絞好多。好似係 IDA Pro 等嘅架生會因為呢個原因而好深入噉使用反組合嘅過程,而黑客等嘅人物會運用呢啲噉嘅架生嚟解開商業軟件嘅源碼​​再(例如)將呢啲源碼賣俾出嗰個軟件間公司嘅同行競爭者[37]

註釋

[編輯]
  1. 「低級」係指抽象化嘅程度低,所以隻語言會反映部電腦內部嘅運算嘅實況。
  2. 呢個例子咁寫純粹係示範性質。現實中,如果寫 61h,通常即係呢個數值正常係會用十六進制表示或者寫十六進制會易明啲;如果正常係用十進制,通常都會直接寫 97,唔會貪得意寫 61h。
  3. 唔同組合語言好多時會用唔同記憶術代表同一個命令。喺 1985 年,電機電子工程師學會(IEEE)出版咗《694 號標準》(Standard 694)諗住統一組合器所用嘅記憶術,但電腦科學界一般都唔係好睬佢哋。到咗廿一世紀初,各款組合器都仲係傾向各自用自己嘅記憶術。
  4. 「xchg ax, ax」 即係 「將 AX 暫存器嘅內容同 AX 暫存器嘅內容對掉」,技術上有做嘢,但係事實上等如冇做。
  5. 如果之前定義咗變數大細,而之前嘅定義係正確大細,就冇需要;如果可以根據暫存器名判斷正確長度,亦冇需要。
  6. 只限於 amd64 架構。
  7. 「xor cx, cx」 係指 「CX 暫存器嘅內容同 CX 暫存器嘅內容做邏輯異或(結果擺返喺 CX 暫存器)」。任何數值同自己做邏輯異或結果都係 0,所以事實上係將 CX 設成 0;咁寫係一種慣用手法(idiom),原意可能係想慳位,或者可能係想慳執行時間。

睇埋

[編輯]

文獻

[編輯]

[編輯]
  1. "Assembler language". HLASM Language Reference (英文). IBM Knowledge Center. 2014. 喺2018年11月17號搵到.
  2. Moore, J. Strother (2007). Piton: a mechanically verified assembly-level language. Automated Reasoning Series.第3卷. Springer.
  3. Kornelis, A.F. (2013-06-09). "High Level Assembler - Opcodes overview" (英文). 喺2018年11月17號搵到.
  4. Macro instructions. HLASM Language Reference (英文). IBM Knowledge Center. 喺2018年11月17號搵到.
  5. James Saxon; William Plette (1962). Programming the IBM 1401. Prentice-Hall. LCCN 62-20615 – via HathiTrust.
  6. 6.0 6.1 6.2 6.3 6.4 Kahanwal, D. (2013). Abstraction level taxonomy of programming language frameworks. arXiv preprint arXiv:1311.3293.
  7. 7.0 7.1 "Assembly: Review - The Ohio State University" (PDF). 2016.
  8. System calls often vary, e.g. for MVS vs. VSE vs. VM/CMS; the binary/executable formats for different operating systems may also vary. "How do assembly languages depend on operating systems?".
  9. Tech Target - machine code (machine language).
  10. Hennessy, John L.; Patterson, David A. Computer Organization and Design. The Hardware/Software Interface. Morgan Kaufmann Publishers.
  11. Intel Architecture Software Developer's Manual, Volume 2: Instruction Set Reference. Intel Corporation. 1999.
  12. 12.0 12.1 Intel Architecture Software Developer's Manual, Volume 2: Instruction Set Reference. Intel Corporation. 1999. pp. 442 and 35.
  13. Evans, David (2006). "x86 Assembly Guide". University of Virginia.
  14. Moskovitch, R., Feher, C., Tzachar, N., Berger, E., Gitelman, M., Dolev, S., & Elovici, Y. (2008, December). Unknown malcode detection using opcode representation. In European conference on intelligence and security informatics (pp. 204-215). Springer, Berlin, Heidelberg.
  15. Runwal, N., Low, R. M., & Stamp, M. (2012). Opcode graph similarity and metamorphic detection. Journal in computer virology, 8(1-2), 37-52.
  16. IEEE 694-1985 - IEEE Standard for Microprocessor Assembly Language 互聯網檔案館歸檔,歸檔日期2019年10月24號,.. IEEE Standards Association.
  17. Z80 Op Codes for ZINT. Z80.de.
  18. Extended instruction mnemonics. IBM Knowledge Center.
  19. "The SPARC Architecture Manual, Version 8" (PDF). SPARC, International. 1992.
  20. 20.0 20.1 20.2 20.3 20.4 20.5 David Salomon (1993). Assemblers and Loaders.
  21. Microsoft Corporation. "MASM: Directives & Pseudo-Opcodes" (PDF).
  22. Chapter 8 - Pseudo Op-Codes.
  23. 23.0 23.1 Elsner, Dean; Fenlason, Jay; 等 (January 1994). "Syntax". Using as (美國英文). 喺2024年9月9號搵到.
  24. "Introduction to x64 Assembly" (PDF) (英文). Università della Svizzera italiana. p. 2. 喺2024年9月9號搵到.
  25. 25.0 25.1 Beck, Leland L. (1996). "2". System Software: An Introduction to Systems Programming. Addison Wesley.
  26. Hyde, Randall. "Chapter 12 – Classes and Objects". The Art of Assembly Language, 2nd Edition. No Starch Press. © 2010.
  27. B. Schwarz, S. Debray, and G. Andrews, "Disassembly of Executable Code Revisited", Proc. of 9th Working Conference on Reverse Engineering (WCRE), pp. 45–54, 2002.
  28. Difference between assembly language and high level language. IT Release.
  29. Decision-Making in Assembly Language. UMBC.
  30. Randall Hyde. "The Great Debate".
  31. "TIOBE Index". TIOBE Software.
  32. "Writing the Fastest Code, by Hand, for Fun: A Human Computer Keeps Speeding Up Chips". New York Times, John Markoff.
  33. "Bit-field-badness". Hardwarebug.org.
  34. "GCC makes a mess". HardwareBug.org.
  35. Click, Cliff. "A Crash Course in Modern Hardware".
  36. Hyde, Randall (1996-09-30). "Foreword ("Why would anyone learn this stuff?"), op. cit.".
  37. A Crash Course in x86 Assembly for Reverse Engineers (PDF).

[編輯]