|
四、桥式法:
桥式法是利用读写记忆体的特性,将程式中若干指令直接填入,作为临时便桥,以改变此段程式的功能。 例如在显示时,希望能提供多种变化,而又不愿减低速度及增加太多的程式。最好的方法,便是利用桥式法,在同一位址,填入需要的指令。 桥式法用得好而又灵活时,对程式的效率极有助益。但是应该注意一点,就是只能用在可读可写的记忆区中,如若要制成「韧体」,即置入仅读记忆体(ROM) 中的程式,绝不可使用此法。 下面的实例,即为萤幕显示的桥式应用。首先,把架桥的「材料」设置在缓冲器中,如: CDSPMOD DB88H;8805 = MOV [DI],AL DB30H;3005 = XOR [DI],AL DB08H;0805 = OR[DI],AL DB20H;2005 = AND [DI],AL CDSPMOD 即为缓冲器,其中有四个数据,分别为机器码的相异部份,如分号后所注。因为四组机器码皆有 05 ,不必再填。=右边部份,即为该机器语言相对应的指令。 程式部份先设妥功能定义,利用一、所说的变数应用法,依序由0至3先载入暂存器BX中。根据 BX 值,将所需机器码载入程式中。 10:CLOD: 11:MOVAL,CDSPMOD[BX];用BX取预存码 12:MOVCS:CDSP2[1],AL;载入CDSP2 1 13:CDSP: 14:SUBSI,SI;资料由0起 15:CDSP1: 16:LODSB;取资料 17:CDSP2LABEL BYTE;载入的位置 18:XORES:[DI],AL;原码26 30 05 19:INCDI;须改 30 部份 20:LOOPCDSP1 21:RET
五、流水线法:
工业上的流水线生产作业,需要极为严格的规格限制,原器件分别研制完毕后,统一送到生产线上组装。 程式亦可采用同样的方法,只可惜一时手头上找不到现成的、适用的例子,只得将方法概述如下: 先设定处理流程,凡是能用这种生产流程者,皆适用。 再设定处理流程中所采用的「生产线」,也就是缓冲器。因为流水线上所用的资料都需要由缓冲器提供。 此缓冲器的长度由流程决定,缓冲器中的资料则由各调用本流程的原程式载入。 各调用程式可视个别条件,将所需处理的资料,放在缓冲器内(全部或部份)。待调用后,再从原缓冲器中取出经过处理后的资料。
六、对应表法
凡是指根据某种需要,将经过整理的资料,以某种固定的格式,安排在一特定区域中。每当需要时,立刻可以按照排列的位置取出来使用的,皆可称之为对应表。 这种对应表是我最喜欢利用的技巧,速度奇快不说,修改也极其容易。尤其是我做事一向不拘小节,写起程式来,专出小错。自从采用了表格对照法后,凡是适合这种形式的程式,只要想通了最理想的结构,几个指令就把程式写完了。 兹将附录中所举的例子,对字形放大所采用的查表法,在此作进一步的介绍。 假设有一组图形,要在萤幕上左右放大一倍。一般程式师做这种题目,都是在暂存器内移来移去,每一个字元的资料,起码要移八次之多,每次都要用借位作为转换值。而转换时,又要放进一个16位元的暂存器中,尽管可以用回路去做,时间的延误相当大,读者可参考附录二以做比较。 当然,表格要占用空间,以本例而言,如果一次用256B,取足则要512B。 因此这种技术可以说是以空间换取时间。在第一章第三节「效率」的第四条定律下,我们知道键盘输入速度,决定于人的操作速度,而人的反应远远不及电脑,故应以人的速度为时间边际值,尽量设法节省。 目前,所涉及的是显示时间,每个人在电脑前,都期望着立即得到结果。因此,显示速度不仅要快,而且越快越好。所以,前述的空时交换应在可能范围中,视实际的边际效应,以作取舍。 现在看看资料分析,下面列举的二进位资料,在左边为原图形点阵,在右边则为放大一倍后的点阵: 原点阵左右放大一倍 0000000100000000 00000011 0000001000000000 00001100 0000001100000000 00001111 .. 0101010100110011 00110011 .. 1111111111111111 11111111 现在有两个因素非常明显,第一,不论什么点阵,放大后长度加一倍,一字元有256 种。放大后点形种类不变,但字元数加倍为 512个。其次,由于放大后的 512个中,有一半皆相同,故仍可用256 种表示。 至于取前者或后者,当视情况而定。 决定以后,将之定义在缓冲器中,以原图形的点阵资料作为索引值,即可采间接定址法,立即取得放大后点阵。 在制作对应表时,应养成良好的习惯,根据资料的规则,以等长度、固定的格式输入。这样不仅对表中的资料能一目瞭然,而且容易输入、侦错、修改,一举数得。 如某表格为: 100 TBXXXDB0,1,3,7,0FH,1FH,3FH,7FH,0FFH,2,6,0EH,1EH,3EH,7EH,0FEH 此表看去远不如下表来得清楚、规律: 100 TBXXX DB000H,001H,003H,007H,00FH,01FH,03FH,07FH 200 DB0FFH,002H,006H,00EH,01EH,03EH,07EH,0FEH 从事程式写作,规律的思考方式及追求,经常事半功倍。这种小技巧看似没有多大作用。事实上,在输入时,规则化的结构可以轻易地利用现有的功能,或复制,或修改。更有利的是能一眼看出该表的意义及正确性,在程式侦错时,往往可以节省大量的时间。
七、模式法
所谓模式法,是指在程式的处理过程中,分析其规律,以期找到一种共同具有的「模式」。并用此模式,设计成为一个个程式单元,以追求最高效率。 这种模式,可用「概念」来代表,但最理想的表达方法,仍以视觉图形为宜。也就是说,最好能把分析出来的模式,用图形表示,并据以理解及设计程式。 兹以常用的功能「排序」为例,来说明模式法的应用,并设计成为程式。 先假定需要排序的资料结构为: 11每笔资料之长度固定为一字元。 12资料形式为 ASCII码,16进位值,由 20H到 7EH。 13排序时,资料数值小者排在低位,大者排在高位。 14程式开始时参数设定为: AL= 高位之资料。 AH= 低位之资料。 DS:SI=资料存贮处。 资料由低位开始检查,并同时排序,直到全部查完为止。排序时,交换高位及低位之资料,以使 高位住址资料≧低位住址中之资料。 由于人类行为与视觉息息相关,故最有效的认知方式,是以作图来说明。以下即为上一陈述之图形说明。
│? │ 模式一供检查├─┤ AL,AH 之大小 ┌ AH <--│? │<-- AL ┐ 模 │├─┤ │模 模式二交换资料式 ┤ AL <--│? │<-- AH ├式 其中 AH>AL 一 │├─┤ │二 └ SI =│? │ =SI ┘ ├─┤
由上图可见在模式一中,AH为低位资料,AL为高位资料。比较 AL,AH 之大小,即可知是否符合序列规定。如符合,则继续做下去,否则依模式二,将小值放进低位,大值放进高位住址中。程式只要设法保持此一处理之形式,即可简单明瞭地完成任务。 1: COMPAR: 2:MOVAH,AL;设AH为低位值 3: COMPAR1: 4:LODSB;取资料 5:CMPAL,AH;比大、小 6:JAECOMPAR;高位大,不变 7:MOV[SI-2],AX ;交换AH,AL,排序 8:DECSI;向低位再查 9:MOVAH,[SI-2] 10:JMPCOMPAR1
当然,上面这段程式并不成立,因为没有出口,永远做不完。程式的终止有很多方法,一是用计数器,一是用位置来比较,也有用终止指令的,不一而足,各有长短。 首先,假设在DS:SI 中,有一长度值,兹以计数器的回路来试试看: 1:LODSW 2:MOVCX,AX;似此,3B 18C ;若用MOV CX,[SI] ;INC SI ;INC SI ;则需6B,21T 3:SUBAL,AL;先设最小值,备用 4: COMPAR: 5:MOVAH,AL;设AH为低位值 6: COMPAR1: 7:LODSB;取资料 8:CMPAL,AH;比大、小 9:JBCOMPAR2 ;低位大,需排序 10:LOOPCOMPAR;回路 11:RET;完成 12: COMPAR2: 13:MOV[SI-2],AX ;交换AH,AL,排序 14:DECSI;向低位再查 15:MOVAH,[SI-2] 16:JMPCOMPAR1 程式中的回路,对前面有一比较分支不太有利,因为回路每次要17T ,比较分支就是现成的回路,不利用形成浪费。 若把回路改为位置比较,程式即为: 1:MOVCX,SI 2:ADDCX,[SI] 3:INCSI 4:INCSI 5:SUBAL,AL;先设为最小值,备用 6: COMPAR: 7:MOVAH,AL;设AH为低位值 8: COMPAR1: 9:LODSB;取资料 10:CMPSI,CX;比位置到终点? 11:JAECOMRET;完成 12:CMPAL,AH;比大、小 13:JAECOMPAR;高位大,再查 14:MOV[SI-2],AX ;交换AH,AL,排序 15:DECSI;向低位再查 16:MOVAH,[SI-2] 17:JMPCOMPAR1 18: COMRET: 19:RET 如此,在分支时,在第13条指令做回路,10,11 则比较住址以决定是否完成。这一来,完成结束只有一次,需时 16T,其余所有执行时间皆为4T,较前一回路快了13T 之多。 再试用「终止指令」法,其必要条件为资料中有多余的组合可供选择。一般多以 00H,0FFH 等极端值比较理想,下面且以0FFH作为终止指令,并置于资料终止处。 1:MOVCL,0FFH ;终止检查用 2:SUBAL,AL;先设为最小值,备用 3: COMPAR: 4:MOVAH,AL;设AH为低位值 5: COMPAR1: 6:LODSB;取资料 7:CMPAL,CL;比是否终止指令? 8:JAECOMRET;完成 9:CMPAL,AH;比大、小 10:JAECOMPAR;高位大,再查 11:MOV[SI-2],AX ;交换AH,AL,排序 12:DECSI;向低位再查 13:MOVAH,[SI-2] 14:JMPCOMPAR1 15: COMRET: 16:RET 似此,程式较短,其他效果差不多。 这段程式,在处理速度上,还大有油水。因为已经检查过的资料,因为回路关系,还会不断地重复检查,是否能够避免这种情况呢?
事实上,当排序到某住址时,即表示由该住址起,上面已经检查完毕。因此,只要记录下来,下次再查时,将住址还原即可。 1:MOVCL,0FFH ;终止检查用 2: COMPAR0: 3:SUBAL,AL;先设为最小值,备用 4: COMPAR: 5:MOVAH,AL;设AH为低位值 6: COMPAR1: 7:LODSB;取资料 8:CMPAL,CL;比是否终止指令? 9:JAECOMRET;完成 10:CMPAL,AH;比大、小 11:JAECOMPAR;高位大,再查 12:MOVDI,SI;暂时保存 13: COMPAR2: 14:MOV[SI-2],AX ;交换AH,AL,排序 15:DECSI;向低位再查 16:MOVAH,[SI-2] 17:LODSB;取排序资料 18:CMPAL,AH;比是否该排 19:JBCOMPAR2 ;是 20:MOVSI,DI;否,将原位址还原 21:JMPCOMPAR0 ;从头再做 22: COMRET: 23:RET 总而言之,程式的变化无穷无尽,尤其是用组合语言制作程式,更是灵活精妙。就像下围棋一般,往往一两个指令就足以将整个局势扭转过来。 程式的效率经常决定在回路上,读者千万不要以为一两个时钟脉冲算不了什么。要知道,汪洋大海,也是由一点一滴的水珠累积而成的。 这段程式还有不少值得深思的,读者们不妨自行研究吧!想得多了,自然会有生花妙笔。
真要作大量的资料排序,还有更有效的方法,也是应用模式分析的原则,先找出资料的「型」。 假如以同样性质的资料为例,为了避免资料一一查找,浪费时间。我们不妨研究一下,是否有可能,直截了当,就把资料依据大小,予以定位,一次排好? 电脑的好处,就在于资料的规律性,我们理应利用这种优点,来找出其排序的模式。 前例曾分为两个模式,一是查找,一是搬移。如果我们把查找改为记录,把搬移改为安排,则情形就大大的不同了。 记录时利用间接定址技巧,每笔取到的资料,皆可视为一个数值,对应于一记录的缓冲区。如果资料中每笔资料总值大于256 且小于 65536,则可以用二字元记录之。再若资料为二进位值,可由 0至 255,即设 512个对应单位。 假定原资料在 DS:SI中,长度在CX中。 首先,设一记录区为: 1: RECORDDB512 DUP (0) 2:PUSHSI;程式开始
[1] [2] 下一页
|