| 
			| 
					
						| KBAC | 
								|  | «  : 12-06-2012 14:45 »  |  | 
 
 Здравствуйте всем. Надо заменить обработчик прерывания irq1. У меня получается его подменить, но выполняется он почему-то только один раз. А на дальнейшие дествия не реагирует.  ;=====================; my interrupt handler
 ;=====================
 my_handler_int9 proc
 pushf
 
 call ClearScreen
 
 xor ax,ax
 in al,60h
 and al,07Fh
 
 call ByteToHex
 lea dx,buffer
 call PrintStr_bios
 
 cmp al,01h
 je progover
 
 ; mov al,20h
 ; out 20h,al
 jmp cs:old_handler
 my_handler_int9 endp
 main procassume cs:_text
 lds dx,dword ptr old_handler
 
 call int9_change ; exchange old_handler to my_handler
 
 xor bx,bx
 endless_loop:
 cmp bx,0Ah
 jne endless_loop
 
 call progover
 main endp
 ;================================; change interrupt handler
 ;================================
 int9_change proc
 push ax
 push bx
 push dx
 push ds
 push es
 
 ; get old_handler
 mov ax,3509h ; ah = 35, al = 9 (irq1)
 int 21h ; get old_handler offset in es:bx
 
 ; remember old_handler's offset
 mov word ptr old_handler,bx
 mov word ptr old_handler+2,es
 
 ;write my_handler offset to vector's table
 ; new offset in ds:dx
 mov ax,2509h
 mov dx,seg my_handler_int9
 mov ds,dx
 lea dx,my_handler_int9
 
 pushf
 cli ; stop interrupting
 int 21h
 popf ; continue interrupting
 
 pop es
 pop ds
 pop dx
 pop bx
 pop ax
 ret
 int9_change endp
 Процедуры ByteToHex и др. отлажены. |  
						| 
								|  |  
								|  |  Записан | 
 
 У тебя все получится, главное -- верить и делать.Порадоваться, когда все плохо -- легче, чем ты думаешь.
 В действии счастье.
 Вовлекая людей важно быть увлеченным чужой жизнью.
 |  |  | 
	| 
			| 
					
						| RXL | 
								|  | « Ответ #1 : 12-06-2012 18:19 »  |  | 
 
 KBAC, почему твой обработчик не сохраняет все регистры? Команды PUSHA и POPA. |  
						| 
								|  |  
								|  |  Записан | 
 
 ... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С. |  |  | 
	| 
			| 
					
						| Finch 
								СпокойныйАдминистратор    Offline 
								Пол:    
								Пролетал мимо
								
								
								
								
								
							 | 
								|  | « Ответ #2 : 12-06-2012 18:46 »  |  | 
 
 Из одного прерывания вызывать другое прерывание не рекомендуется. Насколько я понял ClearScreen и PrintStr_bios должны по идее говоря использовать. Насколько я помню, при вызове прерывания, флаг прерывания блокируется и во время выполнения прерывания, другие прерывания не вызываются. Разблакировка происходит при вызове iret. |  
						| 
								|  |  
								|  |  Записан | 
 
 Не будите спашяго дракона.              Джаффар (Коша) |  |  | 
	| 
			| 
					
						| RXL | 
								|  | « Ответ #3 : 12-06-2012 20:42 »  |  | 
 
 Finch, "программные прерывания" не маскируют аппаратные прерывания. Но по сути поддерживаю: мы ничего не знаем о вызываемых процедурах.
 Каскадирование обработчиков через long jmp допускается.
 |  
						| 
								|  |  
								|  |  Записан | 
 
 ... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С. |  |  | 
	| 
			| 
					
						| darkelf 
								Молодой специалист    Offline | 
								|  | « Ответ #4 : 13-06-2012 05:30 »  |  | 
 
 KBAC, кроме того, что сказали Finch и RXL, ещё в my_handler_int9 Вы вызываете jmp cs:old_handler, т.е. указатель old_handler у Вас в сегменте кода, а в int9_change - Вы сохраняете mov word ptr old_handler,bx - т.е. идёт неявная адресация по сегменту данных, проверьте, действительно они у Вас совпадают? Для избежания возможных проблем в будущем, тут лучше тоже. имхо, явно указывать, что ячейки находятся в cs. Кстати в данном случае word ptr, имхо, лишний - ассемблер по регистру bx сам может узнать, размерность приёмника. |  
						| 
								|  |  
								| « Последнее редактирование: 13-06-2012 08:14 от darkelf » |  Записан | 
 |  |  | 
	| 
			| 
					
						| KBAC | 
								|  | « Ответ #5 : 13-06-2012 12:30 »  |  | 
 
 RXL, пишу с использованием команд только 8086.  Я вообще сомневаюсь в использовании pushf в моем обработчике. Ведь команды  pushf call int_handler
  заменяет использование команды int. Наверно эта команда все же выполняется при вызове аппаратного прерывания. Т.е. если взять обработчик полностью заменяющий старый обработчик я должен в конце (из обязательного) поставить  mov al,20hdarkelfout 20h,al
 iret
 , С адресацией я действительно намудрил. Запутался в конец. |  
						| 
								|  |  
								| « Последнее редактирование: 13-06-2012 12:41 от KBAC » |  Записан | 
 
 У тебя все получится, главное -- верить и делать.Порадоваться, когда все плохо -- легче, чем ты думаешь.
 В действии счастье.
 Вовлекая людей важно быть увлеченным чужой жизнью.
 |  |  | 
	| 
			| 
					
						| Finch 
								СпокойныйАдминистратор    Offline 
								Пол:    
								Пролетал мимо
								
								
								
								
								
							 | 
								|  | « Ответ #6 : 13-06-2012 12:46 »  |  | 
 
 Все регистры ты в прерывании в любом случае должен сохранять в стеке. А потом, перед выходом из прерывания, вытаскивать из стека. Просто для 8086 это выглядит длинее. Кстати, старый обработчик имеет iret. Так что, лучше не мудрить и прыгать в него через jmp. |  
						| 
								|  |  
								|  |  Записан | 
 
 Не будите спашяго дракона.              Джаффар (Коша) |  |  | 
	| 
			| 
					
						| KBAC | 
								|  | « Ответ #7 : 13-06-2012 13:09 »  |  | 
 
 Finch, понятно что он имеет iret. call - в случае если надо его вызвать перед тем, как свой код сработает.И зачем мне сохранять все регистры, если я не пользуюсь всеми?
 |  
						| 
								|  |  
								|  |  Записан | 
 
 У тебя все получится, главное -- верить и делать.Порадоваться, когда все плохо -- легче, чем ты думаешь.
 В действии счастье.
 Вовлекая людей важно быть увлеченным чужой жизнью.
 |  |  | 
	| 
			| 
					
						| Dimka 
								ДеятельКоманда клуба    Offline 
								Пол:    | 
								|  | « Ответ #8 : 13-06-2012 13:16 »  |  | 
 
 И зачем мне сохранять все регистры, если я не пользуюсь всеми? А ты понимаешь, что такое прерывание? (С точки зрения состояний вычислительного процесса.) |  
						| 
								|  |  
								|  |  Записан | 
 
 Программировать - значит понимать (К. Нюгард)Невывернутое лучше, чем вправленное (М. Аврелий)
 Многие готовы скорее умереть, чем подумать (Б. Рассел)
 |  |  | 
	| 
			| 
					
						| KBAC | 
								|  | « Ответ #9 : 13-06-2012 13:19 »  |  | 
 
 Dimka, расскажи? Основную мысль, что ты хотел этим вопросом мне сказать. |  
						| 
								|  |  
								| « Последнее редактирование: 13-06-2012 13:35 от KBAC » |  Записан | 
 
 У тебя все получится, главное -- верить и делать.Порадоваться, когда все плохо -- легче, чем ты думаешь.
 В действии счастье.
 Вовлекая людей важно быть увлеченным чужой жизнью.
 |  |  | 
	| 
			| 
					
						| Finch 
								СпокойныйАдминистратор    Offline 
								Пол:    
								Пролетал мимо
								
								
								
								
								
							 | 
								|  | « Ответ #10 : 13-06-2012 13:50 »  |  | 
 
 С точки зрения текушего процесса, прерывание это по типу дубинкой по башке. Вот и нужно делать так, чтобы было наиболее безболезнено. По крайней мере, те регистры, которые используются, нужно экранировать. Кстати, регистр флагов также. А все экранируются, как зашита от забывчивости. Ты можеш добавлять и править код в последствии, И о данной особенности кода, что у тебя не все регистры заикранированы, можеш запросто забыть. |  
						| 
								|  |  
								|  |  Записан | 
 
 Не будите спашяго дракона.              Джаффар (Коша) |  |  | 
	| 
			| 
					
						| Sla | 
								|  | « Ответ #11 : 13-06-2012 15:06 »  |  | 
 
 Смотри... прерывание приходит в ЛЮБОЙ момент. Прерывается вычислительный процесс. Чтобы корректно продолжить работу, необходимо запомнить состояние "вычислителя" (push), обработать прерывание, и "запустить" (pop) опять вычислитель с того места где его прервали. Когда перехватываешь аппаратное прерывание, то ...  Необязательно отдавать "штатному" обработчику состояние - нужно корректно обработать. А можно  отдать и штатному, но для этого нужно понимать как штатный обработчик работает.  В основном все аппаратные прерывания работают с портами и оперативными регистрами.  Поэтому нужно сохранять/восстанавливать именно их.  зы. бывают случаи... это мы оставим для следующего поколения   |  
						| 
								|  |  
								|  |  Записан | 
 
 Мы все учились понемногу... Чему-нибудь и как-нибудь. |  |  | 
	| 
			| 
					
						| KBAC | 
								|  | « Ответ #12 : 13-06-2012 15:32 »  |  | 
 
 Finch, спс.  Где можно прочитать как обрабатывает ядро пришедшее на запрос прерывание?  Мне сегодня задали вопрос, как обрабатывает ЦП запрос на прерывание? Требовалось ответить, что цп останавливает конвейер (ждет выполнения последней задачи и больше ничего не запускает) и запускает обработку прерывания. Но так как это мне препод рассказал, то мне нужно ему в следующий раз более доходчиво объяснить как работает механизм прерывания   Sla , в таком случае надо вообще все регистры, т.е. не только РОН , в стек сохранять ?  И все таки не понятно, если аппаратное прерывание приходит, то pushf автоматически до моего кода будет происходить (командa int), или же мне надо в своем обработчике это проделать ?  |  
						| 
								|  |  
								|  |  Записан | 
 
 У тебя все получится, главное -- верить и делать.Порадоваться, когда все плохо -- легче, чем ты думаешь.
 В действии счастье.
 Вовлекая людей важно быть увлеченным чужой жизнью.
 |  |  | 
	| 
			| 
					
						| Finch 
								СпокойныйАдминистратор    Offline 
								Пол:    
								Пролетал мимо
								
								
								
								
								
							 | 
								|  | « Ответ #13 : 13-06-2012 15:44 »  |  | 
 
 Как раньше было    Сейчас просто настолько все интегрировано, что может быть и непраильные рассуждения. Была специальная микросхемка, которая заведовала прерываниями. Насколько я помню, в 8086 было 8 внешних прерываний. Начиная с 80286 поставили 2 такие микросхемки, Получилось 16 (вернее 15, одно прерывание шло на каскадирование) внешних прерываний. Так вот, когда приходило прерывания, схемка посыла на специальный вывод процессора сигнал. Процессор, дорабатывал текушее действие. Затем слал запрос на схемку, какое именно прерывание его потревожило. Запрашивал в памяти адрес обработчика прерывания. Позиционировал CS:IP на этот адрес и запирал флаг прерывания. Дальше уже работа происходила в штатном режиме с точки зрения процессора.  |  
						| 
								|  |  
								|  |  Записан | 
 
 Не будите спашяго дракона.              Джаффар (Коша) |  |  | 
	| 
			| 
					
						| RXL | 
								|  | « Ответ #14 : 13-06-2012 15:44 »  |  | 
 
 Sla, в таком случае надо вообще все регистры, т.е. не только РОН , в стек сохранять ? 
 Да! Все РОН, кроме SP и все сегментные, кроме SS и CS. Еще раз смотри работу команд PUSHA/POPA - тебе надо написать функциональный аналог. Регистр флагов сохранять тоже нет необходимости - для  аппаратного любого прерывания он сохраняется в стеке автоматически и восстанавливается командой iret. Входная процедура:     push axpush bx
 push cx
 push dx
 push bp
 push si
 push di
 mov ax, ds
 push ax
 mov ax. es
 push ax
 Выходная процедура:     pop axmov es, ax
 pop ax
 mov ds, ax
 pop di
 pop si
 pop bp
 pop dx
 pop cx
 pop bx
 pop ax
 ;    iret или far jmp
 |  
						| 
								|  |  
								| « Последнее редактирование: 13-06-2012 15:57 от RXL » |  Записан | 
 
 ... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С. |  |  | 
	| 
			| 
					
						| Sla | 
								|  | « Ответ #15 : 13-06-2012 16:04 »  |  | 
 
 KBAC, не обязательно сохранять все. Желательно!  Если ты работаешь только с аккумулятором, то зачем тебе сохранять все регистры? Вот гляди.. 1. Сохранили вектор прерывания 2. Установили свой обработчик Обработчик 1. Сохранили состояние 2. обработали 2.а Восстановили состояние 3. Вызвали старый вектор (он сам всем остальным займется мы ему доверяем) 4. Вернулись из прерывания Тут есть один момент, (давно с этим не работал) нужен ли в данном случае iret, скорей всего нуженhttp://www.codenet.ru/progr/dos/int_0007.php вот здесь перехват нужной кнопки Если нужная кнопка , то обработать, иначе отдать старому обработчику Это самый простой способ зы достоверность кода не гарантирую, но память подсказывает, что правильно. |  
						| 
								|  |  
								|  |  Записан | 
 
 Мы все учились понемногу... Чему-нибудь и как-нибудь. |  |  | 
	| 
			| 
					
						| RXL | 
								|  | « Ответ #16 : 13-06-2012 16:43 »  |  | 
 
 Sla, посмотри код в начальном посте. Тут сохранять надо все. |  
						| 
								|  |  
								|  |  Записан | 
 
 ... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С. |  |  | 
	| 
			| 
					
						| darkelf 
								Молодой специалист    Offline | 
								|  | « Ответ #17 :  14-06-2012 05:48 »   |  | 
 
 И все таки не понятно, если аппаратное прерывание приходит, то pushf автоматически до моего кода будет происходить (командa int), или же мне надо в своем обработчике это проделать ? 
 аппаратное прерывание и команда int это, имхо, всё-же концептуально разные вещи, очень похожие, но разные, т.к. int это не вызов аппаратного прерывания, это, скорее, попытка его эмулировать. Что происходит, когда происходит аппаратное прерывание описал Finch . |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| RXL | 
								|  | « Ответ #18 : 14-06-2012 06:54 »  |  | 
 
 darkelf, команда int тоже сохраняет флаги на стеке и тоже запрещает прерывания. Сверься со справочником.PIC, в том виде, в каком он был в 8086, посылал по шине номер вектора прерывания и процессор фактически выполнял команду int.
 |  
						| 
								|  |  
								|  |  Записан | 
 
 ... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С. |  |  | 
	| 
			| 
					
						| darkelf 
								Молодой специалист    Offline | 
								|  | « Ответ #19 : 14-06-2012 07:10 »  |  | 
 
 RXL, то, что она тоже выполняет такие действия, не значит, что это одно и тоже. Всё-таки в случае аппаратного прерывания инициатором является внешнее оборудование (в данном случае PIC) и оно является асинхронным, а во втором случае - пользовательская программа, и уже назвать асинхронным это прерывание сложновато.. Хотя, возможно, в данном случае это уже ньюансы. |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| RXL | 
								|  | « Ответ #20 : 14-06-2012 08:27 »  |  | 
 
 Согласен, что в аппаратном и программном прерывании политика разная, но команда одна. |  
						| 
								|  |  
								|  |  Записан | 
 
 ... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С. |  |  | 
	| 
			| 
					
						| KBAC | 
								|  | « Ответ #21 : 15-06-2012 13:21 »  |  | 
 
 Sla,То ли коменты неправильные, то ли я их неправильно понял. Что значит "кнопка вызова". Я сначала подумал, что это проверка на отпускание клавиши - но нет.  И, если это не POP_KEY, то мы обрабатываем клавишу по-обычному, иначе непонятные махинации, которые ,имхо, ничего не делают. Разве что проц успеет за какие-то доли секунды (пока делаем запись нового, чтение старого и снова запись значения) что-то сделать.  popup - это обратная операция push'у, я правильно понял?   push    axin      al,60H             ;читать ключ
 cmp     al,POP_KEY         ;это кнопка вызова?
 je      do_pop             ; да, активизировать popup
 ;  нет, уйти на исходный обработчик
 pop     ax
 jmp     cs:[int9_vect]     ;переход на первоначальный обработчик
 do_pop:  ;------ следующий код необходим для отработки аппаратного прерывания
 in      al,61H             ;взять значениe порта управления клавиатурой
 mov     ah,al              ; сохранить его
 or      al,80h             ;установить бит разрешения для клавиатуры
 out     61H,al             ; и вывести его в управляющий порт
 xchg    ah,al              ;извлечь исходное значение порта
 out     61H,al             ; и записать его обратно
 mov     al,20H             ;послать сигнал "конец прерывания"
 out     20H,al             ; контроллеру прерываний 8259
 ;------ дальше - прочие проверки, и наконец - активизация popup
 |  
						| 
								|  |  
								|  |  Записан | 
 
 У тебя все получится, главное -- верить и делать.Порадоваться, когда все плохо -- легче, чем ты думаешь.
 В действии счастье.
 Вовлекая людей важно быть увлеченным чужой жизнью.
 |  |  | 
	| 
			| 
					
						| Sla | 
								|  | « Ответ #22 : 15-06-2012 14:01 »  |  | 
 
 >Что значит "кнопка вызова"Та ничего не значит. Пример условный
 Прочитали содержимое 60-го порта
 Если там лежит нужный код (кнопка вызова) то обработать ее, иначе отдать все старому обработчику.
 
 ;послать сигнал "конец прерывания
 ; контроллеру прерываний 8259
 
 Пока не "пошлем" прерываний не будет
 |  
						| 
								|  |  
								|  |  Записан | 
 
 Мы все учились понемногу... Чему-нибудь и как-нибудь. |  |  | 
	| 
			| 
					
						| KBAC | 
								|  | « Ответ #23 : 17-06-2012 10:03 »  |  | 
 
 Что-то никак не могу починить свой код. Вот он новый.  .model small.stack 256d
 .data
 old_handler_offset dw ?
 old_handler_seg dw ?
 
 buffer db 10 dup (?)
 endl db 0Ah, 0Dh, '$'
 
 .code
 start:
 main proc
 assume cs:_text
 mov ax,@data
 mov ds,ax
 
 call int9_change ; exchange old_handler to my_handler
 
 jmp $
 
 call progover
 main endp
 
 ;=====================
 ; my interrupt handler
 ;=====================
 my_handler_int9 proc
 push ax
 push bx
 push dx
 push cx
 push bp
 push si
 push di
 push es
 push ds
 
 in al,60h
 and al,7Fh
 
 cmp al,01h
 je progover
 
 pop ds
 pop es
 pop di
 pop si
 pop bp
 pop cx
 pop dx
 pop bx
 pop ax
 
 jmp dword ptr old_handler_offset
 my_handler_int9 endp
 
 ;=================
 ; dos exit proc
 ;=================
 progover proc
 call int9_restore
 mov ax,4c01h        ; quit dos with 01 code
 int 21h
 progover endp
 
 ;=======================
 ; restore old_handler
 ;=======================
 int9_restore proc
 push ds
 push dx
 push ax
 
 mov ax,2509h
 mov dx,old_handler_seg
 mov ds,dx
 mov dx,old_handler_offset
 int 21h
 
 pop ax
 pop dx
 pop ds
 ret
 int9_restore endp
 
 ;================================
 ; change interrupt handler
 ;================================
 int9_change proc
 push ax
 push bx
 push dx
 push ds
 push es
 
 ; get old_handler
 mov ax,3509h ; ah = 35, al = 9 (irq1)
 int 21h ; get old_handler offset in es:bx
 
 ; remember old_handler's offset
 mov old_handler_offset,bx
 mov old_handler_seg,es
 
 ;write my_handler offset to vector's table
 ; new offset in ds:dx
 mov ax,2509h
 mov dx,seg my_handler_int9
 mov ds,dx
 lea dx,my_handler_int9
 
 pushf
 cli ; stop interrupting
 int 21h
 popf ; continue interrupting
 
 pop es
 pop ds
 pop dx
 pop bx
 pop ax
 ret
 int9_change endp
 
 end start
 Интересует как правильно делать far jmp.  т.е. когда я пишу jmp old_handler_offset ассемблер должен видеть, что первое слово содержит смещение не из сегмента, где сама команда jmp  и берет селектор сегмента из второго слова? Еще я не уверен, что правильно запоминаю адрес старого обработчика.  Потому что как только я пытаюсь сделать jmp моя прога виснет. Еще не понятно чем отличаются следующие записи  mov      eax,dword ptr es:[87h*4]mov      eax,dword ptr es:87h
 Понятно, что адресацией. Как я понимаю: в первом случае мы берем двойное слово, хранящееся по смещению es + 87; а во втором у нас идет автоматическая подстановка ассемблером операнда в код. Но какая разница?  И зачем писать 87h * 4, если написано dword ptr? ================== С far jmp более менее разобрался. Обновил код. Теперь не заружается старый обработчик. Т.е. когда я возвращаюсь в дос, то клава не работает - на консоле не выводятся символы.  |  
						| 
								|  |  
								| « Последнее редактирование: 17-06-2012 11:47 от KBAC » |  Записан | 
 
 У тебя все получится, главное -- верить и делать.Порадоваться, когда все плохо -- легче, чем ты думаешь.
 В действии счастье.
 Вовлекая людей важно быть увлеченным чужой жизнью.
 |  |  | 
	| 
			| 
					
						| RXL | 
								|  | « Ответ #24 : 17-06-2012 17:01 »  |  | 
 
 KBAC, извини, но ты какой-то бред несешь. Сам написал и сам не понимаешь, чего написал. Не говоря уже про грамматику. Ты хоть знаешь, что надо получить? Искал описание синтаксиса твоего ассемблера (компилятора)? |  
						| 
								|  |  
								| « Последнее редактирование: 17-06-2012 17:12 от RXL » |  Записан | 
 
 ... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С. |  |  | 
	| 
			| 
					
						| KBAC | 
								|  | « Ответ #25 : 17-06-2012 19:56 »  |  | 
 
 Я уже все сам доделал. Всем спасибо.  На каждую кнопочку генерится разный звук теперь.  Осталось лишь понять почему при первом нажатии на кнопку клавиатуры идет щелкающий звук, как будто колонки включаются и сразу отключаются, а после уже программа адекватно на все реагирует.  .model small.stack 256d
 .data
 old_handler_offset dw ?
 old_handler_seg dw ?
 
 timer_channel_0 EQU 40h
 timer_channel_2 EQU 42h
 timer_ManageRegister            EQU 43h
 loudspeaker_ManageRegister      equ 61h
 loudspeaker_lngt equ 1000
 
 ; table notes
 do_1 dd 4591EEh
 .code
 start:
 main proc
 assume cs:_text
 mov ax,@data
 mov ds,ax
 
 call int9_change ; exchange old_handler to my_handler
 
 jmp $
 
 call progover
 main endp
 
 ;=====================
 ; my interrupt handler
 ;=====================
 my_handler_int9 proc
 push ax
 push bx
 
 in al,60h
 push ax
 mov bx,ax ; bx uses in Bdeni
 and al,80h
 jnz key_pop
 
 call Bdeni
 
 key_pop:
 pop ax
 and al,07Fh     ; get clear scan-code of key
 
 cmp al,01h ; if esc pushed
 je progover
 
 mov al,20h ; end
 out 20h,al ; of interrupt
 
 pop bx
 pop ax
 ; jmp dword ptr old_handler_offset
 
 iret
 my_handler_int9 endp
 
 ;=================
 ; dos exit proc
 ;=================
 progover proc
 mov al,20h ; end
 out 20h,al ; of interrupt
 
 call int9_restore
 mov ax,4c01h        ; quit dos with 01 code
 int 21h
 progover endp
 
 ;=======================
 ; restore old_handler
 ;=======================
 int9_restore proc
 push ds
 push dx
 push ax
 
 mov ax,2509h
 lds dx,dword ptr old_handler_offset
 ; mov dx,word ptr old_handler_seg
 ; mov ds,dx
 ; mov dx,word ptr old_handler_offset
 int 21h
 
 pop ax
 pop dx
 pop ds
 ret
 int9_restore endp
 
 ;================================
 ; change interrupt handler
 ;================================
 int9_change proc
 push ax
 push bx
 push dx
 push ds
 push es
 
 ; get old_handler
 mov ax,3509h ; ah = 35, al = 9 (irq1)
 int 21h ; get old_handler offset in es:bx
 
 ; remember old_handler's offset
 mov word ptr old_handler_offset,bx
 mov word ptr old_handler_seg,es
 
 ;write my_handler offset to vector's table
 ; new offset in ds:dx
 mov ax,2509h
 mov dx,seg my_handler_int9
 mov ds,dx
 lea dx,my_handler_int9
 
 pushf
 cli ; stop interrupting
 int 21h
 popf ; continue interrupting
 
 pop es
 pop ds
 pop dx
 pop bx
 pop ax
 ret
 int9_change endp
 ;===================
 ; Beep
 ; input - bx = key code
 ;
 ; each channel ticks with the same rate
 ; v = 1,19318 MHz
 ; i.e v/(Amount of needed ticks) = requied freaquency
 ;===================
 Bdeni proc
 push ax
 push di
 push bp
 xor di,di
 xor bp,bp
 
 and bx, 07fh ; clear scan-code
 
 ; programming timer for channel 2
 ;manage string: SC RW M BCD
 mov al,         10110110b
 out timer_ManageRegister,al             ; send to chan
 
 mov ax,0100h            ; the higher val the lower sound
 mul bx
 out timer_channel_2,al
 mov al,ah
 out timer_channel_2,al
 
 ; turning on loudspeaker
 in al,loudspeaker_ManageRegister
 or al,03h       ; last two bites is 1 for channel 2 and for loudspk
 out loudspeaker_ManageRegister, al
 
 ; delay for not immediately turning off of ldspk
 mov bp,00h              ; little part
 mov di,0ffh             ; big part
 call delay1
 
 ; turning off loudspeaker
 in al,loudspeaker_ManageRegister
 and al,11111100b        ; last two bites is 0
 out loudspeaker_ManageRegister, al
 
 pop bp
 pop di
 pop ax
 ret
 Bdeni endp
 
 ;====================
 ; with help of counter-latch-command
 ; input - di:bp (length of signal)
 ;====================
 delay1 proc
 push ax
 push bx
 push cx
 push dx
 push si
 
 xor ax,ax ; latch of CE
 out timer_ManageRegister,al
 
 in al, timer_channel_0  ; Chtenie tekyshego znacheniya schetchika
 mov ah, al
 in al, timer_channel_0
 
 xor cx,cx ; for delta LEAST meaning word
 xor si,si       ; for delta MOST meaning word
 
 LOAD_NEW_VAL:
 mov bx,ax               ; old val to bx
 xor ax,ax ; latch of CE
 out timer_ManageRegister,al
 
 in al, timer_channel_0
 mov ah, al
 in al, timer_channel_0      ; new val to ax
 
 cmp ax,bx
 je LOAD_NEW_VAL ; means no ticks there are yet
 ja CMP2
 jb CMP3
 
 CMP2:   ; ax > bx
 ; find delta
 mov dx, 0ffffh ; high value of counter
 sub dx,ax
 add dx,bx
 add cx,dx
 jo OVERLOAD_CX
 
 start_cmp:
 jmp CMP_delta_delay
 
 CMP3:   ; ax < bx
 mov dx,bx
 sub dx,ax
 add cx,dx
 jo OVERLOAD_CX
 
 CMP_delta_delay:
 cmp di,0 ; di > 0 ?
 je DI0
 
 _DI:
 cmp di,si       ; cmp more signed word of delay and delta
 jb end2                 ; delay < si
 je CMP_cx_bp    ; di = si
 ja LOAD_NEW_VAL
 
 DI0: ; di = 0
 cmp si,0
 jne end2
 CMP_cx_bp:
 cmp bp,cx ; cmp delay delta referently
 ja LOAD_NEW_VAL
 jb end2
 je LOAD_NEW_VAL
 
 OVERLOAD_CX:
 inc si ; most signed word +=1
 jmp start_cmp
 
 end2:
 pop si
 pop dx
 pop cx
 pop bx
 pop ax
 ret
 delay1 endp
 
 end start
 |  
						| 
								|  |  
								| « Последнее редактирование: 17-06-2012 20:01 от KBAC » |  Записан | 
 
 У тебя все получится, главное -- верить и делать.Порадоваться, когда все плохо -- легче, чем ты думаешь.
 В действии счастье.
 Вовлекая людей важно быть увлеченным чужой жизнью.
 |  |  | 
	|  |