Помощь в написании студенческих работ
Антистрессовый сервис

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

КурсоваяПомощь в написанииУзнать стоимостьмоей работы

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

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

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

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

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

Формат DLL-библиотеки почти идентичен формату загрузочного модуля приложения Windows, однако вы не можете «запустить» DLL-библиотеку на выполнение, как обычное приложение. И это понятно, так как назначение 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, stdcall

option casemap: none

; - ————————————————————————

PUBLIC DLLP1

; константы

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

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

DLL_PROCESS_DETACH equ 0

DLL_PROCESS_ATTACH equ 1

DLL_THREAD_ATTACH equ 2

DLL_THREAD_DETACH equ 3

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

includelib user32. lib

includelib kernel32. lib

include windows. inc

include kernel32. inc

include user32. inc

; - ————————————————————————;

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

. data

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

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

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

TEXT DB 'Вызов процедуры из DLL', 0

; - ————————————————————————;

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

. code

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

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

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

DLLENTRY:

MOV EAX, DWORD PTR [EBP+0CH]

CMP EAX, 0

JNE D1

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

invoke MessageBox, 0, OFFSET TEXT2, OFFSET MS, 0

JMP _EXIT

D1:

CMP EAX, 1

JNE _EXIT

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

invoke MessageBox, 0, OFFSET TEXT1, OFFSET MS, 0

_EXIT:

MOV EAX, 1

RET 12

; - —————————

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

DLLP1 PROC EXPORT

PUSH EBP

MOV EBP, ESP

CMP DWORD PTR [EBP+8], 1

JNE _EX

invoke MessageBox, 0, OFFSET TEXT, OFFSET MS, 0

_EX:

POP EBP

RET 4

DLLP1 ENDP

END DLLENTRY

dllex. asm:

.386P

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

. MODEL FLAT, stdcall

option casemap: none

; - ————————————————————————

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

includelib user32. lib

includelib kernel32. lib

include windows. inc

include kernel32. inc

include user32. inc

; - ————————————————————

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

. data

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

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

LIBR DB 'DLL1. DLL', 0

HLIB DD?

NAMEPROC DB '_DLLP1@0', 0

; - ————————————————————

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

. code

START:

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

invoke LoadLibrary, OFFSET LIBR

CMP EAX, 0

JE _ERR

MOV HLIB, EAX

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

invoke GetProcAddress, HLIB, OFFSET NAMEPROC

CMP EAX, 0

JNE YES_NAME

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

_ERR:

invoke MessageBox, 0, OFFSET TXT, OFFSET MS, 0

JMP _EXIT

YES_NAME:

PUSH 1; параметр

CALL EAX

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

invoke FreeLibrary, HLIB

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

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

; выход

_EXIT:

invoke ExitProcess, 0

END START

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

Рисунок 1

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

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

dll1. asm:

.386P

. MODEL FLAT, stdcall

option casemap: none

; - ————————————————————————

PUBLIC DLLP1

; константы

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

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

DLL_PROCESS_DETACH equ 0

DLL_PROCESS_ATTACH equ 1

DLL_THREAD_ATTACH equ 2

DLL_THREAD_DETACH equ 3

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

includelib user32. lib

includelib kernel32. lib

include windows. inc

include kernel32. inc

include user32. inc

; - ————————————————————————;

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

. data

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

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

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

TEXT DB 'Вызов процедуры из DLL', 0

; - ————————————————————————;

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

. code

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

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

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

DLLENTRY:

MOV EAX, DWORD PTR [EBP+0CH]

CMP EAX, 0

JNE D1

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

invoke MessageBox, 0, OFFSET TEXT2, OFFSET MS, 0

JMP _EXIT

D1:

CMP EAX, 1

JNE _EXIT

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

invoke MessageBox, 0, OFFSET TEXT1, OFFSET MS, 0

_EXIT:

MOV EAX, 1

RET 12

; - —————————

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

DLLP1 PROC EXPORT

PUSH EBP

MOV EBP, ESP

CMP DWORD PTR [EBP+8], 1

JNE _EX

invoke MessageBox, 0, OFFSET TEXT, OFFSET MS, 0

_EX:

POP EBP

RET 4

DLLP1 ENDP

END DLLENTRY

dllex. asm:

.386P

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

. MODEL FLAT, stdcall

option casemap: none

; - ————————————————————————

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

includelib user32. lib

includelib kernel32. lib

include windows. inc

include kernel32. inc

include user32. inc

includelib dll1. lib

EXTERN DLLP1@0: NEAR

; - ——————————————————————————

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

. data

; - ——————————————————————————

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

. code

START:

PUSH 1

CALL DLLP1@0

; выход

_EXIT:

invoke ExitProcess, 0

END START

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

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

Рисунок 2

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

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

dll3. asm:

.386P

PUBLIC SETIC

. MODEL FLAT, stdcall

option casemap: none

; - ————————————————————————

; константы

WM_SETICON equ 80h

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

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

includelib user32. lib

includelib kernel32. lib

include windows. inc

include kernel32. inc

include user32. inc

; - ————————————————————————

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

. data

PRIZ DB 0

; - ————————————————————————

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

. code

DLLENTRY:

MOV EAX, 1

RET 12

; [EBP+8]

; [EBP+0CH]

SETIC PROC EXPORT

PUSH EBP

MOV EBP, ESP

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

CMP PRIZ, 0

JZ IC1

MOV PRIZ, 0

invoke LoadIcon, DWORD PTR [EBP+0CH], 3

JMP CONT

IC1:

MOV PRIZ, 1

invoke LoadIcon, DWORD PTR [EBP+0CH], 10

CONT:

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

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

invoke PostMessage, DWORD PTR [EBP+08H], WM_SETICON, 0, EAX

POP EBP

RET 8

SETIC ENDP

END DLLENTRY

dllex3. asm:

.386P

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

. MODEL FLAT, stdcall

option casemap: none

; - ———————————————————————;

; константы

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

WM_CLOSE equ 10h

WM_INITDIALOG equ 110h

WM_SETICON equ 80h

WM_LBUTTONDOWN equ 201h

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

includelib user32. lib

includelib kernel32. lib

include windows. inc

include kernel32. inc

include user32. inc

Procedura Proto

; - ———————————————————————;

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

. data

LIBR DB 'DLL3. DLL', 0

HLIB DD?

HINST DD?

PA DB «DIAL1», 0

NAMEPROC DB «_SETIC@0», 0

; - ———————————————————————;

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

. code

START:

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

invoke GetModuleHandle, 0

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

MOV [HINST], EAX

invoke DialogBoxParam, [HINST], OFFSET PA, 0, OFFSET Procedura, 0

_EXIT:

invoke ExitProcess, 0

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

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

; [EBP+014Н]; LPARAM

; [EBP+10Н]; WAPARAM

; [EBP+0CH]; MES

; [EBP+8]; HWND

Procedura PROC

PUSH EBP

MOV EBP, ESP

PUSH EBX

PUSH ESI

PUSH EDI

; - —————————

CMP DWORD PTR [EBP+0CH], WM_CLOSE

JNE L1

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

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

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

invoke FreeLibrary, HLIB

invoke EndDialog, DWORD PTR [EBP+08H], 0

JMP FINISH

L1:

CMP DWORD PTR [EBP+0CH], WM_INITDIALOG

JNE L2

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

invoke LoadLibrary, OFFSET LIBR

MOV HLIB, EAX

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

invoke LoadIcon, [HLIB], 3

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

invoke PostMessage, DWORD PTR [EBP+08H], WM_SETICON, 0, EAX

JMP FINISH

L2:

CMP DWORD PTR [EBP+0CH], WM_LBUTTONDOWN

JNE FINISH

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

invoke GetProcAddress, HLIB, OFFSET NAMEPROC

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

