汇编语言源程序基础分析--定时器发声


前言

以定时器控制频率发声汇编代码为例,介绍汇编代码基础知识


一、示例代码

代码如下(示例):

;  演奏“友谊地久天长”——使用8254虚拟电路
DATA     SEGMENT 
FREQ_LIST  DW  371,495,495,495,624,556,495,556,624  ;频率表
           DW  495,495,624,742,833,833,833,742,624
           DW  624,495,556,495,556,624,495,416,416,371
   	       DW  495,833,742,624,624,495,556,495,556,833
   	       DW  742,624,624,742,833,990,742,624,624,495
           DW  556,495,556,624,495,416,416,371,495,0
TIME_LIST  DB  4,6,2,4,4,6,2,4,4                    ;时间表
     	    DB  6,2,4,4,12,1,3,6,2
     	    DB  4,4,6,2,4,4,6,2,4,4
     	    DB 12,4,6,2,4,4,6,2,4,4
           DB  6,2,4,4,12,4,6,2,4,4
     	    DB  6,2,4,4,6,2,4,4,12
TIM_CTL    EQU 453H       ;8254 状态/命令口地址
TIMER1     EQU 451H       ;8254 定时计数器1地址
MODE00     db 70h
MODE03     db 76h
sound_FREQ dw  523,587,659,698,784,880,988,1046,1175,1318,1397, 1568,1760,1967
s          db "Playing a tune. Please wait a moment...",0dh,0ah,"$" 
DATA     ENDS
code     segment
           assume  cs:code,ds:data
go:        mov ax,data
           mov ds,ax 
           mov dx,offset s     ; 显示提示
           mov ah,9
           int 21h
           mov dx,TIM_CTL      ; 定时器1工作在方式3
           mov al,MODE03
           out dx,al  
           LEA SI,OFFSET FREQ_LIST
           LEA DI,OFFSET TIME_LIST
m1:        cmp WORD PTR [si],0
           jz exit
           mov ah,0bh
           int 21h   ; 检测有无按键,返回AL=0FFh(有按键)0(无按键)
           cmp al,0FFh
           jz Exit
           call sound    
           call DALLY       
           inc si
           inc si
           inc di
           loop m1
exit:  
           mov dx,TIM_CTL      ; 定时器1工作在方式0(关闭)
           mov al,MODE00
           out dx,al    
           mov ah,4ch       ; 结束
           int 21h
     
DALLY    PROC         ;延时子程序。若电脑速度慢可减少CX或AX的值
           push ax
           push bx
           push cx
           mov bl,[di]
D0:        MOV CX,12H
D1:        MOV AX,02000H
D2:        DEC AX
           JNZ D2 
           LOOP D1
           dec bl
           jnz d0
           pop cx
           pop bx
           pop ax
	       RET
DALLY    ENDP

sound    PROC         ;发音
         push ax
         push bx
         push cx
         push dx
         MOV DX,0fH                  ;输入时钟为1MHz,1M = 0F4240H  
         MOV AX,4240h               ;除法中被除数默认DX放高16位,AX放低十六位,除数为16位则,AX存商,DX存余数
         DIV  WORD PTR [SI] ;取出频率值计算计数初值,0F4240H / 输出频率  
         MOV cx,AX
         MOV dx,TIMER1       ; 定时器1计数初值 
         MOV al,cl
         out dx,al
         MOV al,ch
         out dx,al 
         pop dx
         pop cx
         pop bx
         pop ax
         ret 
sound   ENDP
code ends
     END  go




二、代码分析

1.LEA

取FREQ_LIST内偏移地址放入SI,即SI记录频率,DI记录时间
代码如下:

go:    LEA SI,OFFSET FREQ_LIST
       LEA DI,OFFSET TIME_LIST

取源操作数地址的偏移量,并把它传送到目的操作数所在的单元。

2.WORD PTR

比较判断SI是否为01,若为0则退出
代码如下(示例):

m1:    cmp WORD PTR [si],0
       jz exit

WORD PTR:指明为两个字节单元

3.PROC

代码如下(示例):

sound    PROC 
...
sound   ENDP

proc是定义子程序的伪指令,位置在子程序的开始处,它和endp分别表示子程序定义的开始和结束两者必须成对出现。

4.DIV

除法,取出频率值计算计数初值,0F4240H / 输出频率,计算出初值,存在cx寄存器
代码如下(示例):

sound:    ...
         MOV DX,0fH                  ;输入时钟为1MHz,1M = 0F4240H  
         MOV AX,4240h               
         DIV  WORD PTR [SI] ;取出频率值计算计数初值,0F4240H / 输出频率  
         MOV cx,AX

div,(无符号除法)指令执行 8 位、16 位和 32 位无符号数除法。其中,单寄存器或内存操作数是除数
寄存器分布

位数被除数余数
8位AXALAH
16位DX:AXAXDX
32位EDX:EAXEAXEDX
64位RDX:RAXRAXRDX

本代码为16位,DX存高位16位,AX存低位16位

5.声音频率输出

dx存入时间初值,定时器记录初值。由低位到高位依次输出cx内计算得出的声音频率,发声成功
代码如下(示例):

L1:   ...
 		 MOV dx,TIMER1       ; 定时器1计数初值 
         MOV al,cl
         out dx,al
         MOV al,ch
         out dx,al 

6.延时

DALLY    PROC         ;延时子程序。若电脑速度慢可减少CX或AX的值
           push ax
           push bx
           push cx
           mov bl,[di]
D0:        MOV CX,12H
D1:        MOV AX,02000H
D2:        DEC AX
           JNZ D2 
           LOOP D1
           dec bl
           jnz d0
           pop cx
           pop bx
           pop ax
	       RET
DALLY    ENDP

7.loop循环

延时结束后,si值+2,inc值+1,随后跳转回m1开端进入循环,直至si为0,跳转至exit。

代码:

m1:        cmp WORD PTR [si],0
           jz exit
           ...
		   inc si
           inc si
           inc di
           loop m1

exit:定时器转到MODE00,定时器关闭程序结束

exit:  
           mov dx,TIM_CTL      ; 定时器1工作在方式0(关闭)
           mov al,MODE00
           out dx,al    
           mov ah,4ch       ; 结束
           int 21h

总结

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值