25键钢琴书(2)

来源:互联网 发布:网络摄像头传输距离 编辑:程序博客网 时间:2024/03/29 17:14

;#######################################################

        CODE  SEGMENT

              ASSUME    CS:CODE,DS:DATA

;-------------------------------------------------

        MAIN  PROC      FAR

                  PUSH      AX

                  PUSH      BX

                  PUSH      CX

                  PUSH      DX

                  PUSH      BP

                  PUSH      SP

                  PUSH      SI

                  PUSH      DI

 

                  MOV       AX,DATA

                  MOV       DS,AX

;*****定义一个宏******

;       SHOW  MACRO     b           ;9号端口的字符串输出功能

;                   LEA       DX,b

;                   MOV       AH,9

;                   INT       21H

;                   ENDM

;**********************

;*****调用宏***********

;             SHOW      HOST        ;就可输出首地址为HOST的,结束符为'$'的字符串

;**********************

      STEP0:

              CALL      CLEAR

              MOV       DX,0        ;为后面的回滚功能与退出作铺垫

              CALL      MENU

              CALL      INPUT       ;选择是 "用钢琴" 还是 "点插机"

              CALL      TIMELATE    ;为了在输入框体现出刚才的选择

              CALL      TIMELATE

 

     STEP10:

              CMP       AL,'1'      ;钢琴

              JNZ       STEP11

              CALL      CLEAR

              CALL      MSGPIAN

              CALL      PIANO25

              CMP       DX,'1'

              JZ           EXITM0

              CMP       DX,'2'

              JZ           STEP0

     STEP11:

              CMP       AL,'2'      ;音乐

              JNZ         STEP12

              CALL      CLEAR

              CALL      MSGMUSI

              CALL      MUSMENU

              CMP       DX,'1'

              JZ           EXITM0

              CMP       DX,'2'

              JZ           STEP0

     STEP12:

              CMP       AL,'Q'

              JNZ         STEP13

              JMP       EXITM0

     STEP13:

              CMP       AL,'q'

              JZ           EXITM0

      STEP3:

              CALL      ERROR

              CALL      INPUT

              CALL      TIMELATE

              CALL      TIMELATE

              JMP         STEP10

     EXITM0:

              CALL      CLEAR

              CALL      MSGBACK

              MOV       AH,1H

              INT         21H         ;起到暂停的作用

              CALL      CLEAR

              POP       DI

              POP       SI

              POP       SP

              POP       BP

              POP       DX

              POP       CX

              POP       BX

              POP       AX

              RET

        MAIN  ENDP

;-------------------------------------------------

        MENU  PROC      NEAR        ;主菜单

                   PUSH      DX

                   LEA        DX,HOSTMAI

;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

                   CALL      CLEIN       ;清除输入框架中的内容

;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

                   PUSH      DX

                   MOV       DH,0

                   MOV       DL,0

                   CALL      FIRST

                   POP       DX

                   PUSH      AX

                   PUSH      CX

                   PUSH      DX

                   MOV       AL,12       ;指明滚动的行数

                   MOV       CH,1        ;始行

                   MOV       CL,20       ;始列

                   MOV       DH,12       ;未行

                   MOV       DL,57       ;未列

                   CALL      SECOND

                   POP       DX

                   POP       CX

                   POP       AX

                   MOV       AH,9

                   INT         21H

                   CALL      CURSORP     ;置光标到输入框的中心处

                   POP       DX

                   RET

           MENU  ENDP

;-------------------------------------------------

     MSGPIAN  PROC      NEAR        ;键位菜单

                      PUSH      DX

                      LEA        DX,HOSTPIA

;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

                      CALL      CLEIN       ;清除输入框架中的内容

;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

                      PUSH      DX

                      MOV       DH,0

                      MOV       DL,0

                      CALL      FIRST

                      POP       DX

                      PUSH      AX

                      PUSH      CX

                      PUSH      DX

                      MOV       AL,21       ;指明滚动的行数

                      MOV       CH,1        ;始行

                      MOV       CL,14       ;始列

                      MOV       DH,20       ;未行

                      MOV       DL,64       ;未列

                      CALL      SECOND

                      POP       DX

                      POP       CX

                      POP       AX

                      MOV       AH,9

                      INT       21H

                      CALL      CURSORP     ;置光标到输入框的中心处

                      POP       DX

                      RET

     MSGPIAN  ENDP

;-------------------------------------------------

     MSGMUSI  PROC      NEAR        ;音乐选择菜单

                      PUSH      DX

                      LEA       DX,HOSTMUS

;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

                      CALL      CLEIN       ;清除输入框架中的内容

;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

                      PUSH      DX

                      MOV       DH,2        ;决定行

                      MOV       DL,0

                      CALL      FIRST       ;置光标位置

                      POP       DX

                      PUSH      AX

                      PUSH      CX

                      PUSH      DX

                      MOV       AL,15       ;指明滚动的行数

                      MOV       CH,3        ;始行

                      MOV       CL,20       ;始列

                      MOV       DH,17       ;未行

                      MOV       DL,57       ;未列

                      CALL      SECOND      ;指定白色背景的区域

                      POP       DX

                      POP       CX

                      POP       AX

                      MOV       AH,9

                      INT         21H

                      CALL      CURSORP     ;置光标到输入框的中心处

                      POP       DX

                      RET

    MSGMUSI  ENDP

;-------------------------------------------------

;退出窗口菜单

     MSGBACK  PROC      NEAR

                        PUSH      DX

                        LEA       DX,BACKS

                        CALL      CLEIN

;///////////////////////////////

;消除掉输入框架

                        PUSH      AX

                        PUSH      CX

                        PUSH      DX

                        MOV       AL,0        ;指明滚动的行数

                        MOV       CH,23       ;始行

                        MOV       CL,20       ;始列

                        MOV       DH,23       ;未行

                        MOV       DL,57       ;未列

                        PUSH      BX

                        MOV       AH,6        ;

                        MOV       BH,07H      ;改回背景为黑    即:消除掉输入框架

                        INT       10H

                        POP       BX

                        POP       DX

                        POP       CX

                        POP       AX

;//////////////////////////////

                        PUSH      DX

                        MOV       DH,5

                        MOV       DL,0

                        CALL      FIRST       ;置光标位置

                        POP        DX

                        PUSH      AX

                        PUSH      CX

                        PUSH      DX

                        MOV       AL,12       ;指明滚动的行数

                        MOV       CH,6        ;始行

                        MOV       CL,19       ;始列

                        MOV       DH,15       ;未行

                        MOV       DL,58       ;未列

                        CALL      SECOND      ;指定白色背景的区域

                        POP       DX

                        POP       CX

                        POP       AX

                        MOV       AH,9

                        INT       21H

;///////////////////

;屏蔽掉光标

                        PUSH      AX

                        PUSH      CX

                        MOV       AH,1

                        MOV       CH,10H

                        INT        10H

                        POP       CX

                        POP       AX

;///////////////////

                        POP       DX

                        RET

     MSGBACK  ENDP

;-------------------------------------------------

       ERROR  PROC      NEAR        ;出错提示函数

                      PUSH      DX

                      LEA        DX,HOSTERR

                      CALL      CLEIN

                      PUSH      DX

                      MOV       DH,22       ;决定行

                      MOV       DL,0

                      CALL      FIRST

                      POP       DX

                      MOV       AH,9

                      INT         21H

;///////////////////

;屏蔽掉光标

                      PUSH      AX

                      PUSH      CX

                      MOV       AH,1

                      MOV       CH,10H

                      INT        10H

                      POP       CX

                      POP       AX

;///////////////////

                      CALL      CURSORP     ;置光标到输入框的中心处

                      POP       DX

                      RET

       ERROR  ENDP

;-------------------------------------------------

     MUSIC_S  PROC      NEAR

                      PUSH      DX

                      MOV       DH,22

                      MOV       DL,20

                      CALL      FIRST       ;置光标位置

                      POP       DX

                      PUSH      AX

                      MOV       AH,9H

                      INT         21H

                      POP       AX

                      RET

     MUSIC_S  ENDP

;------------------------------------------------

;入口无,出口AL

       INPUT  PROC      NEAR        ;单个字符输入 [输入内容存储在AL里]

                   MOV        AH,1

                   INT          21H

                   CALL      TIMELATE

                   RET

       INPUT  ENDP

;-------------------------------------------------

;置光标的初始位置为:DH=行,DL=列

;入口CX(左上角),DX(右下角),AX(主要是al),BX(中的BH)

       FIRST  PROC      NEAR        ;控制显示位置

                   PUSH      AX

                   PUSH      BX

                   MOV       BH,0

                   MOV       AH,2

                   INT         10H

                   POP       BX

                   POP       AX

                   RET

       FIRST  ENDP

;-------------------------------------------------

;入口 指定白色背景的区域

      SECOND  PROC      NEAR        ;背景白色,前景黑色

                      PUSH      BX

                      MOV       AH,6

                      MOV       BH,70H

                      INT        10H

                      POP       BX

                      RET

      SECOND  ENDP

;-------------------------------------------------

;无入口,无出口

    TIMELATE  PROC      NEAR        ;时间延迟

                       PUSH       BX          ;设置时间延迟

                       PUSH       CX

                       MOV        BX,3

      BACK2:

                       MOV        CX,8286     ;现为0.125秒

                       CALL       WAITF

                       DEC        BL

                       JNZ         BACK2

                       POP        CX

                       POP        BX

                       RET

    TIMELATE  ENDP

;-------------------------------------------------

;清除输入框架中的内容

       CLEIN  PROC      NEAR

                   PUSH      AX

                   PUSH      CX

                   PUSH      DX

                   MOV       AL,0        ;指明滚动的行数

                   MOV       CH,23       ;始行

                   MOV       CL,20       ;始列

                   MOV       DH,23       ;未行

                   MOV       DL,57       ;未列

                   CALL      SECOND      ;指定白色背景的区域

                   POP       DX

                   POP       CX

                   POP       AX

                   RET

       CLEIN  ENDP

