Создание динамических библиотек (DLL)

 

Оглавление



Введение

Теоретическая часть

Описание функций, использующихся в программах

Примеры реализации DLL

Использование ресурсов

Использование общей памяти

Передача параметров

Вывод


Введение


Для операционных систем Microsoft Windows, большая часть функциональных возможностей операционной системы (ОС) обеспечивается библиотеки динамической компоновки (DLL). Кроме того при запуске программы на одной из этих операционных систем Windows, большинство функций программы могут предоставлять библиотеки DLL. Например, некоторые программы могут содержать множество различных модулей, и каждый модуль программы содержится в библиотеках DLL.

Использованию библиотек DLL способствует модульная структура кода, повторное использование кода, эффективное использование оперативной памяти и дисковое пространства. Таким образом, операционная система и программы загружаются быстрее, работают быстрее и занимают меньше места на жестком диске компьютера.

Так же DLL позволяет упростить и саму разработку программного обеспечения. Вместо того чтобы каждый раз перекомпилировать огромные ЕХЕ-программы, достаточно перекомпилировать лишь отдельный динамический модуль. Кроме того, доступ к динамической библиотеке возможен сразу из нескольких исполняемых модулей, что делает многозадачность более гибкой.

Когда программа использует библиотеку DLL, возникает проблема, которая называется зависимость. ОС может вызвать программу на выполнение, в то время когда другая программа использует библиотеку эту DLL, создается зависимость по данным. Всё это приводит к сбоям в этих приложениях и к конфликтам, резко снижая общую надёжность операционных систем.

С появлением платформы.net Framework было устранено большинство проблем с зависимостями с помощью готовых сборок. Поздние версии Windows стали разрешать параллельное использование разных версий DLL (технология SxS), что свело на нет преимущества изначального принципа модульности.


Теоретическая часть


В среде Windows практикуются два механизма связывания:

·по символьным именам;

·по порядковым номерам.

В первом случае функция, определенная в динамической библиотеке, идентифицируется по ее имени, во втором - по порядковому номеру, который должен быть задан при трансляции. Связывание по порядковому номеру в основном практиковалось в старой операционной системе Windows З. х, связывание по имени - более удобный механизм.

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

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

·1-й параметр. Идентификатор DLL-модуля.

·2-й параметр. Причина вызова.

·3-й параметр. Резерв.

Рассмотрим подробнее второй параметр процедуры входа. Вот четыре возможных значения этого параметра:

·DLL_PROCESS_DETACH equ 0

·DLL_PROCESS_ATTACH equ 1

·DLL_THREAD_ATTACH equ 2

·DLL_THREAD_DETACH equ 3

DLL_PROCESS_ATTACH - сообщает, что динамическая библиотека загружена в адресное пространство вызывающего процесса._THREAD_ATTACH - сообщает, что Текущий процесс создает новый поток. Такое сообщение посылается всем динамическим библиотекам, загруженным к этому времени процессом._PROCESS_DETACH - сообщает, что динамическая библиотека выгружается из адресного пространства процесса._THREAD_DETACH - сообщает, что некий поток, созданный данным процессом, в адресное пространство которого загружена данная динамическая библиотека, уничтожается.

Формат DLL-библиотеки почти идентичен формату загрузочного модуля приложения Windows, однако вы не можете "запустить" DLL-библиотеку на выполнение, как обычное приложение. И это понятно, так как назначение DLL-библиотек другое - они служат хранилищем функций, вызываемых приложениями во время работы. Функции, расположенные в DLL-библиотеках, могут вызывать функции, которые находятся в других библиотеках.библиотека находится в памяти в единственном экземпляре, содержит сегменты кода и ресурсы, а так же один сегмент данных. Можно сказать, что для DLL-библиотеки создается одна копия состоящая только из сегмента данных, и один модуль, состоящий из кода и ресурсов.

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

Тем не менее, функции, расположенные в DLL-библиотеке, пользуются сегментом данных, принадлежащей этой библиотеке, а не копии приложения. При этом возникают трудности, связанные с тем, что сегментный регистр SS, с помощью которого адресуется стек, указывает на стек копии приложения, а регистр DS - на сегмент данных DLL-библиотеки.

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

