常見指令家族(mov、add、cmp、jmp、call、ret)
一個 ISA 可能列出數百條指令,但在一般編譯出來的程式碼裡,出乎意料地只有一小撮在做大部分工作。按職責把它們分組,幾乎任何反組譯都會變得可讀。把它們想成幾個家族:資料搬移、算術、比較、流程控制、呼叫,以及堆疊搬移。
日常的家族是這些。資料搬移:mov 在暫存器與記憶體間複製一個值;在像 ARM 的載入—儲存機器上,同樣的工作拆成載入(ldr)與儲存(str)。算術與邏輯:add、sub、mul,以及位元的 and、or、xor、shl/shr 做實際的計算。比較:cmp 相減以設定旗標卻不保留結果,test 則為相同目的做位元 AND。流程控制:jmp 是無條件跳躍,而條件分支(je、jne、jl、jg 等)只在旗標允許時跳躍——if 與迴圈就是這樣建起來的。呼叫:call 跳到一個函式同時推入返回位址,ret 彈出那個位址以跳回。堆疊搬移:push 把一個值放上堆疊,pop 取下一個。
學會這六個家族,你就能跟上幾乎任何函式的骨架:幾條 mov 把資料挪到位、一條 add 或 sub 做事、一條 cmp 接條件跳躍做出決策、一條 call 呼叫輔助函式、push/pop 在其前後保存與還原值、一條 ret 把控制權交回。其餘一切都是疊在這小而反覆出現之詞彙上的變化與細節。
if (a == b) f(); 大致編譯成:cmp eax, ebx / jne skip / call f / skip:——比較、依旗標分支、再有條件地呼叫。
少數幾個家族——搬移、算術、比較、分支、呼叫/返回、推入/彈出——涵蓋了大部分編譯出來的程式碼。
助憶符名稱因 ISA 而異:x86-64 用 mov/jmp/call,AArch64 用 mov/ldr/str/b/bl,但家族彼此對應。注意 cmp 與 test 刻意丟棄它們的結果——它們唯一的目的是設定旗標這個副作用,供緊接的分支使用。