Powrót do strony wyboru lekcji

Programowanie bibliotek dynamicznych(DLL)



W odróżnieniu od bibliotek statycznych wykorzystywanych w procesie konsolidacji statycznej programu, którą to przeprowadzamy przed uruchomieniem programu, konsolidacja biblioteki dynamicznej - DLL, odbywa się podczas działania programu. Zalety tych bibliotek to przede wszystkim: możliwość asemblowania pojedynczych bibliotek zamiast całego wielkiego pliku .exe oraz bardziej ekonomiczne wykorzystanie dysku, gdyż procedura z takiej biblioteki jest zapisana tylko raz, natomiast funkcje z bibliotek statycznych znajdują się w każdym tworzonym programie, do których zostały dołączone biblioteki statyczne. Schemat konsolidacji statycznej i dynamicznej przedstawiony jest na rysunku poniżej - Rys.1.

Nie można wyświetlić obrazu
Rys.1.Konsolidacja statyczna i dynamiczna.

Przykład

Tworzymy prosty program korzystający z biblioteki dynamicznej, która ładuje nam napis do pola edycyjnego programu. Na początku zdefiniujemy kod asemblerowy biblioteki DLL:


.586P ;typ instrukcji procesora

.MODEL FLAT,STDCALL

includelib c:\masm32\lib\user32.lib
includelib c:\masm32\lib\kernel32.lib

WM_SETTEXT           EQU 0Ch
DLL_PROCESS_DETACH   EQU 0
DLL_PROCESS_ATTACH   EQU 1

PUBLIC LADUJ
EXTERN SendMessageA@16:NEAR

.DATA
BUFF         DB    100  DUP (0)
TXT          DB   'Biblioteka uruchomiona', 0

Stała DLL_PROCESS_DETACH określa usuwanie biblioteki z przestrzeni adresowej procesu. Natomiast DLL_PROCESS_ATTACH informuje procedurę, że aktualny proces tworzy nowy wątek. Procedurę, która będzie wykorzystywana przez zewnętrzne moduły należy zadeklarować jako publiczną - dyrektywa PUBLIC. Sekcja kodu biblioteki DLL wygląda następująco:


.CODE

;[EBP +10H] - Parametr zarezerwowany
;[EBP +0CH] - Przyczyna wywołania
;[EBP +8] - Identyfikator modułu DLL

ADRES:

MOV  EAX,DWORD  PTR  [EBP + 0CH]

CMP  EAX, DLL_PROCESS_DETACH  
JNE  D1

JMP  _EXIT

D1:

CMP  EAX, DLL_PROCESS_ATTACH   
JNE  _EXIT

_EXIT:

MOV EAX, 1
RET

LADUJ PROC EXPORT

PUSH  EBP
MOV  EBP,ESP

PUSH  OFFSET TXT
PUSH  100
PUSH  WM_SETTEXT
PUSH  DWORD  PTR  [EBP + 08H]
CALL  SendMessageA@16

POP  EBP
RET 8

LADUJ   ENDP

END ADRES

Na początku sekcji kodu sprawdzamy czy nie został wygenerowany któryś z komunikatów : DLL_PROCESS_DETACH lub DLL_PROCESS_ATTACH pod adresem EBP + OCH. Procedurę z biblioteki DLL, którą będziemy wykorzystywać w głównym programie należy zaopatrzyć w słowo kluczowe: EXPORT. W procedurze wywołujemy funkcję SendMessageA@16, która spowoduje wypisanie zmiennej tekstowej TXT w polu edycyjnym naszego programu głównego. W instrukcji powrotu z procedury RET należy podać jako argument ilość bajtów potrzebnych dla parametrów procedury. W naszym wypadku jest to 8. Cały kod biblioteki DLL przedstawiony jest na listingu poniżej:


.586P ;typ instrukcji procesora

.MODEL FLAT,STDCALL

includelib c:\masm32\lib\user32.lib
includelib c:\masm32\lib\kernel32.lib

WM_SETTEXT           EQU 0Ch
DLL_PROCESS_DETACH   EQU 0
DLL_PROCESS_ATTACH   EQU 1

PUBLIC LADUJ
EXTERN SendMessageA@16:NEAR

.DATA
BUFF         DB    100  DUP (0)
TXT          DB   'Biblioteka uruchomiona', 0