С помощью DLL-библиотек можно организовать коллективное использование ресурсов или данных, расположенных в сегменте данных библиотеки. Более того, вы можете создать DLL-библиотеки, состоящие только из одних ресурсов, например, из пиктограмм или изображений bitmap. В состав Windows входит DLL-библиотека moricons. dll, состоящая из одних пиктограмм. Файлы с расширением. fon представляют собой ни что иное, как DLL-библиотеки, содержащие шрифты в виде ресурса.

Функции, входящие в состав DLL-библиотеки, могут заказывать блоки памяти с атрибутом GMEM_SHARE. Такой блок памяти не принадлежит ни одному приложению и поэтому не освобождается автоматически при завершении работы приложения. Так как в Windows версии 3.1 все приложения используют общую глобальную память, блоки памяти с атрибутом GMEM_SHARE можно использовать для обмена данными между приложениями. Управлять таким обменом могут, например, функции, расположенные в соответствующей DLL-библиотеке. Однако в следующих версиях Windows каждое приложение будет работать в собственном адресном пространстве, поэтому для организации обмена данных между приложениями следует использовать специальный механизм динамического обмена данными DDE.

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

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

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

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

Во-вторых, в дополнение к exe-файлу вместе с приложением необходимо устанавливать один или несколько dll-файлов, что в некоторой степени усложняет процесс установки и сопровождения приложения. Может также возникнуть ситуация, при которой приложение не находит свою DLL-библиотеку, несмотря на то, что нужная библиотека есть на диске.

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

Фактически, полных преимуществ от внедрения DLL получить не удалось по причине явления, называемого DLL hell ("ад DLL"). DLL Hell возникает, когда несколько приложений требуют одновременно различные, не полностью совместимые, версии DLL-библиотек, что приводит к сбоям в этих приложениях. Когда система выросла до определённых размеров, количество DLL стало превышать многие тысячи, не все из них обладали полной надёжностью и совместимостью, и конфликты типа DLL Hell стали возникать очень часто, резко понижая общую надёжность системы. Поздние версии Microsoft Windows стали разрешать параллельное использование разных версий DLL, что свело на нет преимущества изначального принципа модульности.


Описание функций, использующихся в программах


Функция LoadIcon

function LoadIcon (Instance: THandle; IconName: PChar): HIcon;

Загpужает поименованный pесуpс пиктогpаммы.

Паpаметpы:

·Instance: Экземпляp модуля, исполнимый файл котоpого содеpжит пиктогpамму или 0 для пpедопpеделенной пиктогpаммы.

·IconName: Стpока или имя целочисленного идентификатоpа или пpедопpеделенная пиктогpамма, опpеделенная одной из констант idi.

Возвpащаемое значение: В случае успешного завеpшения - идентификатоp пиктогpаммы; 0 - впpотивном случае.

Функция находится в файле user32. dll.

Функция LoadLibrary

function LoadLibrary (LibFileName: PChar): THandle;

Загpужает поименованный модуль библиотеки.

Паpаметpы:

·LibFileName: Имя файла библиотеки (заканчивающееся пустым символом).

Возвpащаемое значение: В случае успешного завеpшения - идентификатоp экземпляpа модуля библиотеки (значение, больше 32); если нет, то его значение меньше 32 и является одним из следующих: (0) нет памяти; (5) попытка связать задачу; (11) невеpный файл EXE; (12) пpикладная задача из OS/2; (13) пpикладная задача из DOS 4.0; (14) невеpный тип EXE; (15) незащищенный pежим.

Функция находится в файле kernel32. dll.

Функция PostMessage

function PostMessage (Wnd: HWnd; Msg, wParam: Word; lParam: Longint): Bool;

Напpавляет сообщение окну пpикладной задачи.

Паpаметpы:

·Wnd: Окно, котоpое будет пpинимать сообщение, или $FFFF для всех пеpекpываемых или всплывающих окон.

·Msg: Тип сообщения.

