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

Сущность DLL как динамических библиотек, позволяющих многократное использование различных программных приложений. Характеристика двух механизмов связывания в среде Windows. Описание функций LoadIcon, LoadLibrary, PostMessage, ExitProcess, их параметры.

Рубрика Программирование, компьютеры и кибернетика
Вид курсовая работа
Язык русский
Дата добавления 10.02.2015
Размер файла 331,7 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

Размещено на http://www.allbest.ru

Содержание

Введение

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

2. Описание функций

3. Реализация на примерах

Выводы

Список литературы

Введение

DLL (англ. Dynamic Link Library -- «библиотека динамической компоновки», «динамически подключаемая библиотека») (Расширение приложения) в операционных системах Microsoft Windows и IBM OS/2 -- динамическая библиотека, позволяющая многократное использование различными программными приложениями. K DLL относятся также элементы управления ActiveX и драйверы.

В мире UNIX аналогичные функции выполняют так называемые общие объекты (англ. shared objects).

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

Использование динамических библиотек (по-другому - библиотек динамической компоновки) - это способ осуществления модульности в период выполнения программы. Динамическая позволяет упростить и саму разработку программного обеспечения. Вместо того чтобы каждый раз перекомпилировать огромные ЕХЕ-программы, достаточно перекомпилировать лишь отдельный динамический модуль. Кроме того, доступ к динамической библиотеке возможен сразу из нескольких исполняемых модулей, что делает многозадачность более гибкой. Фактически, полных преимуществ от внедрения динамически подключаемых библиотек получить не удалось по причине явления, называемого DLL hell («DLL ад»).

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

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

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

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

Рис. 1 Общая структура

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

В любой динамической библиотеке следует определить точку входа (процедура входа). По умолчанию за точку входа принимают метку, указываемую за директивой 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 - сообщает, что динамическая библиотека загружена в адресное пространство вызывающего процесса.

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

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

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

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

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

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

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

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

программный библиотека windows

2. Описание функций

Функция 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ащаемое значение:

Не нуль в случае успешного заве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ом Result, возв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

3. Реализация на примерах

Простейшая библиотека

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

1.bat:

C:\masm32\bin\ml.exe /c /coff /DMASM dll1.asm

C:\masm32\bin\link.exe /subsystem:windows /DLL dll1.obj

pause 0

dll1.asm:

.386P

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

IFDEF MASM

.MODEL FLAT, stdcall

ELSE

.MODEL FLAT

ENDIF

PUBLIC DLLP1

; константы

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

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

DLL_PROCESS_DETACH equ 0

DLL_PROCESS_ATTACH equ 1

DLL_THREAD_ATTACH equ 2

DLL_THREAD_DETACH equ 3

IFDEF MASM

; MASM

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

EXTERN MessageBoxA@16:NEAR

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

includelib c:\masm32\lib\user32.lib

includelib c:\masm32\lib\kernel32.lib

ELSE

; TASM

EXTERN MessageBoxA:NEAR

MessageBoxA@16 = MessageBoxA

includelib c:\tasm\lib\import32.lib

ENDIF

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

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

_DATA SEGMENT DWORD PUBLIC USE32 'DATA'

TEXT1 DB 'Вход в библиотеку',0

TEXT2 DB 'Выход из библиотеки',0

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

TEXT DB 'Процедура из DLL',0

_DATA ENDS

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

_TEXT SEGMENT DWORD PUBLIC USE32 'CODE'

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

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

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

DLLENTRY:

MOV EAX,DWORD PTR [EBP+0CH]

CMP EAX,0

JNE D1

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

PUSH 0

PUSH OFFSET MS

PUSH OFFSET TEXT2

PUSH 0

CALL MessageBoxA@16

JMP _EXIT

D1:

CMP EAX,1

JNE _EXIT

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

PUSH 0

PUSH OFFSET MS

PUSH OFFSET TEXT1

PUSH 0

CALL MessageBoxA@16

_EXIT:

MOV EAX,1

RET 12

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

; [EBP+8] ; параметр процедуры

DLLP1 PROC EXPORT

PUSH EBP

MOV EBP,ESP

CMP DWORD PTR [EBP+8],1

JNE _EX

PUSH 0

PUSH OFFSET MS

PUSH OFFSET TEXT

PUSH 0

