汇编语言实现音乐播放器

目标程序

用汇编语言实现一个音乐播放器,并支持点歌

Overview

乐曲是按照一定的高低、长短和强弱关系组成的音调,在一首乐曲中,每个音符的音高和音长与频率和节拍有关,因此我们要分别为3首要演奏的乐曲定义一个频率表和一个节拍时间表。
请添加图片描述

利用8253/54定时器来驱动扬声器,在8253/54中的43端口送一个控制字0B6H,该控制字对定时器2进行初始化,使定时器2准备接收计数初值。在8253/54中的42H端口装入一个16位的计数值,以建立将要产生的发声频率。把输出端口61H的0、1两位置1,发出声音。

输入不同的数字,要播放相应的音乐。因此我们要利用输入的数字来获取歌曲的频率表地址和节拍时间表地址来播放对应音乐,利用直接定址表即可迎刃而解。

在CMOS RAM中存放着当前的时间,秒、分、时、日、月、年分别存放在0,2,4,7,8,9的单元中。这些数据以BCD码的方式存放,因此我们若要输出时间还需将他们转换为ASCII码才可正确输出。

更改界面颜色。在内存地址空间中,B8000H~BFFFFH共32KB的空间,为80*25彩色字符模式的显示缓冲区。一个字符占两个字节的存储空间,低位字节存储字符的ASCII码,高位字节存储字符的属性。属性字节的格式:7:BL闪烁 6、5、4:RGB背景色 3:I高亮 2、1、0:RGB前景色。更改属性字节即可更改界面颜色。

效果预览

初始界面

请添加图片描述

开始播放

请添加图片描述

结束播放

请添加图片描述

流程图

请添加图片描述

源码

;点歌系统:
;输入不同的数字,播放相应的音乐。
;其中“1”代表《刚好遇见你》音乐,“2”代表《成都》音乐,“3”代表《暧昧》音乐。
;输入数字“0”,则退出点歌系统。
;----------------------------------------------------
stack   segment para stack 'stack'
        db 100 dup ('?')
stack   ends
;----------------------------------------------------
data	segment para 'data'
tip0	db	'-----------------------------------','$'
tip1	db	'|  1: just met you-- Fei Yuqing   |','$' 
tip2	db	'|  2:    ChenDu   --  Zhao Lei    |','$' 
tip3	db	'|  3:   ambiguity -- Xue Zhiqian  |','$'
tip4	db	'|  0: exit                        |','$'
tip5	db	'  --please input your choice:      ','$'
tip		dw	tip0,tip1,tip2,tip3,tip4,tip0,tip5 ;界面
tip6	db	'music over!','$'
tip7	db	'begin:','$'
tip8	db	'end  :','$'
tip9	db	'You have exited successfully.','$'
tip10	db	'input error!please input again:','$'
time	db 'yy/mm/dd hh:mm:ss','$'				;输出时间的格式
table	db 9,8,7,4,2,0							;CMOS ROM中时间信息的存放单元

;----------------------------------------------------
;《刚好遇见你》
mus_freq1 dw 262,262,262
		  dw 262,220,524,440,440,440,392
		  dw 392,330,330,262,294,262,262
		  dw 262,220,524,587,524,524,440
		  dw 440,392,330,392,294,262,247
		  dw 262,220,524,440,440,440,392
		  dw 392,392,330,392,294,262,294
		  dw 262,247,262,262,262,294
		  dw 330,294,262,262,247,262,262
		  dw -1
mus_time1 dw 25,25,25
		  dw 25,25,25,25,50,25,25
		  dw 25,25,25,25,50,25,25
		  dw 25,25,25,25,50,25,25
		  dw 25,25,25,25,50,25,25
		  dw 25,25,25,25,50,25,25
		  dw 25,25,25,25,50,25,25
		  dw 25,12,12,100,25,25
		  dw 25,12,12,25,12,12,100
;---------------------------------------------------
;《成都》
mus_freq2 dw 196,262
		  dw 262,294,330
		  dw 392,330,330
		  dw 330,196
		  dw 262
		  dw 294,262,220
		  dw 196,196
		  dw 262,262,294,330
		  dw 440,330,392
		  dw 330,294
		  dw 262
		  dw 294,392
		  dw 330,294
		  dw 330,392
		  dw 392,330,392
		  dw 440,524,440
		  dw 330,294,262
		  dw 294,330,330
		  dw 196,392
		  dw 330,330
		  dw 294,262,262
		  dw 196,294,262
		  dw 330,294,262
		  dw 262
		  dw -1
