Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Замена обработчика асинхронного прерывания.  (Прочитано 22409 раз)
0 Пользователей и 11 Гостей смотрят эту тему.
KBAC
Постоялец

ru
Offline Offline
Пол: Мужской

« : 12-06-2012 14:45 » 

Здравствуйте всем. Надо заменить обработчик прерывания irq1. У меня получается его подменить, но выполняется он почему-то только один раз. А на дальнейшие дествия не реагирует.
Код: (ASM)
;=====================
; 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
Код: (ASM)
main proc
        assume 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
Код: (ASM)
;================================
; 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
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #1 : 12-06-2012 18:19 » new

KBAC, почему твой обработчик не сохраняет все регистры? Команды PUSHA и POPA.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #2 : 12-06-2012 18:46 » 

Из одного прерывания вызывать другое прерывание не рекомендуется. Насколько я понял ClearScreen и PrintStr_bios должны по идее говоря использовать. Насколько я помню, при вызове прерывания, флаг прерывания блокируется и во время выполнения прерывания, другие прерывания не вызываются. Разблакировка происходит при вызове iret.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #3 : 12-06-2012 20:42 » 

Finch, "программные прерывания" не маскируют аппаратные прерывания. Но по сути поддерживаю: мы ничего не знаем о вызываемых процедурах.

Каскадирование обработчиков через long jmp допускается.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
darkelf
Молодой специалист

de
Offline 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
Постоялец

ru
Offline Offline
Пол: Мужской

« Ответ #5 : 13-06-2012 12:30 » 

RXL, пишу с использованием команд только 8086.
Я вообще сомневаюсь в использовании pushf в моем обработчике. Ведь команды
Код: (ASM)
pushf
call int_handler
заменяет использование команды int. Наверно эта команда все же выполняется при вызове аппаратного прерывания. Т.е. если взять обработчик полностью заменяющий старый обработчик я должен в конце (из обязательного) поставить
Код: (ASM)
mov al,20h
out 20h,al
iret
darkelf, С адресацией я действительно намудрил. Запутался в конец.
« Последнее редактирование: 13-06-2012 12:41 от KBAC » Записан

У тебя все получится, главное -- верить и делать.
Порадоваться, когда все плохо -- легче, чем ты думаешь.
В действии счастье.
Вовлекая людей важно быть увлеченным чужой жизнью.
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #6 : 13-06-2012 12:46 » 

Все регистры ты в прерывании в любом случае должен сохранять в стеке. А потом, перед выходом из прерывания, вытаскивать из стека. Просто для 8086 это выглядит длинее. Кстати, старый обработчик имеет iret. Так что, лучше не мудрить и прыгать в него через jmp.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
KBAC
Постоялец

ru
Offline Offline
Пол: Мужской

« Ответ #7 : 13-06-2012 13:09 » 

Finch, понятно что он имеет iret. call - в случае если надо его вызвать перед тем, как свой код сработает.
И зачем мне сохранять все регистры, если я не пользуюсь всеми?
Записан

У тебя все получится, главное -- верить и делать.
Порадоваться, когда все плохо -- легче, чем ты думаешь.
В действии счастье.
Вовлекая людей важно быть увлеченным чужой жизнью.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #8 : 13-06-2012 13:16 » 

Цитата: КВАС
И зачем мне сохранять все регистры, если я не пользуюсь всеми?
А ты понимаешь, что такое прерывание? (С точки зрения состояний вычислительного процесса.)
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
KBAC
Постоялец

ru
Offline Offline
Пол: Мужской

« Ответ #9 : 13-06-2012 13:19 » 

Dimka, расскажи? Основную мысль, что ты хотел этим вопросом мне сказать.
« Последнее редактирование: 13-06-2012 13:35 от KBAC » Записан

У тебя все получится, главное -- верить и делать.
Порадоваться, когда все плохо -- легче, чем ты думаешь.
В действии счастье.
Вовлекая людей важно быть увлеченным чужой жизнью.
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #10 : 13-06-2012 13:50 » 

