На этом шаге мы рассмотрим пример использования DLL в ассемблерных программах.
В заключение приведем пример того, как динамическая библиотека, созданная на Delphi, может быть использована в программе на языке ассемблера. В алгоритме, реализованном на Delphi, осуществляется размещение ярлыка программы на рабочем столе и одновременно создается пункт в меню Программы (Пуск). Этот алгоритм оформлен в виде DLL.
Данный пример предполагает передачу в процедуру четырех параметров:
Если вы посмотрите на ассемблерный модуль, то увидите, что никаких особенностей в вызове данной динамической библиотеки нет.
Текст DLL.
library lnk;
uses
ShareMem, SysUtils, Classes, Windows, ShlObj, ActiveX,
ComObj, Registry, syncobjs;
procedure setup(prog, uns, jar, menu: PChar); stdcall;
var
MyObject : IUnknown;
MySLink : IShellLink;
MyPFile : IPersistFile;
FileName : String;
Directory : String;
WFileName : WideString;
MyReg : TRegIniFile;
ps1,ps2,sn,path : string;
f : System.text;
begin
CoInitialize(Nil);
MyObject := CreateComObject(CLSID_ShellLink);
MySLink := MyObject as IShellLink;
MyPFile := MyObject as IPersistFile;
FileName := prog;
path := ExtractFilePath(FileName);
with MySLink do
begin
SetArguments('');
SetPath(PChar(FileName));
SetWorkingDirectory(PChar(ExtractFilePath(FileName)));
end;
//Вначале ярлык на экране.
MyReg := TRegIniFile.Create('Software\MicroSoft\Windows\
CurrentVersion\Explorer');
Directory := MyReg.ReadString('Shell Folders','Desktop','');
WFileName := Directory+'\';
WFileName := WFileName+jar;
WFileName := WFileName+'.lnk';
MyPFile.Save(PWChar(WFileName),False);
ps1:=string(WFileName);
//Создание ярлыка в главном меню.
Directory :=MyReg.ReadString('Shell Folders', 'Programs','') + '\';
Directory:=Directory+menu;
WFileName := Directory+'\';
WFileName := WFileName+jar;
WFileName := WFileName+'.lnk';
CreateDir(Directory);
ps2:=Directory+'\';
MyPFile.Save(PWChar(WFileName),False);
//***************************************
MyObject := CreateComObject(CLSID_ShellLink);
MySLink := MyObject as IShellLink;
MyPFile := MyObject as IPersistFile;
FileName := uns;
path := ExtractFilePath(FileName);
with MySLink do
begin
SetArguments('');
SetPath (PChar(FileName));
SetWorkingDirectory (PChar (ExtractFilePath(FileName)))
end;
WFileName := Directory+'\';
WFileName := WFileName+'UNFILES.lnk';
MyPFile.Save (PWChar (WFileName),False);
MyReg.Free;
//Создать файл, куда будет помещена
//нужная для дальнейшей инсталляции информация.
sn:=path+'perebros.lk';
AssignFile(f,sn);
rewrite (f);
writeln(f,ps1);
writeln(f,ps2);
CloseFile(f);
end;
//********************************
Procedure DLLMain (r:DWORD);
begin
end;
Exports
setup;
begin
DLLProc:=@DLLMain;
DLLMain (dll_Process_Attach);
end.
Текст программы, использующей DLL.
.386P ;Плоская модель. .MODEL FLAT, STDCALL ;Прототипы внешних процедур. IFDEF MASM EXTERN GetProcAddress@8:NEAR EXTERN LoadLibraryA@4:NEAR EXTERN FreeLibrary@4:NEAR EXTERN ExitProcess@4:NEAR EXTERN MessageBoxA@16:NEAR includelib \masm32\lib\user32.lib includelib \masm32\lib\kernel32.lib ELSE 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 includelib e:\tasm\lib\import32.lib ENDIF ;------------------------------------------------ ;Сегмент данных. _DATA SEGMENT DWORD PUBLIC USE32 'DATA' TXT DB 'Ошибка динамической библиотеки', 0 MS DB 'Сообщение',0 LIBR DB 'LNK.DLL',0 HLIB DD ? PAR1 DB "C:\PROG\FILES.EXE", 0 PAR2 DB "C:\PROG\UNINST.EXE",0 PAR3 DB "Универсальный поиск",0 PAR4 DB "Программа универсального поиска",0 NAMEPROC DB 'setup',0 _DATA ENDS ;Сегмент кода. _TEXT SEGMENT DWORD PUBLIC USE32 'CODE' ;[EBP+10H] ;Резервный параметр. ;[ЕВР+0СН] ;Причина вызова. ;[ЕВР+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 PAR4 PUSH OFFSET PAR3 PUSH OFFSET PAR2 PUSH OFFSET PAR1 CALL EAX ;Закрыть библиотеку. ;Библиотека автоматически закрывается также ;при выходе из программы. ;(Закомментировано, так как выдает сообщение ;об ошибке, но при этом работает правильно.) ; PUSH HLIB ; CALL FreeLibrary@4 ;Выход. _EXIT: PUSH 0 CALL ExitProcess@4 _TEXT ENDS END START
Трансляция программы:
ML /с /coff /DMASM pr93_2.asm
LINK /SUBSYSTEM:WINDOWS pr93_2.obj
TASM32 /ml pr93_2.asm
TLINK32 -aa pr93_2.obj
На следующем шаге мы рассмотрим небольшую программу, выводящую произвольный текст под заданным углом.