ITEEDU

4.4 更多的技术

4.4节导航:第一页 第二页 第三页 第四页

MUSIC已经是我们所编制的最复杂的程序了,在这个程序中我们使用了很重要的间接寻址技术用于取得数据,本节我们将讨论和CALL指令有关的间接寻址技术。
下面给出的程序可以在我们的控制下产生滑音。程序一开始运行就在屏幕上显示一个"菜单",有三个选项:选"1"可以使机器发出连续上升的声音;选"2"可以使机器发出连续下降的声音;其它按键则使程序结束。请看源程序:

    SIREN.ASM                        
       PORTB  EQU       61H
      M_WORD  EQU       10110110B
                        
        CODE  SEGMENT
              ASSUME    CS:CODE,DS:CODE
              ASSUME    ES:CODE,SS:CODE
                        
              ORG       100H
        MAIN  PROC      FAR
              JMP       START
                        
        ADDR  DW        OFFSET RISE        ;RISE子过程偏移地址
              DW        OFFSET FALL        ;FALL子过程偏移地址
                        
      OUTMSG  DB        0DH,0AH        ;定义菜单
              DB        '1---RISE',0DH,0AH
              DB        '2---FALL',0DH,0AH
              DB        'OTHER---EXIT',0DH,0AH
              DB        'CHOICE:',24H
                        
      START:  MOV       AH,09
              MOV       DX,OFFSET OUTMSG
              INT       21H        ;显示菜单
                        
              MOV       AH,01H
              INT       21H        ;等待输入选择
              CMP       AL,'1'
              JB        EXIT        ;小于1则退出
              CMP       AL,'2'
              JA        EXIT        ;大于2,退出
              SUB       AL,30H        ;ASCII码转换成数字
              CBW       ;BYTE转换成WORD
              DEC       AX
              SHL       AX,1        ;(数字-1)×2,计算地址指针
              MOV       BX,AX        ;地址指针置入BX寄存器
              CALL      ADDR[BX]        ;转至相应子过程
              JMP       START        ;循环
                        
       EXIT:  INT       20H        ;返回DOS
        MAIN  ENDP      ;主过程结束
                        
        RISE  PROC      NEAR
              CALL      OPEN_T        ;调用OPEN_T子程序打开定时器
              MOV       AX,3000H        ;设定频率初值
                        
      LOOP1:  CALL      SOUND         ;输出频率
                        
              CALL      DELAY        ;调用延时子程序
              DEC       AX        ;频率升高
              JNZ       LOOP1        ;循环输出
                        
              CALL      CLOSE_T        ;调用CLOSE_T子程序关闭定时器
              RET       ;子程序返回
        RISE  ENDP
                        
        FALL  PROC      NEAR
              CALL      OPEN_T        ;打开定时器
              MOV       AX,0        ;设定频率初值
                        
      LOOP2:  CALL      SOUND        ;输出频率
              CALL      DELAY        ;延时
              INC       AX        ;频率降低
              CMP       AX,3000H        ;是否到预定值?
              JNE       LOOP2        ;若未到,循环输出
                        
              CALL      CLOSE_T        ;关闭定时器
              RET       ;子程序返回
        FALL  ENDP
                        
       SOUND  PROC      NEAR
              PUSH      AX        ;保存AX寄存器至堆栈
              OUT       42H,AL        ;输出低字节
              MOV       AL,AH
              OUT       42H,AL        ;输出高字节
              POP       AX        ;恢复AX寄存器
              RET       ;子程序返回
       SOUND  ENDP
                        
      OPEN_T  PROC      NEAR
              MOV       AL,M_WORD        ;MAGIC WORD送入AL寄存器
              OUT       43H,AL        ;初始化8253定时器通道
              IN        AL,PORTB        ;读61H端口的原值
              OR        AL,03H        ;bit0,bit1置1
              OUT       61H,AL        ;开启定时器
              RET       ;子程序返回
      OPEN_T  ENDP
                        
     CLOSE_T  PROC      AL,61H        ;恢复61H端口的原值
              IN        AL,11111100B
              AND       61H,AL
              OUT       ;子程序返回
              RET
     CLOSE_T  ENDP
                NEAR        
       DELAY  PROC      CX        ;将CX寄存器保存至堆栈
              PUSH      CX,500H        ;CX寄存器置入500H
              MOV       DELAY1        ;循环等待
     DELAY1:  LOOP      CX        ;恢复CX寄存器
              POP       ;返回主程序
              RET
       DELAY  ENDP

程序中多了两条新的条件跳转指令--JA和JB:

助记符:JA(Jump if above)
用 途:判断比较(减法运算)的结果是不是"前高于后"(为正)
格 式:JA 目的地址
执 行:若两个数比较(相减),前一个数比后一个数大(相减结果为正)则执行转移

助记符:JB(Jump if below)
用 途:判断比较(减法运算)的结果是不是"低于"(为负)
格 式:JB 目的地址
执 行:若两个数比较(相减),前一个数比后一个数小(相减结果为负)则执行转移

这两条指令是功能相对的,它常用于"CMP"指令或"SUB"等算术运算指令后面。应用这两个指令时要注意这样一点那就是只有在两个"符号相同"的数相比较后才可用此指令根据结果转移,它不适用于判断"异符号数"运算结果。