在 x86 匯編語言中,方括號 `[]` 是極為核心的語法元素,它代表「記憶體間址運算」與「間接定址」。簡單來說,`[]` 內的運算式會被視為一個記憶體位址,指令會存取該位址處的資料,而非運算式本身的數值。本文將系統整理常見指令中 `[]` 的用法,並補充實戰範例,幫助讀者建立清晰的觀念。
此外,`[]` 內可包含暫存器、位移量、比例因子等複雜運算式(如 `[ebp+8]`、`[eax*4+ebx]`),編譯器會自動計算有效位址(Effective Address, EA)。
mov [edi], eax ; 將 EAX 的值(dword)寫入 EDI 指向的記憶體
mov [bp-2], dx ; 將 DX 的值(word)寫入 BP-2 指向的記憶體
mov esi, [bp+14] ; 從 BP+14 位址讀取 dword 存入 ESI
mov eax, dword ptr [ebp-4] ; 明確指定大小:從 EBP-4 讀取 dword
mov cl, byte ptr [34h] ; 從絕對位址 0x34 讀取 byte 存入 CL
mov dx, word ptr [3Eh] ; 從絕對位址 0x3E 讀取 word 存入 DX
mov al, byte ptr [eax+ecx] ; 基址+索引定址:讀取 EAX+ECX 處的 byte
關鍵點:當目的或來源運算元為記憶體時,若無法從暫存器大小推斷操作寬度(如絕對位址),必須加上 `byte ptr`、`word ptr`、`dword ptr` 等大小前綴。
cmp dword ptr [ebp-4], 7 ; 比較 EBP-4 處的 dword 與 7
cmp byte ptr [si], 0 ; 比較 SI 指向位址的 byte 與 0
`cmp` 不會保留結果,僅更新旗標暫存器(ZF、CF、SF 等),供後續條件跳轉使用。
lea eax, [edx-2] ; 計算 EDX-2 的有效位址,結果存入 EAX(不存取記憶體)
lea di, [bp-22h] ; 同理,將 BP-22h 的位址值存入 DI
`lea` 常被用於算術運算(如 `lea eax, [eax*4+10h]`),因其不存取記憶體,速度極快。
test byte ptr [bx+8FDh], 0FFh ; 邏輯 AND 操作,僅影響旗標
mov cx, [eax]
; 處理器執行流程:
; 1. 讀取 EAX 的值 → 視為記憶體位址
; 2. 從該位址讀取 16 位元資料(因目的暫存器 CX 為 16 位元)
; 3. 將讀取的 word 存入 CX
這裡體現了「目標暫存器大小決定存取寬度」的原則:目的為 `cx`(16 位元),故存取 word;若為 `ecx` 則存取 dword。
| 指令類型 | 括號語法 | 含義 |
|---|---|---|
| MOV | `mov [mem], reg` | 寫入記憶體 |
| MOV | `mov reg, [mem]` | 從記憶體讀取 |
| CMP/TEST | `cmp [mem], imm` | 比較記憶體值與立即數 |
| LEA | `lea reg, [mem]` | 計算有效位址,不存取記憶體 |
熟練掌握 `[]` 的語意,是編寫高效、正確匯編代碼的基石。建議讀者結合除錯器(如 x64dbg、OllyDbg)觀察實際記憶體存取過程,加深理解。