Тема: Створення динамічних бібліотек DLL.
Мета: Навчитись створювати динамічні бібліотеки DLL в середовищі ОС
Windows.
Основні теоретичні відомості
У процесі розробки програми іноді виникає потреба у використанні функції із іншої програми. Цю функцію можна просто скопіювати, що затруднить читання програми і відповідно збільшить розміри виконуваного файла. Можна також створити окремі об’єктні модулі (*.obj) з потрібних функцій і включити їх у бібліотеку (*.lib), і згодом викликати ці модулі із своєї програми. Такий процес називається статичним компонуванням (лінкуванням - Static Linking). У цьому випадку при компонуванні (лінкуванні) програми з бібліотекою компоновщик (лінкувальник) вибирає ті функції, які необхідні нашій програмі і вставляє їх у виконуваний файл. Такий процес не зменшує розмір виконуваного файлу, але дозволяє зробити код програми меншим, нагляднішим і легшим для сприйняття і читання. Даний спосіб використовувався для комп’ютерів з операційною системою MS-DOS. Недоліком цього способу є те, що можна створити велику кількість виконуваних файлів, які будуть мати ідентичні функції. Та для ОС MS-DOS це не було дуже важливою проблемою, оскільки в пам’яті могла бути тільки одна активна програма.
|
|
Інша ситуація в ОС Windows, де в пам’ять завантажується велика кількість виконуваних програм, а якщо ці програми мають функції що повторюються, то такий спосіб буде загромаджувати пам’ять. Цю проблему розв’язують динамічні бібліотеки (DLL – Dynamic Link Libraries). Динамічна бібліотека являє собою велику кількість функцій які зібрані у один файл. При запуску програми, котра використовує бібліотеку DLL, Windows автоматично завантажує її у пам’ять. Якщо запустити іншу програму, що використовує цю ж саму DLL, то Windows вже не буде завантажувати другої копії DLL у пам’ять. В пам’яті буде лише одна копія DLL яку запущені процеси розділяють між собою. Копіюється тільки секція даних для кожного процесу. В даному випадку програма компонується (лінкується) з DLL під час виконання. Такий спосіб називається динамічним компонуванням (лінкуванням - Dynamic Linking).
Динамічна бібліотека може мати різні розширення, наприклад.EXE,.FON. Стандартним розширенням є.DLL. ОС Windows автоматично завантажує тільки такі бібліотеки. Бібліотеки з іншим розширенням потрібно завантажити з програми, використовуючи функції LoadLibrary або LoadLibraryEx.
Приклад програми створення DLL
;--------------------------------------------------
; My_DLL.asm
;---------------------------------------------------
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
|
|
.data
AppName db "My_DLL",0
HelloMsg db "Привіт! Це функція з бібліотеки My_DLL",0
LoadMsg db "Завантаження бібліотеки DLL у пам'ять ",0
UnloadMsg db "Вивантаження бібліотеки DLL з пам'яті",0
ThreadCreated db "Створення вітки у цьому процесі",0
ThreadDestroyed db "Знищення вітка цього процесу",0
.code
DllEntry proc hInstance:HINSTANCE, reason:DWORD, reserved1:DWORD
.if reason==DLL_PROCESS_ATTACH
invoke MessageBox,NULL,addr LoadMsg,addr AppName,MB_OK
.elseif reason==DLL_PROCESS_DETACH
invoke MessageBox,NULL,addr UnloadMsg,addr AppName,MB_OK
.elseif reason==DLL_THREAD_ATTACH
invoke MessageBox,NULL,addr ThreadCreated,\
addr AppName,MB_OK
.else ;.if reason== DLL_THREAD_DETACH
invoke MessageBox,NULL,addr ThreadDestroyed,\
addr AppName,MB_OK
.endif
mov eax,TRUE
ret
DllEntry Endp
TestHello proc
invoke MessageBox,NULL,addr HelloMsg,addr AppName,MB_OK
ret
TestHello endp
End DllEntry
Опис файлу лістинга з розширенням *.def
;--------------
; My_DLL.def
;--------------
LIBRARY My_DLL
EXPORTS TestHello
Опис програми My_DLL.asm та файлу лістінга My_DLL.def
Кожна DLL повинна мати стартову функцію.
Windows викликає цю функцію у випадку коли:
- DLL завантажується перший раз у пам’ять;
- DLL вивантажується з пам’яті;
- створюється нова вітка в цьому ж процесі;
- знищується нова вітка цього процесу;
Ця функція одержує три параметри:
hinstDLL – це дескриптор модуля DLL.
reason - може мати одне з чотирьох значень:
· DLL_PROCESS_ATTACH – DLL одержує це значення коли вперше загружається в адресний простір процесу.
· DLL_PROCES_DETACH – DLL одержує це значення коли вивантажується з адресного простору процесу.
· DLL_THREAD_ATTACH – DLL одержує це значення коли процес створює нову вітку.
· DLL_THREAD_DETACH –DLL одержує це значення коли процес
reserved – визначає наступні аспекти встановлення або очищення
DLL. (рідко викоритовується)
Для того, щоб можна було використовувати функції з бібліотеки іншою програмою, їх потрібно оголосити в файлі імпорту: My_DLL.def
LIBRARY My_DLL
EXPORTS TestHello
LIBRARY - Вказує ім’я бібліотеки.
EXPORTS - Повідомляє компонувальник (лінкер) які функції в DLL експортуються, тобто викликаються із інших програм. В даному випадку нам потрібно щоб інші програми могли викликати функцію TestHello.
Трансляція та компонування DLL
Для того, щоб відтранслювати(ML.EXE) та зкомпонувати (LINK.EXE) даний.ASM код, потрібно використовувати наступні параметри:
ML.EXE /c /coff /Cp My_DLL.asm
LINK.EXE /DLL /SUBSYSTEM:WINDOWS /DEF:My_DLL.def /LIBPATH:d:\masm32\lib My_DLL.obj
Опис параметрів:
/c – говорить MASM’у створити.obj файл формату COFF (Common Object File), який використовується в ОС UNIX як його власний об'єктний і виконуваний формат файлів.
/Cp – говорить MASM’у зберігати регістр назв, заданих програмістом. Можна також вставити в код програми (після директиви.model) стрічку:option casemap:none, щоб одержати такий самий ефект, тобто, щоб MASM розрізняв великі і малі символи.
/DLL – говорить link’еру створити DLL
/SUBSYSTEM:WINDOWS – говорить ink’еру якого виду буде виконуваний модуль.
/DEF - підключає файл імпорту в якому оголошені функції.
/LIBPATH – говорить link’еру де знаходяться бібліотеки імпорту.