С точки зрения текушего процесса, прерывание это по типу дубинкой по башке. Вот и нужно делать так, чтобы было наиболее безболезнено. По крайней мере, те регистры, которые используются, нужно экранировать. Кстати, регистр флагов также. А все экранируются, как зашита от забывчивости. Ты можеш добавлять и править код в последствии, И о данной особенности кода, что у тебя не все регистры заикранированы, можеш запросто забыть.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Sla
Модератор

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #11 : 13-06-2012 15:06 » 

Смотри...
прерывание приходит в ЛЮБОЙ момент.
Прерывается вычислительный процесс.
Чтобы корректно продолжить работу, необходимо запомнить состояние "вычислителя" (push), обработать прерывание, и "запустить" (pop) опять вычислитель с того места где его прервали.

Когда перехватываешь аппаратное прерывание, то ...
Необязательно отдавать "штатному" обработчику состояние - нужно корректно обработать.
А можно  отдать и штатному, но для этого нужно понимать как штатный обработчик работает.
В основном все аппаратные прерывания работают с портами и оперативными регистрами.
Поэтому нужно сохранять/восстанавливать именно их.

зы. бывают случаи... это мы оставим для следующего поколения Улыбаюсь
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
KBAC
Постоялец

ru
Offline Offline
Пол: Мужской

« Ответ #12 : 13-06-2012 15:32 » 

Finch, спс.
Где можно прочитать как обрабатывает ядро пришедшее на запрос прерывание?
Мне сегодня задали вопрос, как обрабатывает ЦП запрос на прерывание? Требовалось ответить, что цп останавливает конвейер (ждет выполнения последней задачи и больше ничего не запускает) и запускает обработку прерывания. Но так как это мне препод рассказал, то мне нужно ему в следующий раз более доходчиво объяснить как работает механизм прерывания Улыбаюсь
Sla, в таком случае надо вообще все регистры, т.е. не только РОН , в стек сохранять ?
И все таки не понятно, если аппаратное прерывание приходит, то pushf автоматически до моего кода будет происходить (командa int), или же мне надо в своем обработчике это проделать ?
Записан

У тебя все получится, главное -- верить и делать.
Порадоваться, когда все плохо -- легче, чем ты думаешь.
В действии счастье.
Вовлекая людей важно быть увлеченным чужой жизнью.
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #13 : 13-06-2012 15:44 » 

Как раньше было Улыбаюсь Сейчас просто настолько все интегрировано, что может быть и непраильные рассуждения. Была специальная микросхемка, которая заведовала прерываниями. Насколько я помню, в 8086 было 8 внешних прерываний. Начиная с 80286 поставили 2 такие микросхемки, Получилось 16 (вернее 15, одно прерывание шло на каскадирование) внешних прерываний. Так вот, когда приходило прерывания, схемка посыла на специальный вывод процессора сигнал. Процессор, дорабатывал текушее действие. Затем слал запрос на схемку, какое именно прерывание его потревожило. Запрашивал в памяти адрес обработчика прерывания. Позиционировал CS:IP на этот адрес и запирал флаг прерывания. Дальше уже работа происходила в штатном режиме с точки зрения процессора.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #14 : 13-06-2012 15:44 » 

Sla, в таком случае надо вообще все регистры, т.е. не только РОН , в стек сохранять ?

Да! Все РОН, кроме SP и все сегментные, кроме SS и CS. Еще раз смотри работу команд PUSHA/POPA - тебе надо написать функциональный аналог.

Регистр флагов сохранять тоже нет необходимости - для аппаратного любого прерывания он сохраняется в стеке автоматически и восстанавливается командой iret.

Входная процедура:

Код: (ASM)
    push ax
    push bx
    push cx
    push dx
    push bp
    push si
    push di
    mov ax, ds
    push ax
    mov ax. es
    push ax

Выходная процедура:

Код: (ASM)
    pop ax
    mov 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
Модератор

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #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
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #16 : 13-06-2012 16:43 » 

