PC compatibles have a built-in capability to make sounds and music via the
small speaker attached to the system board. This feature is very limited,
but creative programmers have performed miracles in the past, producing
beeps and squawks for games and even producing recognizable speech.
The only BIOS-supported sound can be produced via INT 10H 0eH (Write
Character as TTY), passing AL=07H, to output a standard beep.
The speaker is connected to PPI port B, port 61H (see PPI Ports). Set
bit 1 to pulse the speaker out and clear bit 1 it to bring the speaker
back to normal. For instance,
in al,61H ;get current value
again: or al,02H ;set bit 2 to pulse it out
delay: loop delay ;wait a little while
and al,0fdH ;clear bit 2 to pulse it back in
By pulsing it in and out at a given frequency, a specific tone is
produced. The above example produces various tones, depending upon
For better control, you can use the PC internal timer to pulse it of and
on at a given frequency. Timer channel 2 can be gated directly to the
speaker. To make a specific tone:
1) Program timer channel 2 to output a square-wave pulse at the desired
frequency by writing b6H to port 43H. Then output a divisor word to
port 42H (do that by writing first the low then the high byte -- see
The divisor word is a 16-bit value which, when divided into the
timer's frequency (1.19318 MHz), selects the desired output
frequency. For instance, middle C has a frequency of about 261 Hz.
To obtain that output, use a divisor of 4560 (1,193,180/261 = 4560).
2) Enable the speaker by setting bit 1 of I/O port 61H.
3) Gate the channel-2 timer output into the speaker by setting bit 0 of
4) After a while (say, half of a second), disable the speaker by
clearing bits 0-1 of I/O port 61H.
Step 4, above, determines the duration of the tone. The standard way to
set the duration is by watching the tick count at 0040:006c in the
BIOS Data Area and counting the number of 55ms-interval that occur. The
timer-tick interrupt occurs 18.2 times per second, so (for instance) 9
timer ticks occur in about 1/2 of a second.
On ATs, a more accurate duration can be obtained by using the BIOS timer
accuracy has been used in the past by the orginal PC's BASIC: It sped up
the standard timer tick by a factor of four whenever music was being
mov al, 0d0H ;low-byte of divisor (11d0H = 4560 = middle C)
mov al, 11H ;high-byte of divisor word
in al, 61H ;get current value of PPI
or al, 03H ;send timer output to speaker and enable speaker
mov cx, 0007H ;high-word for AT INT 15H (wait) service
mov dx, 0a120H ;low-word (0007a120H = 500,000ms = 1/2-second)
in al, 61H ;get current value of PPI
and al, 0fcH ;clear bits 0 and 1
out 61H, al ;turn off the speaker
...plays middle C for one half of a second.