1个回答
展开全部
; 本程序通过编译,运行正确
Code Segment
Assume CS:Code,DS:Code
CR equ 000DH
LF equ 000AH
; -----------------------------------------
; 功能:显示指定地址(Str_Addr)的字符串
; 入口:
; Str_Addr=字符串地址(要求在数据段)
; 用法: Output Str_Addr
; 用法举例:Output PromptStr
Output MACRO Str_Addr
push ax
lea dx,Str_Addr
mov ah,9
int 21h
pop ax
EndM
; -----------------------------------------
; 入口参数
; SI=声音频率地址
; bx=时间节拍地址
Do_Music Proc Near
push dx
push cx
push ax
@@Sound: test word ptr [si],0ffffh
jz @@Return
mov al,0b6h ;向计数器写控制字
out 43h,al ;方式3、双字节写和二进制计数方式写到控制口
mov dx,12h ;设置被除数
mov ax,533h*896
div word ptr [si] ;其商ax为预置值
out 42h,al ;先送LSB
mov al,ah
out 42h,al ;后送MSB
in al,61h ;读端口原值
mov ah,al
or al,3
out 61h,al ;接通扬声器
mov cx,[bx]
@@Waitf1: push cx
mov cx,28010 ;设循环次数为8ff0h
@@delay1: loop @@delay1
pop cx ;循环持续cx次,即传进来的节拍时间
loop @@Waitf1
inc si
inc si ;下一个频率值
inc bx
inc bx ;下一个节拍值
mov al,ah ;写回61h端口值,关闭扬声器
out 61h,al ;关闭扬声器
jmp @@Sound
@@Return: pop ax
pop cx
pop dx
ret
Do_Music EndP
; -----------------------------------------
; 音乐菜单
Music_Str db '***********************************',CR,LF
db '1. Mary had a little lamb',CR,LF ;玛丽有只小羊羔
db '2. Christmas ring',CR,LF ;圣诞铃声
db '3. Little Starlet',CR,LF ;小星星
db '4. Little bee',CR,LF ;小蜜蜂
db '0. Exit',CR,LF ;结束程序
db '***********************************',CR,LF
db 'Please choose the music you want:$' ;提示选择乐曲
Prompt_Str db CR,LF,CR,LF ;音乐播放前的提示信息
db CR,LF,' Now,playing the music which you chose ^_^ please waiting...'
db CR,LF,CR,LF,0eh,'...$'
; 以下为对应各乐曲的频率表和节拍时间表
merry_freq dw 330,294,262,294,3 dup(330),3 dup(294),330,392,392
dw 330,294,262,294,4 dup(330),294,294,330,294,262,0
merry_time dw 6 dup(25*400),50*400,2 dup(25*400,25*400,50*400),12 dup(25*400),100*400
christ_freq dw 7 dup(330),392,262,294,330,4 dup(349),2 dup(330),330,294,294,262,294,392
dw 7 dup(330),392,262,294,330,4 dup(349),2 dup(330),392,392,349,294,262,0
christ_time dw 2 dup(25*400,25*400,50*400),4 dup(25*400),100*400,2 dup(25*400,25*400,50*400)
dw 4 dup(25*400),2 dup(50*400),2 dup(25*400,25*400,50*400)
dw 4 dup(25*400),100*400,2 dup(25*400,25*400,50*400),4 dup(25*400),100*400
star_freq dw 262,262,392,392,440,440,392,349,349,330,330,294,294,262
dw 2 dup(392,392,349,349,330,330,294)
dw 262,262,392,392,440,440,392,349,349,330,330,294,294,262,0
star_time dw 3 dup(6 dup(25*400),50*400,6 dup(25*400),50*400)
bee_freq dw 392,330,330,349,294,294,262,294,330,349,4 dup(392),330,330,349,294,294
dw 262,330,392,392,3 dup(330),5 dup(294),330,349,5 dup(330),349,392
dw 392,330,330,349,294,294,262,330,392,392,262,0
bee_time dw 2 dup(25*400,25*400,50*400),4 dup(25*400),3 dup(25*400,25*400,50*400)
dw 3 dup(6 dup(25*400),50*400)
dw 2 dup(25*400,25*400,50*400),4 dup(25*400),100*400
; 乐曲频率和节拍时间地址表
Music_Table dw merry_freq,merry_time,christ_freq,christ_time,star_freq,star_time,bee_freq,bee_time
Cursor_Tmp dw ? ;音乐菜单光标位置
Start: push cs
pop ds
push cs
pop es ;使数据段、附加段与代码段同段
Output Music_Str ;显示音乐菜单
xor bx,bx
mov ah,3 ;取光标位置
int 10h
mov Cursor_Tmp,dx ;保存音乐菜单光标位置
Choise_Item: mov dx,Cursor_Tmp ;取音乐菜单光标位置
xor bx,bx
mov ah,2 ;设置光标位置
int 10h
@@Read_Chr: mov ah,1
int 21h
cmp al,'0'
jb @@Read_Chr
cmp al,'4'
ja @@Read_Chr
and al,0fh
test al,0ffh
jz Exit_Proc
dec al
cbw
shl ax,1
shl ax,1
mov di,ax
Output Prompt_Str ;显示音乐播放前的提示信息
mov si,Music_Table[di] ;对应的频率值地址
mov bx,Music_Table[di][2] ;对应的节拍值地址
call Do_Music ;激活扬声器,使之发出指定频率、指定时长的声音,奏乐
xor bx,bx
mov ah,8 ;度光标位置的字符和属性
int 10h
mov bh,ah ;字符属性
mov cx,Cursor_Tmp
inc ch
xor cl,cl
mov dh,ch
add dh,6
mov dl,79
mov ax,606h ;显示内容上滚
int 10h
jmp Choise_Item
Exit_Proc: mov ah,4ch ;结束程序
int 21h
Code ENDS
END Start ;编译到此结束
Code Segment
Assume CS:Code,DS:Code
CR equ 000DH
LF equ 000AH
; -----------------------------------------
; 功能:显示指定地址(Str_Addr)的字符串
; 入口:
; Str_Addr=字符串地址(要求在数据段)
; 用法: Output Str_Addr
; 用法举例:Output PromptStr
Output MACRO Str_Addr
push ax
lea dx,Str_Addr
mov ah,9
int 21h
pop ax
EndM
; -----------------------------------------
; 入口参数
; SI=声音频率地址
; bx=时间节拍地址
Do_Music Proc Near
push dx
push cx
push ax
@@Sound: test word ptr [si],0ffffh
jz @@Return
mov al,0b6h ;向计数器写控制字
out 43h,al ;方式3、双字节写和二进制计数方式写到控制口
mov dx,12h ;设置被除数
mov ax,533h*896
div word ptr [si] ;其商ax为预置值
out 42h,al ;先送LSB
mov al,ah
out 42h,al ;后送MSB
in al,61h ;读端口原值
mov ah,al
or al,3
out 61h,al ;接通扬声器
mov cx,[bx]
@@Waitf1: push cx
mov cx,28010 ;设循环次数为8ff0h
@@delay1: loop @@delay1
pop cx ;循环持续cx次,即传进来的节拍时间
loop @@Waitf1
inc si
inc si ;下一个频率值
inc bx
inc bx ;下一个节拍值
mov al,ah ;写回61h端口值,关闭扬声器
out 61h,al ;关闭扬声器
jmp @@Sound
@@Return: pop ax
pop cx
pop dx
ret
Do_Music EndP
; -----------------------------------------
; 音乐菜单
Music_Str db '***********************************',CR,LF
db '1. Mary had a little lamb',CR,LF ;玛丽有只小羊羔
db '2. Christmas ring',CR,LF ;圣诞铃声
db '3. Little Starlet',CR,LF ;小星星
db '4. Little bee',CR,LF ;小蜜蜂
db '0. Exit',CR,LF ;结束程序
db '***********************************',CR,LF
db 'Please choose the music you want:$' ;提示选择乐曲
Prompt_Str db CR,LF,CR,LF ;音乐播放前的提示信息
db CR,LF,' Now,playing the music which you chose ^_^ please waiting...'
db CR,LF,CR,LF,0eh,'...$'
; 以下为对应各乐曲的频率表和节拍时间表
merry_freq dw 330,294,262,294,3 dup(330),3 dup(294),330,392,392
dw 330,294,262,294,4 dup(330),294,294,330,294,262,0
merry_time dw 6 dup(25*400),50*400,2 dup(25*400,25*400,50*400),12 dup(25*400),100*400
christ_freq dw 7 dup(330),392,262,294,330,4 dup(349),2 dup(330),330,294,294,262,294,392
dw 7 dup(330),392,262,294,330,4 dup(349),2 dup(330),392,392,349,294,262,0
christ_time dw 2 dup(25*400,25*400,50*400),4 dup(25*400),100*400,2 dup(25*400,25*400,50*400)
dw 4 dup(25*400),2 dup(50*400),2 dup(25*400,25*400,50*400)
dw 4 dup(25*400),100*400,2 dup(25*400,25*400,50*400),4 dup(25*400),100*400
star_freq dw 262,262,392,392,440,440,392,349,349,330,330,294,294,262
dw 2 dup(392,392,349,349,330,330,294)
dw 262,262,392,392,440,440,392,349,349,330,330,294,294,262,0
star_time dw 3 dup(6 dup(25*400),50*400,6 dup(25*400),50*400)
bee_freq dw 392,330,330,349,294,294,262,294,330,349,4 dup(392),330,330,349,294,294
dw 262,330,392,392,3 dup(330),5 dup(294),330,349,5 dup(330),349,392
dw 392,330,330,349,294,294,262,330,392,392,262,0
bee_time dw 2 dup(25*400,25*400,50*400),4 dup(25*400),3 dup(25*400,25*400,50*400)
dw 3 dup(6 dup(25*400),50*400)
dw 2 dup(25*400,25*400,50*400),4 dup(25*400),100*400
; 乐曲频率和节拍时间地址表
Music_Table dw merry_freq,merry_time,christ_freq,christ_time,star_freq,star_time,bee_freq,bee_time
Cursor_Tmp dw ? ;音乐菜单光标位置
Start: push cs
pop ds
push cs
pop es ;使数据段、附加段与代码段同段
Output Music_Str ;显示音乐菜单
xor bx,bx
mov ah,3 ;取光标位置
int 10h
mov Cursor_Tmp,dx ;保存音乐菜单光标位置
Choise_Item: mov dx,Cursor_Tmp ;取音乐菜单光标位置
xor bx,bx
mov ah,2 ;设置光标位置
int 10h
@@Read_Chr: mov ah,1
int 21h
cmp al,'0'
jb @@Read_Chr
cmp al,'4'
ja @@Read_Chr
and al,0fh
test al,0ffh
jz Exit_Proc
dec al
cbw
shl ax,1
shl ax,1
mov di,ax
Output Prompt_Str ;显示音乐播放前的提示信息
mov si,Music_Table[di] ;对应的频率值地址
mov bx,Music_Table[di][2] ;对应的节拍值地址
call Do_Music ;激活扬声器,使之发出指定频率、指定时长的声音,奏乐
xor bx,bx
mov ah,8 ;度光标位置的字符和属性
int 10h
mov bh,ah ;字符属性
mov cx,Cursor_Tmp
inc ch
xor cl,cl
mov dh,ch
add dh,6
mov dl,79
mov ax,606h ;显示内容上滚
int 10h
jmp Choise_Item
Exit_Proc: mov ah,4ch ;结束程序
int 21h
Code ENDS
END Start ;编译到此结束
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询