汇编实验——乐曲程序(两只老虎)

2024-02-08 12:32

本文主要是介绍汇编实验——乐曲程序(两只老虎),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

       首先需要知道的是PC机是通过什么来发声的,8255(A)可编程序外围接口芯片(PPI)。PPI有三个八位寄存器,两个用于输入,一个用于输出,而输出寄存器的I/O端口为61h,这是会在程序中体现的,而该输出寄存器端口号的第0位和第1位是选择扬声器的驱动方式。用汇编实现发声系统程序,有两种方式,一种是位触发方式,另一种是定时器方式。

       其中位触发方式直接使61h的PB1交替置1和0来实现脉冲电流,控制扬声器从而交替打开和关闭,产生不同音高和不同音长的声音。

       而定时器方式需要用到定时器内部的Counter2和控制寄存器,它们分别对应的端口号是42h43h。在该方式中需要将一个控制字送入43h中(类似于计算机组成原理中的ROM微指令),控制字为8位,由高到低,前两位选择计数器,第3、4位选择计数器读写指示位,第5、6和7位选择操作模式(输出脉冲的形状),最后一位选择计数值格式(0为二进制,1为BCD码格式),另外42h存放的是计算得到的延迟时间。当然61h的0和1位需要都置为1。

       实现了输出一个简谱音符的同时响相应的音,之前将输出音符放在了扬声器输出声音的后面,出现了声音延迟于音符输出,在数据段mes存放数据的开头增加一个空格依然无法同步,原因很简单,在主程序段中,di、bx和si是同步增加的,程序会将空格字符与一个声音对应起来。

       最后,不要问我为什么后面输出的低阶sol没有显示成5下有个小点~~

       下面是“两只老虎”的参考代码:

;************************************************************************************
datasg segment
       mus_freq   dw 262,294,330,262,262,294,330,262      ;频率决定音高
                  dw 330,349,392,330,349,392,392,440
                  dw 392,349,330,262,392,440,392,349
                  dw 330,262,294,196,262,294,196,262

       mus_time   dw 2500,2500,2500,2500,2500,2500,2500,2500,2500,2500    ;节拍决定音长
                  dw 5000,2500,2500,5000,1200,1200,1200,1200,2500,2500
                  dw 1200,1200,1200,1200,2500,2500,2500,2500,5000,2500,2500,5000

    mes    db 31h,32h,33h,31h,31h,32h,33h,31h,33h,34h,35h,33h,34h,35h,35h,36h
      db 35h,34h,33h,31h,35h,36h,35h,34h,33h,31h,32h,35h,31h,32h,35h,31h,'$'
    
datasg ends
;************************************************************************************
;************************************************************************************
codesg segment
    main    proc   far
         assume cs:codesg,ds:datasg
   org    100h     ;链接器将之后的程序放在0100h的开始位置
;-----------------------------------------------------
 start:
         push ds
   sub  ax,ax
   push ax
   mov  ax,datasg
   mov  ds,ax

            lea  di,mus_freq   ;频率
            lea  bx,mus_time   ;节拍
   lea  si,mes    ;音符
            mov  cx,32d;
;-----------------------------------------------------
 new_shot:  
            push cx
      call sound
   add  di,2
      add  bx,2
   add  si,1
   mov  cx,0ffffh
;-----------------------------------------------------
 silent:
   loop silent
         pop  cx
   loop new_shot
   mov  al,48h
         out  61h,al
           
   mov  ah,4ch
   int  21h
   
      ret
 main endp
 
;-----------------------------------------------------
sound proc near

   mov  ah,02h    ;利用中断21h的02功能调用,显示音符简谱
   and  si,00ffh
   mov  dx,[si]
   int  21h

   in  al,61h
   and  al,11111100b
  sing:
      xor  al,2    ;将PB1置1,打开扬声器
   out  61h,al

   push ax
   call widnth
   pop  ax
   mov  cx,dx
  waits:
      loop waits    ;循环延迟,由此控制开关电路所产生脉冲的频率
      dec  WORD PTR [bx]  ;实现相应节拍的声音
   jnz  sing

   
      and  al,11111100b  ;关闭扬声器
   out  61h,al
   ret       ;一轮实现了一个音的输出
  
sound endp
;----------------------------------------------------- 
;-----------------------------------------------------
widnth proc near     ;控制脉宽的计数值
            mov  ax,2801    
   push bx     ;保存的是节拍
   mov  bx,50
            mul  bx
   div  WORD PTR [di]  ;除以了相应的频率
   mov  dx,ax
   pop  bx
   ret
widnth endp
;-----------------------------------------------------
codesg ends  
;************************************************************************************   
 end start
;************************************************************************************





这篇关于汇编实验——乐曲程序(两只老虎)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/691047

相关文章

uniapp接入微信小程序原生代码配置方案(优化版)

