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

Ассемблер? Это просто! Учимся программировать Выпуск N 23 (Резидент)


Служба Рассылок Subscribe.Ru проекта Citycat.Ru

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

Выпуск N 23 (Резидент)

Доброе время суток, уважаемые подписчики!

Сегодня в номере:

  • Информация для новеньких. Часто задаваемые вопросы от новичков.

  • Ваши письма. Проблемы с ответами

  • Сотрудничество

  • Резидент



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

    Всю нужную информацию (предыдущие выпуски, адреса экспертов, необходимые программы, документацию, а также многое другое) можно найти на сайте http://www.Kalashnikoff.ru. Рекомендую Вам прежде ознакомиться с разделом "Информация для новых подписчиков".

    Если у Вас нет выхода в Сеть, то предыдущие выпуски рассылки, информацию для новеньких и адреса экспертов можно получить по почте, направив пустое письмо по адресу AssmNew@Kalashnikoff.ru. Информация (320 Кб) будет выслана Вам в течение двух рабочих дней с момента получения Вашего письма. Однако, пожалуйста, не злоупотребляйте этим, т. к. высылка писем подобного объема несет дополнительную нагрузку на почтовые сервера.

    _______

    Самая большая ошибка, которую допускают новички

    Многие из вас, уважаемые новые подписчики, стараются побыстрее догнать остальных, что ни к чему толковому не приводит. По выпускам-то вы догонятете, но не по знаниям. Пожалуйста, не спешите! Внимательно знакомьтесь со всеми предыдущими выпусками! Иначе придется потом все начинать с начала... Я часто получаю вопросы, ответы на которые есть в следующих выпусках или которые были в предыдущих. Дорогие мои, я не могу перепечатывать вам предыдущие выпуски или искать, в каком номере рассылки находится ответ на ваш вопрос. Единственный совет: будьте терпеливы и внимательны!

    _______

    Вопросы от новичков.

    Ко мне приходит очень много объемных вопросов. Я, к сожалению, при всем своем желании не могу отвечать ВСЕМ, т.к. это отнимает огромное количество времени. Дорогие мои! Я просто не смогу вести рассылку, работать, учиться и отдыхать, если буду отвечать на все ваши вопросы такого плана.

    Хочу посоветовать еще раз: читайте внимательно предыдущие выпуски рассылки. Там все изложено более-менее по-порядку. Не спешите! Я понимаю, что вам хочется быстрее догнать ушедших вперед подписчиков. Читайте все внимательно! В рассылке я писал и про работу отладчика, и про ассемблирование программ и про многое другое, что вы спрашиваете в письмах...

    Более того, могу сказать, что вам, уважаемые новички, повезло гораздо больше, чем тем подписчикам, которые подписались раньше. В первой главе книги я постарался обратить внимание на все те моменты, дать ответы на наиболее часто задаваемые вопросы, которые обычно интересуют новых читателей. Вам осталось только все внимательно и не торопясь читать и учиться!

    Добавлю еще, что для всех новых подписчиков теперь доступна помощь экспертов, адреса которых вы можете найти в архиве. Прежде всего, пытайтесь сами найти выход из тупиковой (как вам кажется) ситуации, затем (если решение не найдено) задавайте вопросы экспертам. Если же все равно ничего не поймете, то обращайтесь ко мне, цитируя переписку с экспертами, а также предоставьте максимум информации о сложившейся проблеме и ваши способы ее решения.



    Уважаемые подписчики!

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

    1. В предыдущем, 22-ом выпуске я проворонил одно словечко, которое обычно в рассылках не публикуется. Я прошу прощения и обещаю, что подобного больше не повториться. Более того, я заменил это слово на другое, общеупотребительное. Так что, новые подписчики будут получать измененный вариант. Хочу также попросить читателей, присылающих письма, впредь не допускать в письмах ненормативной лексики. Спасибо.

    2. Я допустил ошибку в 18 номере. Фамилию известного певца следует читать как Малявин. Прошу прощения.

    Во-вторых, на прошлой неделе пришло огромное количество писем, касающихся записи вируса в flash и CMOS. Мнения разделились полностью. К огромному сожалению, я не могу привести их все в данном выпуске, т.к. это займет почти все место в рассылке. Поэтому я в скором времени опубликую их на сайте. Жаль, что пока нет времени написать программку на Перле, которая бы автоматически опубликовывала ваши письма и ответы на них. Получился бы очень даже неплохой форум узкой направленности... Но скоро все будет!

    Все желающие смогут в ближайшие дни посмотреть мнения подписчиков по указанным выше темам на сайте http://www.Kalashnikoff.ru.

    В-третьих, хочу поблагодарить всех, кто откликнулся на мой "крик о помощи" помочь в переводе с одного формата в другой. Писем пришло много. Но, как вы понимаете, мне нужно всего 2-3 помощника. Со временем я разберусь с вашими письмами и напишу ответ. Пожалуйста, не высылайте больше предложений!

    В-четвертых, у меня было очень мало времени раньше. Я, возможно, вас разочарую, если скажу, что с сегодняшнего дня его будет еще меньше. Дело в том, что у меня поменялись обязанности. Теперь занимаю должность системного администратора (слежу за работой программного обеспечения, телефонной линией, мини-АТС, локальной сетью и Интернет). Работы на ближайший месяц - море. Нужно установить новый сервер, подключить к нему компьютеры, настроить их и пр. Более того, мы теперь устанавливаем новую телефонную станцию в офисе, с которой я никогда раньше не сталкивался. Нужно будет ознакомиться с инструкцией, а потом попробовать сделать так, чтобы эта штуковина заработала, что не так просто...

    Так что, друзья мои, вы уж не обижайтесь, если я кому-то не отвечу в срок или не пришлю ответ вообще. Поверьте, я внимательно знакомлюсь со всеми вашими письмами, стараюсь следовать вашим советам. Тем не менее, к сожалению, бывают длинные задержки с ответами... Чтобы не потерять работу и, тем самым, не закрыть рассылку, мне придется выполнять прежде всего обязанности, возложенные на меня трудовым договором, а уж потом - заниматься своими личными делами. Однако, я стараюсь уделять внимание как работе, так и рассылкам. Вторым, как правило, я занимаюсь дома по выходным или после работы (если позволяет время).

    Пожалуйста, извините, если что...



    Дорогие мои друзья! Хотел я рассказать кое что об интересном ресурсе в Интеренте, с автором которого у меня начинает завязываться сотрудничество. Перед самым выходом данного номера, выяснилось, что его очень сильно подвел хваленый мной некогда сервер AGAVA.RU. Очень жаль, а так хотелось поделиться с вами своим открытием! Сайт действительно был стоящий, аналогов которому в Интеренете практически не существует. Ну что ж, надеюсь, что автор проекта восстановит все до выхода следующего выпуска нашей рассылки, и тогда я расскажу вам о его проекте.




    RESID23.ASM

    ENV23.ASM

    Файл-приложение в Интернете для ленивых: http://www.Kalashnikoff.ru/Assembler/Issues/Enclosures/Resid23.rar.


    Сегодня у нас резидент, как резидент. Ничего особенного. Хотя, постойте! Я ведь не могу делать обычные выпуски. Нам нужно скорее переходить к Windows! С каждым очередным номером вы должны узнавать что-то новое, полезное для себя. Вот и сегодня мы рассмотрим очень интересные вещи, которые не затрагивали в предыдущих выпусках. И как обычно на элементарном примере, чтобы было всем понятно. Вероятно, особо любопытные читатели уже давно открыли для себя все то, что будет в этом выпуске. Если так, то я очень рад.

    Итак, сегодня мы узнаем:

    • что такое окружение DOS;
    • как уменьшить размер резидента в памяти;
    • как менять "на лету" параметры резидента;
    • как получить переданные нашей программе параметры в командной строке;
    • как фиксировать в файл нажимаемые пользователем клавиши (в т.ч. и ввод паролей в DOS'е);
    • и прочее, по мелочам.

    Интересно? Надеюсь, что так...

    ______________

    Прежде, чем начнем рассматривать подробно работу резидента, я бы хотел обратить ваше внимание на то, как мы теперь задаем имя файла, в котором будем хранить нажатые пользователем клавиши (в дальнейшем этот файл именуется, как log-файл).

    В одном из предыдущих выпусков нашей рассылки, мы сохраняли действия программ (запуск, создание, удаление файла, создание / удаление каталога и пр.) тоже в log-файле, имя которого задавали перед ассемблированием программы. Т.е. в последствии, после ассемблирования, мы не могли менять его имя и местоположение в каталогах (ну, если не менять его самим в com-файле, используя какой-нибудь текстовый редактор типа Hacker's View).

    Теперь же наш резидент стал более гибким. Имя log-файла можно задавать при запуске программы, указав его в параметрах командной строки. Например:

    RESID23.COM c:\assm\log_file.txt

    После загрузки, резидент создаст файл c:\assm\log_file.txt, в который и будет заносить нажатые пользователем клавиши.

    Но это еще не все! Допустим, мы загрузили резидент. Допустим, перед загрузкой указали имя log-файла a:\super\file.log. А что, если мы хотим изменить имя log-файла, не перезагружая резидент (т.е. не удаляя его из памяти, а затем не загружая его снова с новым параметром в командной строке)? Возможно ли такое? Вот с этим, в частности, мы и будем разбираться сегодня.

    Но и это еще не все! А что, если мы, запуская резидент, не укажем никаких параметров в командной строке? И нужно ли их всегда указывать? Как вы поняли, естественно не нужно. Если резидент загружается, и в параметрах командной строки ничего не указано, то он создает по умолчанию файл c:\keys, куда и будет заносить всю информацию.

    Как такое возможно, мы и рассмотрим в настоящем выпуске.

    Передача и получение параметров в/из командной строки.

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

    Параметры командной строки указываются при запуске файла и должны располагаться после имени запускаемого файла. Например:

    SYS.COM C: A:

    Здесь "SYS.COM C: A:" - командная строка, а "C: A:" - параметры командной строки, которые передаются файлу SYS.COM. В данном примере SYS.COM скопирует системные файлы с диска С: на диск А:. Как же нашей программе получить эти параметры?

    Все очень просто! Как уже общеизвестно, параметры командной строки, передаваемые файлу, располагаются в PSP по смещению 80h. PSP, в свою очередь, находится в том сегменте, в котрый загрузился наш com-файл. Проще говоря, первая инструкция com-файла начинается со смещения 100h (ORG 100h), а по смещению 80h находятся параметры командной строки, а также по умолчанию DTA (помните, как мы переносили тело вируса в область экрана для того, чтобы не затереть эти параметры при поиске файлов?). Как они там оказываются? Просто, прежде, чем наша программа получит управелние, DOS сама занесет их по этому адресу. Вот и весь фокус!

    Что конкретно находится по смещению 80h? Какова структура размещения параметров?

    Все опять-таки очень просто. Первый байт, распологающийся по смещению 80h, указывает на длину командной строки. Если файлу никаких параметров не было передано, то этот байт будет равен нулю.

    Второй байт, как правило, - пробел (20h). За ним идет собственно то, что мы указали после имени запускаемого файла. Заканчиваются параметры командной строки символом 0Dh (код клавиши "Enter").

    Вот таблица:

    +80h +81h +82h ?
    Длина "Пробел" (20h = 32) Параметры Символ 0Dh (13)

    Допустим, мы запускаем программу SYS.COM таким образом:

    SYS.COM C: D:

    Тогда по смещению 80h будет находится следующее:

    +80h +81h +82h +87h
    06h "Пробел" (20h = 32) 43h 3Ah 20h 44h 3Ah Символ 0Dh (13)

    Примечание. 43h 3Ah 20h 44h 3Ah - ASCII-символы "C:_D:" (символ "_" - пробел).

    Длина 06 байт потому, что DOS считает пробел, расположенный по адресу 81h, как символ командной строки.

    Окружение DOS.

    В окружении DOS находятся параметры, которые указываются в файле autoexec.bat. Например:

    PATH C:\WINDOWS;C:\WINDOWS\COMMAND

    COMSPEC=C:\COMMAND.COM

    TEMP=C:\TEMP

    PROMPT=$P$G

    и прочие.

    Окружение DOS передается каждой программе, которая загружается (не важно, резидент это или оболочка DOS).

    Читая информацию из окружения DOS, многие программы находят файлы, которые указаны в PATH. Более того, так действуют некоторые вирусы, заражающие файлы по пути, указанном после PATH.

    Где же находятся все эти параметры? Они располагаются в сегменте, адрес которого можно найти в PSP по смещению 2Ch. Смещение окружения всегда нулевое. Пример будет ниже. Прежде рассмотрим, чем данное окружение может помешать нашему резиденту.

    Дело в том, что, как вы вероятно заметили, резидент, как правило, занимает больше места в памяти, чем на диске. Иными словами, com-файл на винчестере может "весить" 130 байт, а в памяти - 350 и более байт (числа условные). Почему так происходит?

    Вспомните, что перед вызовом 27h прерывания (которое оставляет программу в памяти) необходимо указать в регистре DX последний освобождающийся байт. Все, что идет перед смещением, указанном в DX, остается в памяти. Вот таблица:

      Смещение Что находится
    * 0000h Начало PSP. Команда INT 20h
    * 002Ch Сегментный адрес окружения DOS
    * 0080h Командная строка и по умолчанию DTA
    * 00FFh Последний байт PSP
    ** 0100h Метка начала программы (напр.: Begin:)
    ** --- Тело резидента. Т.е. то, что будет постоянно находиться в памяти
      0134h Метка, указывающая на то, что после нее можно освобождать память (напр.: Init)
    X --- Инициализация резидента (вывод сообщений на экран, получение, сохранение и установка векторов прерываний и пр.)
    X 0154h Команда INT 27h (оставляет часть программы в памяти и выходит в DOS)
    X 0156h Данные, строки для вывода и пр., что не требуется резиденту в процессе работы. Необходимы только для того, чтобы вывести сообщения на экран, сохранить в процессе инициализации резидента некоторые переменные и пр. Удаляются из памяти после выполнения команды INT 27h.

    Примечания.

    • Символом "звездочка" (*) отмечен PSP, который остается в памяти вместе с резидентом.
    • Символом "две звездочки" (**) отмечена резидентная часть (часть нашей программы, остающаяся в памяти). Вспомним, что метки памяти не занимают.
    • Символом "икс" (Х) отмечена часть программы, которая удалится из памяти после вызова прерывания 27h.

    Как я уже говорил, PSP нашему резиденту абсолютно не нужно. В нашем примере мы используем его (256 байт), как буфер (хотя можно и сместить программу на 100h байт, но этим мы займемся в последующих выпусках). Вот и считайте: наша программа, остающаяся в памяти + 256 байт PSP (не будем брать во внимание ту часть программы, которая удаляется после вызова 27h).

    Но и это еще не все, что остается в памяти и "висит" вместе с резидентной частью нашей программы (резидентная часть - та часть программы, которая остается в памяти. Резидент - более широкое понятие, включающее в себя еще и процедуру инициализации. Иногда я назывю резидентом резидентную часть, что не совсем верно, зато коротко. Думаю, что вы меня понимаете).

    Так что же еще осталяет резидент вместе с собой в памяти? Ответ прост: окружение DOS, которое может занимать 32 и более килобайт, но, как правило, "тянет" на 50-100 байт. Вроде мелочи, а неприятно... Да и не "эстетично" это. Посмотрит "крутой" программист нашу программу и скажет: "Вот это ламеры писали. Сразу видно!". Как же нам избавиться от окружения DOS, тем самым поднявшись на ступеньку выше к профессионализму?

    Здесь не совсем просто, но вы без труда поймете. Я уверен.

    Итак, повторю еще раз. В PSP по смещению 2Ch находится сегмент окружения DOS. Вспомните, как мы в одном из прошлых выпусков урезали память и отводили блок памяти. Тоже самое нам надо сделать и с окружением DOS.

    Вот, как это выглядит в файле-приложении:

    mov es,word ptr cs:[2Ch] ;Получим сегмент строки окружения.
    mov ah,49h ;Функция освобождения памяти.
    int 21h ;Освобождаем память...

    Функция 49h прерывания 21h освобождает блок памяти:

    Вход: AH=49h
    ES=сегмент распределенного блока
    Выход: JC - ошибка, при этом:
    AX-код ошибки

    После выполнения данной функции, память освобождается. Это легко проверить, если запустить резидент, при этом освобождая память (т.е. используя функцию 49h) и, соответственно, не освобождая. Размер занимаемой памяти тем или иным резидентом можно посмотреть, например, в DOS Navigator'e или Volcov Commander'e. Попробуйте, поэкспериментируйте!

    Для того, чтобы лучше понять что такое окружение DOS, я прилагаю к данной рассылке программу ENV23.ASM, которая выводит на экран все переменные DOS, указанные в autoexec.bat. Настоятельно рекомендую вначале запустить данный файл и посмотреть результат. Затем запустить его под отладчиком и тщательно изучить! Причем, прямо сейчас. Это очень важно!

    Ну вот, разобрали мы окружение DOS. Надеюсь, что вопросов по данной теме быть не должно...

    ___________

    Теперь подробней о работе резидента.

    Даже не знаю, с чего начать... Начну с середины.

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

    В данном случае мы будем использовать PSP в качестве буфера, в котором будет храниться опеределенное количество ASCII-кодов нажатых клавиш, которые, в свою очередь, будут периодически (после выполнения определенных условий) сохраняться в файле. Можно, конечно, сохранять сразу же нажатую клавишу, но это будет не совсем красиво, да и пользователь заподозрит "что-то ненормальное". Хорошо, если в памяти загружен Smartdrive. А если нет? Тогда винчестер будет каждый раз, после очередного нажатия, записывать код данной клавиши, что в какой-то степени замедлит работу.

    Куда проще сохранять в буфер, скажем, максимум 80 символов, а затем их сбрасывать в файл. Более того, мы сможем производить некоторую коррекцию вводимых пользователем строк. Например, замеченные опечатки, которые будут меняться при нажатии на BackSpace. Мы в памяти также будем это делать, что избавит LOG-файл от "мусора".

    Договорились, что будем использовать PSP в качестве буфера. Все равно память, отведенная под PSP резиденту не нужна. А это, как уже отмечалось, лишние 256 (100h) байт. Зачем добру пропадать?

    Клавиши будут сохраняться, начиная со смещения 0 сегмента, в который загрузился наш резидент. По смещению 00F6h будем хранить смещение, по которому следует заносить очередной символ (и, в тоже самое время, количество введеных пользователем символов). В принципе, хватило бы и одного байта, но слово удобнее будет использовать, например, при записи символов в файл.

    Когда будем производить сброс буфера в LOG-файл?

    Сброс буфера будет производиться в случае, если:

    1. Пользователь нажмет Enter;

    2. Пользователь нажмет клавишу, код которой расширенный (например: F1 - F10, "стрелки" и пр.);

    3. Пользователь введет 80 символов, ни один из которых не будет равен коду, перечисленному в пунктах 1 и 2 (дабы избежать переполнения буфера).

    Зачем мы сбрасываем буфер, если пользователь нажимает клавишу, ASCII-код которой расширенный? Думаю, что вы поймете сами, при экспериментах...

    Заносить очередной символ в буфер будет процедура Store_sym:

    __________

    (1) mov di,cs:[0F6h] ;Занесем в DI количество введенных символов
    (2) cmp di,79 ;Оно больше 79?
    (3) jb OK_store ;Нет, меньше. Тогда дописываем в буфер очередной символ.

    (4) push di ;Иначе сбросим буфер в файл.
    (5) push ax
    (6) call Save_string
    (7) pop ax
    (8) pop di

    (9) OK_store:
    (10) stosb ;Занесем очередной символ в буфер.
    (11) inc word ptr cs:[0F6h] ;Увеличим счетчик.
    (12) ret ;Конец процедуры...

    __________

    Никаких вопросов здесь не должно возникнуть, кроме строки (3). Даже если и непонятно что-то, то ничего страшного! Стоит разобраться полностью с резидентом (почитать описания к нему), и все станет на свои места. Однако, я рекомендую прежде прочитать выпуск до конца.

    Обратите внимание, что в строках (2) - (3) мы проверяем на то, больше ли число 79, чем то, которое находится в регистре DI. Если меньше, то переходим на метку OK_store. Это, как вы уже знаете, - условный переход. Однако, данную инструкцию мы не рассматривали пока. В принципе, должно быть все понятно. Если JE (Jump if Equal) - это переход, если равно (т.е. если приемник равен источнику), то JB (Jump if Below - переход, если меньше) - это, как уже ясно из перевода, переход, если приемник меньше источника (т.е. в данном случае, если DI меньше 79).

    Вот таблица (примеры ниже):

    JB (Jump if Below) Переход, если приемник меньше источника
    JBE (Jump if Below or Equal) Переход, если меньше или равно
    JNB (Jump if Not Below) Переход, если не меньше (равносильна JAE)
    JA (Jump if Above) Переход, если больше
    JAE (Jump if Above or Equal) Переход, если больше или равно
    JNA (Jump if Not Above) Переход, если не больше (равносильна JBE)

    Примеры.

    _________

    mov ax,34
    cmp ax,35

    Переход будет выполнен при использовании следующих команд после сравнения:

    • JNE
    • JAE
    • JNA
    • JB
    • JBE

    Переход НЕ будет выполнен при использовании следующих команд после сравнения:

    • JE
    • JA
    • JNB

    Пожалуйста, внимательно разберите и проанализируйте приведенные выше команды!

    _________

    С процедурой Save_string никаких вопросов не должно возникнуть. Пройденный материал...

    _________

    Еще рассмотрим должным образом два новых оператора: STC, CLC:

    Название Перевод Применение Процессор
    STC SeT Carry flag Установка флага переноса 8086

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

    Название Перевод Применение Процессор
    CLC CLear Carry flag Сброс флага переноса 8086

    Для чего нужны данные команды? Где они обычно применяются?

    Как правило, я ими пользуюсь перед выходом из процедуры (не обращайте особого внимания на приведенные ниже команды. Главное - понять принцип.):

    call Find_symbol
    jc Not_found

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

    call Find_symbol
    cmp ax,1
    je Not_found

    Т.е., если AX=1, то символ не найден. Как видите, удобнее пользоваться флагом переноса. Однако, следует помнить, что некоторые команды могут менять этот флаг. Поэтому нужно придерживаться следующих правил:

    1. Между установкой / сбросом флага переноса и его проверкой не следует вызывать никакие прерывания или пользоваться командами типа ADD, SUB, MUL и пр.

    2. Проверять флаг как можно быстрее, после его установки / сброса

    Далее. Рассмотрим еще одну команду управления флагами:

    Название Перевод Применение Процессор
    STD SeT Destination flag Установка флага направления 8086

    ______

    Название Перевод Применение Процессор
    CLD CLear Destination flag Сброс флага направления 8086

    Что делают данные команды? Для чего служит флаг направления?

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

    В нашей резиденте мы сбрасываем флаг направелния для того, чтобы команды LODS, STOS и пр., используемые в нем, работали "вперед".

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

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

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

    Поехали дальше.

    _________

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

    Для этой цели мы будем использовать процедуру обработки 10h прерывание. Впрочем, и не только для этой цели. Она нам необходима еще и для того, чтобы проверять на повторную загрузку резидента:

    (1) Int_10h_proc proc
    (2) cmp ax,0FAAFh ;Это мы проверяем на повторную загрузку?
    (3) jne Next_step

    (4) xchg ah,al
    (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-файла. Вот так:

    mov ax,0FBAFh ;Получим сегмент и смещение имени log-файла
    int 10h ;Теперь ES - сегмент, а DI - смещение LOG-файла в памяти.

    Обратите внимание, что вызываем мы данной прерывание после того, как проверим на повторную загрузку!

    Осталось только перенести параметры командной строки в полученные сегмент и смещение!

    Вот, что делает наш обработчик 10h прерывания (Int_10h_proc):

    __________

    cmp ax,0FBAFh ;Это мы получаем текущий адрес log-файла?
    jne Run_int

    push cs ;Заносим в ES сегмент log-файла.
    pop es
    mov di,offset File_name ;Заносим в DI смещение log-файла
    iret


    Вот, вроде и все, что хотел сказать.

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

    На сегодня все! Всем удачи!


    С уважением,

    Автор рассылки: Калашников Олег
    URL сайта подписчиков:
    http://www.Kalashnikoff.ru
    E-mail автора:
    Assembler@Kalashnikoff.ru
    ICQ: 68951340

    Москва, 2001.


    (C) Авторское право принадлежит автору рассылки. Использование материала из рассылки в коммерческих и иных подобных целях, а также публичное публикование без письменного согласия автора влечет ответственность за нарушение авторских прав.


    http://subscribe.ru/
    E-mail: ask@subscribe.ru
    Поиск

    В избранное