.CODE

;[EBP +10H] - Parametr zarezerwowany
;[EBP +0CH] - Przyczyna wywołania
;[EBP +8] - Identyfikator modułu DLL

ADRES:

MOV  EAX,DWORD  PTR  [EBP + 0CH]

CMP  EAX, DLL_PROCESS_DETACH  
JNE  D1

JMP  _EXIT

D1:

CMP  EAX, DLL_PROCESS_ATTACH   
JNE  _EXIT

_EXIT:

MOV EAX, 1
RET

LADUJ PROC EXPORT

PUSH  EBP
MOV  EBP,ESP

PUSH  OFFSET TXT
PUSH  100
PUSH  WM_SETTEXT
PUSH  DWORD  PTR  [EBP + 08H]
CALL  SendMessageA@16

POP  EBP
RET 8

LADUJ   ENDP

END ADRES

Pobierz kod

Aby utworzyć bibliotekę dynamiczną wykonujemy następujące polecenia asemblera i konsolidatora:

ml   /c   /coff   b.asm
link   /subsystem:windows   /dll   /entry:ADRES   b.obj

  , gdzie b.asm to nazwa naszego pliku źródłowego biblioteki. W parametrze /entry: należy wpisać adres etykiety wskazującej na początek sekcji kodu naszej biblioteki, w naszym przypadku jest to etykieta ADRES.

Następnie tworzymy kod programu głównego wykorzystującego utworzoną bibliotekę:


.586 ;typ instrukcji procesora

.MODEL FLAT,STDCALL

includelib c:\masm32\lib\user32.lib
includelib c:\masm32\lib\kernel32.lib

WM_DESTROY   EQU 2

WM_CREATE    EQU 1

WM_COMMAND   EQU 111h

CS_VREDRAW          EQU 1h

CS_HREDRAW          EQU 2h

CS_GLOBALCLASS      EQU 4000h

WS_TABSTOP          EQU 10000h

WS_SYSMENU          EQU 80000h

WS_THICKFRAME       EQU 40000h

WS_MAXIMIZEBOX      EQU 10000h

WS_OVERLAPPEDWINDOW EQU WS_TABSTOP + WS_SYSMENU

STYLE               EQU CS_HREDRAW OR CS_VREDRAW OR CS_GLOBALCLASS OR WS_MAXIMIZEBOX

BS_DEFPUSHBUTTON    EQU 1h

WS_VISIBLE          EQU 10000000h

WS_CHILD            EQU 40000000h

WS_BORDER           EQU 800000h

STYLBTN             EQU WS_CHILD + BS_DEFPUSHBUTTON + WS_VISIBLE + WS_TABSTOP

STYLEDT             EQU WS_CHILD + WS_VISIBLE + WS_BORDER + WS_TABSTOP

IDI_APPLICATION     EQU 32512

IDC_ARROW           EQU 32512

SW_SHOWNORMAL       EQU 1

EXTERN GetProcAddress@8:NEAR

EXTERN LoadLibraryA@4:NEAR

EXTERN FreeLibrary@4:NEAR

EXTERN CreateWindowExA@48:NEAR

EXTERN DefWindowProcA@16:NEAR

EXTERN MessageBoxA@16:NEAR

EXTERN DispatchMessageA@4:NEAR

EXTERN ExitProcess@4:NEAR

EXTERN GetMessageA@16:NEAR

EXTERN GetModuleHandleA@4:NEAR

EXTERN LoadCursorA@8:NEAR

EXTERN LoadIconA@8:NEAR

EXTERN PostQuitMessage@4:NEAR

EXTERN RegisterClassA@4:NEAR

EXTERN ShowWindow@8:NEAR

EXTERN TranslateMessage@4:NEAR

EXTERN UpdateWindow@4:NEAR

MSGSTRUCT STRUC
MSHWND       DD      ? ;uchwyt komunikatu
MSMESSAGE    DD      ? ;nazwa komunikatu
MSWPARAM     DD      ? ;dodatkowa informacja komunikatu
MSWLARAM     DD      ? ;dodatkowa informacja komunikatu
MSTIME       DD      ? ;określa czas w który wiadomość była wysłana
MSPT         DD      ? ;określa pozycję kursora
MSGSTRUCT ENDS