·wParam: Дополнительная инфоpмация о сообщении.

·lParam: Дополнительная инфоpмация о сообщении.

Возвращаемое значение: не нуль в случае успешного завеpшения; 0 - если нет.

Функция находится в файле user32. dll.

Функция GetModuleHandle

function GetModuleHandle (ModuleName: PChar): THandle;

Считывает описатель модуля.

Паpаметpы:

·ModuleName: Имя модуля (заканчивающееся пустым символом).

Возвpащаемое значение: в случае успешного завеpшения - идентификатоp модуля; 0 - в пpотивном случае.

Функция находится в файле kernel32. dll.

Функция DialogBoxParam

function DialogBoxParam (Instance, THandle; TemplateName: PChar; Parent: HWnd; DialogFunc: TFarProc; InitParam: Longint): Integer;

Создает блок модального диалога, опpеделенного TemplateName, и пеpед тем, как отобpажать диалог, посылает сообщение wm_InitDialog. Также позволяет пеpедавать функции обpатного вызова начального паpаметpа.

Паpаметpы:

·Instance: Экземпляp модуля, исполнимый файл котоpого содеpжит шаблон блока диалога.

·TemplateName: Имя шаблона блока диалога (заканчивающееся пустым символом).

·Parent: Окно владельца.

·DialogFunc: Адpес экземпляpа пpоцедуpы функции диалога.

·InitParam: Пеpедается в паpаметpе lParam сообщения wm_InitDialog.

Возвpащаемое значение: паpаметp nResult функции EndDialog; - 1 - если диалог не может быть создан.

Функция находится в файле user32. dll.

Функция ExitProcess

function ExitProcess (uExitCode);

Закончить данный процесс со всеми подзадачами (потоками).

Параметры:

·uExitCode Определяет код выхода для процесса, и для всех потоков, которые завершают работу в результате вызова этой функции.

Возвpащаемое значение: у этой функции нет возвращаемого значения.

Функция FreeLibrary

function FreeLibrary (LibModule: THandle);

Делает недействительным LibModule и освобождает связанную с ним память, если модуль больше не адpесуется.

Паpаметpы:

·LibModule: Загpуженный библиотечный модуль.

Возвращаемые значение: если функция завершается успешно, возвращаемое значение не нуль. Если функция завершается ошибкой, возвращаемое значение равняется нулю.

Функция находится в файле kernel32. dll.

Функция EndDialog

function EndDialog (Dlg: Hwnd; Result: Integer);

Теpминиpует модальный блок диалога. Значение, указанное паpаметpом esult, возвpащается в создающую функцию DialogBox.

Паpаметpы:

·Dlg: Уничтожаемый диалог.

·Result: Возвpащаемое значение.

Возвращаемые значение: если функция завершается успешно, возвращаемое значение отлично от нуля. Если функция не выполняет задачу, возвращаемое значение нулевое.

Функция находится в файле user32. dll

Функция GetProcAddress

function GetProcAddress (Module: THandle; ProcName: PChar): TFarProc;

Считывает адpес экспоpтиpованной библиотечной функции.

Паpаметpы:

·Module: Библиотечный модуль.

·ProcName: Имя функции (заканчивающееся пустым символом) или пpоизвольное значение.

Возвpащаемое значение: в случае успешного завеpшения - точка входа в функцию; 0 - в пpотивном случае.

Функция находится в файле kernel32. dll.

Функция MessageBox

function MessageBox (Parent: HWnd; Txt, Caption: PChar; TextType: Word): Integer;

Создает и отобpажает блок диалога, содеpжащий указанное сообщение и заголовок, а также пpедопpеделенные пиктогpаммы и текстовые кнопки, в соответствии с паpаметpом TexType.

Паpаметpы:

·Parent: Окно, владеющее блоком сообщений.

·Txt: Отобpажаемое сообщение (заканчивающееся пустым символом).

·Caption: Заголовок блока диалога (заканчивающийся пустым символом) или nil для "Error" ("Ошибка").

·TextType: Одна или комбинация констант mb.

