寫組合語言非指令堆砌,而是嚴謹的工程過程。本章以倉頡碼繪圖模組為例,完整展示暫存器分配、規格定義、程式實作與三大核心技巧(變數法、對稱法、虛擬法)。
| 功能 | 暫存器 | 說明 |
|---|---|---|
| 字形大小 X 軸 | BL (起) / BH (迄) | 上限 256,置於 8 位暫存器 |
| 字形大小 Y 軸 | DL (起) / DH (迄) | |
| 筆畫粗細 | CL (值) / CH=0 | 保留 CH=0 利於後續運算 |
| 字碼輸入 | SI | 來源索引 |
| 點陣輸出 | DI | 目的索引,依 BX/DX 計算 |
;; 功能:倉頡表格碼繪圖
;; 輸入:DS:SI=字碼(1-2碼, 0=結束)
;; BL=X1 BH=X2 DL=Y1 DH=Y2
;; CX=筆畫粗細
;; 輸出:點陣在 ES:DI
;; 破壞:全暫存器
CCODIN: ; 主流程:輸入字碼 → 分派繪圖
LODSB ; 取一碼
MOV CL, AL ; 粗細值
INC AX
AND AX, 001Eh ; 24 個有效雙數值
PUSH BX ; 保存 BX/DX
PUSH DX
MOV SI, AX ; AX 不能間接定址
AND CL, 07h ; 有效粗細範圍
CALL CCODTB[SI] ; 間接定址跳轉 (假設 CS=DS)
POP DX
POP BX
JMP CCODIN ; 循環處理下一碼
CCOD00: ; 碼 0:結束
ADD SP, 6 ; 清理堆疊 (退回主程式)
RET
; 各碼處理模組:設定座標中點、粗細加倍、跳轉畫橫/直核心
CCOD06: SHL CL,1 ; E,F 粗細加倍
CLFT02: ADD BH,BL ; A,B 左橫中點
SHR BH,1
JMP CHOR00 ; 畫橫
CCOD08: SHL CL,1
CLEF04: ADD DH,DL ; C,D 上直中點
SHR DH,1
JMP CVER00 ; 畫直
... (其餘碼類似)
; 間接定址表
CCODTB DW CCOD00, CCOD02, CCOD04, CCOD06, CCOD08, CCOD0A, CCOD0C, CCOD0E
DW CCOD10, CCOD12, CCOD14, CCOD16, CCOD18
程式長 88 位元組。畫橫/直核心 CHOR00/CVER00 另存。編碼規劃不夠理想導致多處 SHL CL,1,留待讀者優化。
將固定值改為變數,賦予程式彈性。例如視窗邊界(上/下/左/右)設為變數,即得可調整視窗功能。
; 共用子程式 DYBPJ1,唯調用的下層子程式不同
MAP87: MOV BP, OFFSET MAPF4 ; 先設定 BP 指向目標子程式
CALL MOVS211
CALL DYBPJ1
MAP9A: MOV BP, OFFSET MAP46
CALL DYBPJ1
DYBPJ1:
PUSH BX
PUSH DX
MOV DH, DL
CALL BP ; 間接調用 BP 指向的子程式
POP AX
XCHG DH, AH
POP BX
RET
兩段代碼僅暫存器/緩衝器不同,透過整理緩衝區相對順序,用 SI/DI 間接定址合併。
; 整理前:ABCD 處理 DX/CL/BUFA/BUFD...,EFGH 處理 BX/CH/BUFG/BUFH...
; 整理後:
ABCD: MOV SI, OFFSET BUFA
MOV DI, OFFSET BUFB
MOV BX, DX
MOV CH, CL
JMP SHORT EFGH1
EFGH: MOV SI, OFFSET BUFG
MOV DI, OFFSET BUFI
EFGH1:
CMP BX, [SI]
JB EFGH2
CMP CH, [SI+2]
JB EFGH2
MOV [DI], BX
MOV [DI+2], CH
INC BYTE PTR [DI+3]
DEC BYTE PTR [DI+4]
EFGH2: ...
緩衝區按相同邏輯順序排列:BUFA(比較值) BUFD(比較值) BUFB(結果) BUFC(結果) BUFE(增) BUFF(減),同樣結構對應 BUFG/BUFH/BUFI/BUFJ/BUFK/BUFL。
游標控制範例:九個方向鍵 + 多種功能模式(區塊移動、十字游標、視窗移動、畫筆、橡皮擦、閃爍游標、文字顯示)。
; 虛擬功能參數緩衝區
BBBLKMOV DB ? ; 區塊移動位移
BBCROCSR DB ? ; 十字游標
BBFRMMOV DB ? ; 視窗移動
BBDRW DB ? ; 畫筆寬度
BBDEL DB ? ; 橡皮擦寬度
BBCSR DB ? ; 游標寬度
BBCHRDSP DB ? ; 文字框值
BWMOV DW ? ; 當前功能移動值
BWTOP DW ? ; 視窗上限
BWBTM DW ? ; 視窗下限
BWLFT DW ? ; 視窗左限
BWRGT DW ? ; 視窗右限
BWADDX DW ? ; 右邊界邊際值
; 主流程:掃描碼 → 計算 X/Y 位移 → 統一視窗邊界檢查 → 功能分派
KEYIN:
SUB AH, 47h ; HOME 鍵基準
JB KEYRET
CMP AH, 11 ; 範圍檢查
JA KEYRET
MOV BL, AH
SUB BH, BH
SHL BX, 1
MOV AX, BWMOV ; 取得當前功能移動值
JMP CHKKEY[BX] ; 跳轉各方向處理
CK47: SUB DX, AX ; Y 向 (左上)
CK4B: NEG AX ; 向左為負
CK49: ADD BP, AX ; X 向
JMP SHORT CKFUN
CK4D: SUB DX, AX ; 右
JMP CK49
CK51: ADD DX, AX ; 右下
JMP CK49
CK48: NEG AX ; 向上為負
CK50: ADD DX, AX ; 下
CKFUN: ; 統一視窗邊界檢查 (變數法)
CMP DX, BWTOP; JNS CKFUN1; MOV DX, BWTOP
CKFUN1: CMP DX, BWBTM; JBE CKFUN2; MOV DX, BWBTM
CKFUN2: CMP BP, BWLFT; JNS CKFUN3; MOV BP, BWLFT
CKFUN3: PUSH BP; ADD BP, BWADDX; CMP BP, BWRGT; POP BP; JBE CKFUN4; MOV BP, BWRGT
CKFUN4: ... 功能分派
多種功能共用邊界檢查與方向計算,程式精簡且快速。
暫存器規劃是效能基石,規格文件是維護生命線。變數法賦予彈性,對稱法消除冗餘,虛擬法統一多態處理。三大技巧配合間接定址與緩衝區設計,能讓組合語言程式達到高階語言難以企及的時空效率與結構優雅度。