汇编课程设计:音乐播放器详解

程序说明:
这是一个音乐程序,按大写字母“A”,唱乐曲“玛丽有只小羔羊”;
按大写字母“B”,唱乐曲“太湖船”
按大写字母“C”,唱乐曲“祝福歌”
按"X"鍵,退出
函数图:
音乐播放器流程图

DATA      SEGMENT PARA 'DATA'	;数据段
								;数据对齐到para,1 para=16
								;相当于段首址
								;link过程中,同一程序的不同模块中, 相同组合名的段会组合到一起
INFO1     DB 0DH,0AH,'WELCOME YOU TO COME HERE!$'	;显示信息
INFO2     DB 0DH,0AH,'this is a music program!$'
INFO3     DB 0DH,0AH,'please select!$'
INFO4     DB 0DH,0AH,'INPUT ERROR!$'
INFO5     DB 0DH,0AH,'PLEASE INPUT AGAIN!$'
MUSLIST   DB 0DH,0AH,'A MUSIC1'
          DB 0DH,0AH,'B MUSIC2'
          DB 0DH,0AH,'C MUSIC3'
          DB 0DH,0AH,'Q EXIT'
          db 0dh,0ah,'$'
MUS_FREG1 DW 330,294,262,294,3 DUP (330)	;音乐频率表
          DW 3 DUP (294),330,392,392
          DW 330,294,262,294,4 DUP (330)
          DW 294,294,330,294,262,-1
MUS_TIME1 DW 6 DUP (25*8),50*8				;音乐节拍表
          DW 2 DUP (25*8,25*8,50*8)
          DW 12 DUP (25*8),100*8

MUS_FREG2 DW 330,392,330,294,330,392,330,294,330
          DW 330,392,330,294,262,294,330,392,294
          DW 262,262,220,196,196,220,262,294,332,262,-1
MUS_TIME2 DW 3 DUP(50),25,25,50,25,25,100
          DW 2 DUP(50,50,25,25),100
          DW 3 DUP(50,25,25),100

MUS_FREG3 DW 262,262,294,262,349
          DW 330,262,262,294,262
          DW 392,349,262,262,523
          DW 440,349,262,262,466
          DW 466,440,262,392,349,-1
        
MUS_TIME3 DW 50,50,100,100,100
          DW 100,100,50,50,100,100
          DW 100,100,100,50,50,100
          DW 100,100,100,100,100,50
          DW 50,100,100,100,100,100
DATA      ENDS

STACK     SEGMENT PARA STACK 'STACK'	;堆栈段
          DB 200 DUP ('STACK')
STACK     ENDS

CODE      SEGMENT		;代码段
          ASSUME DS:DATA,SS:STACK,CS:CODE
MAIN      PROC FAR		;跨间调用main
						;系统把主程序当作DOS调用的一个子程序
						;DOS内核与主程序不是在同一个段地址内
						;所以主程序参数要用far
          MOV AX,DATA	
          MOV DS,AX		;把data放到数据段中
          MOV aH, 0		;终止进程
          MOV AL,4		
          INT 10H		
          MOV AH,0BH	;检测键盘状态
          MOV BH,0		
          MOV BL,4
          INT 10H
          MOV AH,0BH	;检测键盘状态
          MOV BH,01H	
          MOV BL,00
          INT 10H
;*****定义一个宏*****
SHOW      MACRO b		;输出字符串b,show为宏名
          LEA DX,b		
          MOV AH,9
          INT 21H
          ENDM
;**********************
          show INFO1	
          show INFO2	
          show INFO3	
          show MUSLIST
INPUT:    MOV AH,01H	
          INT 21H
          CMP AL,'Q'
          JZ retu
          CMP AL,'A'
          JNZ B0
          CALL MUSIC1	;跳转子函数MUSIC1
          JMP EXIT1
B0:       CMP AL,'B'
          JNZ C0
          CALL MUSIC2	;跳转子函数MUSIC2
          JMP EXIT1
C0:       CMP AL,'C'
          JNZ exit
          CALL MUSIC3	;跳转子函数MUSIC3
EXIT1:    show INFO5
          JMP INPUT 
EXIT:     
          call clear	;跳转子函数clear
          show INFO4
          show INFO5
          show INFO1
          show INFO2
          show INFO3
          show MUSLIST
          jmp input
RETU:     MOV AH,4CH
          INT 21H
MAIN ENDP 

MUSIC1    PROC NEAR
          PUSH DS
          SUB AX,AX
          PUSH AX
          LEA SI,MUS_FREG1	;频率的地址赋给si
          LEA BP,DS:MUS_TIME1	;节拍的地址赋给bp
FREG1:     MOV DI,[SI]		
          CMP DI,-1			;-1是频率的结束标志
          JE END_MUS1		;zf=0时跳转
          MOV DX,DS:[BP]	
          MOV BX,1400		
          CALL GENSOUND		;跳转gensound
          ADD SI,2			
          ADD BP,2			
          JMP FREG1					
END_MUS1:
          RET
MUSIC1    ENDP

;实现音乐的播放函数
GENSOUND PROC NEAR
          PUSH AX		;保护现场
          PUSH BX
          PUSH CX
          PUSH DX
          PUSH DI
          MOV AL,0B6H	;初始化控制字
          OUT 43H,AL	;将al写入端口43h,程序中断计时器
          MOV DX,12H	
          MOV AX,533H*896	;计算非896hz的声音的计数值。
          					;其它频率声音的时间计数值应为:
							;533H×896÷给定频率=123280H÷给定频率	
          DIV DI					
          OUT 42H,AL	;将al写入端口42h,磁带或者扩音器的程序中断计时器
          				;8253中的42端口送一个控制字0B6H(10110110B)
          				;该控制字对定时器2进行初始化,使定时器2准备接收计数初值
          MOV AL,AH		
          OUT 42H,AL	;传入时间计数值
          IN AL,61H		;al从61h端口中读取,扬声器端口
          MOV AH,AL
          OR AL,3		;逻辑或运算(3要进行二进制运算,也就是0011)把输出端口61H的PB0、PB1两位 置1,发出声音
          OUT 61H,AL	;将al写入端口61h

WAIT1:    MOV CX,8FF0H	;相当于不断分配cpu时钟周期,使播放能够完成
DELAY1:   LOOP DELAY1	;循环是bx不断减少
          DEC BX		
          JNZ WAIT1		;bx不为0就跳到wait1,等待bx*8ff0h*loop使用的cpu时钟周期
          MOV AL,AH		
          OUT 61H,AL	
          POP DI		;恢复现场
          POP DX
          POP CX
          POP BX
          POP AX
          RET
GENSOUND ENDP

MUSIC2    PROC NEAR
          PUSH DS
          SUB AX,AX
          PUSH AX
          LEA SI,MUS_FREG2
          LEA BP,DS:MUS_TIME2
FREG2:    MOV DI,[SI]
          CMP DI,-1
          JE END_MUS2
          MOV DX,DS:[BP]
          MOV BX,1400
          CALL GENSOUND
          ADD SI,2
          ADD BP,2
          JMP FREG1
END_MUS2:
          RET
MUSIC2    ENDP
MUSIC3    PROC NEAR
          PUSH DS
          SUB AX,AX
          PUSH AX
          LEA SI,MUS_FREG3
          LEA BP,DS:MUS_TIME3
FREG3:    MOV DI,[SI]
          CMP DI,-1
          JE END_MUS3
          MOV DX,DS:[BP]
          MOV BX,1400
          CALL GENSOUND
          ADD SI,2
          ADD BP,2
          JMP FREG1
END_MUS3:
          RET
MUSIC3    ENDP
;输错了的情况
clear proc near
      push ax
      push bx
      push cx
      push dx
      mov  ah,6		;直接控制台i/o,输出dl中ascii码对应的字符
      mov al,0		;初始化各种参数
      mov ch,0
      mov cl,0
      mov dh,24
      mov dl,79
      mov bh,7
      int 10h
      pop dx
      pop cx
      pop bx
      pop ax
      ret
clear endp
CODE      ENDS
          END MAIN

参数传递
本题无参数传递

中断向量计算
中断向量:
本题用到了10H、21H函数库的函数调用,入口地址为0:40h ,0:84h。
10H号函数库:CS=410h+2h=42h , IP=410h=40h 。中断向量为0:40H。
21H号函数库:CS=421h+2h=86h , IP=421h=84h 。中断向量为0:84h。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

飞行模式HR

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值