Книга: О.А.Калашников. Ассемблер Это Просто. Учимся программировать

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам
background image

Часть III. Файловая оболочка, вирус, резидент 

234 

Данная команда устанавливает флаг переноса, а следующая — сбрасывает его. 

Таблица 23.7. Команда 

clc

Команда  Перевод 

Назначение 

Процессор 

clc 

Clear carry flag 

— сбросить флаг 

переноса 

Сброс флага переноса 

8086 

 
Для чего нужны данные команды? Где они обычно применяются? 
В наших примерах мы ими в основном пользуемся перед выходом из процеду-

ры. Например, возьмем часть такого кода (листинг 23.4). 

Листинг 23.4. Использование команд управления флагом переноса 

... 
call Find_symbol 
jc Not_found 
... 

В  данном  примере  вызывается  процедура  поиска  какого-то  символа  в  памяти.  

В  конце  этой  процедуры  мы  устанавливаем  флаг  переноса,  если  символ  найден,  
и  сбрасываем,  если  нет.  Это  проще и быстрее, чем если бы мы использовали для 
этой цели какой-нибудь регистр (листинг 23.5). 

Листинг 23.5. Использование регистра 

... 
call Find_symbol 
cmp ax,1 
je Not_found 
... 

Если 

ax=1

, то символ не найден. Как видите, удобнее пользоваться флагом пе-

реноса. Однако следует помнить, что некоторые команды могут менять этот флаг. 
Поэтому нужно придерживаться следующих правил: 

 

между установкой/сбросом флага переноса и его проверкой не следует вызывать 
никакие прерывания или пользоваться командами типа 

add

, 

sub

, 

mul

 и пр.; 

 

после установки/сброса флага его нужно проверять как можно быстрее. 
Рассмотрим еще две команды управления флагами направления (табл. 23.8, 23.9). 

Таблица 23.8. Команда 

std

Команда 

Перевод 

Назначение 

Процессор 

std 

Set destination flag 

— устано-

вить флаг направления 

Установка флага направ-
ления 

8086 

background image

Глава 23. Область PSP и DTA. Системные переменные (окружение DOS) 

235 

Таблица 23.9. Команда 

cld

Команда 

Перевод 

Назначение 

Процессор 

cld 

Clear destination flag 

— сбро-

сить флаг направления 

Сброс флага направления 

8086 

 
Какие действия выполняют эти команды? Для чего служит флаг направления? 
Данный  флаг  служит  при  указании  направления  для  инструкций  работы  со 

строками (

lods

, 

stos

, 

movs

 и пр.). До сих пор мы перемещали байты только вперед, 

например,  от  0  до  4000,  а  не  от  4000  до 0 (вспомните вирус, который перемещал 
свой код в область видеопамяти). Вот этот флаг отвечает за то, каким образом про-
изводить перемещение, поиск и пр. Иначе говоря, в каком направлении это делать 
(отсюда и название флага — флаг направления). Как правило, применяют направ-
ление  вперед,  и,  следовательно,  флаг  обычно  сброшен.  Но  бывают  случаи,  когда 
необходимо установить флаг, тем самым производя работу "назад". В нашем рези-
денте мы сбрасываем флаг направления для того, чтобы команды 

lods

, 

stos

 и пр., 

используемые в нем, работали "вперед". 

Как уже упоминалось, некоторые прерывания (в том числе и 

09

) могут быть вы-

званы в любой момент работы какой-нибудь программы (в тот момент, когда поль-
зователь  нажмет  клавишу).  Установлен  ли  этот  флаг  или  сброшен —  нам  не  из-
вестно.  Проще  всего  сбросить  его  самим  в  начале  резидентной  части,  что  мы, 
собственно, и делаем: 

cld    ;Направление — вперед! 

Обращаем ваше внимание еще раз: как правило, этот флаг сброшен, но лучше не 

рисковать и самим сбросить или установить его. Практиковаться с ним мы будем 
позже, при написании оболочки.  

23.3.3. Изменение параметров резидента "на лету" 

Допустим,  наш  резидент  загружен  в  память  и  уже  успешно  работает  (т. е.  

в LOG-файле фиксирует нажатые пользователем клавиши). А что, если мы хотим 
поменять имя LOG-файла в процессе работы резидента? Для этой цели будем ис-
пользовать процедуру обработки прерывания 

10h

. Впрочем, не только для этой це-

ли. Она нам необходима еще и для того, чтобы проверять резидент на повторную 
загрузку (листинг 23.6). 

Листинг 23.6. Процедура обработки прерывания 10h 

... 
(1) Int_10h_proc proc 
(2)    cmp ax,0FAAFh     ;Проверяем на повторную загрузку? 
(3)    jne Next_step 
 
(4)    xchg ah,al 

background image

Часть III. Файловая оболочка, вирус, резидент 

236 

(5)    iret 
 

(6) Next_step: 

(7)    cmp ax,0FBAFh     ;Получаем текущий адрес LOG-файла? 

(8)    jne Run_int 

(9)    push cs           ;Заносим в es сегмент LOG-файла 

(10)   pop es 

(11)   mov di,offset File_name   ;Заносим в di смещение LOG-файла 

(12)   iret 

