Будь умным!


У вас вопросы?
У нас ответы:) SamZan.net

DLL (англ Dynamic Link Library «библиотека динамической компоновки», «динамически подключаемая библиотека»)

Работа добавлена на сайт samzan.net: 2016-03-30

Поможем написать учебную работу

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

Предоплата всего

от 25%

Подписываем

договор

Выберите тип работы:

Скидка 25% при заказе до 19.5.2024

Содержание

  1.  Введение……………………………………………………………………3
  2.  Теоретическая часть………………………….……………………………4
  3.  Описание Функций………………………….………………………..……7
  4.  Реализация на примерах…………….………………………………...….11
  5.  Выводы…………………………………………………………………….29
  6.  Список литературы……………………………………………………….30

 

Введение

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), что свело на нет преимущества изначального принципа модульности.

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

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

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

Функция 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

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

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

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

Рис. 69. Результат работы программы (часть 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)




1. Русский марксиз
2. САМАРСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ ЮРИДИЧЕСКИЙ ФАКУЛЬТЕТ А
3. Подъемно-транспортные машины
4. Тест самоконтроля по курсу юридическая психология
5. на тему- Жилище в первой половине XIX века Доклад составил- ученица 8 Б класса Дудко Диана
6. курсова робота для студентів 4 курсу 8го семестру навчання 2013-2014 навчального року Напрям підготов
7. 1 Принципы равноправной международной торговли
8. 05сентября2012 2 ЭКЗАМЕНАЦИОННЫЕ ВОПРОСЫ и ответы по дисциплине Плавание и методика
9. Лабораторная работа 9 Определение момента инерции плоского тела относительно различных осей Физи
10. на тему- Аттестация персонала
11. Психология интеллекта в журналистик
12. субъективныйвыбор из альтернативы; объективный неопределенность внешней среды Источники опаснос
13. Доврачебная помощь при травмах собак.html
14. тема охорони здоров~я та її структура Для напряму- 5
15. где ijbii 1m j 1n ~ заданные вещественные числа а x1xn ~ неизвестные величины
16. Тема- Моделирование данных Учебные вопросы- 1.
17. Российский экспорт топливно-энергетических ресурсов
18. Озимий ріпак.html
19. ЮжноУральский государственный университет Факультет Физической культуры и спорта Кафедра Адаптив
20. акты принимаемы по вопросам местного значения населением муниципальных образований непосредственно и или