Возвpащаемое значение: в случае успешного завеpшения одна из следующих констант: id_Abort, id_Cancel, id_Ignore, id_No, id_OK, id_Retry или id_Yes.

Функция находится в файле user32. dll.

Функция Invoke

function Invoke (имя API функции, параметры): Integer;

Данная функция помещает параметры в стек и вызывает указанную API функцию.

Сообщение операционной системы Windows:

·WM_SETICON - Приложение посылает окну данное сообщение, чтобы ассоциировать с ним новую иконку (значок).

·WM_CLOSE - Сообщение, приходящее на процедуру окна при его закрытии. Приходит до WM_DESTROY. Дальнейшее выполнение DefWindowProc, EndDialog или WindowsDestroy и вызывает появление сообщения WM_DESTROY.

·WM_INITDIALOG - Сообщение, приходящее на функцию диалогового окна вместо сообщения WM_CREATE.

·WM_LBUTTONDOWN - Сообщение генерируется при нажатии левой кнопки мыши.


Примеры реализации DLL


Явное связывание

Библиотека должна быть вначале загружена при помощи функции LoadLibrary. Затем определяется адрес процедуры с помощью функции GetProcAddress, после чего можно осуществлять вызов. Как и следовало ожидать, MASM помещает в динамическую библиотеку вместо DLLP1 имя _DLLP1@0, тогда как TASM помещает имя без искажения. Это учитывается в программе.


dll1. asm:

.386P

. MODEL FLAT, stdcallcasemap: none

; - ------------------------------------------------

PUBLIC DLLP1

; константы

; сообщения, приходящие при открытии

; динамической библиотеки_PROCESS_DETACH equ 0_PROCESS_ATTACH equ 1_THREAD_ATTACH equ 2_THREAD_DETACH equ 3

; директивы компоновщику для подключения библиотек

includelib user32. libkernel32. libwindows. inckernel32. incuser32. inc

; - -------------------------------------------------

; сегмент данных

. data

TEXT1 DB 'Вход в библиотеку',0DB 'Выход из библиотеки',0DB 'Сообщение из библиотеки',0DB 'Вызов процедуры из DLL',0

; - -------------------------------------------------

; сегмент кода

. code

; [EBP+10H]; резервный параметр

; [EBP+0CH]; причина вызова

; [EBP+8]; идентификатор DLL-модуля

DLLENTRY:EAX,DWORD PTR [EBP+0CH]

CMP EAX,0D1

; закрытие библиотеки

invoke MessageBox, 0, OFFSET TEXT2, OFFSET MS, 0_EXIT:EAX,1_EXIT

; открытие библиотекиMessageBox, 0, OFFSET TEXT1, OFFSET MS, 0

_EXIT:EAX,112

; - ------------------

; [EBP+8]; параметр процедурыPROC EXPORTEBPEBP,ESPDWORD PTR [EBP+8],1_EXMessageBox, 0, OFFSET TEXT, OFFSET MS, 0

_EX:EBP4ENDPDLLENTRY

dllex. asm:

.386P

; плоская модель

. MODEL FLAT, stdcallcasemap: none

; - ------------------------------------------------

; директивы компоновщику для подключения библиотек

includelib user32. lib

includelib kernel32. libwindows. inckernel32. incuser32. inc

; - ----------------------------------------

; сегмент данных

. data

TXT DB 'Ошибка динамической библиотеки',0

MS DB 'Сообщение',0

LIBR DB 'DLL1. DLL',0

HLIB DD?DB '_DLLP1@0',0

; - ----------------------------------------

; сегмент кода

. code:

; загрузить библиотекуLoadLibrary, OFFSET LIBREAX,0 _ERR

MOV HLIB,EAX

; получить адрес процедуры

invoke GetProcAddress, HLIB, OFFSET NAMEPROCEAX,0 YES_NAME

; сообщение об ошибке

_ERR:MessageBox, 0, OFFSET TXT, OFFSET MS, 0_EXIT_NAME:1; параметрEAX

; закрыть библиотекуFreeLibrary, HLIB

; библиотека автоматически закрывается также

; при выходе из программы

; выход

_EXIT:ExitProcess, 0START

Результат работы программы:


Рисунок 1


Неявное связывание.

Здесь важно заметить, что, во-первых, необходимо объявить вызываемую из динамической библиотеки процедуру как внешнюю, а, во-вторых, подключить статическую библиотеку DLLP1. LIB.


dll1. asm:

.386P

. MODEL FLAT, stdcallcasemap: none

; - ------------------------------------------------DLLP1

; константы

; сообщения, приходящие при открытии

; динамической библиотеки

DLL_PROCESS_DETACH equ 0_PROCESS_ATTACH equ 1_THREAD_ATTACH equ 2_THREAD_DETACH equ 3

; директивы компоновщику для подключения библиотекuser32. lib

includelib kernel32. libwindows. inckernel32. incuser32. inc

; - -------------------------------------------------

; сегмент данных

. dataDB 'Вход в библиотеку',0DB 'Выход из библиотеки',0DB 'Сообщение из библиотеки',0DB 'Вызов процедуры из DLL',0

; - -------------------------------------------------

; сегмент кода

. code

; [EBP+10H]; резервный параметр

; [EBP+0CH]; причина вызова

; [EBP+8]; идентификатор DLL-модуля

DLLENTRY:EAX,DWORD PTR [EBP+0CH]

CMP EAX,0D1

; закрытие библиотеки

invoke MessageBox, 0, OFFSET TEXT2, OFFSET MS, 0_EXIT:EAX,1_EXIT

; открытие библиотекиMessageBox, 0, OFFSET TEXT1, OFFSET MS, 0

_EXIT:EAX,112

; - ------------------

; [EBP+8]; параметр процедурыPROC EXPORTEBPEBP,ESPDWORD PTR [EBP+8],1_EXMessageBox, 0, OFFSET TEXT, OFFSET MS, 0

_EX:EBP4ENDPDLLENTRY

dllex. asm:

.386P

; плоская модель

. MODEL FLAT, stdcallcasemap: none

; - ------------------------------------------------

; директивы компоновщику для подключения библиотек

includelib user32. lib

includelib kernel32. libwindows. inckernel32. incuser32. incdll1. libDLLP1@0: NEAR

; - ----------------------------------------------------

; сегмент данных

. data

; - ----------------------------------------------------

; сегмент кода

. code

START:1DLLP1@0

; выход

_EXIT: ExitProcess, 0

END START


Как видно, текст программы стал несколько проще.

Результат работы программы:


Рисунок 2

Использование ресурсов


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


dll3. asm:

.386PSETIC

. MODEL FLAT, stdcallcasemap: none

; - ------------------------------------------------

; константы_SETICON equ 80h

; прототипы внешних процедур

; директивы компоновщику для подключения библиотек

includelib user32. libkernel32. libwindows. inckernel32. incuser32. inc

; - ------------------------------------------------

; сегмент данных

. dataDB 0

; - ------------------------------------------------

; сегмент кода

. code:EAX,112

; [EBP+8]

; [EBP+0CH]PROC EXPORTEBPEBP,ESP

; выбрать, какую иконку устанавливатьPRIZ,0

JZ IC_1PRIZ,0LoadIcon, DWORD PTR [EBP+0CH], 3CONT_1:PRIZ,1LoadIcon, DWORD PTR [EBP+0CH], 10

CONT:

; загрузить иконку из ресурсов библиотеки

; установить значок окнаPostMessage, DWORD PTR [EBP+08H], WM_SETICON, 0, EAX

POP EBP8ENDPDLLENTRY

dllex3. asm:

.386P

; плоская модель

. MODEL FLAT, stdcall casemap: none

; - -----------------------------------------------

; константы

; сообщение приходит при закрытии окна

WM_CLOSE equ 10h_INITDIALOG equ 110h_SETICON equ 80h_LBUTTONDOWN equ 201h

; директивы компоновщику для подключения библиотек

includelib user32. lib

includelib kernel32. libwindows. inckernel32. incuser32. incProto

; - -----------------------------------------------

; сегмент данных

