Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

RFpro.ru: Ассемблер? Это просто! Учимся программировать


Хостинг портала RFpro.ru:
Московский хостер
Профессиональный ХОСТИНГ на базе Linux x64 и Windows x64

РАССЫЛКИ ПОРТАЛА RFPRO.RU

Чемпионы рейтинга экспертов в этой рассылке

Boriss
Статус: Академик
Рейтинг: 2484
∙ повысить рейтинг »
_Ayl_
Статус: Профессионал
Рейтинг: 1939
∙ повысить рейтинг »
vladisslav
Статус: 6-й класс
Рейтинг: 1227
∙ повысить рейтинг »

/ КОМПЬЮТЕРЫ И ПО / Программирование / Assembler (Ассемблер)

Номер выпуска:1369
Дата выхода:30.06.2010, 22:00
Администратор рассылки:Лысков Игорь Витальевич, Старший модератор
Подписчиков / экспертов:232 / 63
Вопросов / ответов:1 / 1
IRC-канал по теме:#assembler

Вопрос № 179170: Уважаемые эксперты! Требуется написать программу(с комментариями).Разработать резидентную программу для ОС MSDOS. Программа может быть выполнена в виде exe или com файла.При нажатии клавиши F12 программа заменяет вводимые пользователем алфавитные сим...



Вопрос № 179170:

Уважаемые эксперты! Требуется написать программу(с комментариями).Разработать резидентную программу для ОС MSDOS. Программа может быть выполнена в виде exe или com файла.При нажатии клавиши F12 программа заменяет вводимые пользователем алфавитные символы на другие (например q->w, w->e, e->r и т.д.). Ассемблер TASM. Буду очень признателен если сделаете программу.

Отправлен: 20.06.2010, 21:38
Вопрос задал: Филимонов Алексей Викторович, 1-й класс
Всего ответов: 1
Страница вопроса »


Отвечает amnick, Профессионал :
Здравствуйте, Филимонов Алексей Викторович.

Эту задачу можно решить, перехватывая прерывание клавиатурное прерывание: 9 (аппаратное) или 16h (программное). Более универсальным методом является перехват int 9, но он несколько сложнее в реализации. В моей программе перехватывается int 16h.

Сначала программа проверяет, установлена ли она уже в памяти, если да, то выводится сообщение и выполнение завершается. Если программа еще не установлена, то резидентный код перемещается в младшие адреса для экономии памяти (в PSP по смещению 5Ch — это вполне безопасно), освобождается сегмент окружения, перехватывается вектор 16h и программа завершается с оставлением в памяти резидентной части. Программа занимает в памяти всего 320 байт.

Резидентный код сначала проверяет вызванную функцию прерывания 16h. Мы обрабатываем ф-и 0, 1, 10h и 11h, остальные функции передаются оригинальному обработчику. Для перечисленных функций сначала вызывается оригинальный код прерывания, а затем анализируется возвращенное значение. Небольшое отличие заключается в том, что для ф-й 1 и 11h после возврата из оригинального обработчика необходимо проверить флаг нуля — если никакая клавиша не была нажата, то перекодирование не требуется. Затем проверяется, не была ли нажата клавиша F12. Если да, то переключается режим перекодирования — вкл/выкл. Нажатие клавиши F12 "не съедается", т.е. вызвавшая программа получит код клавиши. Здесь есть такой момент: если вызывается ф-я 11h, а затем 10h, то при нажатии F12 режим перекодирования переключится дважды, т.е. не переключится вообще. Чтобы избежать этого, нужно обрабатывать F12 так, как будто никакая клавиша не была нажата вообще.

Затем проверяется, нажата буквенная клавиша или нет. Для буквенных клавиш выполняется перекодирование по таблице (здесь - просто циклический сдвиг). Вот, собственно, и все.

Программу компилировать в COM-файл.

Успехов!

Код:
locals @@
.model tiny

HOTKEY = 8600h ; расширенный код F12