CALL MessageBoxA@16

_EX:

POP EBP

RET 4

DLLP1 ENDP

_TEXT ENDS

END DLLENTRY

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

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

Файл библиотеки из предыдущего пункта.

Основной модуль:

dllex.asm:

.386P

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

.MODEL FLAT, stdcall

; константы

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

IFDEF MASM

;MASM

EXTERN GetProcAddress@8:NEAR

EXTERN LoadLibraryA@4:NEAR

EXTERN FreeLibrary@4:NEAR

EXTERN ExitProcess@4:NEAR

EXTERN MessageBoxA@16:NEAR

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

includelib c:\masm32\lib\user32.lib

includelib c:\masm32\lib\kernel32.lib

ELSE

; TASM

EXTERN GetProcAddress:NEAR

EXTERN LoadLibraryA:NEAR

EXTERN FreeLibrary:NEAR

EXTERN ExitProcess:NEAR

EXTERN MessageBoxA:NEAR

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

includelib c:\tasm32\lib\import32.lib

GetProcAddress@8 = GetProcAddress

LoadLibraryA@4 = LoadLibraryA

FreeLibrary@4 = FreeLibrary

ExitProcess@4 = ExitProcess

MessageBoxA@16 = MessageBoxA

ENDIF

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

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

_DATA SEGMENT DWORD PUBLIC USE32 'DATA'

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

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

LIBR DB 'DLL1.DLL',0

HLIB DD ?

IFDEF MASM

NAMEPROC DB '_DLLP1@0',0

ELSE

NAMEPROC DB 'DLLP1',0

ENDIF

_DATA ENDS

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

_TEXT SEGMENT DWORD PUBLIC USE32 'CODE'

START:

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

PUSH OFFSET LIBR

CALL LoadLibraryA@4

CMP EAX,0

JE _ERR

MOV HLIB,EAX

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

PUSH OFFSET NAMEPROC

PUSH HLIB

CALL GetProcAddress@8

CMP EAX,0

JNE YES_NAME

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

_ERR:

PUSH 0

PUSH OFFSET MS

PUSH OFFSET TXT

PUSH 0

CALL MessageBoxA@16

JMP _EXIT

YES_NAME:

PUSH 1 ; параметр

CALL EAX

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

PUSH HLIB

CALL FreeLibrary@4

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

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

; выход

_EXIT:

PUSH 0

CALL ExitProcess@4

_TEXT ENDS

END START

1.bat:

c:\masm32\bin\ml /c /coff /DMASM dllex.asm

c:\masm32\bin\link /subsystem:windows dllex.obj

pause 0

Рис. 2 Результат работы программы

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

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

Файл библиотеки тот же самый.

dllex.asm:

.386P

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

IFDEF MASM

.MODEL FLAT, stdcall

ELSE

.MODEL FLAT

ENDIF

; константы

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

includelib dll1.lib

IFDEF MASM

; MASM

EXTERN DLLP1@0:NEAR

EXTERN ExitProcess@4:NEAR

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

includelib c:\masm32\lib\user32.lib

includelib c:\masm32\lib\kernel32.lib

ELSE

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

includelib c:\tasm32\lib\import32.lib

EXTERN DLLP1:NEAR

EXTERN ExitProcess:NEAR

DLLP1@0 = DLLP1

ExitProcess@4 = ExitProcess

ENDIF

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

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

_DATA SEGMENT DWORD PUBLIC USE32 'DATA'

_DATA ENDS

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

_TEXT SEGMENT DWORD PUBLIC USE32 'CODE'

START:

PUSH 1 ; параметр

CALL DLLP1@0

; выход

_EXIT:

PUSH 0

CALL ExitProcess@4

_TEXT ENDS

END START

1.bat:

c:\masm32\bin\ml /c /coff /DMASM dllex.asm

c:\masm32\bin\link /subsystem:windows dllex.obj

pause 0

Рис. 3 Результат работы программы

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

Основной процесс и динамическая библиотека используют одно и тоже адресное пространство.

Процесс передает адреса строк, которые находятся в блоке данных основного процесса.

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

dll2.asm:

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

.386P

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

IFDEF MASM

.MODEL FLAT, stdcall

ELSE

.MODEL FLAT

ENDIF

PUBLIC DLLP1

