Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 16.04.2012, 22:36   #1
Glaciuse
Пользователь
 
Регистрация: 22.05.2011
Сообщений: 44
По умолчанию Замена прерывания 1Ch (таймер)

Пытаюсь сделать писк динамика, при этом интервал писка отслеживать через прерывание 1Ch, которое вызывается внутри 08h.

Вот как делаю:

Код:
	;Заменяем прерывание 1C, на свое собственное

	;Получаем адрес прерывания 1C и сохраняем его
	mov ax, 351Ch           		                ;AH = 35h, AL = номер прерывания
        int 21h                 		                ;получить адрес обработчика
	mov word ptr oldInt1Ch, bx		                ;Запоминаем адрес старого обработчика
	mov word ptr oldInt1Ch + 2, es	                        ;Зпоминаем адрес es
	;Тут имеем сохраненный адрес прерывания 1C
	
	mov ax, 251Ch					;AH = 35h, AL = номер прерывания
	mov dx, offset newInt1Ch		        ;Загружаем в dx адрес newInt1Ch
	int 21h					        ;Устанавливаем своего обработчика 1C вместо обработчика по умолчанию
	
	;Тут вместо прерывания 1C по умолчанию будет вызываться функция newInt1Ch
	
	mov al, 02h					;Загружаем в al длительность  сигнала в секундах
	mov bx, 1356D					;Частота Ля 2ой октавы (реальная: 880.00 Гц, расчитывается по форумле 1193180/X = реальная)
	
	call setTimerFrequency			        ;Процедура установки полученной частоты из determineTimerFrequency в регистр таймера CR2
	
	mov bx, 880D					;Частота сигнала из таймера (880 раз в сек)
	mov ah, 00h
	mul bx						;В dx:ax количество кол-во тиков таймера (для простоты результат только в ax)
	
	call initSpeaker				;Включаем динамик
	
	;В ax находится число тиков за 2 секунды
	mov bx, 00h
	xor cx, cx
	
waiting:
        Вот тут в cx должна появиться 1, но не появляется
        Во время выполнения этого цикла пищит динамик,
        значит и должно выполнятся прерывание 1Ch (замененное на newInt1Ch), 
        которое со временем должно поместить в cx 1, но этого не происходит.
	cmp cx, 01h

	jne waiting

	call disableSpeaker
	
	;Восстанавливаем прерывание
	mov ax, 251Ch				;AH = 21h, AL = номер прерывания
	lds dx, dword ptr oldInt1Ch	        ;Загружаем в dx адрес oldInt1Ch с указанием сегментного регистра
	int 21h				        ;Восстанавливаем обработчик прерывания 1Ch по умолчанию обратно
	;Прерывание восстановлено
Вот так выглядит новый обработчик:

Код:
newInt1Ch proc far
	;При каждом тике таймера будет вызываться прерывание mewInt1Ch и будет увеличиваться счетчик тактов
	inc bx
	cmp ax, bx
	jne cont
	mov cx, 01h
cont:
	iret
newInt1Ch endp
Вот как выглядят процедуры initSpeaker и disableSpeaker:

initSpeaker:
Код:
initSpeaker proc near
	push ax
	in al, 61h 		;Получаем значение порта 61
	or al, 00000011B 	;Устанавливаем 0й и 1й биты равные 1, чтобы включить динамик
	out 61h, al 		;отправляем изменения в 61 порт
	pop ax
	ret
initSpeaker endp
disableSpeaker:
Код:
disableSpeaker proc near
	push ax
	in al, 61h 		;Получаем значение порта 61
	and al, 11111100B 	;Устанавливаем 0й и 1й биты равные 0, чтобы выключить динамик
	out 61h, al 		;отправляем изменения в 61 порт
	pop ax
	ret
	ret
disableSpeaker endp
В итоге при запуске динамик начинает пищать без остановки, где может быть ошибка?
Заранее спасибо.

Последний раз редактировалось Glaciuse; 16.04.2012 в 23:03.
Glaciuse вне форума Ответить с цитированием
Старый 16.04.2012, 22:46   #2
Glaciuse
Пользователь
 
Регистрация: 22.05.2011
Сообщений: 44
По умолчанию

Перед первым куском кода, инициализирую таймер для работы с динамиком так:

