Учебник по ассемблеру (ASM)
 

Ассемблер в примерах - Работа с динамиком

Вопрос:
не могу понять в чем проблема с пищалкой...звук должен генерироваться без использования счетчика-таймера...(текст программы приводится ниже)..и вопрос..как нужно рассчитать время, чтобы сделать задержку в секундах?
.model small 
.386 
.stack 256h 
.data 
;частоты из учета 1193180/частоту ноты
music		dw	4063, 2559, 3835	;ре = 293,7 ля-диез = 466,2 ре-диез = 311,1
;длительность воспроизведения
duration	dw	27, 36, 18		;ре = 1,5 ля-диез = 2 ре-диез = 1 = > 18.2*время в секундах
dlina		dw	3

.code

start:
	mov	ax, @data
	mov	ds, ax
	mov	si, 0
	cli                 ;зaпpeт пpepывaний
play:
	mov   dx, duration[si]  ;длитeльнocть тoнa в dx
    in    al, port_b     ;пoлучaeм знaчeниe из пopтa b
    and   al, 11111110b  ;oтключaeм динaмик oт тaймepa
next_cycle:
    or    al, 00000010b  ;включaeм динaмик
    out   port_b, al     ;пocылaeм кoмaнду в пopт b
    mov   cx, music[si]  ;зaдepжкa нa пoл-циклa в cx
first_half:
    loop  first_half    ;дeлaeм зaдepжку
    and   al, 11111101b  ;выключaeм динaмик
    out   port_b, al     ;пocылaeм кoмaнду в пopт b
    mov   cx, music[si]  ;зaдepжкa нa пoл-циклa в cx
second_half:
	loop  second_half   ;дeлaeм зaдepжку
	dec   dx            ;вычитaeм eдиницу из cчeтчикa
	jnz   next_cycle    ;ecли 0, тo нaдo кoнчaть

	dec	dlina
	mov	cx, dlina
	inc	cx
	inc   si
	inc   si
	loop  play
	sti                 ;paзpeшaeм пpepывaния

	mov	ax, 4c00h
	int	21h
end start

Ответ:
Вам нужно использовать стандартную функцию BIOS ah=86h, прерывания 15h.
Расчитываете паузу в микросекундах и подставляете в регистры CX:DX(старшее слово числа микросекунд паузы:младшее слово).
Необходимые значения считаете по формуле:
ПАУЗА(мкс)=( 1 000 000 / ЧАСТОТА ) / 2
где ЧАСТОТА=количество периодов с секунду.
Нота РЕ=(1 000 000/293,7)/2=1 70210=6A610
Длительность воспроизведения одной ноты или количество повторов воспроизведения одного периода:
N=ЧАСТОТА * ВРЕМЯ
Нота РЕ = 293,7 * 1,5 = 44010

В приложении программа с использованием указанной функции, с учетом того, что старшее слово паузы в микросекундах(СХ) будет всегда равно 0.
Программа под tasm.

ps: Используя в качестве задержки, строки first_half: loop first_half, Вы считаете её в тактах процессора. При современных процессорах, с высокой тактовой частотой, генерируемый звук будет на грани слышимости, около 20кГц.
model tiny 
.186 
.code
org 100h
start:
;
    	in	al, 61h     ;пoлучaeм знaчeниe из пopтa b
	and	al, 11111100b  ;oтключaeм динaмик oт тaймepa
;
	cli                 ;зaпpeт пpepывaний
;количество нот
	mov	cx,3
play:	push	cx
;загружаем данные
	mov	cx, duration[si];длитeльнocть тoнa в сx
	mov	dx, music[si];длительность полу-волны в dx
next_cycle:
	push	cx
;генерируем частоту
	call	beep;
	call	beep;
;цикл вопроизведения одной ноты
	pop	cx
	loop	next_Cycle
;востанавливаем счетчик
	pop	cx
;следующее значение
	inc	si
	inc	si
;цикл проигрывания всй мелодии
	loop	play
	sti;paзpeшaeм пpepывaния
;ждем нажатия на любую клавишу
	xor	ax,ax
	int	16h
;выход в DOS
	ret
;инвентируем бит включения-выключения динамика
beep:	xor	al,00000010b
	out	61h,al
;запоминаем состояние порта
	push	ax
;запоминаем задержку
	push	dx
;сбрасываем старшеё слово паузы
	xor	cx,cx
;функция задержки
	mov	ah,86h
	int	15h
;востанавливаем регистры
	pop	dx
	pop	ax
	ret
;длительность одной полуволны ноты
music		dw	6a6h,430h,647h;ре = 293,7 ля-диез = 466,2 ре-диез = 311,1
;длительность воспроизведения
duration	dw	440, 892, 311;ре = 1,5 ля-диез = 2 ре-диез = 1 в секундах
end start

   Вперёд
   Содержание