📄 piano.asm
字号:
stack segment
db 64 dup('stack...')
stack ends
;****************************************************************************
dseg segment
table dw 220 ;A3
dw 247 ;B3
dw 262 ;C4
dw 294 ;D4
dw 330 ;E4
dw 349 ;F4
dw 392 ;G4
dw 440 ;A4
dw 494 ;B4
dw 523 ;C5
eromsg db 0ah,0dh,'your input error!',0ah,0dh,'$'
welcome db 'Press 0-9 to produce A3-C5 and Press "." to exit!',0dh,0ah,'$'
dseg ends
;****************************************************************************
cseg segment
assume cs:cseg,ds:dseg,ss:stack
;----------------------------------------------------------------------------
main proc far
mov ax,dseg
mov ds,ax
lea dx,welcome ;输出提示
mov ah,9
int 21h
new_note:
mov ah,1 ;调用21号中断1号功能
int 21h
cmp al,'.'
je exit ;若输入字符为'.',则结果程序
cmp al,'0'
jb error ;若输出字符的ASCII小于字符'0',则输出错误提示
cmp al,'9'
ja error ;若输出字符的ASCII大于字符'9',则输出错误提示
sub al,30h ;(al)-=30h,将al中的内容转换成输出的数字
and ah,00h
mov bl,2
mul bl ;(ax)=(ax)*2
mov bx,ax
mov di,table[bx] ;从table表中获取本次音的频率
mov bx,100 ;设定音长
call soundf
jmp new_note
error:
lea dx,eromsg
mov ah,09
int 21h
jmp new_note
exit:
mov ah,4ch
int 21h
main endp
;****************************************************************************
;发声控制
soundf proc near
mov al,0b6h ;将计数器2设定为模式3
out 43h,al ;将al写入8253/54的控制寄存器
mov dx,12h ;设置8253/54的时钟输入频率
mov ax,348ch
div di ;根据给定的频率,应用12348ch/di来算得装入计数器2的数值
out 42h,al ;先将(al)写入CLK2的低位
mov al,ah
out 42h,al ;再将(ah)写入CLK2的高位
in al,61h ;将端口61h置数
mov ah,al ;保存端口61h的初始状态
or al,3
out 61h,al ;给61h的第0,1位置1,打开扬声器
back: mov cx,2000 ;633=10ms
call waitf
dec bx
jnz back
mov al,ah
out 61h,al ;恢复端口61h的初态
ret
soundf endp
;**********************************************
;延时15.08us
waitf proc near
push ax
waitf1:
in al,61h
and al,10h
cmp al,ah
je waitf1
mov ah,al
loop waitf1
pop ax
ret
waitf endp
cseg ends
end main
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -