На этом шаге мы рассмотрим пример использования 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
На следующем шаге мы рассмотрим небольшую программу, выводящую произвольный текст под заданным углом.