WNDCLASS STRUC
CLSSTYLE       DD      ? ;styl okna
CLWNDPROC      DD      ? ;adres procedury okna
CLSCBCLSEX     DD      ? ;dodatkowe bajty na miejsce dla struktury w pamięci
CLSCBWNDEX     DD      ? ;dodatkowe bajty na miejsce dla egzemplarza w pamięci
CLSHINST       DD      ? ;uchwyt danego egzemplarza modułu
CLSHICON       DD      ? ;uchwyt ikony z funkcji LoadIcon
CLSHCURSOR     DD      ? ;uchwyt kursora z funkcji LoadCursor
CLBKGROUND     DD      ? ;kolor tła okna
CLMENUNAME     DD      ? ;uchwyt menu
CLNAME         DD      ? ;nazwa klasy okna
WNDCLASS ENDS

.DATA?
MSG   MSGSTRUCT <?>
WC    WNDCLASS  <?>
NEWHWND     DD   ? ;uchwyt okna zdefiniowanego za pomocą funkcji CreateWindowExA
HLIB        DD   ?

.DATA
HINST       DD   0 ;uchwyt aplikacji
BLAD        DB   'Błąd biblioteki DLL',   0
LIB         DB   'b.dll',   0
PROCEDURA   DB   '_LADUJ@0',   0
ADR         DD   0
KOMUNIKAT   DB   'Komunikat',   0
TITLENAME   DB   'Biblioteki DLL',   0 ;nazwa okna wyświetlona na pasku
CLASSNAME   DB   'KlasaOkna',   0 ;nazwa klasy okna
BTNNAME     DB   'Załaduj bibliotekę',   0 ;nazwy kontrolek
EDTNAME     DB   ' ',   0
CLSBUTN     DB   'BUTTON',   0 ;nazwy klas kontrolek dla CreateWindowExA@48
CLSEDIT     DB   'EDIT',   0
HWNDBTN     DWORD    0 ;uchwyty kontrolek
HWNDEDT     DWORD    0

Funkcja GetProcAddress@8 określa adres procedury z załadowanej do pamięci biblioteki za pomocą LoadLibraryA@4 , FreeLibrary@4 natomiast służy do jej usunięcia. W sekcji niezainicjalizowanych danych umieszczamy uchwyt naszej biblioteki dynamicznej - HLIB , natomiast w sekcji zainicjalizowanych nazwę pliku biblioteki - LIB, nazwę procedury - PROCEDURA oraz zmienną przechowującą adres naszej procedury - ADR. Na początku sekcji korzystamy z wyżej zdefiniowanych funkcji i ładujemy wcześniej przygotowaną bibliotekę DLL:


.CODE

START:

PUSH  OFFSET  LIB
CALL  LoadLibraryA@4

CMP  EAX,0
JE   _ERR

MOV   HLIB,EAX

PUSH  OFFSET  PROCEDURA
PUSH  HLIB
CALL  GetProcAddress@8

CMP  EAX,0
JNE  ZALADOWANA

_ERR:

PUSH  0
PUSH  OFFSET  KOMUNIKAT
PUSH  OFFSET  BLAD
PUSH  0
CALL  MessageBoxA@16
JMP   _EXIT

ZALADOWANA:

MOV   ADR,EAX

Jeżeli któraś z funkcji zwróci błąd, wyświetlana jest informacja o błędzie przy pomocy funkcji MessageBoxA@16. Po załadowaniu adres procedury LADUJ biblioteki jest kopiowany do zmiennej ADR. Pozostała część kodu to standardowy program tworzenia okna z kontrolkami, korzystając z funkcji CreateWindowExA@48, w sekcji WMCOMMAND po wciśnięciu przycisku wywołujemy naszą procedurę z adresu zapisanego wcześniej w zmiennej ADR. Jako parametry funkcji podajemy: 0 i uchwyt pola edycyjnego:


PUSH  0
CALL  GetModuleHandleA@4
MOV  [HINST],EAX

MOV  [WC.CLSSTYLE],STYLE
MOV  [WC.CLWNDPROC],OFFSET WNDPROC
MOV  [WC.CLSCBCLSEX],0
MOV  [WC.CLSCBWNDEX],0
MOV  EAX,[HINST]
MOV  [WC.CLSHINST],EAX