mus_time2 dw 25,75
		  dw 50,12,12
		  dw 25,25,25
		  dw 25,50
		  dw 75
		  dw 25,25,25
		  dw 125,25
		  dw 75,50,12,12
		  dw 25,25,50
		  dw 25,25
		  dw 75
		  dw 50,25
		  dw 25,100
		  dw 25,75
		  dw 25,25,25
		  dw 25,25,75
		  dw 25,50,25
		  dw 50,25,125
		  dw 25,100
		  dw 25,25
		  dw 25,25,75
		  dw 25,50,25
		  dw 50,12,12
		  dw 200
;-------------------------------------------------
;《暧昧》
mus_freq3 dw 262,262,262,294,262
		  dw 392,440,330,330,294
		  dw 247,247,247,262,247
		  dw 330,392,247,294,262
		  dw 220,247,220,247,220
		  dw 330,349,262,220,247
		  dw 196,262,294,294
		  dw 349,330,330,294,262,294
		  dw 330,262,262,262,294,262
		  dw 392,440,330,330,294
		  dw 294,247,247,247,262,247
		  dw 330,392,247,294,262
		  dw 220,247,220,247,220
		  dw 330,349,220,262,247
		  dw 247,330,392,294,262
		  dw -1
mus_time3 dw 25,25,25,25,25
		  dw 25,100,25,25,100
		  dw 25,25,25,25,25
		  dw 25,100,25,25,100
		  dw 25,25,25,25,25
		  dw 25,100,25,25,75
		  dw 25,50,50,25
		  dw 50,25,25,25,50,25
		  dw 75,25,25,25,25,25
		  dw 25,100,25,25,25
		  dw 75,25,25,25,25,25
		  dw 25,100,25,25,100
		  dw 25,25,25,25,25
		  dw 25,100,25,25,25
		  dw 100,50,25,50,75
;---------------------------------------------------
;直接定址表
mus_time  dw mus_time1,mus_time2,mus_time3
mus_freq  dw mus_freq1,mus_freq2,mus_freq3
data ends
;----------------------------------------------------
code    segment para 'code'
        assume cs:code,ss:stack,ds:data
music   proc far
			
        mov ax,data
        mov ds,ax
        
        call tips;打印界面
               
		mov bh,00;第0页
        mov dh,06;第7行
        mov dl,42;第42列
        mov ah,02
        int 10h;设置光标位置
        
		mov ah,01
		int 21h;键盘输入并回显
		
input:	cmp al,30h;和'0'比较
		jb	end_error;调用end_error处理错误输入
		cmp al,33h;和'3'比较
		ja	end_error;调用end_error处理错误输入
		cmp al,30h;判断输入是否为'0'
		je	end_exit;调用end_exit退出程序
		
		sub al,30h;ASCII码转换为对应数字
		dec al;减一,因为地址从0开始
		mov ah,0;ax寄存器高位置0
		shl ax,1;每个地址数据占两个字节,向左移位实现*2
		mov di,ax;相对位移赋值给变地寄存器实现寄存器相对寻址
		mov si,mus_freq[di]
		mov bp,mus_time[di]
		
		
		mov ah,02
		mov dh,08
		mov dl,20
		int 10h;设置光标位置
		
		mov ah,09
		lea dx,tip7
		int 21h;显示输出
		
		push dx
		mov dh,08
		mov dl,26
		call timer;调用timer子程序显示开始播放时间,dh设置显示行数,dl设置显示列数
		pop dx
		
freq:
        mov     di,[si]
        cmp     di,-1
        je      end_mus;遇到-1时中止乐曲
        mov     bx,ds:[bp]
        call    soundf;调用发声子程序
        add     si,2
        add     bp,2
        jmp     freq
end_mus:
		mov bh,00
		mov dh,10
		mov dl,26
		mov ah,2
		int 10h;设置光标位置
		
		mov	ah,09
		lea dx,tip6
		int 21h;显示输出

		mov ah,02
		mov dh,11
		mov dl,20
		int 10h;设置光标位置
		
		mov ah,09
		lea dx,tip8
		int 21h;显示输出

		push dx
		mov dh,11
		mov dl,26
		call timer;调用timer程序显示结束时间
		pop dx
		
		jmp music_end;