Sla, посмотри код в начальном посте. Тут сохранять надо все.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
darkelf
Молодой специалист

de
Offline Offline

« Ответ #17 : 14-06-2012 05:48 » 

И все таки не понятно, если аппаратное прерывание приходит, то pushf автоматически до моего кода будет происходить (командa int), или же мне надо в своем обработчике это проделать ?
аппаратное прерывание и команда int это, имхо, всё-же концептуально разные вещи, очень похожие, но разные, т.к. int это не вызов аппаратного прерывания, это, скорее, попытка его эмулировать. Что происходит, когда происходит аппаратное прерывание описал Finch.
Записан
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #18 : 14-06-2012 06:54 » 

darkelf, команда int тоже сохраняет флаги на стеке и тоже запрещает прерывания. Сверься со справочником.
PIC, в том виде, в каком он был в 8086, посылал по шине номер вектора прерывания и процессор фактически выполнял команду int.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
darkelf
Молодой специалист

de
Offline Offline

« Ответ #19 : 14-06-2012 07:10 » 

RXL, то, что она тоже выполняет такие действия, не значит, что это одно и тоже. Всё-таки в случае аппаратного прерывания инициатором является внешнее оборудование (в данном случае PIC) и оно является асинхронным, а во втором случае - пользовательская программа, и уже назвать асинхронным это прерывание сложновато.. Хотя, возможно, в данном случае это уже ньюансы.
Записан
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #20 : 14-06-2012 08:27 » 

Согласен, что в аппаратном и программном прерывании политика разная, но команда одна.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
KBAC
Постоялец

ru
Offline Offline
Пол: Мужской

« Ответ #21 : 15-06-2012 13:21 » 

Sla,То ли коменты неправильные, то ли я их неправильно понял. Что значит "кнопка вызова". Я сначала подумал, что это проверка на отпускание клавиши - но нет.
И, если это не POP_KEY, то мы обрабатываем клавишу по-обычному, иначе непонятные махинации, которые ,имхо, ничего не делают. Разве что проц успеет за какие-то доли секунды (пока делаем запись нового, чтение старого и снова запись значения) что-то сделать.
popup - это обратная операция push'у, я правильно понял?
 
Код: (ASM)
 push    ax
         in      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
Модератор

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #22 : 15-06-2012 14:01 » 

>Что значит "кнопка вызова"
Та ничего не значит. Пример условный
Прочитали содержимое 60-го порта
Если там лежит нужный код (кнопка вызова) то обработать ее, иначе отдать все старому обработчику.

;послать сигнал "конец прерывания
; контроллеру прерываний 8259

Пока не "пошлем" прерываний не будет
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
KBAC
Постоялец

ru
Offline Offline
Пол: Мужской

« Ответ #23 : 17-06-2012 10:03 » 

Что-то никак не могу починить свой код. Вот он новый.
Код: (ASM)
.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 моя прога виснет.

Еще не понятно чем отличаются следующие записи
Код: (ASM)
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
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #24 : 17-06-2012 17:01 » 

KBAC, извини, но ты какой-то бред несешь. Сам написал и сам не понимаешь, чего написал. Не говоря уже про грамматику. Ты хоть знаешь, что надо получить? Искал описание синтаксиса твоего ассемблера (компилятора)?
« Последнее редактирование: 17-06-2012 17:12 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
KBAC
Постоялец

ru
Offline Offline
Пол: Мужской

« Ответ #25 : 17-06-2012 19:56 » 

Я уже все сам доделал. Всем спасибо.
На каждую кнопочку генерится разный звук теперь.
Осталось лишь понять почему при первом нажатии на кнопку клавиатуры идет щелкающий звук, как будто колонки включаются и сразу отключаются, а после уже программа адекватно на все реагирует.
Код: (ASM)
.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 » Записан

У тебя все получится, главное -- верить и делать.
Порадоваться, когда все плохо -- легче, чем ты думаешь.
В действии счастье.
Вовлекая людей важно быть увлеченным чужой жизнью.
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines