Файл: О.А.Калашников. Ассемблер Это Просто. Учимся программировать.pdf
Добавлен: 16.02.2019
Просмотров: 36874
Скачиваний: 1802

Глава 15. Обработка аппаратных прерываний
159
абсолютно не надо! Поэтому мы вызываем прежний обработчик прерывания
21h
,
который использовался до загрузки нашего резидента. Это может быть как другой
резидент, так и само ядро DOS. Получается своего рода "фильтр" прерывания
21h
.
Программист может "фильтровать" те или иные функции прерывания и делать
с ними все, что посчитает нужным!
Итак, передали управление прежнему обработчику. Он нам вернул информацию
о найденном файле в DTA. Что дальше?
"Но мы не знаем, где в памяти находится этот DTA!" — скажете вы. Верно, не
знаем. Он может быть где угодно. Получить адрес DTA позволяет функция
2Fh
прерывания
21h
. Но обратите внимание, как мы теперь вызываем
21h
:
int 21h
Почему так? Вызвав
21h
стандартной командой
int 21h
, процессор попадет на
начало нашего обработчика, в самое начало процедуры
Int_21h_proc
. Рассуждаем
так: в этот момент в регистре
ah
у нас находится число
2Fh
. Теперь посмотрите
внимательно, что произойдет, если наша процедура
Int_21h_proc
получит управ-
ление с находящимся в
ah
числом
2Fh
.
А если она же получит управление с числом
4Fh
в
ah
? Вот именно! Поэтому мы,
в случае вызова прерывания
21h
с числом
4Eh
или
4Fh
, вызываем напрямую преж-
ний обработчик командой
call dword ptr cs:[Int_21h_vect]
, а с любым другим
числом — наш обработчик командой
int 21h
. Зачем так делать? Дело в том, что
второй вариант занимает меньше байтов, да и работает быстрее...
Адрес DTA получили. Теперь необходимо получить случайное число. Это мож-
но сделать, вызвав функцию
2Ch
прерывания
21h
, которая вернет в определенных
регистрах текущее время. В файле-приложении вы найдете подробное описание.
1
5.5. Логические команды процессора
Пришло время рассмотреть логические команды процессора, которые использу-
ются в файле-приложении. Логических команд всего несколько:
and
,
or
,
xor
.
Проще всего объяснить их действие на примерах. Главное — понять принцип.
Мы еще не раз будем использовать логические операторы. Это одна из быстрых
и простых вещей ассемблера, в отличие от языков высокого уровня.
15.5.1. Оператор or
Оператор
or
(ИЛИ) служит для включения определенных битов (не байтов!)
в регистре, переменной или в памяти (табл. 15.1 и рис. 15.2).
mov ax,1010b
or ax,1111b
;Теперь ax=1111b=0Fh. Таким образом мы включили (установили)
;первые четыре бита.
Часть III. Файловая оболочка, вирус, резидент
160
Таблица 15.1. Результат работы команды
or
Первый бит
Второй бит
Результат работы or
1
1
1
1
0
1
0
0
0
Рис. 15.2. Результат выполнения команды or
mov ah,1000b
or ah,1001b
;Теперь ah=1001b. Таким образом мы установили нулевой бит, а третий был
;уже установлен до нас, но он остался неизмененным!
15.5.2. Оператор and
Оператор
and
(И) служит для исключения битов (табл. 15.2, рис. 15.3).
mov ax,1010b
and ax,0101b
;Теперь ax=0000b=0h. Таким образом мы исключили первый и третий биты
;(отсчет справа налево, начиная с нуля).
Таблица 15.2. Результат работы команды
and
Первый бит
Второй бит
Результат and
1
1
1
1
0
0
0
0
0

