📄 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 'h','c','j','h','z','x','z','c','h','n','b','n','b','x','v','c','c','h','n','b','n','b','x','c','z'
db 'h','c','x','j','h','h','c','j','j','h','z','x','z','c','h','n','b','n','b','x','v','c'
db 'h','n','b','x','c','v','c','x','z','h','x','z','j','h','h','j','z','x','c','z','j','g','h','z','x','c','c','h'
db 'j','z','x','c','z','j','g','h','z','x','z','z','h','j','z','x','c','z','j','g','h','z','x','c','c','c','h','j','z','x','c','z','j','g'
db 'h','z','x','x','z','z','z','z','x','c','z','j','g','z','j','h','j','h',0
music_d db 8, 8, 16, 4, 4, 4, 4, 16, 8, 8, 4, 4, 4, 4, 4, 4, 16, 8, 8, 4, 4, 4, 4, 16, 16
db 8, 8, 8, 4, 64, 8, 8, 8, 4, 4, 4, 4, 4, 16, 8, 8, 4, 4, 4, 4, 4
db 8, 8, 4, 4, 4, 4, 8, 8, 16, 8, 8, 8, 4, 32, 4, 4, 4, 4, 4, 4, 8, 8, 4, 4, 4, 4, 8, 4
db 4, 4, 4, 4, 4, 8, 8, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 8, 8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8
db 4, 2, 2, 4, 4, 16, 4, 2, 2, 4, 4, 8, 8, 8, 8, 8, 4, 64
jiepai db ? ;节拍变量定义
speed db 2 ;播放速度控制
jiange db 0 ;音符间隔停顿时间
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 + -