組合語言效率建立在指令運用上。本章收錄實戰中常見的低效寫法與優化對照,涵蓋條件判斷、流程安排、錯誤處理、迴圈指令選擇、暫存器運用、常數vs暫存器、分支預測與 JMP SHORT 優化。
; 差:逐一比較
CMP AL,0; JE ABCD0
CMP AL,1; JE ABCD1
CMP AL,2; JE ABCD2
; 優:先比中間值
CMP AL,1
JNE ABCD0
ABCD1: ...
; ABCD0 內再 JA ABCD2
最常見路徑 (ABCD1) 無分支,最快。
; 差
ADD AX,4
ABCD: STOSW; ADD AX,4; ADD DI,2; LOOP ABCD
; 優:將不變操作移出迴圈或合併
ABCD: ADD AX,4; STOSW; INC DI; INC DI; LOOP ABCD
; 差:MOV BX,SI / MOV BX,[BX] / OR BX,BX / JZ / MOV SI,BX / JMP
; 優:LODSW / OR AX,AX / JZ / MOV SI,BX / JMP
直接用 LODSW 載入並檢查,省去間接定址開銷。
; 差:TEST/JNZ 跳轉 CALL / JMP SHORT
; 優:TEST/JZ 直線執行 / INC BX*2 / CALL 統一入口
; 差:PUSH DI / MOV CX,BX / REP STOSB / POP DI
; 優:MOV CX,BX / REP STOSB / SUB DI,BX
; 差:PUSH CX / REP MOVSB / POP CX / SUB DX,CX
; 優:SUB DX,CX / REP MOVSB (CX 不變)
; 差:8 段 TEST/JZ/MOV 重複代碼
; 優:緩衝區按序排列 / MOV DI,OFFSET BUF1 / MOV AL,BL / MOV CX,4
X1: SHR AH,1; JZ X2; STOSB
X2: SHR AH,1; JZ X3; MOV [DI],DX; INC DI; INC DI
X3: LOOP X1
; 差:SUB AH,AH / CMP/JB / SUB/INC/JMP
; 優:MOV AH,-1 / INC AH / SUB AL,BL / JA 迴圈 / ADD AL,BL 還原
; 差:CMP 60h/JA / SUB 40h / JMP / SUB 60h
; 優:AND AL,1Fh ; 直接取字母序數 (A=1..Z=26, a=1..z=26)
測試時假設正確輸入,實際用戶會輸入錯誤。所有有「正確/錯誤」之分的輸入、運算,**必須預先檢查排除錯誤資料**。正確性優先於精簡。
需求:DS:SI 資料長度 CX,BL=0 大轉小,BL=1 小轉大。
LOOP1: CALL CHANGE; JC LOOP11; ADD AL,20h; JMP LOOP12
LOOP11: SUB AL,20h
LOOP12: MOV [SI-1],AL; LOOP LOOP1
CHANGE: LODSB; OR BL,BL; JZ CHANGS; CMP AL,61h; JB CHARET; CMP AL,7Ah; JA CHARET; STC; CHARET: RET
CHANGS: CMP AL,41h; JB CHARET; CMP AL,5Ah; JA CHARET; CLC; RET
每筆資料調用子程式:23+20=43T 開銷,迴圈內再浪費數十 T。
CHANGE: LODSB; OR BL,BL; JZ CHANGS; CMP AL,61h; JB CHANG1; CMP AL,7Ah; JA CHANG1; SUB AL,20h; CHANG0: MOV [SI-1],AL; CHANG1: LOOP CHANGE
CHANGS: CMP AL,41h; JB CHANG1; CMP AL,5Ah; JA CHANG1; ADD AL,20h; JMP CHANG1
MOV AH,20h; MOV DX,7A61h; OR BL,BL; JZ CHANGE; MOV DX,5A41h
CHANGE: LODSB; CMP AL,DL; JB CHANG1; CMP AL,DH; JA CHANG1; XOR AL,AH; MOV [SI-1],AL; CHANG1: LOOP CHANGE; RET
暫存器比較極快,平均 <40T/筆,10MHz 下 10 萬筆約 0.5 秒。
MOV AH,20h; MOV DX,BWCOM; CHANGE: LODSB; CMP AL,DL; JB CHANG1; CMP AL,DH; JA CHANG1; XOR AL,AH; MOV [SI-1],AL; CHANG1: LOOP CHANGE; RET
彈性最大,統一應用介面即可共用。
PUSH/POP/DIV/MUL/CALL (高時脈)
; 位元組版:50,000 次 × 55T = 275M T ≈ 0.25 秒 (10MHz)
LOOP1: LODSB; XOR AL,[DI]; STOSB; LOOP LOOP1
; 字版:25,000 次 × 66T = 165M T ≈ 0.16 秒,快 36%
LOOP1: LODSW; XOR AX,[DI]; STOSW; LOOP LOOP1
LOOP 17T,巢狀極貴CALL/RET 43T,迴圈中絕對避免LODSW/XOR/STOSW/RET 若用 CALL 調用:3B 調用換 4B 本體,得不償失
; 差:外層 LOOP2 內層 LOOP3,PUSH/POP CX 保存外層計數
; 優:單層迴圈 + DEC DX / JNZ 外層標號
; 省 46T → 35T/外層迭代
REPNZ SCASW 比對,間接 CALL便於擴充、表現層次、合併共用代碼。子程式標號按功能集中性排序。
高速路徑設為直線 (假),低概率設為分支 (真)。
CDEF: CMP AL,'?'; JZ ABCD; LOOP CDEF ; '?' 最少,NZ 只需 4T
ABCD: ...
JMP vs JMP SHORTJMP 3B/15T,JMP SHORT 2B/15T (距離 ≤ 128B)JMP SHORT,否則多 1B NOP + 2TJMP,常有斬獲從判斷邏輯重構到迴圈指令換裝,從暫存器預載到分支預測利用,每一個微優化在迴圈累積下都是數量級的效能差距。養成「小事不做,小善不為」的反面習慣——即時優化每一條指令——是邁向組合語言大師的必經之路。