试设计一个程序,能够使用键盘中字母键模拟钢琴按键发音。其中,按照字母在键盘中的排列方式,字母键z/x/c/v/b/n/m分别发出低1—低7共 7个低音音符,字母键a/s/d/f/g/h/j分别发出中1—中7共7个中音音符,字母键q/w/e/r/t/y/u分别发出高1—高7共7个高音音符。按回车键退出程序。
assume CS:code ,DS:data
data segment
;A 到Z 26个字母所对应的频率,其中0的只是填充位置,并不计入计算
HzInOrder dw 261,196,164,329,659,349,392,440,0,493,0,0,246,220,0,0,523,698,293,783,987,174,587,146,880,130
data ends
code segment
start:
; set segment registers:
MOV ax, data
MOV ds, ax
Lop:
MOV AH,8
INT 21H ;获取单个字符,隐藏输入
MOV AH,0
MOV si,0
CMP Al,0DH ;如果是回车符则退出
JZ break
CALL Judge ;判断输入是否合法,不合法则跳到循环开始部分
SUB Al,41H; 将读入数据与大写A对应的ASCII码做减法
MOV si,ax
MOV AX,SI ;SI=SI*2
ADD SI,AX
MOV ax,0B6H
OUT 43H,ax ;初始化2号定时器
CALL DIVMOVE ;除法和输送数据
CALL MUSICON ;控制扬声器发声
CALL DELAY ;控制发声时间
CALL MUSICOFF ;取消发声
Loop Lop
break:
MOV ax, 4c00h ; 退出程序
INT 21h
;------------------------------------------------------------------------
;------------------------------------------------------------------------
;----判断输入是否合法
Judge proc
cmp Al,41H ;
jb Lop
cmp Al,5AH ;
ja Lop
cmp Al,49H ;
jz Lop
cmp Al,4FH ;
jz Lop
cmp Al,50H ;
jz Lop
cmp Al,4BH ;
jz Lop
cmp Al,4CH ;
jz Lop
RET
Judge endp
;------------------------------------------------------------------------
;------------------------------------------------------------------------
;------------------延迟一定时间
DELAY PROC
PUSH CX
MOV CX,10H;
DELAYLOOP1:
PUSH CX;
MOV CX,0FFFFH
DELAYLOOP2:
LOOP DELAYLOOP2
POP CX;
LOOP DELAYLOOP1
POP CX
RET
DELAY ENDP
;----------------------------------------------------------------------
;------------------------------------------------------------------------
;-----------------控制发声
MUSICON PROC
MOV AL,0
IN AL,61H
OR AL,03H
OUT 61H,AL
RET
MUSICON ENDP
;----------------------------------------------------------------------
;------------------------------------------------------------------------
;-----------------取消发声
MUSICOFF PROC
IN AL,61H
MOV AL,03H
AND AL,0FCH
OUT 61H,AL
RET
MUSICOFF ENDP
;----------------------------------------------------------------------
;------------------------------------------------------------------------
;---除法和输送数据
DIVMOVE PROC
PUSH AX
MOV ax,2870H
MOV dx,0012H
DIV word ptr HzInOrder[si] ;除法,低位放在ax,高位放在dx,商放在ax中
OUT 42H,al
MOV al,ah
OUT 42h,al ;分两次输送数据,先送低字节再送高字节
POP AX
RET
DIVMOVE ENDP
;----------------------------------------------------------------------
code ends
end start ; set entry point and stop the assembler.