; константы

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

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

DLL_PROCESS_DETACH equ 0

DLL_PROCESS_ATTACH equ 1

DLL_THREAD_ATTACH equ 2

DLL_THREAD_DETACH equ 3

IFDEF MASM

; MASM

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

EXTERN MessageBoxA@16:NEAR

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

includelib c:\masm32\lib\user32.lib

includelib c:\masm32\lib\kernel32.lib

ELSE

; TASM

EXTERN MessageBoxA:NEAR

MessageBoxA@16 = MessageBoxA

includelib c:\tasm32\lib\import32.lib

ENDIF

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

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

_DATA SEGMENT DWORD PUBLIC USE32 'DATA'

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

_DATA ENDS

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

_TEXT SEGMENT DWORD PUBLIC USE32 'CODE'

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

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

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

DLLENTRY:

MOV EAX,DWORD PTR [EBP+0CH]

CMP EAX,0

JNE D1

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

JMP _EXIT

D1:

CMP EAX,1

JNE _EXIT

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

_EXIT:

MOV EAX,1

RET 12

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

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

; [EBP+8]

; [EBP+0CH]

DLLP1 PROC EXPORT

PUSH EBP

MOV EBP,ESP

PUSH 0

PUSH DWORD PTR [EBP+0CH]

PUSH DWORD PTR [EBP+8]

PUSH 0

CALL MessageBoxA@16

POP EBP

LEA EAX,TEXT

RET 8

DLLP1 ENDP

_TEXT ENDS

END DLLENTRY

dllex.asm:

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

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

.386P

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

.MODEL FLAT, stdcall

; константы

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

IFDEF MASM

; MASM

EXTERN GetProcAddress@8:NEAR

EXTERN LoadLibraryA@4:NEAR

EXTERN FreeLibrary@4:NEAR

EXTERN ExitProcess@4:NEAR

EXTERN MessageBoxA@16:NEAR

includelib c:\masm32\lib\user32.lib

includelib c:\masm32\lib\kernel32.lib

ELSE

; TASM

includelib c:\tasm32\lib\import32.lib

EXTERN GetProcAddress:NEAR

EXTERN LoadLibraryA:NEAR

EXTERN FreeLibrary:NEAR

EXTERN ExitProcess:NEAR

EXTERN MessageBoxA:NEAR

GetProcAddress@8 = GetProcAddress

LoadLibraryA@4 = LoadLibraryA

FreeLibrary@4 = FreeLibrary

ExitProcess@4 = ExitProcess

MessageBoxA@16 = MessageBoxA

ENDIF

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

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

_DATA SEGMENT DWORD PUBLIC USE32 'DATA'

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

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

LIBR DB 'DLL2.DLL',0

HLIB DD ?

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

TEXT DB 'Это в основном модуле',0

IFDEF MASM

NAMEPROC DB '_DLLP1@0',0

ELSE

NAMEPROC DB 'DLLP1',0

ENDIF

_DATA ENDS

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

_TEXT SEGMENT DWORD PUBLIC USE32 'CODE'

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

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

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

START:

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

PUSH OFFSET LIBR

CALL LoadLibraryA@4

CMP EAX,0

JE _ERR

MOV HLIB,EAX

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

PUSH OFFSET NAMEPROC

PUSH HLIB

CALL GetProcAddress@8

CMP EAX,0

JNE YES_NAME

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

_ERR:

PUSH 0

PUSH OFFSET MS

PUSH OFFSET TXT

PUSH 0

CALL MessageBoxA@16

JMP _EXIT

YES_NAME:

PUSH OFFSET MS1

PUSH OFFSET TEXT

CALL EAX

PUSH 0

PUSH OFFSET MS

PUSH EAX

PUSH 0

CALL MessageBoxA@16

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

PUSH HLIB

CALL FreeLibrary@4

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

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

; выход

_EXIT:

PUSH 0

CALL ExitProcess@4

_TEXT ENDS

END START

1.bat:

c:\masm32\bin\ml /c /coff /DMASM dllex2.asm

c:\masm32\bin\link /subsystem:windows dllex2.obj

pause 0

Рис. 4 Результат работы программы (часть 1)

Рис. 5 Результат работы программы (часть 2)

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

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

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

dll3.rc:

// идентификаторы

#define IDI_ICON1 3

