汇编语言程序设计(五)
2007-04-25 09:29:59 来源:WEB开发网17: LODSB ;取排序资料
18: CMP AL,AH ;比是否该排
19: JB COMPAR2 ;是
20: MOV SI,DI ;否,将原位址还原
21: JMP COMPAR0 ;从头再做
22: COMRET:
23: RET
总而言之,程式的变化无穷无尽,尤其是用组合语言制作程式,更是灵活精妙。就像下围棋一般,往往一两个指令就足以将整个局势扭转过来。
程式的效率经常决定在回路上,读者千万不要以为一两个时钟脉冲算不了什么。要知道,汪洋大海,也是由一点一滴的水珠累积而成的。
这段程式还有不少值得深思的,读者们不妨自行研究吧!想得多了,自然会有生花妙笔。
真要作大量的资料排序,还有更有效的方法,也是应用模式分析的原则,先找出资料的「型」。
假如以同样性质的资料为例,为了避免资料一一查找,浪费时间。我们不妨研究一下,是否有可能,直截了当,就把资料依据大小,予以定位,一次排好?
电脑的好处,就在于资料的规律性,我们理应利用这种优点,来找出其排序的模式。
前例曾分为两个模式,一是查找,一是搬移。如果我们把查找改为记录,把搬移改为安排,则情形就大大的不同了。
记录时利用间接定址技巧,每笔取到的资料,皆可视为一个数值,对应于一记录的缓冲区。如果资料中每笔资料总值大于256 且小于 65536,则可以用二字元记录之。再若资料为二进位值,可由 0至 255,即设 512个对应单位。
假定原资料在 DS:SI中,长度在CX中。
首先,设一记录区为:
1: RECORD DB 512 DUP (0)
2: PUSH SI ;程式开始
3: CHECK:
4: LODSB ;取资料,AH永远为0
5: MOV BX,AX ;利用BX间接定址
6: INC WORD PTR RECORD[BX]
7: LOOP CHECK
8: STORE:
9: MOV SI,OFFSET RECORD+512;指向最
;后记录
10: MOV BP,OFFSET RECORD ;供检查
11: POP DI ;资料贮存处
12: STORE1:
13: CMP SI,BP ;查是否完毕?
14: JE RECEND ;完成
15: DEC SI ;向上取
16: DEC SI
17: MOV CX,[SI] ;取记录值
18: JCXZ STORE1 ;无记录,重取
19: MOV AX,SI ;当前之位址
20: SUB AX,BP ;差值
21: SHR AX,1 ;原有值
22: STORE2:
23: REP STOSW ;重新载入
24: JMP STORE1 ;继续
25: RECEND:
26: RET
程式的变化无穷无尽,尤其是用组合语言写作程式,简直没有止境。只要稍稍用点心,加一点点变化因素,一个巧妙无比的程式,就会跃然而出。
写程式的乐趣,就在于心智的投入。学者们不妨试着把这 式再加以改良,其中还有不少可以下手的地方,养成习惯以后,程式自然就会精简了。
八、预置法
预置法适用于流程的安排,尤其是在不确定的情况下,有时需要作多项检查,不仅浪费时间,对空间也不利。
例如有一段程式,其目的在于处理使用者所选择的流程。由于使用者事先通过介面程式,选妥各项工作,现在必须依某一顺序执行。
这是一项难度相当大的工作,要执行固定顺序不难,下面的程式就可以达到目的。当然,一如既往,我们会尝试着将程式一再改进。最后,我们再来讨论如何能执行使用者所安排的顺序。
设子流程有八种,使用者选用时,可令BX值等于子程式的代号。选用方式为「开关式」,即单数次为开,设定参数,复数次为关,取消设定。
设定后,因为共有八种程式,可以用八个位元来设置所需要执行的旗号。当然,这要看程式的多少而定,八位元正好用一个旗号FLAG:
1: SETUP:
2: CMP BX,MAXVAL ; 最大值检查
3: JA SETRET ; 超过,无效
4: SHL BX,1 ; 参数乘2
5: JMP SUBTB[BX] ; 各种程式
6: SUBTB DW SUB1 ; 各种程式
7: DW SUB2 ; 程式中设定
8: .. ; flag
9: DW SUBN
10: ENTER:
11: SHR FLAG,1 ; 检查FLAG
12: JNC ENTER1
13: CALL SUB1 ; 有设定
14: ENTER1:
15: SHR FLAG,1
16: JNC ENTER2
17: CALL SUB2
18: ENTER2:
19: .. ; 如此连续进行八次
显然这种做法其笨无比,第十条以后,可用回路取代:
10: ENTER:
11: MOV CX,8
12: MOV AL,FLAG ; 暂存器较有效
13: OR AL,AL
14: JZ ENTRET ; 不必做
15: SUB BX,BX
16: LOOP0:
17: SHR AL,1
18: JNC LOOP1
19: PUSH AX
20: PUSH BX
21: PUSH CX
22: CALL SUBTB[BX]
23: POP CX
24: POP BX
25: POP AX
26: LOOP1:
27: INC BX
28: INC BX
29: LOOP LOOP0
30: ENTRET:
31: RET
这样好得多了,可是,还能不能再加改进呢?组合语言的妙处就在于变化无穷,且看看是否还能变出花样来。
从设置开始,方式稍微改变一下,旗号的观念是供程式检查用。在应用时,要占用一个暂存器,而暂存器有限,浪费了可惜。此外,八个不同的子程式,又要占用一个计数用的暂存器,最好能够省掉。
因此,设置的重要性就显而易见了,程式的好坏,并非仅仅在于指令的应用。原始的理念,及程式的规划,经常在程式设计之前已经决定了。
更多精彩
赞助商链接