Обучающие курсы:

Обучение профессии "Разработчик C#" + стажировка в Mail.ru
Обучение профессии "Разработчик Python" + трудоустройство
Обучение профессии "Веб-разработчик" + стажировка в Mail.ru


Главная страница
Библиотека (скачать книги)
Скачать софт
Введение в программирование
Стандарты для C++
Уроки по C#
Уроки по Python
HTML
Веб-дизайн
Ассемблер в среде Windows
ActiveX
Javascript
Общее о Линукс
Линукс - подробно
Линукс - новое
Delphi
Паскаль для начинающих
Турбопаскаль
Новости
Партнеры
Наши предложения
Архив новостей





Компоновщик генерирует два файла — собственно библиотеку динамической компоновки Sum2.dll и библиотеку импорта Sum2.1ib. Назначение Sum2.dll понятно — в ней находятся экспортируемые процедуры Sum2 и Sub2. Зачем тогда нужен файл Sum2.1ib?

Дело в том, что приложение может использовать DLL одним из двух способов. Первый способ — подключить библиотеку DLL статически, на этапе загрузки приложения. Однако компоновщик не может просто выделить процедуры из библиотеки DLL и поместить их в исполняемый файл приложения. Это связано со сложностью привязок адресов (address fixups) функций, определенных в DLL. Помочь в разрешении этой проблемы может библиотека импорта LIB, в которой содержится необходимая для компоновщика информация, позволяющая корректно "связать" наше приложение с DLL.

Хочется напомнить, что подобный вариант использования DLL мы видим на примерах разработки полнофункциональных приложений на ассемблере, встречающихся в этой книге. В таких программах мы используем функции WIN API из системных библиотек kernel32.dll, user32.dll и gdi32.dll. Для вызова функций из DLL в ассемблерный модуль включается информация из соответствующих библиотек импорта. Это делается с помощью директив includelib:
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\user32.lib

Если мы хотим использовать библиотеку Sum2.dll, то должны будем включить в программу библиотеку импорта Sum2.1ib:
includelib Sum2.1ib
Кроме того, необходимо описать прототипы функций Sum2 и sub2 из DLL:
Sum2 PROTO
Sub2 PROTO

Это все, что необходимо сделать для статического подключения DLL к приложению. Далее рассмотрим пример, демонстрирующий описанную выше методику.
Разработаем программу, которая будет выводить результат суммирования двух целых чисел в окно приложения при нажатии левой кнопки мыши и результат вычитания — при нажатии правой кнопки. Программа будет использовать процедуры Sum2 и Sub2 из библиотеки Sum2.dll.
Исходный текст программы (назовем ее LOADSUM2) приведен далее в листинге 5.26.
Листинг 5.26. Программа, использующая библиотеку импорта LIB для вызова функций из DLL
LOADSUM2 . ASM
.386
.model flat, stdcaii
option casemap :none ; различаем регистр символов
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
.data
szClassName DB "LoadDLL_Class", 0
szDisplayName DB "ЗАГРУЗКА DLL ПРИ СТАРТЕ
CommandLine DD 0
hWnd DD 0
hlnstance DD 0
il DD 23
i2 DD --54
isum DD 0
isub DD 0
lpFmt DB "%s%d", 0
slnts DB "ПЕРВОЕ ЧИСЛО = 23, BTOPC
lslnts EQU $-s!nts
-54"
si
s2
buf
stitlel
stitle2
DB "СУММА = ", 0
DB "РАЗНОСТЬ = ", 0
DB 32 dup (0)
DB "ВЫЧИСЛЕНИЕ СУММЫ ДВУХ ЦЕЛЫХ ЧИСЕЛ", 0
DB "ВЫЧИСЛЕНИЕ РАЗНОСТИ ДВУХ ЦЕЛЫХ ЧИСЕЛ", '0
. code
include \masm32\include\gdi32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\gdi32.lib

Библиотека импорта, сгенерированная компилятором
includelib Sum2.1ib

Прототипы функций, включая функции из DLL
WinMain PROTO :DWORD,:DWORD,:DWORD, :DWORD
WndProc PROTO :DWORD,:DWORD,:DWORD, :DWORD
Sura2 PROTO ; функция Sum2 из библиотеки Sum2.dll
Sub2 PROTO ; функция Sub2 из библиотеки Sum2.dll
start:
invoke GetModuleHandle, NULL
mov hlnstance, EAX
invoke GetCommandLine
mov CommandLine, EAX
invoke WinMain, hlnstance, NULL, CommandLine, SW_SHOWDEFAULT
invoke ExitProcess, EAX
WinMain proc hlnst :DWORD,
hPrevInst :DWORD,
CmdLine :DWORD,
CmdShow :DWORD
LOCAL wc :WNDCLASSEX
LOCAL msg :MSG

Заполнение структуры WNDCLASSEX требуемыми параметрами
mov wc.cbSize, sizeof WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW or CS_BYTEALIGNWINDOW
mov wc.lpfnWndProc, offset WndProc
mov wc.cbClsExtra, NULL
mov wc.cbWndExtra, NULL
push hlnst
pop wc.hIns t ance
mov wc.hbrBackground, C0L0R_WIND0W-1
mov wc.IpszMenuName, NULL
mov wc.IpszClassName, offset szClassName
invoke Loadlcon, hlnst, 500
mov wc.hlcon, EAX
invoke LoadCursor, NULL, IDC_ARROW
mov wc.hCursor, EAX
mov wc.hlconSm, 0
invoke RegisterClassEx, ADDR wc
invoke CreateWindowEx, WS_EX_OVERLAPPEDWINDOW, ADDR szClassName,\
ADDR szDisplayName, WS_OVERLAPPEDWINDOW,\
CWJJSEDEFAULT, CWJJSEDEFAULT, CWJJSEDEFAULT, \
CW USEDEFAULT, NULL, NULL, hlnst, NULL
mov hWnd, ЕАХ
invoke ShowWindow, hWnd, SW_SHOWNORMAL
invoke UpdateWindow, hWnd

Цикл обработки сообщений
StartLoop:
push 0
push 0
push NULL
lea EAX, msg
push EAX
call GetMessage
cmp EAX, 0
je ExitLoop
lea EAX, msg
push EAX
call T ranslat eMes s age
lea EAX, msg
push EAX
call DispatchMessage
jmp StartLoop
ExitLoop:
mov EAX, msg.wParam
ret
WinMain endp

Оконная процедура приложения
WndProc proc hWin :DWORD,
uMsg :DWORD,
wParam :DWORD,
lParam :DWORD
LOCAL hdc :HDC
LOCAL rect :RECT
LOCAL ps :PAINTSTRUCT
cmp uMsg, WM_PAINT
}ne next 1
lea EDX, ps
push EDX
408 Гпава 5
push hWin
call BeginPaint
mov hdc, EAX
invoke TextOut, hdc, 10, 10, ADDR slnts, lslnts
lea EDX, ps
push EDX
push hWin
call EndPaint
ret
push
next_l:
push offset si
push offset lpFmt
push offset buf
call wsprintf
add ESP, 16
invoke MessageBox, hWin,ADDR buf, ADDR stitlel, MB_OK
ret
next_2:
cmp uMsg, WM_RBUTTONDOWN
jne next_3
push i2
push il
call Sub2
mov isub, EAX
push isub
push offset s2
push offset buf
call wsprintf
add ESP, 16
invoke MessageBox, hWin, ADDR buf, ADDR stitle2, MB_OK
ret
next_3:
cmp uMsg, WM_DESTROY
jne next_4
invoke PostQuitMessage, NULL
xor EAX, EAX
ret
WndProc endp
end start

Следует обратить ваше внимание на то, как вызываются процедуры Sum2 и Sub2 в обработчиках нажатия кнопок мыши. Параметры передаются через стек в соответствии с директивой stdcaii. Результат возвращается, как обычно, в регистре ЕАХ И помещается либо в переменную isum (при сложении), либо в переменную isub (при вычитании). Для преобразования полученных значений в текстовые строки используется знакомая нам функция WIN API wsprintf. Назначение и смысл остальных операторов и команд, думаю, понятен.

Рассмотрим второй способ использования DLL — без библиотек импорта. В этом случае DLL загружается и выгружается динамически самим приложением, которое ДЛЯ ЭТОГО ИСПОЛЬЗует фуНКЦИИ WIN API LoadLibrary, GetProcAddress И FreeLibrary.


 
 
 

Библиотека программиста. 2009.
Администратор: admin@programmer-lib.ru