#define IDI_ICON2 10

// определили иконку

IDI_ICON1 ICON "ico1.ico"

IDI_ICON2 ICON "ico2.ico"

dllex.rc:

// определение констант

#define WS_SYSMENU 0x00080000L

#define WS_MINIMIZEBOX 0x00020000L

#define WS_MAXIMIZEBOX 0x00010000L

#define DS_3DLOOK 0x0004L

// определение диалогового окна

DIAL1 DIALOG 0, 0, 340, 120

STYLE WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | DS_3DLOOK

CAPTION "Диалоговое окно с иконкой из динамической библиотеки"

FONT 8, "Arial"

{

}

dll3.asm:

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

.386P

PUBLIC SETIC

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

IFDEF MASM

.MODEL FLAT, stdcall

ELSE

.MODEL FLAT

ENDIF

; константы

WM_SETICON equ 80h

IFDEF MASM

; MASM

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

EXTERN LoadIconA@8:NEAR

EXTERN PostMessageA@16:NEAR

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

includelib c:\masm32\lib\user32.lib

includelib c:\masm32\lib\kernel32.lib

ELSE

; TASM

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

EXTERN LoadIconA:NEAR

EXTERN PostMessageA:NEAR

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

includelib c:\tasm\lib\import32.lib

LoadIconA@8 = LoadIconA

PostMessageA@16 = PostMessageA

ENDIF

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

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

_DATA SEGMENT DWORD PUBLIC USE32 'DATA'

PRIZ DB 0

_DATA ENDS

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

_TEXT SEGMENT DWORD PUBLIC USE32 'CODE'

DLLENTRY:

MOV EAX,1

RET 12

; [EBP+8]

; [EBP+0CH]

SETIC PROC EXPORT

PUSH EBP

MOV EBP,ESP

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

CMP PRIZ,0

JZ IC_1

MOV PRIZ,0

PUSH 3

JMP CONT

IC_1:

MOV PRIZ,1

PUSH 10

CONT:

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

PUSH DWORD PTR [EBP+0CH] ; идентификатор

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

; библиотеки

CALL LoadIconA@8

; установить значок окна

PUSH EAX

PUSH 0

PUSH WM_SETICON

PUSH DWORD PTR [EBP+08H] ; дескриптор окна

CALL PostMessageA@16

POP EBP

RET 8

SETIC ENDP

_TEXT ENDS

END DLLENTRY

dllex3.asm:

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

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

.386P

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

IFDEF MASM

.MODEL FLAT, stdcall

ELSE

.MODEL FLAT

ENDIF

; константы

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

WM_CLOSE equ 10h

WM_INITDIALOG equ 110h

WM_SETICON equ 80h

WM_LBUTTONDOWN equ 201h

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

IFDEF MASM

; MASM

EXTERN PostMessageA@16:NEAR

EXTERN GetProcAddress@8:NEAR

EXTERN LoadLibraryA@4:NEAR

EXTERN FreeLibrary@4:NEAR

EXTERN ExitProcess@4:NEAR

EXTERN GetModuleHandleA@4:NEAR

EXTERN DialogBoxParamA@20:NEAR

EXTERN EndDialog@8:NEAR

EXTERN LoadIconA@8:NEAR

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

includelib c:\masm32\lib\user32.lib

includelib c:\masm32\lib\kernel32.lib

ELSE

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

includelib c:\tasm\lib\import32.lib

EXTERN PostMessageA:NEAR

EXTERN GetProcAddress:NEAR

EXTERN LoadLibraryA:NEAR

EXTERN FreeLibrary:NEAR

EXTERN ExitProcess:NEAR

EXTERN GetModuleHandleA:NEAR

EXTERN DialogBoxParamA:NEAR

EXTERN EndDialog:NEAR

EXTERN LoadIconA:NEAR

PostMessageA@16 = PostMessageA

LoadIconA@8 = LoadIconA

EndDialog@8 = EndDialog

GetModuleHandleA@4 = GetModuleHandleA

DialogBoxParamA@20 = DialogBoxParamA

GetProcAddress@8 = GetProcAddress

LoadLibraryA@4 = LoadLibraryA

FreeLibrary@4 = FreeLibrary

ExitProcess@4 = ExitProcess

ENDIF

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

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