PUSH  IDI_APPLICATION
PUSH  0
CALL  LoadIconA@8

MOV  [WC.CLSHICON],EAX

PUSH  IDC_ARROW
PUSH  0
CALL  LoadCursorA@8

MOV  [WC.CLSHCURSOR],EAX

MOV  [WC.CLBKGROUND],16
MOV  DWORD  PTR  [WC.CLMENUNAME],0
MOV  DWORD  PTR  [WC.CLNAME],OFFSET CLASSNAME


PUSH  OFFSET WC
CALL  RegisterClassA@4

PUSH  0;wskaźnik na dowolne dane zawarte w oknie tuż po utworzeniu
PUSH  [HINST] ;uchwyt aplikacji
PUSH  0;uchwyt do paska menu
PUSH  0 ;uchwyt do okna nadrzędnego względem okna które mamy zamiar stworzyć
PUSH  400 ;wysokość okna
PUSH  500 ;szerokość okna
PUSH  100 ;współrzędna pionowa okna
PUSH  100 ;współrzędna pozioma okna
PUSH  WS_OVERLAPPEDWINDOW;styl okna
PUSH  OFFSET TITLENAME;wskaźnik na tytuł okna
PUSH  OFFSET CLASSNAME;wskaźnik do zarejestrowanej nazwy klasy okna
PUSH  0;rozszerzony styl okna
CALL  CreateWindowExA@48

CMP  EAX,0;czy błąd?
JZ   _EXIT

MOV  [NEWHWND],EAX;uchwyt okna
PUSH  SW_SHOWNORMAL
PUSH  [NEWHWND]
CALL  ShowWindow@8

PUSH  [NEWHWND]
CALL  UpdateWindow@4


MSG_LOOP:
PUSH  0
PUSH  0
PUSH  0
PUSH  OFFSET MSG;wskaźnik na strukturę komunikatu
CALL  GetMessageA@16

CMP  EAX,0;czy koniec?
JE   _EXIT

PUSH  OFFSET MSG
CALL  TranslateMessage@4 ;tłumaczenie

PUSH  OFFSET MSG
CALL  DispatchMessageA@4 ;wysłanie

JMP  MSG_LOOP

_EXIT:

PUSH  HLIB
CALL  FreeLibrary@4

PUSH  0
CALL  ExitProcess@4

;parametry:
;[EBP +14H] LPARAM
;[EBP +10H] WPARAM
;[EBP +0CH] MES
;[EBP +8] HWND

WNDPROC   PROC


PUSH  EBP
MOV  EBP,ESP
PUSH  EBX
PUSH  ESI
PUSH  EDI
CMP  DWORD  PTR  [EBP + 0CH],WM_DESTROY;komunikat związany ze zniszczeniem okna
JE  WMDESTROY

CMP  DWORD  PTR  [EBP + 0CH],WM_CREATE;tworzenie kontrolek w oknie
JE  WMCREATE

CMP  DWORD  PTR  [EBP + 0CH],WM_COMMAND;zdarzenie związane z kontrolką
JE  WMCOMMAND

JMP  DEFWNDPROC;nieobsłużone komunikaty kierujemy do DefWindowProcA@16

WMCREATE:

;Przycisk:

PUSH  0
PUSH  [HINST]
PUSH  0
PUSH  DWORD  PTR  [EBP + 08H];uchwyt okna
PUSH  20
PUSH  200
PUSH  150
PUSH  150
PUSH  STYLBTN
PUSH  OFFSET BTNNAME
PUSH  OFFSET CLSBUTN
PUSH  0
CALL  CreateWindowExA@48

MOV  HWNDBTN,EAX

;Pole edycyjne:

PUSH  0
PUSH  [HINST]
PUSH  0
PUSH  DWORD  PTR  [EBP + 08H];uchwyt okna
PUSH  20
PUSH  200
PUSH  120
PUSH  150
PUSH  STYLEDT
PUSH  OFFSET EDTNAME
PUSH  OFFSET CLSEDIT
PUSH  0
CALL  CreateWindowExA@48

MOV  HWNDEDT,EAX

WMCOMMAND:

MOV   EAX,HWNDBTN
CMP  DWORD  PTR  [EBP + 14H],EAX ;Czy LPARAM to uchwyt przycisku?
JNE FINISH

