此外,31,32及43 ,44是浪费的作法,只要在第18条加一标号,就可以省却两个字元输出的指令。另外,还有35及39两条指令,应该合并,一次即将AX设妥,于是,又省下了一个字元。 先令 DH=3 1: CSEND0: 2: MOV DL,0FDH ; 输出埠 3: MOV AL,80H 4: OUT DX,AL ; 输出指令 5: MOV DL,0F8H ; LSB 速度控制 6: MOV AL,06H ; 速度=19200/秒 7: OUT DX,AL 8: INC DX ; MSB 速度控制 9: SUB AL,AL ; 速度=19200/秒 10: OUT DX,AL 11: MOV DL,0FBH ; 行控制暂存器 12: MOV AL,DH ;NO PARITY,1 ; STOP,8 13: OUT DX,AL 14: INC DX ; 通讯控制 15: OUT DX,AL 16: MOV DL,0F9H ; 中断有效 17: SUB AL,AL 18: CSNDA: 19: OUT DX,AL 20: CSND1: 21: MOV DL,0FDH ; 状态暂存器 22: IN AL,DX 23: TEST AL,10H ; 是否可接收? 24: JNZ CRCV0 ; 可 25: TEST AL,20H ; 通道已清否? 26: JZ CSND1 ; 8250未清 27: MOV AH,1 ; 键盘有输入? 28: INT 16H 29: CMP AL,07H ; ='CTRL+G' 30: JE CEND ; 是,完毕 31: MOV DL,0F8H 32: JMP CSNDA ; 送输入字符 33: CRCV0: ; 接收 34: MOV DL,0FCH ; 通讯控制 35: MOV AX,0E08H ; 暂停中断 36: OUT DX,AL ; 及显示 37: MOV DL,0F8H 38: IN AL,DX ; 收字符 39: INT 10H ; 萤屏显示 40: MOV DL,0FCH 41: MOV AL,0BH 42: JMP CSNDA ; 循环工作 43: CEND: 44: RET ; 完成 看来似乎这样太小气,可是所谓艺术,就要具备丝毫不苟且的态度,再说由84个字元变成66个字元,省了近百分之廿,而且,速度也快了。这种程式原本就很精简,只有训练有素,追求完美的程式师,才做得到。 另一种做法,便是将重复的过程写成回路,约可节省廿几个字元。但是,由于时间定律限制,通讯程式颇重时效,回路是否值得,尚要多方面分析,不可轻率决定。
2,回路的实例: 前面曾经讨论过,程式的效率,经常决定于回路的处理方式及其技巧。其对空间上影响比较小,但是良好的设计理念,常使速度上有高达十倍,甚至百倍的差异,读者想必已经知道,但是如何能应用已知的技巧,来改进设计的程式呢? 回路是利用计数器,反复进行相同的程序作业,这种程式,目的就是为了节省空间,相对地,时间上难免有所损失。 因此,在设计回路时,必须先行考虑清楚: 空间的节省与时间的交换是否值得? 其次,则要充份掌握回路的特色,要用得恰到好处,不可掉以轻心。 原则上,在回路中,指令要用得精简,流程要非常明确,尤其重要的是,应力求避免在回路中使用缓冲器,最好充份利用暂存器。如果时间效率极为重要,则不妨放弃回路方式。 有一个显示程式,目的是要将 16*16点阵字形送到萤幕上。对象是Hercules 640*400的图形卡,计分四区交互传送,这是另一个「高科技」界的新鲜奇事,在IBM PC推出时,最高密度的图形态,只有 640X200点阵,那是迁就电视萤幕的扫描方式,先送单线的水平讯号,再送双线,故分两区。Hercules卡为了加高密度,应用Interlace 技术,又在单双水平扫描线中各加了一行,遂成了四区。 Hercules很适宜中文的显示,如用 16X16字形,正好显示25行,每行40字,与英文完全兼容。若希望有一状态显示栏,则可用 15X15字形,留出24条线供做状态栏。 遗憾的是在最需要中文的国内,却偏爱CGA,EGA 等密度不足的显示设备。不但售价偏高,功能也不足,弄得不伦不类。 最理想的还是VGA 显示,计有 640X480之萤幕点阵,不仅空间大,在记忆体中,只有一区,应用非常灵活。 下面,我们先介绍 Hercules 的显示方法,同时探讨回路的处理方式。 1: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2: ;HERCULES 中文显示处理程式。 ; 3: ;输入参数:SI=点阵字形,DI=萤幕位置。 ; 4: ; DS =CG,ES= 0B800H(萤幕段)。 ; 5: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 6: CDSP0: 7: MOV CX,16 ;高16点 8: CDSP1: 9: MOVSW ;移至萤幕上 10: ADD DI,1FFEH ;加一区,每区=2000H 11: JNS CDSP2 ;未超越区限,继续 12: ADD DI,8050H ;超越区限,换区加行 13: CDSP2: 14: LOOP CDSP1 15: RET 程式到此结束,相当精简,技巧在第10至12条区限的检测方式。一般做法是在检查区限时,用: ADD DI,1FFEH ; 加区值 CMP DI,8000H ; 最大区限值 JB CDSP2 ; 未超过 SUB DI,8000H ; 减去区限 如此则多了一条4字元的指令,加上4个时钟脉冲,做16次回路就损失64个时钟脉冲值。在全萤幕显示时,以1,000 个字来算,为数就不少了。 当然,取消了回路速度还可以加快,其结果,则要增加130 个字元,时间则快了 272个时钟脉冲,是否值得,就要看实际需要而定了。 另一个方法,要增加2个字元,但可快上36个时钟脉冲,其法在第11条上: 11: JS CDSP3 12:CDSP2: 13: LOOP CDSP1 14: RET 15:CDSP3: 16: ADD DI,8050H 17: JMP CDSP2 再换一个方法,如果先使 BX 为1FFEH,DX为8050H,则在原程式中,将第10条及12条分别改为: 10: ADD DI,BX 12: ADD DI,DX 这一来,时钟脉冲快了2个,16次则快更多,如果再加上取消回路,其意义更大。空间原增加 130字元,现仅94字元,时间则省下 304个时钟脉冲。如果全萤幕显示了1,000 个字,在8MHZ频率下,将会加快 1/25 秒的速度。 在回路中,如果讲求时间效益,应极力避免使用PUSH及POP ,因PUSH需15个时钟脉冲,而POP 则要12个,两者相加是27个时钟脉冲,非常不值得。 解决方法之一是:设法将欲保留之值贮存在没有用到的暂存器中;再若是固定的常数,也不妨在每次要用时重新置入,祇不过是4个时钟而已。最麻烦是变数值,除了在设计模组之前,妥当地安排外,别无良策。
 
2/2 首页 上一页 1 2 |