Защита от повторной загрузки
Для защиты от повторной загрузки резидентной программы в память инициализирующая секция должна предпринять некоторые действия по обнаружению собственной резидентной секции в памяти, а резидентная секция должна соответствующим образом ответить на эти действия. Для осуществления этих действий можно использовать мультиплексное прерывание DOS int 2Fh.
Функции C0h - FFh этого прерывания зарезервированы для пользователя. В DOS принято, что прерывание 2Fh возвращает в регистре AL следующие состояния резидентной программы:
0 - программа не установлена, но ее можно установить;
1 - программа не установлена, и ее нельзя установить;
FFh - программа установлена.
При ошибке должен быть установлен флаг переноса CF, а в регистре AX следует вернуть код ошибки. Для того чтобы резидентная секция программы реагировала на прерывание 2Fh, в нее следует включить обработчик соответствующих функций этого прерывания. Для нормальной работы этого обработчика инициализирующая секция должна установить новый вектор прерывания 2Fh, сохранив при этом старый вектор во внутренней переменной. Новый обработчик прерывания 2Fh должен выполнить все, что ему положено, а после этого вызвать старый обработчик этого прерывания. В приведенном ниже примере резидентной программы использован именно этот способ защиты от повторной загрузки.
Другим способом защиты от повторной загрузки является использование специального кода для индикации наличия резидентной программы в памяти. Специальный идентифицирующий код помещается в заранее определенное место в памяти или в заранее определенное место в резидентной секции программы. Если код помещается в определенное место в памяти (например, на месте вектора прерывания 60h), при инициализации проверяется наличие этого кода в этом месте. Если код в наличии, загрузка программы не производится.
Если идентифицирующий код (сигнатура) помещается в определенном месте резидентной секции, инициализирующая секция проверяет наличие этого кода по адресу точки входа в резидентную программу (она знает, как определить адрес точки входа) и по положению этого кода относительно точки входа (это она тоже знает). Обнаружение кода влечет за собой отказ от загрузки программы.
ИСПОЛЬЗОВАНИЕ КОМАНДНОЙ СТРОКИ
При запуске программы DOS формирует префикс программного сегмента (PSP), который загружается в память перед программой. Сразу после загрузки DS:0000 и ES:0000 указывают на начало PSP этой программы. Информация, содержащаяся в PSP позволяет выделить имена файлов и всевозможные ключи из командной строки, узнать объем доступной памяти, определить окружение и т. д.
Структура префикса программного сегмента приведена ниже. Для использования командной строки ее следует считать из PSP, учитывая, что сразу после запуска программы .EXE сегментные регистры DS и ES настроены на начало PSP. В случае программы .COM на начало PSP настроены все сегментные регистры (CS, DS, ES, SS).
Ниже приведен фрагмент программы выполняющей анализ командной строки.
Смещ. | Длина | Содержимое | ||||||||||||||
+0 | int | 20h | Выход в DOS | |||||||||||||
+2 | Mem | Top | Вершина доступной памяти в параграфах | |||||||||||||
+4 | (Резерв) | |||||||||||||||
+5 | Call | смещ. | сегмент | Вызов диспетчера функций DOS | ||||||||||||
+0ah | смещ. | сегмент | Адрес завершения (см. int 22h) | |||||||||||||
+0eh | смещ. | сегмент | Адрес обр. Ctrl-Break (см. int 23h) | |||||||||||||
+12h | смещ. | сегмент | Обраб. критич. ошибок (см. int 24h) | |||||||||||||
+16h | 16h | Резервная область DOS | ||||||||||||||
+2ch | Env | Seg | Сегментный адрес окружения | |||||||||||||
+2eh | 2eh | Резервная область DOS | ||||||||||||||
+5ch | 10h | FCB1 | FCB первого параметра команды | |||||||||||||
+6ch | 14h | FCB2 | FCB второго параметра команды | |||||||||||||
+80h | len | Длина области UPA (с адр. 81h) или DTA | ||||||||||||||
+81h | 7fh | Неформ. обл. параметров | Символы ком. строки DOS | |||||||||||||
mov bx,80h
mov cx,[bx] ; Кол. символов командной строки
inc bx ; Начало командной строки
cmd: mov al,[bx] ; Первый символ командной строки
Здесь производится анализ командной строки |
inc bx
loop cmd
Во втором примере резидентной программы выполняется анализ командной строки для распознавания ключа выгрузки /u.
ПРОВЕРКА ФЛАГА АКТИВНОСТИ DOS
В DOS предусмотрен флаг, указывающий, выполняется ли в данный момент какая-либо функция DOS. Для определения адреса этого флага (его называют флагом активности DOS) используется функция 34h прерывания 21h DOS. Эта функция возвращает полный адрес флага в регистрах ES:BX. Следует иметь в виду, что данная функция недокументирована, поэтому использовать ее следует с осторожностью.
Вызов функции: AH = 34h
Возврат: ES:BX = Адрес флага активности DOS
Если флаг содержит не 0, резидентная программа НЕ ДОЛЖНА использовать никаких функций DOS.
Резидентные программы часто активизируются по прерыванию от таймера или клавиатуры. Так как это может произойти в любой момент, не исключено, что в этот момент будет выполняться какая-либо функция DOS. Если резидентная программа в это время вызовет функцию DOS, это разрушит стек DOS и, вероятно, приведет к катастрофической ошибке. Чтобы этого не случилось, следует отложить вызов функции резидентной программой до того момента, пока флаг активности DOS не станет равным нулю.
Для использования этого флага в резидентной программе следует на этапе инициализации определить адрес флага с помощью функции 34h прерывания 21h DOS и запомнить его во внутренней переменной. Во время активизации резидентной секции программы этот адрес следует использовать для анализа состояния флага.
Во втором примере резидентной программы этот флаг используется для определения возможного начала файловых операций.