end_exit:
		mov bh,00
		mov dh,09
		mov dl,20
		mov ah,02
		int 10h;设置光标位置
		
		mov ah,09
		lea dx,tip9
		int 21h;显示输出
		
		jmp music_end
		
end_error:
		mov ax,0b800h
		mov es,ax
		mov si,7*160+44*2
		mov byte ptr es:[si],20h;将输入处清空,以处理第二次仍然是错误的情况

		mov bh,00
		mov dh,07
		mov dl,12
		mov ah,02
		int 10h;设置光标位置
		
		mov ah,09
		lea dx,tip10
		int 21h;显示输出
		
		mov bh,00;第0页
        mov dh,07;第7行
        mov dl,44;第44列
        mov ah,02
        int 10h;设置光标位置
        
		mov ah,01
		int 21h;键盘输入并回显
		
		jmp input
		
music_end:
        mov     ax,4c00h
        int     21h
music   endp
;-----------------------------------------------------
;发声程序
soundf	proc far
        push ax
        push bx
        push cx
        push dx
        push di
        
        mov al,0b6h
        out 43h,al;对定时器2进行初始化
        mov dx,12h
        mov ax,348Ch;12348CH/DI中存放的给定频率得到声音计数值
        div di
        out 42h,al
        mov al,ah
        out 42h,al;分两次先后装入低8位和高8位的声音计数值
        in al,61h
        mov ah,al
        or al,3
        out 61h,al;将61h端口的数据0、1位置1,发声
        
WAIT1:  mov cx,4971;4971*15.08=0.07s
        call waitf;调用延迟程序
        dec bx
        jnz WAIT1

        mov al,ah
        out 61h,al;恢复接口的值
        
        pop di
        pop dx
        pop cx
        pop bx
        pop ax
        ret
soundf endp
;----------------------------------------------------
;时间延迟
waitf	proc far
		push ax
waitf1:
		in	al,61h
		and	al,10h
		cmp	al,ah
		je	waitf1
		
		mov	ah,al
		loop waitf1
		
		pop	ax
		ret
waitf	endp
;------------------------------------------------------
;打印界面 按预先设定的tip中的内容输出并更改背景颜色
tips	proc far
		push ax
		push ds
		push si
		push cx
	
		mov si,offset tip
		sub si,2
		mov cx,7
		mov al,-1
tipsf:

		mov bh,0
		inc al
		mov dh,al
		mov dl,12
		mov ah,2
		int 10h
		
		push ax
		add si,2
		mov dx,[si]
		mov ah,09
		int 21h
		pop ax


		loop tipsf
		
		mov ax,0b800h
		mov es,ax
		mov bp,0
		mov si,25
colorf:;改背景颜色
		mov byte ptr es:[bp+si],00110000B;颜色属性
		add si,2
		cmp si,95;控制改色区域的列的范围
		jb colorf
		add bp,160
		mov si,25
		cmp bp,160*6;控制改色区域为1-6行
		jb colorf
		
		pop cx
		pop si
		pop ds
		pop ax
		ret
		
tips	endp
;------------------------------------------------------
;显示当前时间,dh设置输出所在的行数,dl设置列数
timer proc far
		push ax
		push ds
		push si
		push di
		push cx
		push bx
	
		mov ax,data
		mov ds,ax
start:	mov si,offset table
		mov di,offset time
		
		mov cx,6
s1:		push cx
		mov al,ds:[si]
		out 70h,al;向70h写入要访问的单元的地址
		in al,71h;从71h中得到指定单元的数据
		
		mov ah,al
		mov cl,4
		shr	ah,cl;十位数码值
		add ah,30h;转换位ASCII码
		and al,00001111b;个位数码值
		add al,30h;转换位ASCII码
		mov ds:[di],ah
		mov ds:[di+1],al
		add di,3
		inc si
		pop cx		
		loop s1
		
		mov bh,0
		mov ah,2
		int 10h;根据预先指定的dh,dl设定光标位置
		
		mov dx,offset time
		mov ah,9
		int 21h;显示输出
		
		pop bx
		pop cx
		pop di
		pop si
		pop ds
		pop ax
		ret
timer endp
;------------------------------------------------------
code    ends
;---------------------------------------------------------
        end     music 

