SOUND.ASM 是一個極精簡的 DOS 組合語言程序,利用 PC 機 8253 定時器通道 2 和 8255 PPI 控制蜂鳴器,播放中音 C 起始的 12 半音 (一個八度)。代碼僅包含數據段 (頻率表) 和代碼段,無堆棧段,長度不足 100 行,是學習 PC 硬件定時器與聲音生成的絕佳入門樣本。
dseg segment
notes dw 262,277,294,311,330,349,370,392,415,440,466,494 ; C4~B4
dseg ends
mov al, 0b6h ; 10110110b: Channel 2, Mode 3, Binary, LSB/MSB
out 43h, al ; 寫命令寄存器
nloop:
mov ax, 34dch ; 1193180 (十進制) = 0x1234DC → 高位 0x12, 低位 0x34DC? 實際代碼用 34dch/12h 組合
mov dx, 12h ; DX:AX = 0x001234DC = 1193180
div [notes + si] ; AX = 1193180 / 頻率 = 計數值
out 42h, al ; 寫計數器低位
mov al, ah
out 42h, al ; 寫計數器高位 (AH 為商高位)
; 開啟喇叭
in al, 61h
or al, 3 ; 置 Bit0, Bit1
out 61h, al
; 延遲 ~1/10 秒
mov cx, 6d60h
rpta: loop rpta
; 關閉喇叭
xor al, 3 ; 清 Bit0, Bit1
out 61h, al
; 音符間隙 ~1/100 秒
mov cx, 0af0h
rptb: loop rptb
inc si; inc si ; SI += 2 (WORD)
dec bx
jnz nloop
mov ax, 4c00h
int 21h
DIV 使用 DX:AX 作為被除數,此處 DX=0x12, AX=0x34DC 組成 32 位值 1193180。商在 AX,餘數在 DX。OUT 42h 連續兩次寫入低/高位。6D60h = 28000 次循環約 0.1 秒 (視 CPU 速度);0AF0h = 2800 約 0.01 秒。現代 CPU 需用 INT 15h/86h 或 RDTSC 校準。CS=DS=SS=ES=PSP,SP=FFFEh,調用深度極淺可直接使用默認堆棧。; sound.asm
; This is a small sound example for the IBM PC
; It will play 12 notes of the octave starting at middle C.
;-----------------------------------------------------------------------------
; How to generate sound on the IBM PC :
; The 8255 (port 61H) bit 0 controls the 8253 timer
; bit 1 controls the speaker
; The output channel 2 from the 8253 timer will be ANDed with the
; speaker control bit in order to turn on/off the speaker.
; Timer channel 2 internal count register (port 42h) is loaded in
; two successive OUT operations with the lower byte being loaded first.
; For this to work properly, timer command register has to be loaded first
; with B6H.
; Since the input clock to the timer chip is 1.19318 MHz, the counter value
; to generate the frequency X can be calculated by 1193180 / X.
;-----------------------------------------------------------------------------
; CX is used as a note counter with the frequency effectively being
; incremented by a half tone and the corresponding count being loaded
; into the count register on each iteration.
; No stack segment is needed for this small program, so don't panic
; when you receive the 'No stack segment' warning.
; Arne Asplem 880731 (MASM 4.0)
dseg segment
notes dw 262,277,294,311,330,349,370,392,415,440,466,494
dseg ends
cseg segment
sound proc far
assume cs:cseg, ds:dseg, ss:nothing
start:
mov ax, dseg
mov ds, ax
xor si, si
mov bx, 12
mov al, 0b6h
out 43h, al
nloop:
mov ax, 34dch
mov dx, 12h
div [notes + si]
out 42h, al
mov al, ah
out 42h, al
in al, 61h
or al, 3
out 61h, al
mov cx, 6d60h
rpta:
loop rpta
xor al, 3
out 61h, al
mov cx, 0af0h
rptb:
loop rptb
inc si
inc si
dec bx
jnz nloop
mov ax, 4c00h
int 21h
sound endp
cseg ends
end start
INT 1Ch (Timer Tick, 18.2Hz) 或使用 INT 15h/86h (微秒延遲) 替代軟件循環。SOUND.ASM 用最少代碼展示了 PC 機最基礎的聲音生成鏈路:定時器分頻 → 方波輸出 → PPI 閘控 → 揚聲器。它是理解 x86 實模式硬件編程、定時器編程、I/O 端口操作的經典教具。建議讀者在 DOSBox 或真實 DOS 環境中編譯運行,聽聽那熟悉的「蜂鳴器音樂」。