(13) Run_int: 

(14)   jmp dword ptr cs:[0F8h] 

(15) Int_10h_proc endp 

... 

В  строках  (2)—(5)  мы  проверяем,  вызывается  ли  прерывание 

10h

  с  числом 

0FAAFh

. Если вызывается, то меняем местами 

ah

/

al

, что сигнализирует нашему ре-

зиденту, загружаемому повторно, о том, что он уже в памяти. Подобные вещи рас-
сматривались в предыдущих главах, поэтому подробно останавливаться на этом не 
будем. 

Нас сейчас больше интересуют строки (6)—(12). Если прерывание 

10h

 вызыва-

ется с числом 

0FBAFh

 в 

ax

, то это значит, что наш резидент, загружаемый повторно, 

просит получить сегмент и смещение имени текущего LOG-файла. Для чего? Как 
уже  упоминалось,  резидент  может  менять  в  процессе  работы  имя  своего  LOG-
файла.  Для  этого  необходимо  запустить  его  повторно,  с  указанием  имени  в  ко-
мандной строке. Например, так: 

Resid23.com c:\newfile.txt 

Резидент,  при  попытке  повторно  загрузиться  в  память,  прежде  всего  проверит 

параметры в командной строке. Но как повторно загружаемому резиденту узнать, в 
каком  сегменте  находится  его  резидентная  копия?  Для  этого  мы  воспользуемся 
созданной нами функцией 

0FBAFh

 прерывания 

10h

, которое резидент перехватыва-

ет. В результате, прерывание 

10h

 (а точнее, наша процедура обработки прерывания

10h

) вернет в 

es

 сегмент, а в 

di

 — смещение имени LOG-файла (листинг 23.7). 

Листинг 23.7. Получение сегмента 

... 

mov ax,0FBAFh    ;Получим сегмент и смещение имени LOG-файла 

int 10h          ;Теперь es — сегмент, а di — смещение LOG-файла в памяти. 

... 

А теперь посмотрите первые команды нашего обработчика прерывания 

10h

, ко-

торый, в случае получения в 

ax

 числа 

0FBAFh

, загружает в 

es:di

 сегмент и смеще-

ние  LOG-файла  и  немедленно  выходит  из  этого  прерывания.  Обратите  внимание, 

background image

Глава 23. Область PSP и DTA. Системные переменные (окружение DOS) 

237 

что при инициализации резидента мы сперва проверяем, загружен ли он в память 
или  нет,  и  если загружен, то получаем адрес LOG-файла. Теперь осталось только 
перенести параметры командной строки в полученные сегмент и смещение! 

В  листинге 23.8  приведен  фрагмент  нашего  обработчика    прерывания 

10h

(

Int_10h_proc

). 

Листинг 23.8. Обработчик прерывания 10h 

... 
cmp ax,0FBAFh      ;Получаем текущий адрес LOG-файла 
jne Run_int 
push cs            ;Заносим в es сегмент LOG-файла 
pop es 
mov di,offset File_name 

;Заносим в di смещение LOG-файла 

iret 
... 

23.4. Задание для закрепления сведений 
из данной главы 

Обязательно разберитесь с прилагаемым файлом, т. к. информация, приведенная 

в  нем,  очень  важна  для  понимания  работы  резидентных  программ.  Описаний  
в файле-приложении более чем достаточно. 

background image

Глава 24 

Резидентный антивирус 

В

Н И МА Н И Е

!  

Наш антивирус корректно обезвреживает только вирус, код которого приведен в  гла-
ве 20
.  Если  вы  добавили  или  убрали  хоть  один  байт  в  коде  вируса,  то антивирус не 
сможет корректно вылечить зараженный файл! 

24.1. Регистры микропроцессоров  
80386/80486. Хранение чисел в памяти 

Прежде  чем  приступить  к  рассмотрению  работы  нашего  антивируса,  ознако-

мимся  вкратце  с  некоторыми  регистрами  процессоров 80386/80486.  В  табл. 24.1 
приведен пример на основе аккумулятора. 

Таблица 24.1. Регистры процессоров 386+ 

Количество разрядов 

Регистр 

32 

eax 

16 

ax 

ax 

8 

ah 

al 

ah 

al 

 
Как  видно  из  таблицы, 

eax

 —  32-разрядный  регистр.  Он  может  хранить  число 

65 535   65 535  (т. е.  65 535  в  квадрате).  До  сих  пор  мы  пользовались  только  16-
разрядными  регистрами  (

ax

, 

bx

, 

cx

  и пр.).  С  данной  главы  начнем  использовать  

и 32-разрядные. По большому счету, у нас нет острой необходимости пользоваться 
ими.  Единственная  цель —  показать  вам  возможности  32-разрядных  регистров,  
а также попробовать использовать их на практике. 

В приведенной выше таблице мы рассмотрели только регистр 

eax

. По аналогии 

с ним, можно добавить и регистры 

ebx

, 

ecx

, 

edx

, 

edi

, 

esi

, 

ebp

. 

При  использовании  32-разрядных  регистров  необходимо  в  ассемблерный  лис-

тинг включить одну из следующих директив: 

.386 
.486 

Источник: https://files.student-it.ru/previewfile/2839