. dataDB 'DLL3. DLL',0DD?DD?DB "DIAL1",0DB "_SETIC@0",0

; - -----------------------------------------------

; сегмент кода

. code:

; получить дескриптор приложенияGetModuleHandle, 0

; создать диалог[HINST], EAXDialogBoxParam, [HINST], OFFSET PA, 0, OFFSET Procedura, 0

_EXIT:

invoke ExitProcess, 0

; процедура окна

; расположение параметров в стеке

; [EBP+014Н]; LPARAM

; [EBP+10Н]; WAPARAM

; [EBP+0CH]; MES

; [EBP+8]; HWNDPROCEBPEBP,ESPEBXESIEDI

; - ------------------DWORD PTR [EBP+0CH],WM_CLOSE L1

; закрыть библиотеку

; библиотека автоматически закрывается также

; при выходе из программы

invoke FreeLibrary, HLIB

invoke EndDialog, DWORD PTR [EBP+08H], 0FINISH:DWORD PTR [EBP+0CH],WM_INITDIALOGL2

; загрузить библиотекуLoadLibrary, OFFSET LIBRHLIB,EAX

; загрузить иконкуLoadIcon, [HLIB], 3

; установить иконкуPostMessage, DWORD PTR [EBP+08H], WM_SETICON, 0, EAXFINISH:DWORD PTR [EBP+0CH],WM_LBUTTONDOWN FINISH

; получить адрес процедуры из динамической библиотеки

invoke GetProcAddress, HLIB, OFFSET NAMEPROC

; вызвать процедуру с двумя параметрами

PUSH [HLIB]DWORD PTR [EBP+08H]EAX:EDIESIEBXEBPEAX,0 16

Procedura ENDP

END START


Результат работы программы:


динамическая библиотека ресурс связывание

Рисунок 3


Использование общей памяти


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


dll4. asm:

; динамическая библиотека DLL4. ASM

.386P

; плоская модель

. MODEL FLAT, stdcallcasemap: noneDLLP1

; директивы компоновщику для подключения библиотекuser32. libkernel32. libwindows. inckernel32. incuser32. inc

; - -------------------------------------------------

; сегмент данных

. data DB " В динамической библиотеке",0

MS DB "Сообщение",0

; - -------------------------------------------------

; сегмент кода

. code

; [EBP+10H]; резервный параметр

; [EBP+0CH]; причина вызова

; [EBP+8]; идентификатор DLL-модуля

DLLENTRY:

MOV EAX,1

RET 12

; - -------------------------------------------------

; адреса параметров

DLLP1 PROC EXPORT

PUSH EBPEBP,ESPMessageBox, 0, OFFSET TEXT, OFFSET MS, 0

; изменим строку, расположенную в разделяемой памяти

MOV TEXT,'И'TEXT+1,'з'TEXT+2, ' 'EBPENDPDLLENTRY

dllex4. asm:

; основной модуль DLLEX4. ASM, вызывающий

; процедуру из динамической библиотеки

.386P

; плоская модель

. MODEL FLAT, stdcall casemap: none

; директивы компоновщику для подключения библиотек

includelib user32. libkernel32. libwindows. inckernel32. incuser32. inc

; - ---------------------------------

; сегмент данных

. data DB 'Ошибка динамической библиотеки',0

MS DB 'Сообщение',0

LIBR DB 'DLL4. DLL',0

HLIB DD?DB '_DLLP1@0',0

; - ---------------------------------

; сегмент кода

. code

; [EBP+10H]; резервный параметр

; [EBP+0CH]; причина вызова

; [EBP+8]; идентификатор DLL-модуля

START:

; загрузить библиотекуLoadLibrary, OFFSET LIBREAX,0_ERRHLIB,EAX

; получить адресGetProcAddress, HLIB, OFFSET NAMEPROC EAX,0

JNE YES_NAME

; сообщение об ошибке

_ERR:MessageBox, 0, OFFSET TXT, OFFSET MS, 0_EXIT_NAME:EAXMessageBox, 0, OFFSET MS, OFFSET MS, 0

; закрыть библиотеку

; библиотека автоматически закрывается также