11b;个位数码值
		add al,30h;转换位ASCII码
		mov ds:[di],ah
		mov ds:[di+1],al
		add di,3
		inc si
		pop cx		
		loop s1
		
		mov bh,0
		mov ah,2
		int 10h;根据预先指定的dh,dl设定光标位置
		
		mov dx,offset time
		mov ah,9
		int 21h;显示输出
		
		pop bx
		pop cx
		pop di
		pop si
		pop ds
		pop ax
		ret
timer endp
;------------------------------------------------------
code    ends
;---------------------------------------------------------
        end     music 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/211862.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java Web——动态Web开发核心-Servlet

1. 官方文档 官方文档地址:Overview (Servlet 4.0 API Documentation - Apache Tomcat 9.0.83) servlet 与 Tomcat 的关系:Tomcat 支持 Servlet Tomcat 是一个开源的 Java 服务器,它主要用来提供 Web 服务,包括 HTTP 请求和响应…

<JavaEE> volatile关键字 -- 保证内存可见性、禁止指令重排序

目录 一、内存可见性 1.1 Java内存模型(JMM) 1.2 内存可见性演示 二、指令重排序 三、关键字 volatile 一、内存可见性 1.1 Java内存模型(JMM) 1)什么是Java内存模型(JMM)?Java内存模型即Java Memory Model,简…

【重点】【双指针】11. 盛最多水的容器

题目 注意&#xff1a;二维接雨水&#xff0c;有墙的&#xff0c;有线的&#xff0c;着这个属于线的。 class Solution {public int maxArea(int[] height) {if (height.length < 2) {return 0;}int left 0, right height.length - 1, res 0;while (left < right) {…

三轴加速度计LIS2DW12开发(2)----基于中断信号获取加速度数据

三轴加速度计LIS2DW12开发.2--轮基于中断信号获取加速度数据 概述视频教学样品申请生成STM32CUBEMX串口配置IIC配置CS和SA0设置INT1设置串口重定向参考程序初始换管脚获取ID复位操作BDU设置开启INT1中断设置传感器的量程配置过滤器链配置电源模式设置输出数据速率中断判断加速…

【动态规划】LeetCode-931.下降路径最小和

&#x1f388;算法那些事专栏说明&#xff1a;这是一个记录刷题日常的专栏&#xff0c;每个文章标题前都会写明这道题使用的算法。专栏每日计划至少更新1道题目&#xff0c;在这立下Flag&#x1f6a9; &#x1f3e0;个人主页&#xff1a;Jammingpro &#x1f4d5;专栏链接&…

深度学习记录--logistic回归函数的计算图

计算图用于logistic回归函数 先回顾一下单一样本的logistic回归损失函数的公式&#xff0c;公式如下&#xff1a; 将logistic函数用计算图表示出来(以两个基础量为例)&#xff0c;计算图如下&#xff1a; 前向传播已经完成&#xff0c;接下来完成后向传播 运用链式法则依次求…

Vue---Echarts

项目需要用echarts来做数据展示&#xff0c;现记录vue3引入并使用echarts的过程。 1. 使用步骤 安装 ECharts&#xff1a;使用 npm 或 yarn 等包管理工具安装 ECharts。 npm install echarts 在 Vue 组件中引入 ECharts&#xff1a;在需要使用图表的 Vue 组件中&#xff0c;引入…

如何选择适合的光电传感器与 STM32 微控制器进行接口设计

本文介绍了如何选择适合的光电传感器与 STM32 微控制器进行接口设计的方法。首先我们将介绍一些选择光电传感器的关键因素&#xff0c;包括测量范围、响应时间、分辨率和输出类型。然后我们将介绍如何根据所选传感器的特性进行硬件连接和接口设计。最后&#xff0c;我们将提供示…

20231201将RK3399的挖掘机开发板在Andorid12系统下的强制横屏

20231201将RK3399的挖掘机开发板在Andorid12系统下的强制横屏 2023/12/1 22:54 【不完美的地方&#xff1a;修改之后不满屏】 百度&#xff1a;rk3399 android12 横屏 不满屏 Android 显示不满屏 build.prop https://blog.csdn.net/weixin_39966398/article/details/105595184?…

9.ROS的TF坐标变换(三):坐标系关系查看与一个案例