;-------------------------------------------------

;置光标位置到输入框的中心处

     CURSORP  PROC      NEAR

                        PUSH      DX

                        MOV       DH,23       ;决定行

                        MOV       DL,39

                        CALL      FIRST       ;控制显示位置                       

                        POP       DX

                        RET

     CURSORP  ENDP

;-------------------------------------------------

;入口无,出口无                       //未验证//

       CLEAR  PROC      NEAR        ;清除屏幕上的全部内容

                    PUSH      AX

                    PUSH      BX

                    PUSH      CX

                    PUSH      DX

                    MOV       AH,6

                    MOV       AL,0

                    MOV       BH,7

                    MOV       CH,0

                    MOV       CL,0

                    MOV       DH,24

                    MOV       DL,79

                    INT         10H

                    MOV       DX,0

                    MOV       AH,2

                    INT         10H

                    POP       DX

                    POP       CX

                    POP       BX

                    POP       AX

                    RET

       CLEAR  ENDP

;-------------------------------------------------

;出口:DX=1退出总程序,DX=2回滚

     PIANO25  PROC      NEAR        ;单个音符发音

                     PUSH       AX

                     PUSH       BX

                     PUSH       SI

                     PUSH       DI

   NEW_NOTE:

;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

                     CALL       CLEIN       ;清除输入框架中的内容

                     CALL       CURSORP     ;置光标到输入框的中心处

;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

                     CALL       INPUT

    STOPP00:

                     CMP        AL,'1'      ;退出总程序

                     JNZ         STOPP01

                     MOV       DX,'2'

                     JMP        EXITP       ;如果输入的是1就回滚,借助DX

    STOPP01:

                     CMP       AL,'2'      ;回车的ASCII码是0dH

                     JNZ         STOPP02

                     MOV       DX,'1'

                     JMP        EXITP       ;如果输入的是2就退出总程序,借助DX

    STOPP02:                        ;大写字母的左侧

                     CMP       AL,'A'

                     JB          NEW_NOTE3   ;如果AL<A(且非1、2的数),则跳到new_note3这个位置 提示输入错误

    STOPP03:                        ;大写字母内部没有用到的字母

                     CMP       AL,'V'      ;排除特殊V的情况

                     JZ           NEW_NOTE3

    STOPP04:                        ;大写字母内部

                     CMP       AL,'Z'

                     JBE        NEW_NOTE1   ;如果AL≤Z,则跳到new_note1这个位置  计算位置  即:jnbe

                                    ;排除了大写字母进入stopp05~new_note1之间

    STOPP05:                        ;大写字母与小写字母之间

                     CMP       AL,'a'      ;如果AL<a,则跳到new_note3这个位置  提示输入错误

                     JB          NEW_NOTE3

    STOPP06:                        ;小写字母内部没有用到的字母

                     CMP       AL,'v'      ;如果AL=v,则跳到new_note3这个位置  提示输入错误

                     JZ           NEW_NOTE3

    STOPP07:                        ;小写字母的右侧

                     CMP       AL,'z'

                     JA           NEW_NOTE3   ;如果AL>z,则跳到new_note3这个位置 提示输入错误  即:jnbe

                     SUB        AL,20H      ;将小写的全部转为大写 只有当输入的为a~z时,才会执行这一步

  NEW_NOTE1:

                     CMP       AL,[SI]     ;作比较    如果是 用 mov dx,[si]  则一次送入两个字符到DX中

                     JZ          NEW_NOTE2   ;如果找到则跳出   借助这时BX,知道他在键排中的偏移量

                     INC        BX          ;如果暂未找到,则BX自加1 作为标志用范围[0,24]

                     INC        SI          ;如果暂未找到,SI深入串内

                     JMP       NEXT

  NEW_NOTE2:

                     MOV       AX,BX

                     MOV       BX,OFFSET TALE          ;即:lea bx,tale

                     SHL        AX,1        ;将AX逻辑左移一位 等效于扩大两倍 因为是用字DW存储

                     MOV       SI,AX

                     MOV       DI,[BX][SI] ;SI内放着偏移量

                     MOV       BX,10       ;为什么发音时间是个定量 这个地方非常不好

                     CALL      SOUNDF

                     JMP        NEW_NOTE

  NEW_NOTE3:

                     CALL      ERROR

                     CALL      TIMELATE

                     CALL      TIMELATE

                     CALL      TIMELATE

                     JMP        NEW_NOTE

      EXITP:

                     CALL      TIMELATE    ;为什么在返回 与 退出时我看不到输入的内容

                     CALL      TIMELATE    ; 这边都用了三个停顿了,为什么还看不到输入的字符

                     CALL      TIMELATE

                     POP        DI

                     POP        SI

                     POP       BX

                     POP       AX

                     RET

     PIANO25  ENDP