; при выходе из программы

invoke FreeLibrary, HLIB

; выход

_EXIT:ExitProcess, 0START


Результат работы программы:


Рисунок 4


Рисунок 5


Рисунок 6


Передача параметров


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


dll2. asm:

; динамическая библиотека DLL2. ASM

.386P

; плоская модель

. MODEL FLAT, stdcallcasemap: none

; - ------------------------------------------------DLLP1

; константы

; сообщения, приходящие при открытии

; динамической библиотеки

DLL_PROCESS_DETACH equ 0_PROCESS_ATTACH equ 1_THREAD_ATTACH equ 2_THREAD_DETACH equ 3

; директивы компоновщику для подключения библиотек

includelib user32. lib

includelib kernel32. libwindows. inckernel32. incuser32. inc

; - -------------------------------------------------

; сегмент данных

. data

TEXT DB "Строка в динамической библиотеке",0

; - -------------------------------------------------

; сегмент кода

. code

; [EBP+10H]; резервный параметр

; [EBP+0CH]; причина вызова

; [EBP+8]; идентификатор DLL-модуля

DLLENTRY:EAX,DWORD PTR [EBP+0CH] EAX,0

JNE D1

; закрытие библиотеки

JMP _EXIT:EAX,1 _EXIT

; открытие библиотеки

_EXIT:

MOV EAX,1

RET 12

; - --------------------

; адреса параметров

; [EBP+8]

; [EBP+0CH]PROC EXPORTEBPEBP,ESPMessageBox, 0, DWORD PTR [EBP+8], DWORD PTR [EBP+0CH], 0EBPEAX,TEXT8ENDPDLLENTRY

dllex2. asm:

; основной модуль DLLEX2. ASM, вызывающий

; процедуру из динамической библиотеки

.386P

; плоская модель

. MODEL FLAT, stdcall casemap: none

; - ------------------------------------------------

; директивы компоновщику для подключения библиотек

includelib user32. libkernel32. libwindows. inckernel32. incuser32. inc

; - ---------------------------------------------

; сегмент данных

. data DB 'Ошибка динамической библиотеки',0

MS DB 'Сообщение',0

LIBR DB 'DLL2. DLL',0

HLIB DD?

MS1 DB 'Сообщение из библиотеки',0

TEXT DB 'Строка содержится в основном модуле',0

NAMEPROC DB '_DLLP1@0',0

; - ---------------------------------------------

; сегмент кода

. code

; [EBP+10H]; резервный параметр

; [EBP+0CH]; причина вызова

; [EBP+8]; идентификатор DLL-модуля

START:

; загрузить библиотекуLoadLibrary, OFFSET LIBREAX,0_ERRHLIB,EAX

; получить адресGetProcAddress, HLIB, OFFSET NAMEPROC EAX,0

JNE YES_NAME

; сообщение об ошибке

_ERR:MessageBox, 0, OFFSET TXT, OFFSET MS, 0_EXIT_NAME:OFFSET MS1OFFSET TEXTEAXMessageBox, 0, EAX, OFFSET MS, 0

; закрыть библиотеку

invoke FreeLibrary, HLIB

; библиотека автоматически закрывается также

; при выходе из программы

; выход

_EXIT:

invoke ExitProcess, 0

END START


Результат работы программы:


Рисунок 7


Рисунок 8


Вывод


В ходе данной курсовой работы были освещены основы 32-битного программирования на языке Assembler для ОС WINDOWS.

Во всех приведённых программах для вызова API функций используется функция invoke, которая позволяет намного сократить текст программы и делает программы на языке ассемблера похожими на программы на ЯВУ

Компилятор MASM, ОС Windows 7 SP2 x64.


Оглавление Введение Теоретическая часть Описание функций, использующихся в программах Примеры реализации DLL Использование ресурсов Ис

Больше работ по теме:

КОНТАКТНЫЙ EMAIL: [email protected]

Скачать реферат © 2017 | Пользовательское соглашение

Скачать      Реферат

ПРОФЕССИОНАЛЬНАЯ ПОМОЩЬ СТУДЕНТАМ