data segment
freq dw 196,220
dw 262,262,262,262,262,220,196
dw 262,262,262,262,294,262,220,262
dw 294,294,294,294,294,262,220
dw 294,294,294,294,330,294,330,392
dw 440,440,392,440,392,330
dw 294,294,330,294,262,220,196,220
dw 262,262,262,262,262,220
dw 262,196,220
dw 440,440,392,440,524,440
dw 392,330,294,262,220,196,220
dw 262,262,262,262,294,262
dw 262,330,392
dw 440,440,440,440,524,440
dw 392,392,392,440,392,330,294
dw 262,262,262,262,294
dw 330,330,294
dw 262,262,262,262,524,440
dw 392,392,392,440,392,330,392
dw 440,524,524,440,392
dw 392,330,392
dw 440,440,440,440,524,440
dw 392,392,392,440,392,330,294
dw 262,262,262,262,392
dw 330,330,294
dw 262,262,262,262,294,330
dw 392,392,330,392,330,392
dw 440
dw 19,19,196,660,294,294,262
dw 262,-1
time dw 400,400
dw 400,200,400,400,800,400,400
dw 400,200,400,200,200,800,400,400
dw 400,200,400,400,800,400,400
dw 400,200,400,200,200,800,400,400
dw 400,800,400,800,400,400
dw 400,200,200,400,400,800,400,400
dw 400,200,400,400,800,800
dw 1600,800,800
dw 400,800,400,800,400,400
dw 400,400,400,400,800,400,400
dw 400,800,400,800,400,200
dw 2400,400,400
dw 400,800,400,800,400,400
dw 400,800,200,200,800,400,400
dw 400,800,400,800,800
dw 2400,400,400
dw 400,800,400,800,400,400
dw 400,800,200,200,800,400,400
dw 800,400,800,400,200
dw 2400,400,400
dw 400,800,400,800,400,400
dw 400,800,200,200,800,400,400
dw 400,800,400,800,800
dw 2400,400,400
dw 400,800,400,800,400,400
dw 400,800,400,800,400,400
dw 3200
dw 800,400,400,400,400,400,400
dw 4000
data ends
code segment
assume cs:code,ds:data
start:
mov ax,data
mov ds,ax ;初始化數據段暫存器
lea si,freq ;把freq在數據段的偏移存入si
lea di,time ;把time在數據段的偏移存入di
l1:
mov cx,[si]
cmp cx,-1
je exit ;如果初始化失敗,就像看到的一樣,cx的值是負一那么就退出了
mov bx,[di]
call gensound
add si,2
add di,2
jmp l1 ;每次從time中取一個字,然後調用gensound
exit:
mov ax,4c00h
int 21h
;bx(放延時計數值)、cx(放頻率計數值)為入口參數。
gensound proc near
push dx
MOV AL,0B6H ;位組合格式:通道2,兩位元組計數,模式3,二進制編碼, 得到控制字;
OUT 43H,AL ;將控制字數送43H連線埠(方式暫存器)
mov dx,12h
mov ax,3280h
div cx ;計算123280h/cx--->dx,ax
out 42h,al ;把商的低位元組(頻率計數值)寫入42h連線埠(定時器通道2)
mov al,ah
out 42h,al ;再把商的高位元組寫入到42h連線埠
in al,61h
mov ah,al
or al,3 ;控制音長的時間可以簡單地通過反覆執行循環指令來得到
out 61h,al
;接通揚聲器
push ax
l2:
mov dx,8h ;送基準延時值
mov ax,0f05h
s1:
sub ax,1
sbb dx,0 ;DX:AX減去了1(sbb指令是帶借位減法指令:(dx)=(dx)-0-CF)
jnz s1 ;kill time
dec bx ;這是第一次使用bx,也就是傳入參數。
jnz l2 ;kill time
pop ax
mov al,ah ;果然是保護AH的值的
out 61h,al ;恢復揚聲器原來的設定
pop dx
ret
gensound endp
code ends
end start
