DATA SEGMENT
KEYS DB 'QWERTYU','ASDFGHJ','ZXCVBNM'
FREQ DB 131,147,165,175,196,220,247
WELC DB 'Welcome to "Piano of Keyboard"',0DH,0AH,0DH,0AH,'$'
EXPL DB 'Explanation:', 0DH,0AH,'Key:QWERTYU-Low Notes 1 2 3 4 5 6 7 ', 0DH,0AH,'Key:ASDFGHJ-Middle Notes 1 2 3 4 5 6 7 ',0DH,0AH,'Key:ZXCVBNM-High Notes 1 2 3 4 5 6 7 ', 0DH,0AH, 'Please Note Your Caps Lock Truned On', 0DH,0AH
ESCQ DB 0DH,0AH,'Please play:',0DH,0AH,'(You can Type "ESC" to exit)', 0DH,0AH,0DH,0AH,'$'
LAST DB 0DH,0AH,'Welcome again!','$'
REMI DB 'Reminder:Please play the Key:"QWERTYU-ASDFGHJ-ZXCVBNM"', 0DH,0AH,'$'
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE DS:DATA
START: MOV AX,DATA
MOV DS,AX ;初始化数据区
LEA DX,WELC
MOV AH,9
INT 21H ;显示提示语句
INPUT: MOV AH,7
INT 21H ;不回显输入键盘的KEY
CMP AL,1BH ;判断输入KEY是否为“ESC”
JZ EXIT ;若输入KEY为“ESC”则跳转到退出EXIT
LEA DI,KEYS
MOV CX,21
FIND: CMP AL,[DI]
JZ SING ;找到KEY相对应的偏移地址DI则跳转至SING
INC DI
LOOP FIND ;根据输入KEY的ASCII码找到相对应的偏移地址
LEA DX,REMI
MOV AH,9
INT 21H ;输入的KEY不正确,显示提醒请输入正确的KEY
JMP INPUT ;不是正确的输入KEY,则跳转至INPUT
SING: CALL FIFRE ;进入计算KEY所对应频率值的子程序
CALL SOUND ;进入根据频率值发出音调的子程序
JMP INPUT ;发声完毕后跳转至INPUT
EXIT: LEA DX,LAST
MOV AH,9
INT 21H ;显示退出时的字幕
MOV AX,4C00H
INT 21H ;返回DOS
FIFRE PROC ;计算KEY所对应频率值的子程序
MOV DL,1 ;标记频率基准值的倍数值
LEA BX,KEYS
SUB DI,BX ;计算偏移地址相对与首地址的值
CMP DI,6
JNA SOU ;属于低音直接跳转至SOU
SUB DI,7 ;属于中音,将偏移地址减7
ADD DL,1 ;标记倍数值加倍为2
CMP DI,6
JNA SOU ;属于中音,跳转至SOU
SUB DI,7 ;属于高音,将偏移地址再减7
ADD DL,2 ;标记倍数值再加倍为4
SOU: MOV AX,DI ;将被换码给AL
LEA BX,FREQ
XLAT
MUL DL ;频率基准值乘以倍数得到KEY所对应的频率值
MOV BX,AX
RET
FIFRE ENDP
SOUND PROC ;根据频率值发出音调的子程序
MOV AL,0B6H
OUT 43H,AL ;向8253的43H写入控制字
MOV DX,12H
MOV AX,348CH
DIV BX ;计算计数初值N
OUT 42H,AL
MOV AL,AH
OUT 42H,AL ;向通道2端口42H写入计数初值N
IN AL,61H
OR AL,3
OUT 61H,AL ;打开扬声器
CALL DELAY ;进入延时子程序
IN AL,61H
AND AL,0FCH
OUT 61H,AL ;关闭扬声器
RET
SOUND ENDP
DELAY PROC ;延时时间子程序
PUSH BX
PUSH CX
MOV BX,4000
DY1: MOV CX,0FFFH
DY0: LOOP DY0
DEC BX
JNZ DY1 ;利用LOOP循环和跳转指令进行双循环
POP CX
POP BX
RET
DELAY ENDP
CODE ENDS
END START
在DOSBOX里运行时无论按哪个键它都没办法弹
一直重复显示着那句话!!
求助呀!