PUSH  0
PUSH  HWNDEDT
CALL  [ADR]

JMP FINISH

DEFWNDPROC:

PUSH  DWORD  PTR  [EBP + 14H]
PUSH  DWORD  PTR  [EBP + 10H]
PUSH  DWORD  PTR  [EBP + 0CH]
PUSH  DWORD  PTR  [EBP + 08H]
CALL  DefWindowProcA@16
JMP FINISH

WMDESTROY:

PUSH  0
CALL  PostQuitMessage@4
XOR EAX,EAX

FINISH:

POP  EDI
POP  ESI
POP  EBX
POP  EBP
RET
WNDPROC  ENDP

END Start

Całość programu przedstawiona jest na poniższym listingu:


.586 ;typ instrukcji procesora

.MODEL FLAT,STDCALL

includelib c:\masm32\lib\user32.lib
includelib c:\masm32\lib\kernel32.lib

WM_DESTROY   EQU 2

WM_CREATE    EQU 1

WM_COMMAND   EQU 111h

CS_VREDRAW          EQU 1h

CS_HREDRAW          EQU 2h

CS_GLOBALCLASS      EQU 4000h

WS_TABSTOP          EQU 10000h

WS_SYSMENU          EQU 80000h

WS_THICKFRAME       EQU 40000h

WS_MAXIMIZEBOX      EQU 10000h

WS_OVERLAPPEDWINDOW EQU WS_TABSTOP + WS_SYSMENU

STYLE               EQU CS_HREDRAW OR CS_VREDRAW OR CS_GLOBALCLASS OR WS_MAXIMIZEBOX

BS_DEFPUSHBUTTON    EQU 1h

WS_VISIBLE          EQU 10000000h

WS_CHILD            EQU 40000000h

WS_BORDER           EQU 800000h

STYLBTN             EQU WS_CHILD + BS_DEFPUSHBUTTON + WS_VISIBLE + WS_TABSTOP

STYLEDT             EQU WS_CHILD + WS_VISIBLE + WS_BORDER + WS_TABSTOP

IDI_APPLICATION     EQU 32512

IDC_ARROW           EQU 32512

SW_SHOWNORMAL       EQU 1

EXTERN GetProcAddress@8:NEAR

EXTERN LoadLibraryA@4:NEAR

EXTERN FreeLibrary@4:NEAR

EXTERN CreateWindowExA@48:NEAR

EXTERN DefWindowProcA@16:NEAR

EXTERN MessageBoxA@16:NEAR

EXTERN DispatchMessageA@4:NEAR

EXTERN ExitProcess@4:NEAR

EXTERN GetMessageA@16:NEAR

EXTERN GetModuleHandleA@4:NEAR

EXTERN LoadCursorA@8:NEAR

EXTERN LoadIconA@8:NEAR

EXTERN PostQuitMessage@4:NEAR

EXTERN RegisterClassA@4:NEAR

EXTERN ShowWindow@8:NEAR

EXTERN TranslateMessage@4:NEAR

EXTERN UpdateWindow@4:NEAR

MSGSTRUCT STRUC
MSHWND       DD      ? ;uchwyt komunikatu
MSMESSAGE    DD      ? ;nazwa komunikatu
MSWPARAM     DD      ? ;dodatkowa informacja komunikatu
MSWLARAM     DD      ? ;dodatkowa informacja komunikatu
MSTIME       DD      ? ;określa czas w który wiadomość była wysłana
MSPT         DD      ? ;określa pozycję kursora
MSGSTRUCT ENDS


WNDCLASS STRUC
CLSSTYLE       DD      ? ;styl okna
CLWNDPROC      DD      ? ;adres procedury okna
CLSCBCLSEX     DD      ? ;dodatkowe bajty na miejsce dla struktury w pamięci
CLSCBWNDEX     DD      ? ;dodatkowe bajty na miejsce dla egzemplarza w pamięci
CLSHINST       DD      ? ;uchwyt danego egzemplarza modułu
CLSHICON       DD      ? ;uchwyt ikony z funkcji LoadIcon
CLSHCURSOR     DD      ? ;uchwyt kursora z funkcji LoadCursor
CLBKGROUND     DD      ? ;kolor tła okna
CLMENUNAME     DD      ? ;uchwyt menu
CLNAME         DD      ? ;nazwa klasy okna
WNDCLASS ENDS

.DATA?
MSG   MSGSTRUCT <?>
WC    WNDCLASS  <?>
NEWHWND     DD   ? ;uchwyt okna zdefiniowanego za pomocą funkcji CreateWindowExA
HLIB        DD   ?

.DATA
HINST       DD   0 ;uchwyt aplikacji
BLAD        DB   'Błąd biblioteki DLL',   0
LIB         DB   'b.dll',   0
PROCEDURA   DB   '_LADUJ@0',   0
ADR         DD   0
KOMUNIKAT   DB   'Komunikat',   0
TITLENAME   DB   'Biblioteki DLL',   0 ;nazwa okna wyświetlona na pasku
CLASSNAME   DB   'KlasaOkna',   0 ;nazwa klasy okna
BTNNAME     DB   'Załaduj bibliotekę',   0 ;nazwy kontrolek
EDTNAME     DB   ' ',   0
CLSBUTN     DB   'BUTTON',   0 ;nazwy klas kontrolek dla CreateWindowExA@48
CLSEDIT     DB   'EDIT',   0
HWNDBTN     DWORD    0 ;uchwyty kontrolek
HWNDEDT     DWORD    0
.CODE

START:

PUSH  OFFSET  LIB
CALL  LoadLibraryA@4

CMP  EAX,0
JE   _ERR

MOV   HLIB,EAX

PUSH  OFFSET  PROCEDURA
PUSH  HLIB
CALL  GetProcAddress@8

CMP  EAX,0
JNE  ZALADOWANA

_ERR:

PUSH  0
PUSH  OFFSET  KOMUNIKAT
PUSH  OFFSET  BLAD
PUSH  0
CALL  MessageBoxA@16
JMP   _EXIT

ZALADOWANA:

MOV   ADR,EAX


PUSH  0
CALL  GetModuleHandleA@4
MOV  [HINST],EAX

MOV  [WC.CLSSTYLE],STYLE
MOV  [WC.CLWNDPROC],OFFSET WNDPROC
MOV  [WC.CLSCBCLSEX],0
MOV  [WC.CLSCBWNDEX],0
MOV  EAX,[HINST]
MOV  [WC.CLSHINST],EAX

PUSH  IDI_APPLICATION
PUSH  0
CALL  LoadIconA@8

MOV  [WC.CLSHICON],EAX

PUSH  IDC_ARROW
PUSH  0
CALL  LoadCursorA@8

MOV  [WC.CLSHCURSOR],EAX

MOV  [WC.CLBKGROUND],16
MOV  DWORD  PTR  [WC.CLMENUNAME],0
MOV  DWORD  PTR  [WC.CLNAME],OFFSET CLASSNAME


PUSH  OFFSET WC
CALL  RegisterClassA@4

PUSH  0;wskaźnik na dowolne dane zawarte w oknie tuż po utworzeniu
PUSH  [HINST] ;uchwyt aplikacji
PUSH  0;uchwyt do paska menu
PUSH  0 ;uchwyt do okna nadrzędnego względem okna które mamy zamiar stworzyć
PUSH  400 ;wysokość okna
PUSH  500 ;szerokość okna
PUSH  100 ;współrzędna pionowa okna
PUSH  100 ;współrzędna pozioma okna
PUSH  WS_OVERLAPPEDWINDOW;styl okna
PUSH  OFFSET TITLENAME;wskaźnik na tytuł okna
PUSH  OFFSET CLASSNAME;wskaźnik do zarejestrowanej nazwy klasy okna
PUSH  0;rozszerzony styl okna
CALL  CreateWindowExA@48

CMP  EAX,0;czy błąd?
JZ   _EXIT

MOV  [NEWHWND],EAX;uchwyt okna
PUSH  SW_SHOWNORMAL
PUSH  [NEWHWND]
CALL  ShowWindow@8

PUSH  [NEWHWND]
CALL  UpdateWindow@4


MSG_LOOP:
PUSH  0
PUSH  0
PUSH  0
PUSH  OFFSET MSG;wskaźnik na strukturę komunikatu
CALL  GetMessageA@16

CMP  EAX,0;czy koniec?
JE   _EXIT

PUSH  OFFSET MSG
CALL  TranslateMessage@4 ;tłumaczenie

PUSH  OFFSET MSG
CALL  DispatchMessageA@4 ;wysłanie

JMP  MSG_LOOP

_EXIT:

PUSH  HLIB
CALL  FreeLibrary@4

PUSH  0
CALL  ExitProcess@4

;parametry:
;[EBP +14H] LPARAM
;[EBP +10H] WPARAM
;[EBP +0CH] MES
;[EBP +8] HWND

WNDPROC   PROC


PUSH  EBP
MOV  EBP,ESP
PUSH  EBX
PUSH  ESI
PUSH  EDI
CMP  DWORD  PTR  [EBP + 0CH],WM_DESTROY;komunikat związany ze zniszczeniem okna
JE  WMDESTROY

CMP  DWORD  PTR  [EBP + 0CH],WM_CREATE;tworzenie kontrolek w oknie
JE  WMCREATE

CMP  DWORD  PTR  [EBP + 0CH],WM_COMMAND;zdarzenie związane z kontrolką
JE  WMCOMMAND

JMP  DEFWNDPROC;nieobsłużone komunikaty kierujemy do DefWindowProcA@16

WMCREATE:

;Przycisk:

PUSH  0
PUSH  [HINST]
PUSH  0
PUSH  DWORD  PTR  [EBP + 08H];uchwyt okna
PUSH  20
PUSH  200
PUSH  150
PUSH  150
PUSH  STYLBTN
PUSH  OFFSET BTNNAME
PUSH  OFFSET CLSBUTN
PUSH  0
CALL  CreateWindowExA@48

MOV  HWNDBTN,EAX

;Pole edycyjne:

PUSH  0
PUSH  [HINST]
PUSH  0
PUSH  DWORD  PTR  [EBP + 08H];uchwyt okna
PUSH  20
PUSH  200
PUSH  120
PUSH  150
PUSH  STYLEDT
PUSH  OFFSET EDTNAME
PUSH  OFFSET CLSEDIT
PUSH  0
CALL  CreateWindowExA@48

MOV  HWNDEDT,EAX

WMCOMMAND:

MOV   EAX,HWNDBTN
CMP  DWORD  PTR  [EBP + 14H],EAX ;Czy LPARAM to uchwyt przycisku?
JNE FINISH

PUSH  0
PUSH  HWNDEDT
CALL  [ADR]

JMP FINISH

DEFWNDPROC:

PUSH  DWORD  PTR  [EBP + 14H]
PUSH  DWORD  PTR  [EBP + 10H]
PUSH  DWORD  PTR  [EBP + 0CH]
PUSH  DWORD  PTR  [EBP + 08H]
CALL  DefWindowProcA@16
JMP FINISH

WMDESTROY:

PUSH  0
CALL  PostQuitMessage@4
XOR EAX,EAX

FINISH:

POP  EDI
POP  ESI
POP  EBX
POP  EBP
RET
WNDPROC  ENDP

END Start

Pobierz kod

Uruchomiony program przedstawiony jest na Rys.2. Ciąg znaków z biblioteki po kliknięciu przycisku zostaje wypisany w polu edycyjnym:

Nie można wyświetlić obrazu
Rys.2. Interfejs programu .

Ćwiczenie 10

Napisać program korzystający z biblioteki DLL. Procedura biblioteki DLL ładuje do okna w chwili kliknięcia przycisku "Uruchom bibliotekę" nowy przycisk. Kliknięcie nowo załadowanego przycisku ma spowodować utworzenie nowego procesu programu kalkulator. Przykładowe wywołanie przed skorzystaniem z procedury w bibliotece DLL przedstawiono na Rys.3. Przykładowe wywołanie po kliknięciu przycisku uruchamiającego procedurę w bibliotece DLL przedstawiono na Rys.4

Pobierz szablon

Nie można wyświetlić obrazu
Rys.3. Przykładowe wywołanie programu przed skorzystaniem z procedury w bibliotece DLL.

Nie można wyświetlić obrazu
Rys.4. Przykładowe wywołanie po kliknięciu przycisku uruchamiającego procedurę w bibliotece DLL.

<Poprzednia lekcjaKolejna lekcja>