⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 汇编.txt

📁 会变语言实现的一些程序
💻 TXT
📖 第 1 页 / 共 2 页
字号:
        PUSH    CX
        REP     MOVSB
        POP     CX
        SUB     DX,CX
    为什么不干脆些?
        SUB     DX,CX
        REP     MOVSB

  6,有段程序,很有规律,但却极无效率:
    X1:
        TEST    AH,1
        JZ      X2
        MOV     BUF1,BL
    X2:
        TEST    AH,2
        JZ      X3
        MOV     BUF2,DX     ; 凡双数用DX,单数用BL
    X3:
        TEST    AH,4
        JZ      X4
        MOV     BUF3,BL
    X4:
        ..                  ; 以下各段与上述程序相似
    X8:
        ..
        这种金玉其表的程序,最没有实用价值,改的方法应由缓冲器着手,先安排成
序列,由小而大如:
        BUF1    DB  ?
        BUF2    DW  ?
        BUF3    DB  ?
        BUF4    DW  ?
        ..
    然后,程序改为:
        MOV     DI,OFFSET BUF1      ; 第一个缓冲器
        MOV     AL,BL
        MOV     CX,4
    X1:
        SHR     AH,1
        JZ      X2
        STOSB
    X2:
        SHR     AH,1
        JZ      X3
        MOV     [DI],DX
        INC     DI
        INC     DI
    X3:
        LOOP    X1

  7,回路最怕千回百转,不畅不顺,如:
        SUB     AH,AH
    ABCD:
        CMP     AL,BL
        JB      ABCD1
        SUB     AL,BL
        INC     AH
        JMP     ABCD
    ABCD1:
        ..
      以上 ABCD1这个入口是多余的,下面就好得多:
        MOV     AH,-1
    ABCD:
        INC     AH
        SUB     AL,BL
        JA      ABCD
        ADD     AL,BL       ; 还原
        ..

  8,当处理字码时,需要字母的序数,有这样的写法:
        CMP     AL,60H
        JA      ABCD1
        SUB     AL,40H      ; 大写字母
    ABCD:
        ..
    ABCD1:
        SUB     AL,60H      ; 小写字母
        JMP     ABCD
        要知道字母码的特色在于大写为 40H 至4AH,小写为60H 至6AH ,以上程序,
其实只要一个指令就可以了:
        AND     AL,1FH
    简单明了!

  9,大多数的程序在程序员自己测试下很少发生错误,而一旦换一另个人执,就会发现
错误百出。
        其原因在于写程序者已经假定了正确的情况,当然不会以明知为错误的方式操
作。可是换了一个人,没有先入为主的成见,很可能输入了「不正确」的数据,结果是
问题丛生。
        要知道真正的使用者,绝非设计者本人,在操作过程中,按键错误在所难免。
这种错误应该在程序中事先加以检查,凡是输入数据有「正确、错误」之别者,错误性
数据一定要事先加以排除。
        这样做看起来似乎程序不够精简,可是正确的重要性远在精简之上。一旦发生
了错误,再精简的程序也没有使 用价值。
        此外,在程序中常有加、减的运算,这时也应该作正确性检查,否则会发生上
述同样的问题。

三、指令应用要灵活

    有一段很简单的程序,其写作的方法甚多,但是指令应用的良窳,会使得程序的效
率相去天上地下,难以估计。
    这段程序的用途,是要将一段数据中,英文字符大、小写相互转换。当然,转换的
选择要由使用者决定,在下面程序且略去使用界面,假设已得知转换的方式。
    设数据在 DS:SI中,数据长度=CX ,大写转小写时BL=0,反之,则BL=1。
    我见过一种写法,简直无法原谅:
    1: LOOP1:
    2:  CALL CHANGE
    3:  JC LOOP11
    4:  ADD AL,20H
    5:  JMP SHORT LOOP12
    6: LOOP11:
    7:  SUB AL,20H
    8: LOOP12:
    9:  MOV [SI-1],AL
   10:  LOOP LOOP1
   11:  RET
   12: CHANGE:
   13:  LODSB
   14:  OR BL,BL
   15:  JZ CHANGS
   16:  CMP AL,61H
   17:  JB CHARET
   18:  CMP AL,7AH
   19:  JA CHARET
   20:  STC
   21: CHARET:
   22:  RET
   23: CHANGS:
   24:  CMP AL,41H
   25:  JB CHARET
   26:  CMP AL,5AH
   27:  JA CHARET
   28:  CLC
   29:  RET
    这种程序错在把由12到29的程序写得太长,共 25B,有共享的价值,于是作为子程
序调用。
    试想一下,每一笔数据,都要调用一次,浪费四个字符事小,但每次要费 23+20个
时钟脉冲,数据多时,不啻为天文数字。更何况这段程序写得极差,在回路中,又多浪
费了几十个时钟。关于这一点,下面会继续讨论。
    照上面这段程序,略加改进,写法如下:
    1: CHANGE:
    2:  LODSB
    3:  OR BL,BL
    4:  JZ CHANGS
    5:  CMP AL,61H
    6:  JB CHARET
    7:  CMP AL,7AH
    8:  JA CHARET
    9:  SUB AL,20H
   10: CHANG0:
   11:  MOV [SI-1],AL
   12: CHANG1:
   13:  LOOP CHANGE
   14:  RET
   15: CHANGS:
   16:  CMP AL,41H
   17:  JB CHANG1
   18:  CMP AL,5AH
   19:  JA CHANG1
   20:  ADD AL,20H
   21:  JMP CHANG1
    这样的写法还是不佳,因为在回路中,用常数与寄存器比较,速度较寄存器相比为
