Шаг 93.
Пример использования DLL

    На этом шаге мы рассмотрим пример использования 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 можно взять здесь.

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

    Трансляция программы:

    На следующем шаге мы рассмотрим небольшую программу, выводящую произвольный текст под заданным углом.




Предыдущий шаг Содержание Следующий шаг