当前位置:编程学习 > 汇编语言 >>

新手快速设计汇编语言程序(四)

第五节 程式写作

说了不少,才真正到了写作程式的时候,运用指令就相当于写程式。只是,在运用指令前,一定要充份瞭解一应相关的课题。否则,应用指令如同和稀泥一般,堆砌出一团可以运作的成品,我个人不认为那能叫做「写程式」,充其量只是涂鸦罢了。

一、暂存器安排

因为暂存器不足,必须事先安排妥当,才能有效应用。
再以前例说明,需要安排的因素有:
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以下为功能处理,由前面的功能参数决定。
用这种方法,多种功能可以共用一个入口,程式精简且速度快。

www.zzzyk.com,学习电脑知识的好地方

CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,