实验内容:
试设计一个程序,能够使用键盘中字母键模拟钢琴按键发音。其中,按照字母在键盘中的排列方 式,字母键 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 个高音音符。按 ESC 键退出程序。当按键按下时持续发音,当按键弹起时停止发音。
参考代码:
data segment
; 定义各音调频率,最后的0为了凑齐16字节
high_tone dw 524, 587, 659, 698, 784, 880, 988, 0 ;高音
middle_tone dw 262, 294, 330, 349, 392, 440, 494, 0 ;中音
low_tone dw 131, 147, 165, 175, 196, 220, 247, 0 ;低音
fref dw 0012H, 2870H ;基准频率
data ends
code segment
assume cs:code, ds:data
start:
mov ax, data
mov ds, ax
; 初始化
mov al, 0B6H
out 43H, al
endless_loop:
in al, 60H
; 如果Esc则退出程序
cmp al, 01H
je quit
; 大于90则是break码,停止发声
cmp al, 90H
jb get_offset
; 停止发声
and al, 0FCH
out 61H, al
jmp endless_loop
get_offset:
; 获取音调频率在内存中的偏移量
; si: 0高音 1中音 2低音
; al: 0~6对应Do~Si
mov si, 0
minus14:
cmp al, 16H
jle minus_end
sub al, 0EH
inc si
jmp minus14
minus_end:
sub al, 10H
; 如果小于0则不对,不能发声
cmp al, 0
jl endless_loop
; 通过si,al获取频率
mov cl, 4
shl si, cl
shl al, 1
mov ah, 0
mov bx, si
mov si, ax
mov cx, high_tone[bx][si]
mov dx, fref ; 基准频率高字节
mov ax, fref + 2 ; 基准频率低字节
div cx ; 基准频率除以音调频率
; 商分两次传送
out 42H, al
mov al, ah
out 42H, al
; 发声
or al, 03H
out 61H, al
jmp endless_loop
quit:
; 停止发声并结束程序
and al, 0FCH
out 61H, al
mov ax, 4C00H
int 21H
code ends
end start