📄 pc4.asm
字号:
;/*-------------------------------------------------------------------------------------------*/
;数据段定义
data segment ;数据定义段
assume ds:data ;建立数据段寄存器寻址
msg_1 db '<<---Welcome you to this OS.--->> $',0dh,0ah ;定义字节
msg_2 db 0dh,0ah,'In this OS. you can press below keys to enjoy:$'
msg_3 db 0dh,0ah,'Super Low: q-w-e-r-t-y-u$'
msg_4 db 0dh,0ah,' Low: a-s-d-f-g-h-j$'
msg_5 db 0dh,0ah,' Mid: z-x-c-v-b-n-m$'
msg_6 db 0dh,0ah,' Hig: 1-2-3-4-5-6-7$'
msg_7 db 0dh,0ah,'Anytime you can press ''Esc'' or ''Enter'' to exit.$'
msg_8 db 0dh,0ah,'What''s more, you can press ''p'' to play music!$'
msg_9 db 0dh,0ah,' $'
note_t dw 131,147,165,175,196,220,247 ;超低音
dw 262,294,330,349,392,440,494 ;低音
dw 523,587,659,698,784,880,988 ;中音
dw 1046,1175,1318,1397,1568,1760,1975 ;高音
dw 0 ;休止符0
; '1','2','3','4','5','6','7' ;从低到高
key_t db 'q','w','e','r','t','y','u' ;超低音
db 'a','s','d','f','g','h','j' ;低音
db 'z','x','c','v','b','n','m' ;中音
db '1','2','3','4','5','6','7' ;高音
db '0' ;休止符0
music_n db 'g','c','x','z','g','0','g','h','g','c','x','z'
db 'h','0','h','a','h','v','c','x','j','g','b','b','v','x','c','z'
db 'g','c','x','z','g','0','g','h','g','c','x','z','h','v','c','x'
db 'b','b','b','b','n','b','v','x','z'
db 'c','c','c','c','c','c','c','b','z','x','c'
db 'v','v','v','v','c','c','c','x','x','z','x','b'
db 'c','c','c','c','c','c','c','b','z','x','c'
db 'v','v','v','v','c','c','b','b','v','x','z',0
music_d db 4, 4, 4, 4, 8, 4, 2, 2, 4, 4, 4, 4
db 8, 4, 2, 2, 4, 4, 4, 4, 8, 8, 4, 4, 4, 4, 8, 4
db 4, 4, 4, 4, 8, 4, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4
db 4, 4, 4, 4, 4, 4, 4, 4, 16
db 4, 4, 8, 4, 4, 8, 4, 4, 4, 2, 16
db 4, 4, 8, 4, 4, 8, 4, 4, 4, 4, 8, 8
db 4, 4, 8, 4, 4, 8, 4, 4, 4, 2, 16
db 4, 4, 8, 4, 4, 8, 4, 4, 4, 4, 16
jiepai db ? ;节拍变量定义
speed db 0 ;播放速度控制
jiange db 1 ;音符间隔停顿时间
data ends ;数据定义段结束
;/*-------------------------------------------------------------------------------------------*/
;/*-------------------------------------------------------------------------------------------*/
;代码段定义
code segment ;代码定义段
assume cs:code ;建立代码段寄存器寻址
;/*-------------------------------------------------------------------------------------------*/
;/*-------------------------------------------------------------------------------------------*/
;字符显示
show macro str ;宏定义,输入参数:字符串str
lea dx,str ;装入str的有效地址
mov ah,09h ;调用中断21,09h显示字符串
int 21h
endm ;宏定义结束
;/*-------------------------------------------------------------------------------------------*/
;/*-------------------------------------------------------------------------------------------*/
;主函数
main proc far ;主函数过程定义
mov ax,data ;取数据段地址
mov ds,ax ;装载数据段寄存器ds,使之指向当前数据段
show msg_1 ;调用宏,显示字符串
show msg_2
show msg_3
show msg_4
show msg_5
show msg_6
show msg_7
show msg_8
show msg_9
mov bx,0 ;设定查表数组下标初值
mov al,6
;/*-------------------------------------------------------------------------------------------*/
;/*-------------------------------------------------------------------------------------------*/
;按键扫描
key_scan:
mov jiepai,6 ;初始化节拍
mov bx,0000h ;初始化指针
mov ah, 00h ;利用bios的16号中断,扫描键盘按键
int 16h ;AL中返回按键的ASCII码,AH中返回按键的扫描码
cmp al, 0dh ;判断是否为Enter键
jz exit ;是回车键就退出
cmp al, 1bh ;判断是否为Esc键
jz exit ;是退出键就退出
cmp al, 'p' ;判断是否为p键
jz play ;是p键就play music
lookup:
cmp key_t[bx],al ;取出对应频率值
je next
inc bx ;指针+1
jmp lookup
next:
shl bx,1 ;指针×2,计算频率表指针
mov cx,note_t[bx] ;取得对应数组下标值的频率值
call beep ;调用固定频率子程序
jmp key_scan ;否则继续扫描
;/*-------------------------------------------------------------------------------------------*/
;/*-------------------------------------------------------------------------------------------*/
;音乐播放
play: mov bx,0
next3: mov al,music_n[bx] ;取出music频率值
push ax
mov al,music_d[bx] ;取出music节拍
mov jiepai,al
pop ax
cmp al, 0 ;是否为音乐结束标志符
je key_scan ;是则退出play
push bx ;保存bx,bx为music频率指针
mov bx,0
look1: cmp key_t[bx],al ;查表取出对应频率值的指针bx
je next1 ;找到就beep
inc bx ;指针+1
and bx,0ffh
jmp look1 ;未找到则继续查找
next1:
shl bx,1 ;指针×2,计算频率表指针
mov cx,note_t[bx] ;取得对应数组下标值的频率值
cmp cx,0
je next4
call beep ;调用固定频率子程序
call pause ;调用停顿时间
pop bx ;获得music指针
inc bx ;继续取得下一个音符
jmp next3
next4: call nobeep
call pause ;调用停顿时间
pop bx ;获得music指针
inc bx ;继续取得下一个音符
jmp next3
;/*-------------------------------------------------------------------------------------------*/
;/*-------------------------------------------------------------------------------------------*/
;退出
exit:
mov ah,4ch ;调用中断21,4ch退出系统
int 21h
;/*-------------------------------------------------------------------------------------------*/
;/*-------------------------------------------------------------------------------------------*/
main endp ;主函数过程结束
;/*-------------------------------------------------------------------------------------------*/
;/*-------------------------------------------------------------------------------------------*/
;固定频率响
beep proc near
mov dx,0012h
mov ax,34dch
div cx ;ax为所得分频值
out 42h,al ;输出频率值,低8位
mov al,ah
out 42h,al ;输出频率值,高8位
call spk_on ;开启蜂鸣器
mov ah,00h ;取时钟计数值
int 1ah
mov al,jiepai ;18.2次为1000ms, 2次约为100ms
add al,speed
cbw ;al值转为16位ax
add ax,dx ;加上当前时钟计数值,得到计数终值
mov bx,ax ;计数终值置入bx
delay1: mov ah,00h
int 1ah ;取时钟计数值
cmp bx,dx ;到终值吗?
jnz delay1 ;未到,继续延时
call spk_off ;关闭蜂鸣器
ret
beep endp
;/*-------------------------------------------------------------------------------------------*/
;/*-------------------------------------------------------------------------------------------*/
;休止符延迟时间
nobeep proc near
call spk_off ;关闭蜂鸣器
mov ah,00h ;取时钟计数值
int 1ah
mov al,jiepai ;18.2次为1000ms, 2次约为100ms
add al,speed
cbw ;al值转为16位ax
add ax,dx ;加上当前时钟计数值,得到计数终值
mov bx,ax ;计数终值置入bx
delay2: mov ah,00h
int 1ah ;取时钟计数值
cmp bx,dx ;到终值吗?
jnz delay2 ;未到,继续延时
ret
nobeep endp
;/*-------------------------------------------------------------------------------------------*/
;/*-------------------------------------------------------------------------------------------*/
;音符间隔停顿时间
pause proc near
call spk_off ;关闭蜂鸣器
mov ah,00h ;取时钟计数值
int 1ah
mov al,jiange ;18.2次为1000ms, 2次约为100ms
cbw ;al值转为16位ax
add ax,dx ;加上当前时钟计数值,得到计数终值
mov bx,ax ;计数终值置入bx
delay3: mov ah,00h
int 1ah ;取时钟计数值
cmp bx,dx ;到终值吗?
jnz delay3 ;未到,继续延时
ret
pause endp
;/*-------------------------------------------------------------------------------------------*/
;/*-------------------------------------------------------------------------------------------*/
;开启蜂鸣器
spk_on proc near
push ax
in al,61h
or al,03h
out 61h,al
pop ax
ret
spk_on endp
;/*-------------------------------------------------------------------------------------------*/
;/*-------------------------------------------------------------------------------------------*/
;关闭蜂鸣器
spk_off proc near
push ax
in al,61h
and al,0fch
out 61h,al
pop ax
ret
spk_off endp
;/*-------------------------------------------------------------------------------------------*/
;/*-------------------------------------------------------------------------------------------*/
code ends ;代码段结束
end main ;主程序结束
;/*-------------------------------------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -