Иллюстрированный самоучитель по задачам и примерам Assembler

Разработка динамических (DLL) библиотек. Разработка текста DLL-библиотеки.

Во-первых, этот код должен быть рассчитан на то, что он получает управление в одном из четырех случаев. О наступлении каждого из этих случаев операционная система извещает DLL-библиотеку путем передачи ей одного из четырех предопределенных значений – флагов. Значения этих флагов перечислены в файле winnt.h. Рассмотрим эти флаги и возможные действия при их поступлении в DLL-библиотеку.

  • DLLPR0CESSATTACH-1 – передается операционной системой DLL-библиотеке при проецировании последней в адресное пространство процесса. Передача этого флага DLL-библиотеке производится всего один раз, обычно при загрузке приложения, использующего данную DLL-библиотеку. Если позже другой поток процесса попытается загрузить эту же библиотеку, то система попросту увеличит ее счетчик использования без посылки флага DLLPROCESSATTACH. Получив данный флаг, DLL-библиотека должна выполнить действия по созданию необходимой среды функционирования для своих функций. Например, обеспечить их кучей.
  • DLL_THREAD_ATTACH=2 – передается операционной системой DLL-библиотеке при создании нового потока в процессе. Этим DLL-библиотеке предоставляется возможность нужным образом обработать факт создания нового потока. Следует иметь в виду, что этот процесс не является обратимым, то есть если DLL-библиотека загружается в процесс, когда в нем уже функционируют потоки, то ни одному из них не посылается флаг DLL_THREAD_ATTACH.
  • # DLL_THREAD_DETACH=3 – передается операционной системой DLL-библиотеке при выгрузке потоком DLL-библиотеки.
  • # DLL_PROCESS_DETACH=0 – передается операционной системой DLL-библиотеке при выгрузке DLL-библиотеки из адресного пространства процесса. Логично, что при этом требуется провести завершающие действия по освобождению всех ресурсов, которыми владеет DLL-библиотека. Обычно эти действия являются обратными по отношению к предпринятым при инициализации библиотеки (см. флаг DLLPROCESSATTACH).

Во-вторых, имя точки входа DLL-библиотеки может быть любым. Главное, чтобы при наличии кода инициализации это имя было указано в директиве END.

В-третьих, оформление кода инициализации в виде отдельной процедуры необязательно. Главное, выполнить два основных действия кода инициализации DLL-библиотеки (при его наличии):

  • # вернуть единицу в регистре ЕАХ;
  • # удалить из стека три параметра, которые передаются DLL-библиотеке при передаче описанных выше флагов: hlnstDLL – дескриптор DLL-библиотеки, назначенный ей системой при ее загрузке в адресное пространство процесса;
  • vent – значение флага, передаваемого в DLL-библиотеку;
  • f ImpLoad – параметр не равен 0, если библиотека загружена неявно (см. ниже), и равен 0 в обратном случае.

Структура полного варианта инициализационного кода выглядит так:

includeWindowConA.inc;"проверьте присутствие значений флагов в этом файле"
DllMain ргос
arg hlnstDLL:dword .event:dword,fImpLoad:dword
cmp [event].DLL_PROCESS_ATTACH
jne m выполняем действия для DLL_PROCESS_ATTACH
cmp [event].DLL_THREAD_ATTACH
jnem:выполняем действия для DLL_THREAD_ATTACH
cmp [event]. DLL_THREAD_DETACH
jnem выполняем действия для DLL_THREAD_DETACH
cmp [event].DLL_PROCESS_DETACH
jne m выполняем действия для DLL_PROCESS_DETACH m: moveax.l
ret DllMainendp

Минимальный вариант может выглядеть так, как это сделано в нашем примере:

DllMain рrос
arg hlnstDLL:dword .event:dword,fImpLoad:dword
m: mov eax.l
ret DllMainendp

Или так:

DllMain: m: moveax.l ret 12

Не забывайте, что директива arg приводит к тому, что в код, генерируемый транслятором, вставляются команды ENTERD и LEAVED (см. выше разделы "Реализация рекурсивных процедур" и "Реализация вложенных процедур"). Кроме этого, команда RET процедуры дополняется значением, равным сумме длин параметров, указанных в директиве ARG. Исполнение такой команды приводит к удалению из стека количества байт, равного этому сформированному значению.

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

Последнее, что необходимо отметить, – все экземпляры данных и имена процедур, которые должны быть видны вне пределов DLL-библиотеки, объявляются общими с использованием одной из директив PUBLIC или PUBLICDLL.

Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.