組合語言與 CPU
組合語言
機器碼——CPU 實際執行的位元組——對人類而言難以辨讀:一條加法指令可能是位元組 0x01 後接一個運算元位元組。組合語言是同一份機器碼的一種薄薄的、人類可讀的拼寫。你不寫 0x01 而寫 add;不寫暫存器編號而寫 rax。組合語言的每一行幾乎都一對一地對應到一條機器指令。
組合語言是人通常會寫或讀的最低階語言。它專屬於某一個指令集架構——x86-64 組合語言與 ARM 組合語言是不同的語言——因為它只是那個架構指令的文字替身。一個叫組譯器的程式把組合語言文字翻譯成目的檔中的機器碼位元組;反過來把機器碼轉回可讀組合語言,叫做反組譯。由於這個對應如此直接,組合語言把 C 語言隱藏的一切都攤開來:哪個暫存器裝什麼、每一次記憶體存取、呼叫前後對堆疊的確切操作。
今天幾乎沒人用組合語言寫整支程式——它既繁瑣又不可移植——但讀懂它是一項真正有用的技能。當你開最佳化編譯 C 並看組合語言時,你看到的正是機器會做的事,這能解決高階閱讀無法定奪的問題:某個迴圈是否向量化了、某個檢查是否被最佳化掉了、一段微基準為何快或慢。編譯器也允許你在需要某條語言沒有其他途徑能觸及的指令時,嵌入一小段內嵌組合語言。
C 述句 x = x + 1; 可能編譯成單一行組合語言 add DWORD PTR [rbp-4], 1——這是把記憶體中的 x 加一之機器位元組的可讀簡寫。
組合語言是機器碼幾乎一對一的人類拼寫,專屬於某一個 ISA。
組合語言不是單一通用語言:每個 ISA 都有自己的一套,連 x86-64 都有兩種常見語法(Intel 與 AT&T),它們互換運算元順序與記法,所以同一條指令看起來可能差很多。組合語言預設也不「比 C 快」——一個好的最佳化編譯器通常能追平甚至勝過手寫組合語言。
又称
另见