程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> 匯編語言 >> 匯編語言程序設計(四)

匯編語言程序設計(四)

編輯:匯編語言

第五節 程式寫作

說了不少,才真正到了寫作程式的時候,運用指令就相當於寫程式。只是,在運用指令前,一定要充份瞭解一應相關的課題。否則,應用指令如同和稀泥一般,堆砌出一團可以運作的成品,我個人不認為那能叫做「寫程式」,充其量只是塗鴉罷了。

一、暫存器安排

因為暫存器不足,必須事先安排妥當,才能有效應用。
再以前例說明,需要安排的因素有:
1,字形大小:此項有兩個變數需要安排,一是橫向之始、終值; 另一是縱向之始、終值。因為在設計之初,我已經 考慮到極限值的問題,將上限定在 256點,恰在一個字元 的范圍內。所以我們可以把橫向始值放在暫存器BL中,終值放在BH,而縱向始值放在DL,終值放進DH。

2,筆畫粗細:有四個變數值,放在CL中,並使CH為0。( 這點相當重要,為了精簡和效率,最好有一個暫存器為0)

3,字碼送入:在始存器SI中。

4,字形輸出:在終存器DI中,根據BX及DX值求得。

二、程式規格

第二章第四節已介紹過,在此從略。

三、程式及說明

------程 式 部 份----- ----說明部份----
1: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2: ;功能:倉颉表格碼繪圖用。";"後,皆為注解。 ;
3: ;輸入參數:DS:SI=字碼(1-2 碼),=0為終止。;
4: ; BL=X1 BH=X2 ;
5: ; DL=Y1 DH=Y2 ;
6: ; CX= 筆畫粗細值。 ;
7: ;輸出結果:點陣在ES:DI中。 ;
8: ;破壞暫存器:全部。 ;
9: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10: CCODIN: ; 字碼輸入
11: LODSB ; 取一碼以作圖
12: MOV CL,AL ; 取粗細值
13: INC AX ; 調整碼值
14: AND AX,001EH ; 24個有效雙數值
15: PUSH BX ; 保留後用
16: PUSH DX ; 同上
17: MOV SI,AX ; AX不能間接定址
18: AND CL,07H ; 有效值
19: CALL CCODTB[SI] ; 假設CS=DS
20: POP DX
21: POP BX
22: JMP CCODIN ; 本程式主流程
23: CCOD00: ; CODe為碼
24: ADD SP,6 ; 本程式為子程序
25: RET ; 碼為0執行完畢
26: CCOD06: ; 06為 E,F
27: SHL CL,1 ; E,F 粗細值加倍
28: CLFT02: ; LeFT指左橫
29: ADD BH,BL ; 02為輸入碼 A,B
30: SHR BH,1 ; 左起BH中點值
31: JMP CHOR00 ; HORizon 畫橫
32: CCOD08: ; 08為G,H
33: SHL CL,1
34: CLEF04: ; 04為C,D
35: ADD DH,DL
36: SHR DH,1 ; 上起DH為中點值
37: JMP CVER00 ; VERtical畫直
38: CCOD0E:
39: SHL CL,1
40: CRGT0A: ; RiGhT 指右橫
41: ADD BL,BH ; 0A為碼I,J
42: SHR BL,1 ; BL為中點值
43: JMP CHOR00
44: CCOD10:
45: SHL CL,1
46: CCOD0C:
47: ADD DL,DH
48: SHR DL,1 ; DL為中點值
49: JMP CVER00
50: CCOD16:
51: SHL CL,1
52: CCOD12:
53: JMP CHOR00
54: CCOD18:
55: SHL CL,1
56: CCOD14:
57: JMP CVER00
58: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
59: ;以下為各碼之模組程式,間接定址表 ;
60: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
61: CCODTB DW CCOD00 ; 結束
62: DW CCOD02 ; 碼 A,B左橫細輕
63: DW CCOD04 ; 碼 C,D上直細輕
64: DW CCOD06 ; 碼 E,F左橫粗重
65: DW CCOD08 ; 碼 G,H上直粗重
66: DW CCOD0A ; 碼 I,J右橫細輕
67: DW CCOD0C ; 碼 K,L下直細輕
68: DW CCOD0E ; 碼 M,N右橫粗重
69: DW CCOD10 ; 碼 O,P下直粗重
70: DW CCOD12 ; 碼 Q,R長橫細輕
71: DW CCOD14 ; 碼 S,T長直細輕
72: DW CCOD16 ; 碼 U,V長橫粗重
73: DW CCOD18 ; 碼 W,X長直粗重