uniapp项目需要把微信小程序原生语法的功能代码嵌套过来,无需把原生代码转换为uniapp,可以配置拷贝的方式集成过来 1、拷贝代码包到src目录 2、vue.config.js中配置原生代码包直接拷贝到编译目录中 3、pages.json中配置分包目录,原生入口组件的路径 4、manifest.json中配置分包,使用原生组件 5、需要把原生代码包里的页面修改成组件的方

Java面试八股之怎么通过Java程序判断JVM是32位还是64位

怎么通过Java程序判断JVM是32位还是64位 可以通过Java程序内部检查系统属性来判断当前运行的JVM是32位还是64位。以下是一个简单的方法: public class JvmBitCheck {public static void main(String[] args) {String arch = System.getProperty("os.arch");String dataM

一道经典Python程序样例带你飞速掌握Python的字典和列表

Python中的列表(list)和字典(dict)是两种常用的数据结构,它们在数据组织和存储方面有很大的不同。 列表(List) 列表是Python中的一种有序集合,可以随时添加和删除其中的元素。列表中的元素可以是任何数据类型,包括数字、字符串、其他列表等。列表使用方括号[]表示,元素之间用逗号,分隔。 定义和使用 # 定义一个列表 fruits = ['apple', 'banana

美容美发店营销版微信小程序源码

打造线上生意新篇章 一、引言:微信小程序,开启美容美发行业新纪元 在数字化时代,微信小程序以其便捷、高效的特点,成为了美容美发行业营销的新宠。本文将带您深入了解美容美发营销微信小程序,探讨其独特优势及如何助力商家实现业务增长。 二、微信小程序:美容美发行业的得力助手 拓宽客源渠道:微信小程序基于微信社交平台,轻松实现线上线下融合,帮助商家快速吸引潜在客户,拓宽客源渠道。 提升用户体验:

程序人生--拔丝地瓜

一个会享受生活的人,难免会执迷于探索“三餐茶饭,四季衣裳”的朴素涵义。如今在这繁杂喧闹、竞争激烈的社会环境里,如何才能从周而复始的生活中挖掘出一点儿期待!这是一个仁者见仁智者见智的开放性话题。对于大部分的人来说,看电影、运动、旅游、美食、加班....是假日的备选安排。 春节临走之前,再次尝试“拔丝地瓜”,为何要强调“再次”二字?因为这道甜菜我已经尝试过很多次,失败与成功都经历过。十几年的烧饭经历

逆向学习汇编篇:内存管理与寻址方式

本节课在线学习视频(网盘地址,保存后即可免费观看): ​​https://pan.quark.cn/s/3ceeb9ae6d98​​ 在汇编语言的世界中,内存管理和寻址方式是构建程序的基础。理解这些概念不仅对于编写高效的汇编代码至关重要,也是进行逆向工程分析的关键技能。本文将深入探讨内存管理的基本原则和多种寻址方式,并通过代码案例来展示它们的实际应用。 1. 内存管理 内存管理涉及如何分配

高性能并行计算华为云实验五:

目录 一、实验目的 二、实验说明 三、实验过程 3.1 创建PageRank源码 3.2 makefile的创建和编译 3.3 主机配置文件建立与运行监测 四、实验结果与分析 4.1 采用默认的节点数量及迭代次数进行测试 4.2 分析并行化下节点数量与耗时的变化规律 4.3 分析迭代次数与耗时的变化规律 五、实验思考与总结 5.1 实验思考 5.2 实验总结 E

vscode python pip : 无法将“pip”项识别为 cmdlet、函数、脚本文件或可运行程序的名称

在vscode中控制台运行python文件出现:无法将"pip”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。 使用vscode开发python,需要安装python开发扩展: 本文已经安装,我们需要找的是python安装所在目录,本文实际路径如下: 如果在本文路径中没有此目录,请尝试在C盘中搜索 python,搜索到相关python目录后,点击Python 3.9进入目录,

2_为MFC程序添加菜单

在MFC中添加菜单栏 1,双击资源文件,显示资源视图,点击Menu插入Menu菜单,编辑菜单的ID,自己取名字。 2,点击“请在此处键入”添加菜单选项,输入&E,E的下面就会产生下划线;在产生的弹出菜单中继续编辑,并且可以添加事件处理函数; 在弹出菜单的任意位置,鼠标右键,弹出的菜单中选择“插入分隔符”,即可产生分隔符 3,在你设计的Dialog窗口的属性栏,选择Menu后面的

在Ubuntu 14.04上安装和配置SNMP守护程序和客户端的方法

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 介绍 作为系统管理员的重要工作之一是收集关于服务器和基础设施的准确信息。有许多工具和选项可用于收集和处理这种类型的信息。其中许多工具都是建立在一种叫做 SNMP 的技术之上。 SNMP 代表简单网络管理协议。它是服务器可以共享关于其当前状态的信息的一种方式,也是管理员可以修改预定义值的通道。虽