慢。应该先将需要比较的值,放在暂存器DH,DL 中,改进如次:
    1:  MOV AH,20H
    2:  MOV DX,7A61H
    3:  OR BL,BL
    4:  JZ CHANGE
    5:  MOV DX,5A41H
    6: CHANGE:
    7:  LODSB
    8:  CMP AL,DL
    9:  JB CHANG1
   10:  CMP AL,DH
   11:  JA CHANG1
   12:  XOR AL,AH
   13:  MOV [SI-1],AL
   14: CHANG1:
   15:  LOOP CHANGE
   16:  RET
    以上这段程序,空间小,速度快,每笔数据,平均仅需不到40个时钟值,以10 MHZ
计,十万笔数据,约需半秒钟!
请注意程序中所用的技巧,由2至6的分支法,就比下面这种写法为佳:
    1:  OR BL,BL
    2:  JZ CHAN1
    3:  MOV DX,5A41H
    4:   JMP SHORT CHANGE
    5: CHAN1:
    6:  MOV DX,7A61H
    7: CHANGE:
    这种分支也可以由另一种技巧所取代,即预设法。事先将所需用的参数放在固定的
缓冲区中,此时取用即可:
        MOV  DX,BWCOM   ; 比较之默认值
    这样程序又简单些了:
    1:    MOV AH,20H
    2:  MOV DX,BWCOM
    3: CHANGE:
    4:  LODSB
    5:  CMP AL,DL
    6:  JB CHANG1
    7:  CMP AL,DH
    8:  JA CHANG1
    9:  XOR AL,AH
   10:  MOV [SI-1],AL
   11: CHANG1:
   12:  LOOP CHANGE
   13:  RET

    以上介绍为变量法技巧,即将所要比较的值,放在寄存器中。由于寄存器快速、节
省空间,因此程序效率高。更重要的一点,是程序本身的弹性大,只要应用方式统一,
事先把参数设妥,即可共享。

四、回路中的指令

    回路最重要的是速度,因为本段程序,将在计数器的范围之内,连续执行下去。如
果不小心浪费了几个时钟值,在回路的累积下,很可能使程序成为牛步。
    要想把回路写好,一定要记清楚每个指令的执行时钟,以便选择效率最高者。同时,
要知道哪些指令可以获得相同的处理效果,才能有更多的选择。
    其次,在回路中,最忌讳用缓冲器,不仅占用空间大,处理速度慢,而且不能灵活
运用,功能有限。另外也应极力避免常数,尽量设法经由寄存器执行,用得巧妙时,常
会将整个程序的效率提高百十倍。
    还有便是少用 PUSH,POP,DIV,MUL和 CALL 等浪费时钟的指令。除此之外,小心、
谨慎,深思、熟虑,才是把回路写好的不二法门。
    在前例中,把比较常数的指令换为比较暂存器,便是很好的证明。如果用常数,两
段程序决不可能共享,时、空都无谓地浪费了。
    以下再举数例,乍看这似乎有些吹毛求疵,但是仔细计算一下所浪费的时间,可能
就笑不出声了。
兹假定以下回路需处理五万字符的数据,频率为 10MHZ,其情况为:
    1: LOOP1:
    2:          LODSB
    3:  XOR AL,[DI]
    4:  STOSB
    5:  LOOP LOOP1
    本程序计数器等于50,000,每次需
    12T+14T+11T+17T=55T 个时钟脉冲
若以50,000次计,需时 47*50,000/10,000,000 秒,即约四分之一秒。
    只要稍稍将指令调整一下,为:
    1: LOOP1:
    2:          LODSW
    3:  XOR AX,[DI]
    4:  STOSW
    5:  LOOP LOOP1
    这样计数器只要25,000次,每次
16T+18T+15T+17T=66T
    则25,000次需时 66*25,000/10,000,000 秒,约六分之一秒,比前面的程序快了二
分之一。
    同理,在回路中加回路,而每个回路需 17T,也是很大的浪费。倘若加调用 CALL
指令,则需 23T+20T=43T,浪费得更多,读者不可不慎。
    当某一段程序用得很频繁时,理应视作子程序,例如下面的 LODAX:
    1: LOOP1:
    2:  CALL LODAX
    3:  LOOP LOOP1
    4:  RET
    5: LODAX:
    6:  LODSW
    7:  XOR AX,[DI]
    8:  STOSW
    9:  RET
    其实这是贪小失大,仅四个字符的程序,竟用三个字符的调用指令去交换,是绝对
得不偿失的。
    再如同下面的程序,颇有值得商榷之处。
    1: LOOP1:
    2:  MOV DX,NUMBER1
    3:  MOV CX,NUMBER2
    4: LOOP2:
    5:  PUSH CX
    6:  MOV CX,DX
    7: LOOP3:
    8:  LODSW
    9:  XOR AX,[DI]
   10:  STOSW
   11:  LOOP LOOP3
   12:  INC  DI
   13:  INC  DI
   14:  POP CX
   15:  LOOP LOOP2
   16:  RET
    第二个回路是多余的,这是高级语言常用的观念,对汇编语言完全不适用。
    稍加改动,不损上面程序原有的条件,得到:
    1: LOOP1:
    2:  MOV DX,NUMBER1
    3: LOOP2:
    4:  MOV CX,NUMBER2
    5: LOOP3:
    6:  LODSW
    7:  XOR AX,[DI]
    8:  STOSW
    9:  LOOP LOOP3
   10:  INC  DI
   11:  INC  DI
   12:  DEC     DX
   13:  JNZ LOOP2
   14:  RET
这样回路少了一个,程序中将5,6,14,15 各条中原来为15T+2T+12T+17T=46T的时间,省
为12,13,14条的2T+16T+17T=35T。

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -