汇编语言:写一个简单的音乐程序

先开个头,运行下面的程序,读一读,注意用到的端口(基本是固定的)

assume cs:codeseg
data segment
   dw 262,294,330,349,392,440,494,524
codeseg segment
start: mov ax, data
       mov ds, ax
       mov si, 0
       mov bl,8
play:
       mov al,0b6h    ;8253芯片初始化
       out 43h,al     ;43H是8253芯片控制口的端口地址
       mov dx,12h
       mov ax,34dch
       div word ptr [si]  ;设置声音的频率
       out 42h, al
       mov al, ah
       out 42h, al
       in al, 61h         ;读设备控制器端口原值
       mov ah, al         ;保存原值
       or al, 3           ;打开扬声器和定时器
       out 61h, al        ;接通扬声器,发声

       mov dx, 10         ;延时
delay0: mov cx, 60000  
delay1:
       nop
       loop delay1
       dec dx
       jne delay0

       mov al, ah         ;恢复端口原值
       out 61h, al

       add si, 2
       dec bl
       jne play

       mov ax, 4c00h
       int 21h
codeseg ends
end start

进入主题,实战演练!

对照音符和发音频率(Hz)的对应关系,将曲谱翻译作程序中需要的数据,演奏出音乐来
这里写图片描述

assume cs:codeseg, ds:dataseg, ss:stackseg
dataseg segment
mus_freq dw 262,262,262,196
         dw 330,330,330,262
         dw 262,330,392,392
         dw 349,330,294
         dw 294,330,349,349
         dw 330,294,330,262
         dw 262,330,294,196
         dw 247,294,262,-1
mus_time dw 3 dup(12,12,25,25),12,12,50
         dw 3 dup(12,12,25,25),12,12,50
dataseg ends

stackseg segment
   db 100h dup (0)
stackseg ends

codeseg segment
start:
    mov ax, stackseg
    mov ss, ax
    mov sp, 100h

    mov ax, dataseg
    mov ds, ax

    lea si, mus_freq
    lea di, mus_time

play:
    mov dx, [si]
    cmp dx, -1
    je end_play
    call sound
    add si, 2
    add di, 2
    jmp play

end_play:
    mov ax, 4c00h
    int 21h

;演奏一个音符
;入口参数:si - 要演奏的音符的频率的地址
;         di - 要演奏的音符的音长的地址
sound:
    push ax
    push dx
    push cx

    ;8253 芯片(定时/计数器)的设置
    mov al,0b6h    ;8253初始化
    out 43h,al     ;43H是8253芯片控制口的端口地址
    mov dx,12h
    mov ax,34dch
    div word ptr [si] ;计算分频值,赋给ax。[si]中存放声音的频率值。
    out 42h, al       ;先送低8位到计数器,42h是8253芯片通道2的端口地址
    mov al, ah
    out 42h, al       ;后送高8位计数器

    ;设置8255芯片, 控制扬声器的开/关
    in al,61h   ;读取8255 B端口原值
    mov ah,al   ;保存原值
    or al,3     ;使低两位置1,以便打开开关
    out 61h,al  ;开扬声器, 发声

    mov dx, [di]       ;保持[di]时长
wait1:
    mov cx, 28000
delay:
    nop
    loop delay
    dec dx
    jnz wait1

    mov al, ah         ;恢复扬声器端口原值
    out 61h, al

    pop cx
    pop dx
    pop ax
    ret

codeseg ends
end start

另附几首简单的小曲子,可以尝试着根据曲谱改变以上程序,作新曲。
汇编语言:写一个简单的音乐程序_第1张图片 汇编语言:写一个简单的音乐程序_第2张图片 汇编语言:写一个简单的音乐程序_第3张图片 汇编语言:写一个简单的音乐程序_第4张图片汇编语言:写一个简单的音乐程序_第5张图片

你可能感兴趣的:(汇编语言)