Ассемблер под Windows №16

Dynamic Link Library


Доброго времени суток, уважаемые подписчики.


В начале хочу извиниться за свою пропажу, к сожалению, периодически это может повторяться.. Сегодня, как Вы могли заметить из названия, речь пойдёт о динамических библиотеках, обычно носящих расширение dll. Наверняка тем, кто писали программы под DOS, очень часто требовались одни и те же процедуры при написании абсолютно разных программ. Они наверняка были записаны в отдельный файл (или скомпилированы в obj) и добавлялись таким образом в каждую программу. В DOS - е, где одновременно могла выполняться лишь одна программа, это было достаточно удобно, однако при приходе многозадачности оказалось не совсем разумным, что несколько копий одной и той же процедуры находятся в памяти одновременно. dll же сделаны так, что они загружены в память лишь когда они используются. Кстати, все процедуры, которые мы использовали в наших программах как раз находятся в dll файлах!

После написание программы, которая использует процедуры из dll нужно как-либо обозначить название dll и, так как трудно предугадать, куда будет загружена dll , то нужно правильно узнать адреса процедур. Этот процесс называется связывание (linking). Во всех прошлых программах мы возлагали всю ответственность связывания на компилятор (точнее на link32.exe = связыватель32). Такое связывание называется неявным, при этом управление загрузкой/выгрузкой dll теряет гибкость. Так же возможно явное связывание, но оно относится к программе вызывателю библиотеки и о нём в следующем уроке, а сегодня мы поговорим о том, как можно самому при помощи ассемблера сделать полноценную библиотеку.

В принципе, динамическая библиотека мало чем отличается от обычной программы, но некоторые особенности конечно есть:
- программа запускается при загрузке и выгрузке библиотеки.
- программа получает три параметра и должна отчищать от них стек.
- программа должна возвращать в eax ненулевое значение.
- для совместимости имя каждой процедуры должно начинаться с _ и заканчиваться @колво_параметров
- имя каждой внешне используемой процедуры нужно объявлять публичной (public).

Итак, наша первая библиотека, DLL1.asm:
.386
.model flat
public_CheckStringLength@4
public_CopyString@8
;
.data
.code
;
_CopyString@8proc
push esi
push edi
;
mov edi,[esp+0Ch]
mov esi,[esp+10h]
;
push ecx
xor ecx,ecx
copy_string_loop:
lodsb
test al,al
jz copy_string_end
stosb
inc ecx
jmp copy_string_loop
copy_string_end:
mov eax,ecx
pop ecx
;
pop edi
pop esi
ret 8
_CopyString@8endp
;
_CheckStringLength@4proc
push edi
push ecx
;
xor ecx,ecx
mov edi,[esp+0Ch]
dec ecx
xor eax,eax
repne scasb
neg ecx
mov eax,ecx
dec eax
dec eax
;
pop ecx
pop edi
ret 4
_CheckStringLength@4endp
;
_start@12:
xor eax,eax
inc eax
ret 12
end _start@12

Ничего нового, я думаю, в процедурах нет, поэтому не будем их отдельно разбирать. Компиляция производится следующим образом, нам понадобится два файла, во первых DLL1.bat, во вторых DLL1.lnk, следующего содержания:
DLL1.bat
ml /c /coff /Fl /D_MASM_ dll1.asm
link32 dll1.obj @dll1.lnk

DLL1.lnk
/DLL
/entry:start
/subsystem:windows
/export:CheckStringLength
/export:CopyString
Теперь для создания DLL требуется лишь запустить DLL1.bat

Использование dll мало чем отличается от использование kernel32 или user32, которые мы использовали даже в самой первой нашей программе, так как помимо файла .dll компилятор создаёт также .lib (не кажется ли знакомым?), а при помощи .lib можно создать .inc, который нам и нужен. Можно конечно делать это ручками, но человек ленив, и я не исключение, поэтому я написал програмку, которая создаёт .inc файл из .lib. Думаю, что она может пригодиться всем.


На сегодня это всё. В следующем уроке рассмотрим связывание подробней. Если есть какие вопросы, пишите, обязательно отвечу. Пишите, Dark_Lord@RusFAQ.ru, Dark_Lord@land.ru.
Или свяжитесь со мной по ICQ, мой номер 126222874!

Сайт управляется системой uCoz