_DATA SEGMENT DWORD PUBLIC USE32 'DATA'

LIBR DB 'DLL3.DLL',0

HLIB DD ?

HINST DD ?

PA DB "DIAL1",0

IFDEF MASM

NAMEPROC DB "_SETIC@0",0

ELSE

NAMEPROC DB "SETIC",0

ENDIF

_DATA ENDS

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

_TEXT SEGMENT DWORD PUBLIC USE32 'CODE'

START:

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

PUSH 0

CALL GetModuleHandleA@4

; создать диалог

MOV [HINST], EAX

PUSH 0

PUSH OFFSET WNDPROC

PUSH 0

PUSH OFFSET PA

PUSH [HINST]

CALL DialogBoxParamA@20

; выход

_EXIT:

PUSH 0

CALL ExitProcess@4

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

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

; [EBP+014Н] ; LPARAM

; [EBP+10Н] ; WAPARAM

; [EBP+0CH] ; MES

; [EBP+8] ; HWND

WNDPROC PROC

PUSH EBP

MOV EBP,ESP

PUSH EBX

PUSH ESI

PUSH EDI

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

CMP DWORD PTR [EBP+0CH],WM_CLOSE

JNE L1

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

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

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

PUSH HLIB

CALL FreeLibrary@4

PUSH 0

PUSH DWORD PTR [EBP+08H]

CALL EndDialog@8

JMP FINISH

L1:

CMP DWORD PTR [EBP+0CH],WM_INITDIALOG

JNE L2

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

PUSH OFFSET LIBR

CALL LoadLibraryA@4

MOV HLIB,EAX

; загрузить иконку

PUSH 3 ; идентификатор иконки

PUSH [HLIB] ; идентификатор процесса

CALL LoadIconA@8

; установить иконку

PUSH EAX

PUSH 0 ; тип иконки (маленькая)

PUSH WM_SETICON

PUSH DWORD PTR [EBP+08H]

CALL PostMessageA@16

JMP FINISH

L2:

CMP DWORD PTR [EBP+0CH],WM_LBUTTONDOWN

JNE FINISH

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

PUSH OFFSET NAMEPROC

PUSH HLIB

CALL GetProcAddress@8

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

PUSH [HLIB]

PUSH DWORD PTR [EBP+08H]

CALL EAX

FINISH:

POP EDI

POP ESI

POP EBX

POP EBP

MOV EAX,0

RET 16

WNDPROC ENDP

_TEXT ENDS

END START

1.bat:

c:\masm32\bin\ml /c /coff /DMASM dllex3.asm

c:\masm32\bin\rc dllex3.rc

c:\masm32\bin\link /subsystem:windows dllex3.obj dllex3.res

pause 0

c:\masm32\bin\ml /c /coff /DMASM dll3.asm

c:\masm32\bin\rc dll3.rc

c:\masm32\bin\link /subsystem:windows /DLL /ENTRY:DLLENTRY dll3.obj dll3.res

pause 0

Рис. 6 Результат работы программы (часть 1)

Рис. 7 Результат работы программы (часть 2)

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

Запускаемое приложение загружает динамическую библиотеку и вызывает процедуру из динамической библиотеки, которая меняет данные, расположенные опять же в динамической библиотеке. Запустим теперь второй экземпляр приложения. Оно загружает еще один экземпляр динамической библиотеки. Могут быть ситуации, когда желательно, чтобы второе запущенное приложение "знало", что по команде первого приложения данные уже изменились. Ясно, что в этом случае данные, которыми оперирует динамическая библиотека, должны быть общими. Технически это делается очень просто.

У редактора связей LINK есть опция /section: имя, атрибуты, которая позволяет объявить явно свойства данной секции. Достаточно сказать, что секция - это просто сегмент в старом понимании. В редакторе связей TLINK32 то же действие можно осуществить с помощью файла .DEF.

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

dll4.asm:

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

.386P

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

IFDEF MASM

.MODEL FLAT, stdcall

ELSE

.MODEL FLAT

ENDIF

PUBLIC DLLP1

IFDEF MASM

; MASM

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

EXTERN MessageBoxA@16:NEAR

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

includelib c:\masm32\lib\user32.lib

includelib c:\masm32\lib\kernel32.lib

ELSE

; TASM

EXTERN MessageBoxA:NEAR