; вопрос/ответ для проверки, установлен ли обработчик
MY_QUESTION = 0AFE7h
MY_ANSWER = 64D9h

; изменение адресов после перемещения резидентной части
delta EQU (offset keyTable - 5Ch)

.code
.startup

jmp Install ; переходим на код инициализации

; ---- начало резидентной части ----
; таблица перекодировки клавиш
; заменяются и скан-коды, и соответствующие им символы
keyTable label word
; скан-код нажатой клавиши
; |
; | v----- на какой заменяется
db 'E',12h ; 16 -> 18
db 'R',13h ; 17 -> 19
db 'T',14h ; 18 -> 20
db 'Y' ,15h ; 19 -> 21
db 'U',16h ; 20 -> 22
db 'I',17h ; 21 -> 23
db 'O',18h ; 22 -> 24
db 'P',19h ; 23 -> 25
db 'A',1eh ; 24 -> 30
db 'S',1fh ; 25 -> 31
dw 0 ; 26
dw 0 ; 27
dw 0 ; 28
dw 0 ; 29
db 'D',20h ; 30 -> 32
db 'F',21h ; 31 -> 33
db 'G',22h ; 32 -> 34
db 'H',23h ; 33 -> 35
db 'J',24h ; 34 -> 36
db 'K',25h ; 35 -> 37
db 'L',26h ; 36 -> 38
db 'Z',2ch ; 37 -> 44
db 'X',2dh ; 38 -> 45
dw 0 ; 39
dw 0 ; 40
dw 0 ; 41
dw 0 ; 42
dw 0 ; 43
db 'C',2eh ; 44 -> 46
db 'V',2fh ; 45 -> 47
db 'B',30h ; 46 -> 48
db 'N',31h ; 47 -> 49
db 'M',32h ; 48 -> 50
db 'Q',10h ; 49 -> 16
db 'W',11h ; 50 -> 1 7

my_int16:
cmp ax,MY_QUESTION ; проверка наличия в памяти?
jne @@1
mov ax,MY_ANSWER ; ответ: обработчик уже установлен
iret
@@1:
; обрабатываем функции 0, 1, 10h, 11h прерывания 16h
cmp ah,1
jb @@f0
je @@f1
cmp ah,10h
jb @@old
je @@f0
cmp ah,11h
je @@f1
@@old: ; иная функция, передаем управление старому обработчику
db 0EAh ; код JMP FAR
int16_ptr dd 0 ; адрес перехода

@@f0: ; функции 0 и 10h
; сначала вызовем старый обработчик прерывания
pushf
call dword ptr CS:[int16_ptr-delta]
jmp short @@common

@@f1: ; функции 1 и 11h
; сначала вызовем старый обработчик прерывания
pushf
call dword ptr CS:[int16_ptr-delta]
jz @@ret2 ; не была нажата клавиша

@@common:
pushf ; сохраняем флаги - нужно для 1, 11h

cmp ax,HOTKEY ; была нажата клавиша вкл/выкл перекодировки?
jne @@no_hotkey ; нет

cmp byte ptr CS:[@@no_hotkey+1-delta],al ; дистанция перехода = 0?
jne @@on
; выключаем перекодировку
mov byte ptr CS:[@@no_hotkey+1-delta],offset @@ret - offset @@encode
jmp short @@ret
@@on:
; включаем перекодировку
mov byte ptr CS:[@@no_hotkey+1-delta],al ; 0 - переход на следующую команду
jmp short @@ret

@@no_hotkey: ; если перекодировка выкл (начальное состояние), то выходим
jmp short @@ret ; при включении - просто переходим к следующей команде

@@encode:
test al,al
jz @@ret ; AL = 0 - расширенный код

; проверяем попадание скан-кода в диапазон буквенных латинских клавиш
cmp ah,10h
jb @@ret ; не латинская буква
cmp ah,32h
ja @@ret ; не латинская буква

