This is the past DOS era of the compilation of source code, although has passed, but for the study of the assembly is still helpful, assembly language is just a basic programmer language, most people can grasp, not necessarily in-depth research.
; Sound.asm
;
; This is a small sound example for the IBM PC
; It'll play 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 is 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.
; For this to work properly, the Timer command register has to be loaded
; 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 in each iteration.
;
; No stack segment is needed to this small program, so don ' t panic
; When you receive the ' No stack segment ' Warning.
;
; Arne Asplem 880731 (MASM 4.0)
DSEG segment; Data 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; Set up data segment (DS) Reg.
Xor Si, si
MOV bx, 12; Note Count
; Set up Timer command Register and counter register
mov al, 0b6h; Set 8253 Command Register
Out 43h, AL; For Channel 2, mode 3
Nloop:
mov ax, 34dch; Low part of clock freq.
MOV dx, 12h; Hight part of Clock freq.
div [notes + si]; Get the From data segment
Out 42h, AL; 8253 Command register (low byte)
mov al, ah
Out 42h, AL; 8253 command Regsieter (high byte)
; Turn on low bits in 8255 output port
In Al, 61h; Read current value of 8255 port
or AL, 3; Clear Low Bits
Out 61h, AL; Send new value to port
; Loop while # is sounding
MOV cx, 6d60h
Rpta
Loop Rpta; 1/10 sec delay
; Turn off speaker, check # count, set up next
Xor Al, 3
Out 61h, AL; Turn off speaker
MOV cx, 0af0h
RPTB:
Loop RPTB; 1/100 sec delay
Inc si; Increment Note pointer
Inc si
Dec BX; Decrement Note counter
JNZ Nloop; Loop until BX = 0
mov ax, 4c00h; Terminate program
int 21h
Sound ENDP
Cseg ends
End Start