PUSH [HLIB]

PUSH DWORD PTR [EBP+08H]

CALL EAX

FINISH:

POP EDI

POP ESI

POP EBX

POP EBP

MOV EAX, 0

RET 16

Procedura ENDP

END START

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

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

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

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

dll4. asm:

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

.386P

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

. MODEL FLAT, stdcall

option casemap: none

PUBLIC DLLP1

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

includelib user32. lib

includelib kernel32. lib

include windows. inc

include kernel32. inc

include user32. inc

; - ————————————————————————;

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

. data

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

MS DB «Сообщение», 0

; - ————————————————————————;

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

. code

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

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

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

DLLENTRY:

MOV EAX, 1

RET 12

; - ————————————————————————;

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

DLLP1 PROC EXPORT

PUSH EBP

MOV EBP, ESP

invoke MessageBox, 0, OFFSET TEXT, OFFSET MS, 0

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

MOV TEXT,'И'

MOV TEXT+1,'з'

MOV TEXT+2, ' '

POP EBP

RET

DLLP1 ENDP

END DLLENTRY

dllex4. asm:

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

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

.386P

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

. MODEL FLAT, stdcall

option casemap: none

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

includelib user32. lib

includelib kernel32. lib

include windows. inc

include kernel32. inc

include user32. inc

; - ————————————————;

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

. data

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

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

LIBR DB 'DLL4. DLL', 0

HLIB DD?

NAMEPROC DB '_DLLP1@0', 0

; - ————————————————;

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

. code

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

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

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

START:

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

invoke LoadLibrary, OFFSET LIBR

CMP EAX, 0

JE _ERR

MOV HLIB, EAX

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

invoke GetProcAddress, HLIB, OFFSET NAMEPROC

CMP EAX, 0

JNE YES_NAME

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

_ERR:

invoke MessageBox, 0, OFFSET TXT, OFFSET MS, 0

JMP _EXIT

YES_NAME:

CALL EAX

invoke MessageBox, 0, OFFSET MS, OFFSET MS, 0

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

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

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

invoke FreeLibrary, HLIB

; выход

_EXIT:

invoke ExitProcess, 0

END START

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

Рисунок 4

Рисунок 5

Рисунок 6

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

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

dll2. asm:

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

.386P

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

. MODEL FLAT, stdcall

option casemap: none

; - ————————————————————————

PUBLIC DLLP1

; константы

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

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

DLL_PROCESS_DETACH equ 0

DLL_PROCESS_ATTACH equ 1

DLL_THREAD_ATTACH equ 2

DLL_THREAD_DETACH equ 3

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

includelib user32. lib

includelib kernel32. lib

include windows. inc

include kernel32. inc

include user32. inc

; - ————————————————————————;

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

. data

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

; - ————————————————————————;

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

. 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

invoke MessageBox, 0, DWORD PTR [EBP+8], DWORD PTR [EBP+0CH], 0

POP EBP

LEA EAX, TEXT

RET 8

DLLP1 ENDP

END DLLENTRY

dllex2. asm:

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

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

.386P

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

. MODEL FLAT, stdcall

option casemap: none

; - ————————————————————————

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

includelib user32. lib

includelib kernel32. lib

include windows. inc

include kernel32. inc

include user32. inc

; - ——————————————————————;

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

. data

TXT 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:

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

invoke LoadLibrary, OFFSET LIBR

CMP EAX, 0

JE _ERR

MOV HLIB, EAX

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

invoke GetProcAddress, HLIB, OFFSET NAMEPROC

CMP EAX, 0

JNE YES_NAME

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

_ERR:

invoke MessageBox, 0, OFFSET TXT, OFFSET MS, 0

JMP _EXIT

YES_NAME:

PUSH OFFSET MS1

PUSH OFFSET TEXT

CALL EAX

invoke MessageBox, 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.

Показать весь текст
Заполнить форму текущей работой