Глава 15. Обработка аппаратных прерываний
161
Рис. 15.3. Результат выполнения команды and
mov ah,1001b
and ah,0001b
;Теперь ah=0001b. Таким образом мы исключили третий бит.
15.5.3. Оператор xor
Оператор
xor
(исключающее ИЛИ) используется в основном для кодирования
данных (табл. 15.3, рис. 15.4).
mov ah,1010b
xor ah,1100b ;Теперь ah=0110b=06h
Таблица 15.3. Результат работы команды
xor
Первый бит
Второй бит
Результат xor
1
1
0
1
0
1
0
0
0
Рис. 15.4. Результат выполнения команды xor
Часть III. Файловая оболочка, вирус, резидент
162
Оператор
xor
очень удобен также для включения/исключения одного бита:
mov al,0 ;al=0
xor al,1 ;al=1
xor al,1 ;al=0
xor al,1 ;al=1 и т. д.
Именно этим оператором мы быстро и красиво аннулировали регистры в пре-
дыдущих главах.
15.6. Аппаратные прерывания
нашего резидента
Кроме аппаратных прерываний, в процедуре обработки прерывания
21h
мы пока
ничего рассматривать не будем. В файле-приложении есть описания, которых
вполне достаточно для понимания работы программы.
15.6.1. Аппаратное прерывание 05h
Прерывание
05h
активизируется (т. е. процессор передает управление процедуре
обработки прерывания
05h
) при нажатии комбинации клавиш <Shift>+<Print
Screen>. В этот момент содержимое текстового экрана выводится на принтер (что
изначально и делает оригинальный обработчик BIOS). Теперь вы знаете, какое
прерывание направляет содержимое экрана на принтер. Ничего не мешает про-
граммисту установить свой обработчик на прерывание
05h
. Мы это и делаем в на-
шем резиденте (процедура
Int_05h_proc
).
После загрузки резидента в память пользователь нажимает комбинацию клавиш
<Shift>+<Print Screen> и... содержимое экрана выводится не на принтер, а сохраня-
ется в текстовый файл в текущем каталоге. Имя файла — Screen.txt. Это работает
наша процедура! Абсолютно ничего сложного в ней нет. Далее мы рассмотрим
в двух словах принцип работы нашего обработчика прерывания
05h
. Дополнитель-
ную информацию вы найдете в файле-приложении.
Как вы уже знаете, один символ на экране занимает 2 байта: символ и его атри-
бут. Атрибуты-то нам не надо сохранять в текстовом файле! Поэтому их нужно
"отсеять", оставив только символы. Для временного хранения символов мы исполь-
зуем память первой видеостраницы. Затем, вызвав функцию
40h
прерывания
21h
,
мы сохраняем отделенные от атрибутов символы в текстовый файл Screen.txt. Все!
Можно смотреть этот файл в любом текстовом редакторе...
15.6.2. Аппаратное прерывание 09h
Как уже упоминалось, это прерывание вызывается в случае, если пользователь
нажал или отпустил какую-нибудь клавишу. В компьютере существуют порты вво-
да/вывода, которые сейчас мы подробно рассматривать не будем. При нажатии или
отпускании клавиши в порт
60h
заносится ее скан-код. Чтобы получить из порта
число, нужно пользоваться оператором
in
.

Глава 15. Обработка аппаратных прерываний
163
Следует отличать ASCII-код от скан-кода. Одна из функций прерывания
09h
—
преобразование скан-кода в ASCII-код. Для чего это нужно — рассмотрим позже.
Сейчас главное — уловить принцип работы разных прерываний (листинг 15.9).
Листинг 15.9. Обработчик прерывания 09h
...
(1) Int_09h_proc proc
(2) pusha
(3) in al,60h
(4) cmp al,58h
(5) jne No_F12
(6) xor cs:Num_status,1
(7) No_F12:
(8) popa
(9) jmp dword ptr cs:[Int_09h_vect]
(10) Int_09h_vect dd ?
(11) Int_09h_proc endp
...
Скан-код клавиши <F12> —
58h
(полный список скан-кодов клавиш см. в при-
ложении 3). Мы вначале получаем из порта
60h
скан-код нажатой клавиши. Если
это <F12>, то инвертируем нулевой бит некой переменной
Num_status
и передаем
управление оригинальному обработчику
09h
. Если мы не передадим управление
оригинальному обработчику, то пользователь не сможет работать с клавиатурой,
т. к. прерывание
09h
заносит в буфер клавиатуры ASCII-код нажатой клавиши.
Но мы-то этого в нашем обработчике не делаем! Можно, конечно, самому написать
подобную процедуру, но мы не ставили задачу сделать это в данной главе.
Что же касается "таинственной" переменной
Num_status
, мы рассмотрим ее чуть
позже...
15.6.3. Аппаратное прерывание 1Ch
Это прерывание примечательно тем, что оно само по себе вызывается примерно
18,2 раза в секунду. Если мы напишем какую-нибудь процедуру и установим на нее
вектор прерывания
1Ch
, то она будет автоматически вызываться указанное количе-
ство раз.
В нашем случае процедура
Int_1Ch_proc
"просматривает" содержимое нулевой
страницы и заменяет символы "A" и "a" на "O" и "o". Причем все это происходит
с периодичностью 18,2 раза в секунду. Начало данной процедуры такое:
...
cmp cs:Num_status,0