Код:
initTimer proc near
	push ax
	mov al, 10110110B 	                ;В управляющий регистр таймера пойдут данные:	
                                                ;Формат константы: 16-битное число (0000 - FFFFh) (бит #0)						
                                                ;Режим работы: генерация прямоугольных импульсов (биты #3, #2, #1)						
                                                ;Способ загрузки констант: чтение\запись сначала младшего, затем старшего (биты #5 и #4)						
                                                ;Номер канала; 2 - канал управления динамиком (биты #7 и #6
						
	out 43h, al 		                ;Загружаем настройки в управляющий регистр таймера по порту 43h
	pop ax
	ret
initTimer endp
Вот так вот выставляю частоту в таймере:
Код:
setTimerFrequency proc near
	push ax
	mov ax, bx 			
        ;Устанавливаем частоту звучаний, которая находится в bx (получена в determineTimerFrequency)
	out 42h, al 		        ;Загружаем младший байт в регистр констант пересчета (CR2)
	mov al, ah 			;Помещаем старший байт в al
	out 42h, al 		        ;Отправляем старший байт в регистр констант пересчета (CR2)
	pop ax
	ret
setTimerFrequency endp

Последний раз редактировалось Glaciuse; 16.04.2012 в 23:02.
Glaciuse вне форума Ответить с цитированием
Старый 17.04.2012, 08:49   #3
DiemonStar
Старожил
 
Регистрация: 08.02.2012
Сообщений: 2,173
По умолчанию

Цитата:
Код:
xor cx, cx
	
waiting:
        Вот тут в cx должна появиться 1, но не появляется
        Во время выполнения этого цикла пищит динамик,
        значит и должно выполнятся прерывание 1Ch (замененное на newInt1Ch), 
        которое со временем должно поместить в cx 1, но этого не происходит.
	cmp cx, 01h

	jne waiting
а почему вы решили, что там должна появиться единица? Если мне не изменяет память, обработчик 8-го прерывания делает дальний вызов на этот обработчик, а это означает, что контроллер прерывания ещё не освободил линию и процессор находится в состоянии обработки аппаратного прерывания.
А если вы внимательно почитаете описание таймера, то заметите, что вывод однотонного звука определяется лишь настройками портов таймера и от работы процессора не зависит.
Правильно поставленная задача - три четверти решения.

Последний раз редактировалось DiemonStar; 17.04.2012 в 08:53.
DiemonStar вне форума Ответить с цитированием
Старый 17.04.2012, 11:34   #4
Glaciuse
Пользователь
 
Регистрация: 22.05.2011
Сообщений: 44
По умолчанию

А если сделать так:

Заменить обработчик 08h на:
Код:
.....

;посылаем EOI
mov al, 20h
out 20h, al

inc bx
cmp ax, bx
jne cont
mov cx, 01h
cont: iret
Glaciuse вне форума Ответить с цитированием
Старый 17.04.2012, 11:57   #5
DiemonStar
Старожил
 
Регистрация: 08.02.2012
Сообщений: 2,173
По умолчанию

Я просто не очень понимаю, чего вы этим хотите добиться. Намного проще в обработчике сделать пару глобальных переменных по включению/выключению звука и настройке тональности и при очередном вызове процедуры перенастраивать звук по ним в зависимости от параметров, а вложенными вызовами прерывания вы можете добиться того, что у вас возникнет дикая рекурсия из которой процессор просто не сможет выбраться самостоятельно. Именно во избежание таких проблем и нужен запрет прерываний при выполнении прерывания.

например, организовать так:

Код:
status db 0 ; 1 бит - 1=включить, 1бит - 1=установка тона
freq    dw 0 ; тон звука
delta   dd 0 ; длительность звукового импульса
old_time dd 0 ; время включения импульса
old_vector dd ? ; старый обработчик прерывания
....
pushf
call old_vect ; вызов старого обработчика
...
mov edx, dword ptr 0000:[0070h]
...
test status, 1
jz to2
... ; запускаем звук
mov old_time, edx
to2:
test status, 10b
jz to3
...
to3:
mov ecx, old_time
add ecx, delta
cmp edx, ecx
jl to_exit
... ; отключение звука
to_exit
iret
Правильно поставленная задача - три четверти решения.

Последний раз редактировалось DiemonStar; 17.04.2012 в 12:27.
DiemonStar вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Замена прерывания xWinDx Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 5 24.05.2010 20:18
Прерывания alexdrew Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 1 16.05.2010 00:38
Прерывание 1ch DronSC Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 2 14.05.2010 14:27
Замена кода программы с Delhi5 на Delhi7 либо замена базы данных с Acessa на MySQL DorianLeroy Фриланс 8 18.02.2009 18:52
Прерывания Kn793 Общие вопросы Delphi 3 10.01.2009 18:43