;比较low的钢琴
ASSUME CS:CODE,DS:DATA,SS:STACK
DATA SEGMENT
;设置键盘区位
;中音区 A: 7 S: 8 D: 9 F:10 J:11 K:12 L:13
;高音区 Q:14 W:15 E:16 R:17 U:18 I:19 O:20
;低音区 Z: 0 X: 1 C: 2 V: 3 B: 4 N: 5 M: 6
;填补区 T:17 Y:18 G:10 H:11 P:20
; '[':20 ']':20 ';':14 '"':14 '<':
; '<':5 '>':5 '\':6
; '^':0 '-':0 '`':0
;由于acsii码'A'的号码较小,为了大小写一致,直接减去'A'则得到序号为
NORMALF DD 119000
TIME DW 0
IND DB 7,4,2,9,16,10,10,11,19,11,12,13,6,5,20,20,14,17,8,17,18,3,15,1,18,0,20,6,20,0,0,0,7,4,2,9,16,10,10,11,19,11,12,13,6,5,20,20,14,17,8,17,18,3,15,1,18,0
FRE DW 131,147,165,175,196,220,247,262,294,330,349,392,440,494, 524,587,659,698,784,880,988
STR1 DB "Welcome!!$"
STR2 DB "The keyboard is distributed like that:$"
STR3 DB "0 exit$"
STR4 DB "High Q W E R U I O$"
STR5 DB "Medium A S D F J K L$"
STR6 DB "Low Z X C V B N M$"
LENSTR DW 10,39,7,21,21
DATA ENDS
STACK SEGMENT
BUFF DB 80H DUP(0)
STACK ENDS
CODE SEGMENT
INIT PROC ;直接把所有频率除以基准频率
MOV CX,21
MOV DI,0
LOOP1:
MOV DX,NORMALF[2]
MOV AX,NORMALF
DIV FRE[DI]
MOV FRE[DI],AX
ADD DI,2
LOOP LOOP1
MOV CX,5 ;输出提示语
LEA DI,STR1
MOV AX,0900H
MOV DX,DI
MOV SI,0
INT 21H
CALL NEWLINE
LOOP3:
ADD DI,LENSTR[SI]
ADD SI,2
MOV DX,DI
MOV AX,0900H
INT 21H
CALL NEWLINE
LOOP LOOP3
RET
INIT ENDP
RING PROC ;此时调用的字符存储在栈中
POP SI
POP DI
SUB DI,'A'
MOV AL,IND[DI]
MOV DI,AX
ADD DI,DI
MOV AX,0
MOV AL,0B6H
OUT 43H,AL
MOV AL,BYTE PTR FRE[DI]
OUT 42H,AL
MOV AL,BYTE PTR FRE[DI+1]
OUT 42H,AL
IN AL,61H
OR AL,3
OUT 61H,AL
MOV AL,0
INT 1AH
MOV TIME,DX
BACK1:
MOV AL,0
INT 1AH
SUB DX,TIME
CMP DX,5H
JB BACK1
MOV AX,0
OUT 61H,AL
PUSH SI
RET
RING ENDP
NEWLINE PROC
MOV AH,02H
MOV DL,0DH
INT 21H
MOV AH,02H
MOV DL,0AH
INT 21H
RET
NEWLINE ENDP
BEGIN:
MOV AX,DATA
MOV DS,AX
MOV AX,STACK
MOV SS,AX
CALL INIT
LOOP2:
MOV AH,01H
INT 21H
CMP AL,'A'
JB EXIT
CMP AL,'z'
JA EXIT
MOV AH,0
PUSH AX
CALL RING
JMP LOOP2
EXIT:
MOV AX,4C00H
INT 21H
CODE ENDS
END BEGIN