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.
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
Aby utworzyć bibliotekę dynamiczną wykonujemy następujące polecenia asemblera i konsolidatora:
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
Uruchomiony program przedstawiony jest na Rys.2. Ciąg znaków z biblioteki po kliknięciu przycisku zostaje wypisany w polu edycyjnym:
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