让计算机“唱歌”(1704)

来源:互联网 发布:什么精华液好用 知乎 编辑:程序博客网 时间:2024/04/28 04:19

本文为《汇编语言程序设计》1704小节例程。点击链接…进课程主页。

任务:编程序,让计算机“唱”歌曲《新年好》
程序:

assume cs:codeseg, ds:dataseg, ss:stacksegdataseg segmentmus_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,-1mus_time dw 3 dup(12,12,25,25),12,12,50         dw 3 dup(12,12,25,25),12,12,50dataseg endsstackseg segment   db 100h dup (0)stackseg endscodeseg segmentstart:    mov ax, stackseg    mov ss, ax    mov sp, 100h    mov ax, dataseg    mov ds, ax    lea si, mus_freq    lea di, mus_timeplay:    mov dx, [si]    cmp dx, -1    je end_play    call sound    add si, 2    add di, 2    jmp playend_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, 28000delay:    nop    loop delay    dec dx    jnz wait1    mov al, ah         ;恢复扬声器端口原值    out 61h, al    pop cx    pop dx    pop ax    retcodeseg endsend start

附1:《新年好歌谱》
这里写图片描述
附2:音符和发音频率(Hz)的对应关系
这里写图片描述
附3:Mary had a little lamb数字化歌谱

dataseg segmentmus_freq dw 330, 294, 262, 294, 330, 330, 330         dw 294, 294, 294, 330, 392, 392, 392         dw 330, 294, 262, 294, 330, 330, 330, 330         dw 294, 294, 330, 294, 262, -1mus_time dw 6 dup(25), 50         dw 2 dup(25, 25, 50)         dw 12 dup(25), 100dataseg ends

附4:《九儿》数字化歌谱(部分)

dataseg segment   mus_freq dw 440, 587, 587, 523, 494, 440, 392             dw 440, 294             dw 440, 587, 587, 523, 494, 392, 440, 492, 440,  -1mus_time dw25, 50, 25, 25, 25, 25, 25         dw 50, 150          dw 25, 50, 25, 25, 25, 12, 12, 50, 175dataseg ends