1 查看目前的坐标系变化 我们先安装功能包&#xff1a; sudo apt install ros-melodic-tf2-tools安装成功&#xff01; 我们先启动上次的发布坐标变换的节点&#xff1a; liuhongweiliuhongwei-Legion-Y9000P-IRX8H:~/Desktop/final/my_catkin$ source devel/setup.bash liuho…

RocketMQ- 深入理解RocketMQ的消息模型

1、RocketMQ客户端基本流程 ​ RocketMQ基于Maven提供了客户端的核心依赖&#xff1a; <dependency><groupId>org.apache.rocketmq</groupId><artifactId>rocketmq-client</artifactId><version>4.9.5</version> </dependency&…

RxJava

Single 使用 Flowable 比较重一般使用Single onSubscribe 产生订阅时调用 线程切换1 2 发送顺序事件.just just 源码 钩子方法,进行验证再处理 Single 对象 订阅,RxJavaPlugins.onSubscribe 钩子方法,产生订阅和过滤 Single 核心方法,抽象的,实现为SingleJust 订阅和执行成功回…

同旺科技 USB TO SPI / I2C --- 调试W5500_Ping测试

所需设备&#xff1a; 内附链接 1、USB转SPI_I2C适配器(专业版); 首先&#xff0c;连接W5500模块与同旺科技USB TO SPI / I2C适配器&#xff0c;如下图&#xff1a; 设置寄存器&#xff1a; SHAR&#xff08;源MAC地址寄存器&#xff09;&#xff0c;该寄存器用来设置源MAC…

网络入门---网络编程初步认识和实践

目录标题 前言准备工作udpserver.hpp成员变量构造函数初始化函数(socket,bind)start函数(recvfrom) udpServer.ccudpClient.hpp构造函数初始化函数run函数(sendto) udpClient.cc测试 前言 在上一篇文章中我们初步的认识了端口号的作用&#xff0c;ip地址和MAC地址在网络通信时…

HuggingFace学习笔记--Prompt-Tuning高效微调

1--Prompt-Tuning介绍 Prompt-Tuning 高效微调只会训练新增的Prompt的表示层&#xff0c;模型的其余参数全部固定&#xff1b; 新增的 Prompt 内容可以分为 Hard Prompt 和 Soft Prompt 两类&#xff1b; Soft prompt 通常指的是一种较为宽泛或模糊的提示&#xff0c;允许模型在…

规则引擎专题---3、Drools组成和入门

Drools概述 drools是一款由JBoss组织提供的基于Java语言开发的开源规则引擎&#xff0c;可以将复杂且多变的业务规则从硬编码中解放出来&#xff0c;以规则脚本的形式存放在文件或特定的存储介质中(例如存放在数据库中)&#xff0c;使得业务规则的变更不需要修改项目代码、重启…

初识RocketMQ

1、简介 RocketMQ 是阿里巴巴在 2012 年开源的消息队列产品&#xff0c;用 Java 语言实现&#xff0c;在设计时参考了 Kafka&#xff0c;并做出了自己的一些改进&#xff0c;后来捐赠给 Apache 软件基金会&#xff0c;2017 正式毕业&#xff0c;成为 Apache 的顶级项目。Rocket…

avue-crud中时间范围选择默认应该是0点却变成了12点

文章目录 一、问题二、解决三、最后 一、问题 在avue-crud中时间范围选择&#xff0c;正常默认应该是0点&#xff0c;但是不知道怎么的了&#xff0c;选完之后就是一直是12点。具体问题如下动图所示&#xff1a; <template><avue-crud :option"option" /&g…

YOLOv8改进 | 2023 | SCConv空间和通道重构卷积(精细化检测,又轻量又提点)

一、本文介绍 本文给大家带来的改进内容是SCConv&#xff0c;即空间和通道重构卷积&#xff0c;是一种发布于2023.9月份的一个新的改进机制。它的核心创新在于能够同时处理图像的空间&#xff08;形状、结构&#xff09;和通道&#xff08;色彩、深度&#xff09;信息&#xf…

计算机组成原理笔记——存储器(静态RAM和动态RAM的区别,动态RAM的刷新, ROM……)

■ 随机存取存储器 ■ 1.随机存取存储器&#xff1a;按存储信息的原理不同分为&#xff1a;静态RAM和动态RAM 2.静态RAM&#xff08;SRAM&#xff09;&#xff1a;用触发器工作原理存储信息&#xff0c;但电源掉电时&#xff0c;存储信息会丢失具有易失性。 3.存储器的基本单元…