MessageBoxA@16 = MessageBoxA

includelib c:\tasm\lib\import32.lib

ENDIF

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

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

_DATA SEGMENT DWORD PUBLIC USE32 'DATA'

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

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

_DATA ENDS

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

_TEXT SEGMENT DWORD PUBLIC USE32 'CODE'

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

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

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

DLLENTRY:

MOV EAX,1

RET 12

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

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

DLLP1 PROC EXPORT

PUSH EBP

MOV EBP,ESP

PUSH 0

PUSH OFFSET MS

PUSH OFFSET TEXT

PUSH 0

CALL MessageBoxA@16

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

MOV TEXT,'И'

MOV TEXT+1,'з'

POP EBP

RET

DLLP1 ENDP

_TEXT ENDS

END DLLENTRY

dllex4.asm:

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

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

.386P

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

.MODEL FLAT, stdcall

; константы

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

IFDEF MASM

; MASM

EXTERN GetProcAddress@8:NEAR

EXTERN LoadLibraryA@4:NEAR

EXTERN FreeLibrary@4:NEAR

EXTERN ExitProcess@4:NEAR

EXTERN MessageBoxA@16:NEAR

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

includelib c:\masm32\lib\user32.lib

includelib c:\masm32\lib\kernel32.lib

ELSE

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

includelib c:\tasm\lib\import32.lib

EXTERN GetProcAddress:NEAR

EXTERN LoadLibraryA:NEAR

EXTERN FreeLibrary:NEAR

EXTERN ExitProcess:NEAR

EXTERN MessageBoxA:NEAR

GetProcAddress@8 = GetProcAddress

LoadLibraryA@4 = LoadLibraryA

FreeLibrary@4 = FreeLibrary

ExitProcess@4 = ExitProcess

MessageBoxA@16 = MessageBoxA

ENDIF

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

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

_DATA SEGMENT DWORD PUBLIC USE32 'DATA'

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

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

LIBR DB 'DLL4.DLL',0

HLIB DD ?

IFDEF MASM

NAMEPROC DB '_DLLP1@0',0

ELSE

NAMEPROC DB 'DLLP1',0

ENDIF

_DATA ENDS

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

_TEXT SEGMENT DWORD PUBLIC USE32 'CODE'

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

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

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

START:

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

PUSH OFFSET LIBR

CALL LoadLibraryA@4

CMP EAX,0

JE _ERR

MOV HLIB,EAX

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

PUSH OFFSET NAMEPROC

PUSH HLIB

CALL GetProcAddress@8

CMP EAX,0

JNE YES_NAME

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

_ERR:

PUSH 0

PUSH OFFSET MS

PUSH OFFSET TXT

PUSH 0

CALL MessageBoxA@16

JMP _EXIT

YES_NAME:

CALL EAX

PUSH 0

PUSH OFFSET MS

PUSH OFFSET MS

PUSH 0

CALL MessageBoxA@16

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

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

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

PUSH OFFSET NAMEPROC

PUSH HLIB

CALL FreeLibrary@4

; выход

_EXIT:

PUSH 0

CALL ExitProcess@4

_TEXT ENDS

END START

1.bat:

c:\tasm\bin\tasm32 /ml dll4.asm

c:\tasm\bin\tlink32 -aa -Tpd dll4.obj,,,,dll4.def

c:\tasm\bin\tasm32 /ml dllex4.asm

c:\tasm\bin\tlink32 -aa dllex4.obj

pause 0

Рис. 8 Результат работы программы (часть 1)

Рис. 9 Результат работы программы (часть 2)

Вывод

Для компиляции использовались компиляторы MASM32 и TASM32.

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

Список литературы

1) Динамически подключаемая библиотека. URL: http://ru.wikipedia.org/wiki/Динамически_подключаемая_библиотека/

(Дата обращения 20.04.2014).

2) Пирогов Владислав Юрьевич. Ассемблер для Windows. -- М.: Издатель Молгачева С.В., 2002. --552 с., ил. - ISBN 5-94740-003-0.

3) Динамические библиотеки. Общие положения. URL: http://www.cracklab.ru/pro/cpp.php?r=appli&d=zart178/

(Дата обращения 20.04.2014)

Размещено на Allbest.ru=

...

Подобные документы

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.