Файл: О.А.Калашников. Ассемблер Это Просто. Учимся программировать.pdf
Добавлен: 16.02.2019
Просмотров: 29240
Скачиваний: 1689
Глава 18. Высокоуровневая оптимизация программ
199
Понять работу данной процедуры труда не составит. Все элементарно!
На что хотелось бы обратить ваше внимание, так это на то, как у нас организо-
вана проверка нажатых клавиш (
MAIN_PROC
, main.asm). Также посмотрите процедуру
Quit_prog
в этом же файле. В дальнейшем мы усовершенствуем вывод рамок на
экран с запросом "Да"/"Нет". Это диалоговое окно, как правило, аналогично общему.
Интерес представляет также то, каким образом мы показываем пользователь-
ский экран при нажатии комбинации клавиш <Ctrl>+<F5> (
MAIN_PROC
, main.asm).
18.4. Резюме
По большому счету, вы уже самостоятельно можете написать оболочку типа
Far Manager, используя программу HELPASSM. Наша задача теперь заключается
в том, чтобы показать вам "подводные камни", некоторые алгоритмы, которые не
рассматривались до сих пор, общие понятия при работе с расширенной памятью
и вывод десятичных чисел на экран. Этим мы и займемся в следующих главах.
Как видите, мы уже написали несколько мощных процедур (например,
Draw_frame
,
Print_string
), которыми вы можете пользоваться. Просто вставляйте
их в собственные программы и вызывайте! Безусловно, довольно много времени
уходит на написание самих процедур. Зато как от этого выигрывает скорость рабо-
ты программы и ее размер!
Глава 19
Создание резидентного шпиона
19.1. Резидент
В данной главе приступаем к изучению очередной резидентной программы.
Прежде всего, разберемся, какие функции она выполняет.
Итак, после загрузки в память резидент перехватывает прерывание
21h
. Затем
отслеживает некоторые действия программ (функций, которые они вызывают)
и записывает информацию в свой LOG-файл. Список отслеживаемых функций
прерывания
21h
приведен в табл. 19.1.
Таблица 19.1. Отслеживаемые функции
Номер функции в ax
Описание функции
ax = 4B00h
Запуск файла на выполнение
ah = 39h
Создание каталога
ah = 3Ah
Удаление каталога
ah = 3Bh
Смена каталога
ah = 3Ch
Создание файла
ax = 3D02h
Открытие файла для чтения/записи
ah = 41h
Удаление файла
По стандартам Microsoft перед вызовом всех этих функций прерывания
21h
в регистры
ds:dx
должно быть загружено имя файла или каталога. Поэтому мы вы-
полняем одни и те же действия, если какая-либо функция вызывается. Примеры
корректного вызова этих функций приведены в листингах 19.1 и 19.2.
Листинг 19.1. Создание каталога
mov ah,39h
mov dx,offset Directory
int 21h
Глава 19. Создание резидентного шпиона
201
Листинг 19.2. Удаление файла
mov ah,41h
mov dx,offset File
int 21h
Исключение составляет функция
4B00h
. Для этой функции, помимо указания
смещения на файл в регистрах
ds:dx
, необходимо еще дополнительно хорошо под-
готовиться. Запуск программ на выполнение мы будем рассматривать в последую-
щих главах, т. к. это довольно объемная тема и требует подробного рассмотрения.
Теперь рассмотрим использование этих функций на примере получения атрибу-
тов файла.
В операционных системах MS-DOS и Windows файл может иметь следующие
атрибуты (табл. 19.2).
Таблица 19.2. Атрибуты файлов в MS-DOS
Атрибут
Описание
000001b
Только чтение
000010b
Спрятанный
000100b
Системный
001000b
Метка тома
010000b
Подкаталог
100000b
Архивный
Существенное отличие в атрибутах файлов в Windows и MS-DOS заключается
в том, что в Windows атрибуты более расширенные, в частности: сжатый, шифро-
ванный, индексируемый и т. п.
Атрибуты файла могут комбинироваться, но не все. Например:
100001b
— "только чтение" и "архивный";
000110b
— "системный" и "скрытый".
Однако не следует указывать атрибуты, которые явно противоречат друг другу.
Например, "подкаталог" и "метка тома" вместе.
На рис. 19.1 приведен участок кода, который создает файл в текущем каталоге
с помощью функции
3Ch
. При этом смещение имени создаваемого файла находится
в регистрах
ds:dx
, а атрибуты — в
cx
.
В этом примере атрибуты создаваемого файла будут "архивный" и "скрытый".
В двоичной системе это выглядит как
100010b
, а в шестнадцатеричной —
22h
.
Обратите внимание, что существует такой атрибут, как "метка тома". Метка
диска (тома) — это не что иное, как обычный файл с соответствующим атрибутом
и имеющий нулевую длину. Аналогично и с "файлами", имеющими атрибут "под-
каталог".
Часть III. Файловая оболочка, вирус, резидент
202
Рис. 19.1. Создание файла
Что именно делает наш резидент?
Программы типа COM начинаются со смещения
100h
. От
0
до
0FFh
находится
PSP (Prefix Segment Program). Некоторые поля PSP вы уже знаете. Например, по
смещению 0 находится команда
int 20h
, а по смещению
80h
— DTA и изначально
командная строка.
Оставаясь в памяти, резидент сохраняет с собой также PSP (т. е. "лишние"
100h байт). Получается, что 100h байт памяти постоянно зарезервировано. Вы уже,
возможно, заметили, что наши предыдущие резиденты занимали памяти больше,
чем их реальный размер на диске. Это-то как раз и связано с тем, что в памяти вме-
сте с кодом резидента остается PSP программы (плюс еще строка окружения, но об
этом позже).
Существует несколько способов избежать размещения лишних байтов в памяти:
1. Сделать так, чтобы программа в памяти начиналась не со смещения
100h
, а со
смещения
0
. Однако здесь возможны некоторые проблемы. Об этом позже.
2. Разместить в нашей свободной области стек на то время, пока работают наши
обработчики прерываний.
3. Сделать в области PSP буфер, т. е. задействовать эту память для временного
хранения данных, которые не превышают
100h
байт.
Мы будем использовать третий способ, хотя иногда удобнее пользоваться вто-
рым и даже комбинировать оба этих метода. Для какой цели нам нужен будет этот
буфер, сейчас и рассмотрим.
Как уже упоминалось, мы перехватываем указанные выше функции прерывания
21h
и фиксируем действия программ, которые вызывают данное прерывание в на-
шем LOG-файле (c:\report.txt). Теперь обратим внимание на то, что именно делает
обработчик прерывания
21h
(листинг 19.3).
Глава 19. Создание резидентного шпиона
203
Листинг 19.3. Проверка вызова функций прерывания 21h
...
cmp ax,4B00h ;Это запуск программы?
je Start_f
cmp ah,39h ;Это создание каталога?
je Create_dir
...
;Если что-то другое, то передадим управление оригинальному обработчику
;прерывания 21h ...
jmp short Go_21h
Start_f:
;Строка для записи в наш LOG-файл.
mov si,offset Start_filemess
call Move_string ;Готовим строку и записываем ее в файл...
jmp short Go_21h ;Передадим управление прерыванию 21h...
Create_dir: ;То же самое для остальных...
mov si,offset Create_dirmess
call Move_string
jmp short Go_21h
...
В приведенном фрагменте кода нашего резидента мы вначале выясняем, запус-
кает ли какая-то программа на выполнение или нет. Затем проверяем другие функ-
ции, которые могут вызываться какой-либо программой.
Допустим, некто пытается создать каталог при помощи функции
39h
. Тогда мы
передаем управление на метку
Create_dir
(создание каталога). Это видно из при-
веденного выше примера. Затем в
si
заносится адрес строки
Create_dirmess
:
...
Create_dirmess dw Create_dirmessl
db 'Создание каталога ---> '
Create_dirmessl equ $-Create_dirmess-2
...
Как видите, первые два байта адреса, который заносится в
si
, содержат длину
строки. Обратите внимание, как просто мы получаем эту длину: переменную