前言
LEA (Load Effective Address) 原本用於計算記憶體操作數的有效位址,但因其能在單指令中完成「基址 + 索引×比例 + 位移」的算術運算,且不存取記憶體、不影響旗標,成為替代 MUL/SHL/ADD 序列的高效最佳化指令。
LEA 運算公式
LEA REG, [BASE + INDEX*SCALE + DISP]
; 計算結果 = BASE + INDEX×SCALE + DISP → 存入 REG
; SCALE ∈ {1, 2, 4, 8}
; 不存取記憶體,不影響任何旗標
替代乘法的經典範例
| 目標運算 | 傳統指令序列 | LEA 最佳化 | 優勢 |
EAX * 2 | SHL EAX, 1 / ADD EAX, EAX | LEA EAX, [EAX*2] | 不影響 CF/OF |
EAX * 3 | LEA EAX, [EAX*2+EAX] | LEA EAX, [EAX*2+EAX] | 單指令 |
EAX * 4 | SHL EAX, 2 | LEA EAX, [EAX*4] | 不影響旗標 |
EAX * 5 | LEA EAX, [EAX*4+EAX] | LEA EAX, [EAX*4+EAX] | 單指令 |
EAX * 8 | SHL EAX, 3 | LEA EAX, [EAX*8] | 不影響旗標 |
EAX * 9 | LEA EAX, [EAX*8+EAX] | LEA EAX, [EAX*8+EAX] | 單指令 |
EAX * 10 | LEA EAX, [EAX*8+EAX*2] | LEA EAX, [EAX*8+EAX*2] | 單指令 |
原文範例
; EAX * 5
LEA EAX, [EAX*4 + EAX] ; 比 MUL 快得多
位址計算與陣列索引
; 結構陣列: MYSTRUCT 大小 24 位元組
; 取得第 ECX 個元素的欄位 OFFSET_FIELD 位址
LEA EAX, [ArrayBase + ECX*24 + OFFSET_FIELD]
; 單指令完成: 基址 + 索引×結構大小 + 欄位偏移
組合多項式運算
; 計算 3*EAX + 5*EBX + 10
LEA EAX, [EAX*2 + EAX] ; EAX *= 3
LEA EBX, [EBX*4 + EBX] ; EBX *= 5
LEA EAX, [EAX + EBX*1 + 10] ; 合併 (SCALE=1 即不寫)
限制與注意事項
- SCALE 僅限 1, 2, 4, 8:無法直接計算 ×3, ×5, ×6, ×7, ×9 等,需組合 (如
[EAX*2+EAX] = ×3)。
- 不支援除法:除法仍需
DIV/IDIV 或乘以倒數近似。
- 不影響旗標:若後續需依據乘法結果旗標 (如
CF 判斷溢位),LEA 無法提供,需改用 MUL/IMUL。
- 目的暫存器限制:16/32 位模式下目的為 16/32 位通用暫存器;64 位模式下可為 64 位暫存器。
效能比較 (現代微架構)
| 指令 | 延遲 | 吞吐 | 微操作數 |
LEA (2 操作數) | 1 cycle | 0.5-1/cycle | 1 |
LEA (3 操作數, 基址+索引×比例+位移) | 3 cycles | 1/cycle | 1-2 |
IMUL REG, REG, IMM | 3 cycles | 1/cycle | 1 |
SHL/ADD 序列 | 1-2 cycles | 1-2/cycle | 2-3 |
結論:LEA 在常數乘法、位址計算上通常優於或持平 IMUL/SHL+ADD,且不破壞旗標,是最佳化關鍵路徑的首選。
總結
LEA 不只是載入位址指令,更是一個「免費的算術單元」。善用 [BASE + INDEX*SCALE + DISP] 編碼形式,可將常數乘法 (×2,3,4,5,8,9...)、結構陣列索引、多項式合併濃縮為單指令,同時保留旗標狀態。熟練掌握 LEA 最佳化模式,是組合語言高效能程式設計的標誌性技能。
- 上一篇文章: 組合語言 XOR 指令妙用:雙重異或還原數值與加密應用
- 下一篇文章: 組合語言資料無型別本質解析:BYTE/WORD/DWORD 互轉與緩衝區操作實例
Copyright ©
程式碼之家 All Rights Reserved