程式到此全部完畢,唯畫橫及直與本主題無關,在此不做說明。由這段程式,可以看出最初規劃輸入碼不理想之處,以致於需要在各處加粗細值,讀者不妨自行研究改良之。
程式長度為88個字元,共用程式原來已有,在此不計。
此外,本段程式重復應用了幾個指令,有很多方法可以精簡,也有待讀者動手。
至於畫橫及直的子程式CHOR00和CVER00,其位置遠近也影響寫作方式,在此,且假定在 128B 之內,皆為短跳。否則還要動腦筋,設法簡省之。
還有,讀者應該注意到,這段程式中,沒有檢查錯誤的手續,那是因為在內碼處理時,已經保證無誤。一般說來,檢查錯誤是必要的程序。
改進之方法,姑在此略作導引,設若編碼時,將四個連續碼視作由細至粗,而把位置分為六組,是則更易記憶,且程式可以減少28個字元之多。由此可見,像這樣精簡的程式,因資料結構上的缺陷,仍有改進的余地。


第六節 特殊技巧的運用

技巧的運用,關系組合語言的效率甚钜,雖然其重要性比不上整體規劃,但也可以彌補規劃的不足。
由於「技巧」無法嚴格定義,茲將幾種較常用的技巧介紹如下:

一、變數法:

我非常反對在程式中采用「常數」的觀念,因為常數是固定的,無法靈活應用。例如在 IBM PC 的 BIOS 中,螢幕游標上、下、左、右位置固定設為 0,25,0,80 等常數值。每次移動都受到這四個值的限制,故而形成不變的「視區」。若將這些常數改為變數,且容許使用者自行改變,則立即有了可變「視窗」的功能。
也就是說,螢幕上、下、左、右四個位置,所圍起來的區域,就是我們視覺及資料所限制的「視窗」,所有資料顯示,在系統程式的控制下,無法超出此區。
如果此四個位置值是變數,則使用者可以隨意設定所需數值,如是則靈活方便,也就是所謂的視窗處理。
在下文三、虛擬法例中,CKFUN 該段程式即為用變數處理視窗的范例。下面這段程式,亦為變數法的一種應用, MAP87和MAP9A 中,均需調用子程式DYBPJ1,唯一不同者,是在該子程式中,又需分別調用不同的子程式。共用DYBPJ1的方法,是先將不同子程式的位址,放在BP中,再行調用。
1:MAP87:
2: MOV BP,OFFSET MAPF4
3: CALL MOVS211
4: CALL DYBPJ1
5: MOV DL,AH
6: ..

11:MAP9A:
12: MOV BP,OFFSET MAP46
13: CALL DYBPJ1
14: MOV AH,1
15: ..

20:DYBPJ1:
21: PUSH BX
22: PUSH DX
23: MOV DH,DL
24: CALL BP
25: POP AX
26: XCHG DH,AH
27: POP BX
28:DYBPJRT:
29: RET

二、對稱法:

本法實際上就是利用間接定址的指令,將原系對稱處理,或可以調整成為對稱型的程式,靈活調用。
下面這段程式,表面看來似乎毫不相干,但經過整理後,就有了眉目,然後再以暫存器間接定址,合並為一。像這種程式,規模越大,所節省的空間就越多。
1:ABCD:
2: CMP DX,BUFA
3: JB ABCD1
4: CMP CL,BUFD
5: JB ABCD1
6: MOV BUFC,CL
7: INC BUFE
8: MOV BUFB,DX
9: DEC BUFF
10: ABCD1:
11: ..
12: ..
與另一段程式:
20:EFGH:
21: CMP BX,BUFG
22: JB EFGH1
23: CMP CH,BUFH
24: JB EFGH1
25: INC BUFK
26: DEC BUFL
27: MOV BUFI,BX
28: MOV BUFJ,CH
29:EFGH1:
30: ..
31: ..
看來分別很大,先經過整理,得到左右兩組程式:
EFGH: ABCD:
CMP BX,BUFG CMP DX,BUFA
JB EFGH1 JB ABCD1
CMP CH,BUFH CMP CL,BUFD
JB EFGH1 JB ABCD1
INC BUFK INC BUFE
DEC BUFL DEC BUFF
MOV BUFI,BX MOV BUFB,DX
MOV BUFJ,CH MOV BUFC,CL
EFGH1: ABCD1:
.. ..
.. ..
對照之下可以看出,其所不同的,只是暫存器及緩沖器的分別而已。這種程式的出現,是由於事先規劃不當,未能通盤考慮,頭痛醫頭,腳痛醫腳。原可以把暫存器及緩沖器統一運用,現在木已成舟,想要變更很可能影響大局。
其次是寫作的風格及習慣沒有養成,在用指令時,信手拈來,以致兩段程式,兩種寫法!
現在唯一的補救方法,是利用間接定址法,先將兩組不同的緩沖器,照相對次序排列妥當,再改寫程式。
1:ABCD:
2: MOV SI,OFFSET BUFA
3: MOV DI,OFFSET BUFB
4: MOV BX,DX
5: MOV CH,CL
6: JMP SHORT EFGH1
7:EFGH:
8: MOV SI,OFFSET BUFG
9: MOV DI,OFFSET BUFI
10:EFGH1:
11: CMP BX,[SI]
12: JB EFGH2
13: CMP CH,[SI+2]
14: JB EFGH2
15: MOV [DI],BX
16: MOV [DI+2],CH
17: INC BYTE PTR[DI+3]
18: DEC BYTE PTR[DI+4]
19:EFGH2:
20: ..
其緩沖器的相對順序,如下所示:
35:BUFA DW 0
36:BUFD DB 0
37:BUFB DW 0
38:BUFC DB 0
39:BUFE DB 0
40:BUFF DB 0
41:..
65:BUFG DW 0
66:BUFH DB 0
67:BUFI DW 0
68:BUFJ DB 0
69:BUFK DB 0
70:BUFL DB 0
凡對稱形式或結構相同的程式,都可以采用這種技巧。

三、虛擬法:

對來處不同的資料,只要性質相同,都可以采用虛擬的技巧,將各種參數事先設妥,利用參數統一處理。
茲有一程式,系供螢幕畫圖之用,所有功能皆用游標完成之,特以此段處理游標的程式為例說明如後。
先虛擬各種功能及緩沖器:
區段位移: 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 ? ;?= 字或圖寬
..
程式入口: CHKKEY DW CK47; 向左上移
DW CK48; 向上移
DW CK49; 向右上移
DW CRET; 無效
DW CK4B; 向左移
DW CRET; 無效
DW CK4D; 向右移
DW CRET; 無效
DW CK4F; 向左下移
DW CK50; 向下移
DW CK51; 向右下移
AX = 輸入游標鍵掃瞄碼
BP = 螢幕X向移動值
DX = 螢幕Y向移動值
ES:DI=螢幕記憶區位址

主流程: ( 已知 AL=0 AH=Scan-Code )
1:KEYIN:
2: SUB AH,47H ; =HOME
3: JB KEYRET ; 無效
4: CMP AH,11 ; >掃瞄碼范圍
5: JA KEYRET
6: MOV BL,AH
7: SUB BH,BH
8: SHL BX,1
9: MOV AX,BWMOV ; 移動值
10: JMP CHKKEY[BX] ; 進入各處理程式
..
40:CK47:
41: SUB DX,AX ; Y 向
42:CK4B:
43: NEG AX ; 向左為負
44:CK49:
45: ADD BP,AX ; X 向
46: JMP SHORT CKFUN
47:CK4D:
48: SUB DX,AX
49: JMP CK49
50:CK51:
51: ADD DX,AX
52: JMP CK49
53:CK48:
54: NEG AX ; 向上為負
55:CK50:
56: ADD DX,AX
57:CKFUN: ; 用變數觀念檢查「視窗」
58: CMP DX,BWTOP ; 超出上限?
59: JNS CKFUN1
60: MOV DX,BWTOP ; 上限值
61:CKFUN1:
62: CMP DX,BWBTM ; 超出下限?
63: JBE CKFUN2
64: MOV DX,BWBTM ; 下限值
65:CKFUN2:
66: CMP BP,BWLFT ; 超出左限?
67: JNS CKFUN3
68: MOV BP,BWLFT ; 左限值
69:CKFUN3:
70: PUSH BP
71: ADD BP,BWADDX ; 右限+邊際值再比
72: CMP BP,BWRGT ; 超出右限?
73: POP BP
74: JBE CKFUN4
75: MOV BP,BWRGT ; 右限值
76:CKFUN4:
77: ..
CKFUN4以下為功能處理,由前面的功能參數決定。
用這種方法,多種功能可以共用一個入口,程式精簡且速度快。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved