"Архитектура ввода-вывода персональных ЭВМ IBM PC" - читать интересную книгу автора (Лукач Ю.С.)

jnb Done ;чтобы избежать переполнения
div bx ;ax=(dx,ax)/bx
mov bx,ax ;счетчик таймера
in al,61h ;порт РВ
or al,3 ;установить биты 0-1
out 61h,al
mov al,00001011b ;управляющее слово таймера:
;канал 2, режим 3, двоичное слово
mov dx,43h
out dx,al ;вывод в регистр режима
dec dx
mov al,bl
out dx,al ;младший байт счетчика
mov al,bh
out dx,al ;старший байт счетчика
Done:
pop dx ;восстановить регистры
pop bx
pop ax
ret
Sound endp
;
;подпрограмма выключения звука
;
No_Sound proc near
push ax
in al,61h ;порт РВ
and al,not 3 ;сброс битов 0-1
out 61h,al
pop ax
ret
No_Sound endp

Для генерации музыки можно использовать следующий алгоритм.
Пусть octave - номер октавы (1, 2, ...); note - номер ноты в
октаве (до=1, до#=2, ..., си=12). Тогда:

f := 32.625;
for i := 1 to oktave do f := 2*f;
for i := 1 to note do f := 1.059463094*f
Sound (round(f));

Второй способ генерации звука состоит в том, чтобы
генерировать звуковые импульсы не выходом таймера, а установкой
и сбросом бита 1 в регистре РВ. Для управления задержками можно
использовать программный цикл, например:

;
; Программа генерации звука
; Вход: N=количество импульсов