push bx ; сохраняем используемый регистр
mov bl,ah
xor bh,bh
shl bx,1 ; индексируем массив слов
add bx,offset keyTable - 10h*2 - delta ; смещение таблицы перекодировки со сдвигом
cmp byte ptr CS:[bx],0
je @@no_code ; не латинская буква

cmp al,'a' ; сравнение для определения "прописная - строчная"
mov ax,CS:[bx] ; скан- и ASCII-коды клавиши
jb @@no_code ; и сходный код меньше 'a' - прописная буква
or al,20h ; преобразование в строчную
@@no_code:
pop bx ; восстанавливаем измененный регист
@@ret:
popf ; восстанавливаем флаги после оригинального прерывания
@@ret2:
retf 2 ; возвращаемся с отбрасыванием старых флагов

; ---- конец резидентной части ----

Install: ; код инициализации
mov ah,9 ; AH=9 - вывод сообщения
mov dx,offset msgInfo ; DS:DX - адрес строки
int 21h

mov ax,MY_QUESTION ; проверить наличие в памяти
int 16h
cmp ax,MY_ANSWER ; сравнить с ответом
jne @@set

; программа уже установлена
mov ah,9 ; AH=9 - вывод сообщения
mov dx,offset msgAlready ; DS:DX - адрес строки
int 21h
int 20h ; выход

@@set:
; перемещаем резидентный код для экономии памяти
mov si,offset keyTable
mov di,5Ch
mov cx,(offset Install - offset keyTable + 1)/2 ; кол-во слов
cld
rep movsw

mov ah,49h ; осво бождаем блок окружения (environment)
mov ES,DS:[2Ch] ; сегмент блока окружения
int 21h

; перехватываем прерывание 16h
mov ax,3516h ; AH = 35h - получить вектор, AL - прерывание
int 21h
mov word ptr DS:[int16_ptr-delta],bx ; ES:BX - адрес
mov word ptr DS:[int16_ptr-delta+2],ES

mov ah,25h ; AH = 25h - установить вектор, AL - прерывание
mov dx,offset my_int16 -delta ; DS:DX - адрес обработчика
int 21h

mov dx,offset Install - delta ; адрес конца резидентной части
int 27h ; оставляем резидентный код в памяти и выходим

msgInfo db 'Keyboard encoder',13,10
db 'Press F12 to activate/deactivate encoding',13,10,'$'
msgAlready db 'The encoder has been installed already', 13,10,'$'

end

Ответ отправил: amnick, Профессионал
Ответ отправлен: 24.06.2010, 21:34
Номер ответа: 262272

Вам помог ответ? Пожалуйста, поблагодарите эксперта за это!
Как сказать этому эксперту "спасибо"?
  • Отправить SMS #thank 262272 на номер 1151 (Россия) | Еще номера »
  • Отправить WebMoney:

  • Оценить выпуск »
    Нам очень важно Ваше мнение об этом выпуске рассылки!

    Задать вопрос экспертам этой рассылки »

    Скажите "спасибо" эксперту, который помог Вам!

    Отправьте СМС-сообщение с тестом #thank НОМЕР_ОТВЕТА
    на короткий номер 1151 (Россия)

    Номер ответа и конкретный текст СМС указан внизу каждого ответа.

    Полный список номеров »

    * Стоимость одного СМС-сообщения от 7.15 руб. и зависит от оператора сотовой связи. (полный список тарифов)
    ** При ошибочном вводе номера ответа или текста #thank услуга считается оказанной, денежные средства не возвращаются.
    *** Сумма выплаты эксперту-автору ответа расчитывается из суммы перечислений на портал от биллинговой компании.


    © 2001-2010, Портал RFpro.ru, Россия
    Авторское право: ООО "Мастер-Эксперт Про"
    Автор: Калашников О.А. | Программирование: Гладенюк А.Г.
    Хостинг: Компания "Московский хостер"
    Версия системы: 2010.6.16 от 26.05.2010

    В избранное