Sunteți pe pagina 1din 8

Revista Informatica Economica, nr.

1 (17)/2001 133

Programarea aplicatiilor win32 în limbaj de asamblare

Prof. dr. Ion IVAN, prep. Paul POCATILU, prep. Doru CAZAN
Catedra de Informatica Economica, A.S.E. Bucuresti

Lucrarea prezinta aspectele de baza programarii aplicatiilor Windows pe 32 biti în limbaj


de asamblare. Este descrisa interfata de programare a aplicatiilor Win32, organizarea
memoriei si executia programelor în sistemul Win32, programarea aplicatiilor Windows si
specificul acestora utilizînd limbaje de asamblare.
Cuvinte cheie: Win32 API, modele de memorie, ferestre Windows.

Interfata de programare a aplica- dimensiunea de 1 byte. Un caracter


1 tiilor (API) Win32
API-ul Win32 este implementat în bibli-
Unicode are dimensiunea de 2 octeti. Nu-
mele functiilor API pentru ANSI se
oteci cu legare dinamica (DLL). Aceste termina cu caracterul "A" (de exemplu
biblioteci sunt separate de programul exe- MessageBoxA), iar numele functiilor API
cutabil. Spre deosebire de DOS, API-urile pentru Unicode se termina cu W
nu sunt accesate prin întreruperi. (MessageBoxW). În mod nativ Windows
Codul functiilor Windows este stocat în 95 suporta ANSI iar Windows NT
fisiere din afara programului, numite DLL Unicode. În general în fisierele cu prototi-
(Dynamic Link Libraries) - biblioteci cu purile functiilor exista declaratii echiva-
legaturi dinamice. Atunci când este rulat lente ale acestora în care se elimina
un program Windows, interconectarea caracterul A, respectiv W (de exemplu
acestuia cu sistemul de operare se face prin MessageBox).
procesul de legare dinamica. Un fisier
executabil al unui program Windows con- 2. Organizarea memo riei în Win32
tine referinte la biblioteci cu legaturi dina- Programele Win32 ruleaza în modul
mice. Atunci când un program pentru protejat, acest mod existând începînd cu
Windows este încarcat în memorie, ape- microprocesorul 80286. Windows ruleaza
lurile de functii sunt rezolvate astfel încât fiecare program Win32 în spatii virtuale
sa indice intrarile în functiile din DLL- separate. Aceasta înseamna ca fiecare
urile utilizate, care sunt încarcate în memo- program Win32 va avea propriul spatiu de
rie, în cazul în care nu se afla deja acolo. adresare de 4 GB. Deoarece programele
Principalele biblioteci cu legare dinamica Win32 au 4 GB de memorie adresabila,
sunt kernel32.dll, user32.dll si gdi32.dll. pointerii pot adresa zone de memorie
Biblioteca cu legare dinamica kernel32.dll cuprinse între 00000000H si FFFFFFFFH.
contine functiile API pentru gestionarea În Windows 95, fiecare proces obtine
memoriei si a proceselor. Biblioteca cu propriul spatiu de memorie de 4 GB, spatiu
legare dinamica user32.dll controleaza as- care este în totalitate al sau. De fapt el
pectele interfetei cu utilizatorul ale progra- partajeaza împreuna cu alte aplicatii care
mului. Biblioteca cu legare dinamica ruleaza, primii 2 GB de memorie. Este
gdi32.dll este responsabila cu operatiile important sa se considera ca cei 4GB ai
grafice. În afara de aceste biblioteci prin- spatiului procesul sunt numai si numai ai
cipale se pot utiliza în program si alte acestuia. Acest model de memorie se
biblioteci cu legare dinamica. numeste flat.
Exista doua categorii de functii API: unele Sectiunea cea mai joasa a memoriei (regi-
pentru ANSI si altele pentru Unicode. unea de 64 KB) este rezervata în Windows
Sirurile ANSI sunt vectori de caractere 95 pentru atribuirile de pointeri nuli.
terminate cu NULL. Un caracter ANSI are Restul memorie, pîna la 4 MB este rezer-
134 Revista Informatica Economica, nr. 1 (17)/2001

vata de sistem pentru compatibilitatea cu RAM si furnizeaza un mecanism de con-


aplicatiile Win16 si cu aplicatiile MS- versie a adreselor din memoria virtuala în
DOS. adrese fizice. Programul de gestiune a
Programele Win32 sunt încarcate la adresa memoriei poate muta sau comuta paginile
00400000H (adresa de baza a aplicatiilor de memorie daca este nevoie de spatiu
Win32 în memorie), deci spatiul de lucru suplimentar de memorie fizica. Windows
al programului este pîna la 7FFFFFFFH. schimba memorie în si afara din fisierul de
Începînd cu adresa 80000000H, Windows paginare de pe hard disk. Dimensiunea
95 încarca propriile DLL-uri de sistem. fisierului de paginare împreuna cu dimen-
Începînd cu adresa C0000000H pîna la siunea memoriei RAM este considerata
sfîrsitul celor 4 GB se încarca sistemul de memoria fizica.
operare Windows 95 precum si programele Când este rulat un program, fisierul EXE
pentru dispozitive virtuale. de pe disc (numit imaginea programului)
Putine calculatoare au 4GB de memorie. este considerat ca facând parte din fisierul
Datorita acestui lucru, proiectantii de hard- de paginare de pe hard disk. În acest fel se
ware au introdus ideea de memorie virtuala economiseste timpul necesar încarcarii
si memorie fizica. Memoria virtuala cores- fisierului executabil în memoria RAM.
punde celor 4 GB de memorie adresabila, Imaginea fisierului EXE de pe disc este
memoria fizica este limitata de memoria considerata parte a fisierului de paginare si
RAM disponibila în calculator si de spatiul sectiunile de cod (nu si de date) sunt citite
pe hard disk. Memoria este împartita în de pe disc atunci când este nevoie de ele.
pagini, dimensiunea paginii fiind optimi-
zata în functie de suportul hardware, pe 3. Încarcarea programelor Win32
sistemele 80x86, marimea unei pagini fiind Aplicatiile Win32 ruleaza în segmente de
de 4 KB. 32 de biti, utilizînd modelul de memorie
FLAT. Astfel, programul este în mod auto-
mat în modul protejat. Adresele generate si
utilizate de program se numesc adrese
liniare. Registrele de segment CS, DS, ES
si SS sunt initializate astfel ca nu mai
conteaza ce segment este utilizat pentru a
adresa o locatie data (o adresa liniara).
Adresa de baza la care este încarcat
programul în memorie este 0040000h.
La lansarea în executie a programelor,
valorile initiale ale registrilor sunt:
• CS:EIP – începutul programului
• SS:ESP – începutul stivei
• DS=ES=SS – selectorul de date
• FS=TIB (Thread Information Block)
• GS=0, selectorul nul
• CS si DS sunt mapate pe aceeasi adresa
liniara
• Indicatorul de directie, DF, este sters.
Windows utilizeaza intern registrii ESI,
Fig. 1. Organizarea memoriei în Win32 EDI, EBP si EBX si de aceea presupune ca
valorile acestor registri nu se vor schimba.
Sistemul de gestiune a memoriei determina Se recomanda deci în cazul utilizarii
paginile localizate în memoria virtuala si în acestor registri în cadrul unor functii
callback sa se salveze continutul lor îna inte
Revista Informatica Economica, nr. 1 (17)/2001 135

de modificare si sa se restaureze înainte de Sub Win16 exista doua tipuri de conventii


a da controlul sistemului Windows. O de apel: C si PASCAL.
functie callback este o functie scrisa de Conventia de apel C transmite parametri de
programator, functie ce este apelata de la dreapta la stînga, cel mai din dreapta
Windows. Un exemplu de astfel de functie parametru fiind pus primul pe stiva.
este functia fereastra. Apelatorul este responsabil cu echilibrarea
stivei dupa apel. De exemplu apelul unei
4. Structura unui program Assembler functii f(int a, int b) utilizînd conventia C
Un program Win32 scris în limbaj de de transmitere a parametrilor în limbaj de
asamblare are urmatoarea structura: asamblare va fi:
.386 push [b]
.model flat, stdcall push [a]
option casemap :none call f
include \masm32\include\windows.inc add sp, 8 ; apelatorul echilibreaza stiva

includelib \masm32\lib\user32.lib Conventia de apel PASCAL presupune


.data
transmiterea parametrilor de la stînga la
; dreapta, functia apelata fiind responsabila
;datele initializate
; cu echilibrarea stivei dupa apel.
.data? Conventia de apel C este utila atunci când
;
;datele neinitializate nu se stie exact numarul de parametri ce
; vor fi transmisi functiei. O astfel de functie
.const
; este wsprinf. Nu se stie dinainte cîti
;constantele parametri vor fi pusi pe stiva, deci în
;
.code cadrul functiei nu se poate realiza
eticheta_de_inceput echilibrarea stivei.
;
;codul propriu zis STDCALL este un hibrid între conventiile
; de transmitere a parametrilor C si PAS-
end eticheta_de_inceput
CAL. Parametri sunt pusi pe stiva de la
Directiva .386 anunta asamblorul ca se va dreapta la stînga (ca în conventia C), însa
utiliza setul de instructiuni specifice proce- functia apelata este responsabila cu echili-
sorului 80386. Se pot utiliza si directivele brarea stivei (conventia PASCAL). Plat-
.486, .586. Pentru fiecare model al micro- forma Win32 utilizeaza exclusiv conventia
procesorul sunt doua forme aproape iden- STDCALL cu exceptia functiei wsprintf.
tice ale acestei directive: .386/.386p, .486/ Directiva option casemap :none anunta
.486p. Versiunile cu p sunt necesare atunci MASM ca etichetele sunt case-sensitive.
când programul utilizeaza instructiuni pri- Directiva include \masm32\include \win-
vilegiate. Instructiunile privilegiate sunt re- dows.inc insereaza fisierul windows.inc în
zervate de microprocesor/sistem de operare acest punct în programul sursa. Acest fisier
în modul protejat. Ele pot fi utilizate numai contine declaratiile pentru majoritatea con-
de cod protejat, cum ar fi programele stantelor si structurilor utilizate de API.
pentru echipamente virtuale. Dupa aceasta directiva se urmeaza inclu-
Directiva .model specifica modelul de me- derea fisierelor ce contin antetele functiilor
morie al programului. Sub Win32 exista utilizate din bibliotecile respective. De
numai modelul de memorie flat. exemplu daca se utilizeaza functia Mes-
În directiva .model mai este precizata si sageBox se va scrie include \masm32\in-
conventia de transmitere a parametrilor clude\user32.inc, avînd în vedere ca
(stdcall). Conventia de transmitere a para- aceasta functie exista în user32.dll.
metrilor specifica ordinea de transmitere a Directiva includelib \masm32\lib\user32
parametrilor (de la stînga la dreapta sau de .lib informeaza asamblorul ce biblioteci de
la dreapta la stînga) si de asemenea cine va import sunt utilizate. Când asamblorul în-
echilibra stiva dupa apelul functiei. tîlneste aceasta directiva, el pune o coman-
136 Revista Informatica Economica, nr. 1 (17)/2001

da a editorului de legaturi în fisierul obiect - obtinerea identificatorului instantei pro-


astfel încât editorul de legaturi sa stie ce gramului
biblioteci utilizeaza programul si de unde - obtinerea liniei de comanda (optional)
sa le ia. - înregistrarea clasei fereastra (window
Sectiunea .data contine datele initializate class)
ale programului. Sectiunea .data? contine - crearea ferestrei
datele neinitializate ale programului. A- - afisarea ferestrei
ceasta are avantajul ca fisierul executabil - actualizarea zonei client a ferestrei
nu îsi mareste dimensiunea corespunzator - intrarea în bucla de mesaje infinita
cu marimea datelor neinitializate. Ea doar - daca sunt mesaje pentru fereastra ele sunt
informeaza asamblorul cât spatiu de me- prelucrate de o functie specializata numita
morie este necesar când programul este si functia fereastra
încarcat în memorie. Sectiunea .const con- - terminarea programului
tine declaratiile de constante din program. Obtinerea identificatorului instantei pro-
Aceste nu pot fi modificate în program. gramului se realizeaza prin apelul functiei
Sectiune .code contine codul programului. GetModuleHandle. Functia returneaza
Eticheta_de_inceput este o eticheta ce identificatorul instantei curente a progra-
marcheaza începutul codului programului mului. Prototipul functiei este:
Prima instructiune executabila se afla dupa HMODULE GetModuleHandle(LPCTSTR lpModuleNa
me);
eticheta_de_inceput. Codul trebuie sa fie Prin transmiterea ca parametru a valorii
între eticheta_de_inceput si end etiche- NULL se obtine identificatorul instantei
ta_de_inceput. curente. Dupa apelul functiilor API, rezul-
Pe lînga programul sursa, daca în program tatul returnat se gaseste în registrul EAX.
se utilizeaza resurse ca meniuri, pictogra- .data?
me, casute de dialog, acestea se definesc ;...
într- un fisier special, numit fisier de resur- hinst dd ?
;...
se, fisier ce are extensia .rc. Acesta este un .code
fisier text în care se descriu resursele si se ;...
push 0
face asocierea cu fisiere existente pe disc call GetModuleHandle
De exemplu pentru resursa pictograma este mov hinst,eax
;...
linia: ID_ICON ICON "WHAT1.ICO"
Obtinerea liniei de comanda se face cu
5. Programarea sub Windows functia GetCommandLine . Obtinerea lini-
Majoritatea programelor Windows au o ei de comanda nu este necesara decât daca
fereastra principala asociata. Atunci când programul prelucreaza parametrii din linia
programul este lansat în executie, Win- de comanda.
dows creeaza o coada de mesaje pentru Înregistrarea clasei fereastra se realizeaza
programul respectiv. În aceasta coada de avînd în vedere faptul ca o fereastra este
mesaje sunt pastrate mesajele trimise catre întotdeauna creata pe baza unei clase de
toate ferestrele pe care le creeaza pro- fereastra. Aceasta identifica procedura de
gramul. Programul contine o mica secventa fereastra care prelucreaza toate mesajele
de cod numita bucla de mesaje care preia transmise catre fereastra. Pe baza aceleiasi
mesajele din coada de mesaje si le dis- clase se pot crea mai multe ferestre.
tribuie functiilor fereastra corespunzatoare. Înainte de crearea ferestrei programului
Anumite mesaje sunt trimise direct functiei trebuie înregistrata clasa fereastra prin
fereastra fara a mai fi puse în coada de apelul functiei RegisterClassEx ce are un
mesaje. singur parametru: un pointer la o structura
Pasii necesari crearii unei ferestre sunt: de tipul WNDCLASSEX. Aceasta structu-
ra are urmatorii membri:
Revista Informatica Economica, nr. 1 (17)/2001 137

WNDCLASSEX struc
cbSize dd ? ; dimensiunea structurii WNDCLASSEX
style dd ? ; stilul clasei fereastra
lpfnWndProc dd ? ; pointerul la functia fereastra
cbClsExtra dd ? ; informatii suplimentare pentru clasa
cbWndExtra dd ? ; informatii suplimentare pentru fereastra
hInstance dd ? ; identificatorul instantei curente
hIcon dd ? ; identificatorul pictogramei asociata clasei
hCursor dd ? ; cursorul asociat clasei
hbrBackground dd ? ; culoarea de fundal a ferestrelor din clasa
lpszMenuName dd ? ; pointer la sirul cu denumirea meniului
lpszClassName dd ? ; pointer la sirul cu numele clasei
hIconSm dd ? ; identificatorul pictogramei aplicatiei
WNDCLASSEX ends

Cele mai importante câmpuri sunt al treilea ate pe baza acestei clase.
si penultimul, ele continînd adresa proce- Înainte de apelul functiei RegisterClassEx
durii fereastra folosita de toate ferestrele trebuie initializate cîmpurile variabilei de
create pe baza acestei clase, respectiv nu- tip WNDCLASSEX. Initializarea câmpuri-
mele clasei fereastra. Celelalte cîmpuri de- lor se realizeaza în urmatoarea secventa de
scriu caracteristicile tuturor fe restrelor cre- cod:
;...
.data?
;...
wcex WNDCLASSEX <?>;variabila de tip structura clasa fereastra
NumeFer db 'Programare sub Windows',0 ;Numele ferestrei
hinst dd ? ;identificatorul instantei curente
;...
.code
;...
;completarea cimpurilor structurii fereastra
mov wcex.cbSize, size WNDCLASSEX
mov wcex.style, CS_VREDRAW or CS_HREDRAW or CS_DBLCLKS
mov wcex.lpfnWndProc, offset WndProc
mov wcex.cbClsExtra,0
mov wcex.cbWndExtra,0
push hinst
pop wcex.hInstance

;se incarca pictogtama, definita in fisierul .rc


push ID_ICON ;icon id
push hinst
call LoadIcon
mov wcex.hIcon,eax

;se incarca cursorul sageata standard


push IDC_ARROW
push NULL
call LoadCursor

mov wcex.hCursor,eax
mov wcex.hbrBackground,COLOR_WINDOW+1
mov wcex.lpszMenuName,0
mov wcex.lpszClassName,offset NumeFer
mov wcex.hIconSm,0

Se observa ca pentru initializarea câmpuri- în fisierul de resurse. În program se tran-


lor hIcon si hCursor ale structurii WND- smite ID_ICON, definit în fisierul de
CLASSEX s-au apelat functiile LoadIcon resurse. Functia LoadCursor:
si LoadCursor. Functia LoadIcon are HCURSOR LoadCursor( HINSTANCE hInstance, //
prototipul: identificatorul instantei aplicatiei
LPCTSTR lpCursorName //
HICON LoadIcon( HINSTANCE hInstance, // numele/identificatorul resursei cursor
identificatorul instantei aplicatiei );
LPCTSTR lpIconName // numele/identificatorul
resursei pictograma returneaza identificator de cursor asociat
);
cursorului definit în fisierul de resurse, sau
Functia returneaza un identificator al picto- unuia din cursoarele standard. În aplicatie
gramei asociat resursei pictograma definita s-a utilizat cursorul standard de tip sageata,
138 Revista Informatica Economica, nr. 1 (17)/2001

identificat prin IDC_ARROW. Atunci mai trebuie înregistrate, ele avînd prede-
când se utilizeaza cursoare standard, para- finite functiile fereastra si tratarea anumi-
metrul hInstance al functiei LoadCursor tor mesaje. Pe baza acestor clase de fe-
va fi 0. Apelul functiei RegisterClassEx restre standard se pot crea ferestre de acel
prin care se înregistreaza clasa fereastra: tip, modificându-se anumite caracteristici,
.code modul de functionare ramînînd acelasi.
;... Clasa fereastra defineste caracteristicile
;Inregistrarea clasei fereastra
push offset wcex generale ale unei ferestre, permitînd folo-
call RegisterClassEx sirea acesteia pentru crearea mai multor
;...
ferestre. Când se creeaza o fereastra cu
În cazul în care nu s-a reusit înregistrarea functia CreateWindowEx se pot specifica
clasei de fereastra, functia RegisterClass mai multe detalii despre fereastra respec-
Ex returneaza valoarea 0. tiva (cum ar fi titlul ferestrei, stilul aces-
Sunt definite câteva clase standard de teia, pozitia, meniul asociat si dimensiunea
ferestre înregistrate : "BUTTON", "EDIT", initiale).
"LISTBOX" si altele, clase fereastra ce nu Prototipul functiei CreateWindowEx este:
HWND CreateWindowEx(
DWORD dwExStyle, // stilul extins al ferestrei
LPCTSTR lpClassName, // pointer catre numele clasei înregistrate
LPCTSTR lpWindowName,// pointer catre numele ferestrei
DWORD dwStyle, // stilul ferestrei
int x, // pozitia orizontala a ferestrei
int y, // pozitia verticala a ferestrei
int nWidth, // latimea ferestrei
int nHeight, // înaltimea ferestrei
HWND hWndParent, // indicator catre fereastra parinte
HMENU hMenu, // indicator catre meniu sau fereastra copil
HINSTANCE hInstance, // indicatorul instantei curente a programului
LPVOID lpParam // pointer catre datele de creare a ferestrei
);

Functia returneaza identificatorul ferestrei create. Apelul functiei CreateWindowEx este:


.data?
;...
hwnd dd ? ;identificatorul de fereastra
hinst dd ? ;identificatorul instantei curente
hmeniu dd ? ;identificatorul meniului
;...
.const
;...
NumeFer db 'Programare sub Windows',0 ;Numele ferestrei
NumeApp db 'Programare in Win32 ASM',0;Numele aplicatiei
;...
.code
;...
;Crearea ferestrei
push ID_MENIU
push hinst
call LoadMenu
mov hmeniu,eax
push 0 ; lpParam
push hinst ; hInstance
push hmeniu ; identificator meniu
push 0 ; identificator parinte
push CW_USEDEFAULT ; inaltime
push CW_USEDEFAULT ; latime
push CW_USEDEFAULT ; y
push CW_USEDEFAULT ; x
push WS_OVERLAPPEDWINDOW ; stilul
push offset NumeApp ; titlul ferestrei
push offset NumeFer ; numele clasei
push WS_EX_OVERLAPPEDWINDOW ; stilul extins
call CreateWindowEx
mov hwnd,eax
;...
Revista Informatica Economica, nr. 1 (17)/2001 139

Pentru a asocia resursa meniu definita în În program apelul se realizeaza astfel:


fisierul de resurse se apeleaza functia Load push hwnd
Menu ce are ca parametri identificatorul call UpdateWindow

instantei curente a aplicatiei si numele me- Dupa apelul functiei UpdateWindow, fe-
niului definit în fisierul de resurse. Functia reastra devine vizibila pe ecran.
returneaza identificatorul de meniu asociat. Programul trebuie sa poata prelucra intra-
Dupa apelul functiei CreateWindowEx, rile de la tastatura si de mouse. Windows
fereastra a fost creata însa nu a fost si creeaza o coada de mesaje asociata fiecarui
afisata pe ecran. Pentru afisarea ferestrei program. Când apare un eveniment, acesta
sunt necesare înca doua apeluri de functii: este transformat de Windows într- un mesaj
ShowWindow respectiv UpdateWindow. care este pus în coada de mesaje a
Functia ShowWindo w are prototipul: programului. Mesajele sunt preluate din
BOOL ShowWindow(HWND hWnd, // identificato- coada de mesaje prin intermediul buclei de
// rul ferestrei
int nCmdShow // modul de afisare al fe-
mesaje. În pseudocod bucla de mesaje se
// restrei reprezinta astfel:
);
Asteapta_mesaj:
Apelul functiei în cadrul programului: Daca este apare un mesaj, preia mesajul
Daca mesajul este QUIT Atunci Iesire
push SW_SHOWNORMAL Apeleaza TranslateMessage
push hwnd Apeleaza DispatchMessage
call ShowWindow Trimite mesajul catre procedura fereastra
Înapoi la Asteapta_mesaj
Functia UpdateWindow redeseneaza zona Iesire
client a ferestrei. Prototipul acesteia este: Functia GetMessage preia un mesaj din
BOOL UpdateWindow(HWND hWnd // identificatorul coada de mesaje. Prototipul functiei Get
ferestrei
); Message :
BOOL GetMessage(
LPMSG lpMsg, // adresa structurii cu mesajul
HWND hWnd, // identificatorul ferestrei
UINT wMsgFilterMin, // primul mesaj
UINT wMsgFilterMax // al doilea mesaj
);

Primul parametru este un pointer la o matorul mesaj din coada de asteptare.


structura de tip MSG. Windows comple- Structura MSG este:
teaza cîmpurile structurii de mesaje cu ur-
MSG STRUC
hwnd DWORD ? ; identificatorul ferestrei careia îi este destinat mesajul
message DWORD ? ; identificatorul mesajului
wParam DWORD ? ; parametru dependent de mesaj
lParam DWORD ? ; parametru dependent de mesaj
time DWORD ? ; momentul inserarii mesajului în coada de mesaje
pt POINT <>; pozitia mouse-ului în momentul inserarii mesajului
MSG ENDS

Daca în cîmpul message al structur ii este Functia DispatchMessage , al carei proto-


transmisa o valoare diferita de WM_QUIT, tip este:
functia GetMessage returneaza o valoare LONG DispatchMessage(
diferita de zero. Mesajul WM_QUIT deter- CONST MSG *lpmsg // pointer catre structura
// ce contine mesajul
mina iesirea din bucla de mesaje. În cadrul );
buclei de mesaje se apeleaza doua functii. retransmite structura MSG sistemului de
TranslateMessage transmite structura MS
operare.
G sistemului de operare pentru convertirea Windows trimite apoi mesajul catre functia
unor mesaje de la tastatura. Prototipul a-
fereastra corespunzatoare în vederea prelu-
cesteia este:
crarii acestuia.
BOOL TranslateMessage( CONST MSG *lpMsg //
// pointer la o structura MSG
Bucla de mesaje este implementata astfel:
);
140 Revista Informatica Economica, nr. 1 (17)/2001

;Bucla de mesaje VOID ExitProcess(UINT uExitCode


// codul de iesire al procesului
start_bucla: );
push 0 ; wMsgFilterMax
push 0 ; wMsgFilterMin Secventa de cod din program este:
push NULL ; 0 - toate ferestrele
push offset msg ; lpMsg push 0 ;codul de iesire returnat de aplicatie
call GetMessage ; returneaza FALSE call ExitProcess
; pentru WM_QUIT
or eax,eax Functia fereastra este responsabila de
jz iesire afisarea în zona client a ferestrei, precum si
push offset msg tratarea mesajelor provenite de la tastatura
call TranslateMessage si mouse. Functia fereastra poate avea ori-
push offset msg
call DispatchMessage ce nume, iar un program pentru Windows
jmp start_bucla poate avea mai mult functia fereastra.
Terminarea programului se face prin apelul Functia fereastra este întotdeauna asociata
functiei ExitProcess. Prototipul acesteia unei clase fereastra.
este: Functia fereastra are urmatorul prototip:

LRESULT WndProc(HWND hwnd, //identificatorul ferestrei


UINT msg, //identificatorul mesajului
WPARAM wparam, //parametru asociat mesajului
LPARAM lparam //parametru asociat mesajului
);
Parametri functiei corespund primelor pa- Implementarea functiei fereastra, care tra-
tru cîmpuri ai structurii MSG. Fiecare teaza mesajul WM_DESTROY, celelalte
mesaj receptionat de fereastra este identifi- mesaje fiind tratate de functia standard de
cat printr-un numar (parametrul msg al tratare a mesajelor, este:
functiei fereastra). În fisierele antet din WndProc proc
Windows acestora le corespund identifi- ;parametrii de pe stiva sunt:
;esp+4 --> hwnd
catori prefixati de WM_ (de la window ;esp+8 --> msg
message) ;esp+12 --> wParam
;esp+16 --> lParam
Pentru tratarea diverselor mesaje se utili- cmp dword ptr [esp+8],WM_DESTROY
zeaza o instructiune switch pentru determi- je msg_wm_destroy
jmp DefWindowProc
narea mesajelor primite de fereastra si a msg_wm_destroy:
push 0
modului de prelucrare a acestuia. Atunci call PostQuitMessage
când prelucreaza un mesaj functia fereastra xor eax,eax
trebuie sa returneze valoarea zero. Toate ret 16
WndProc endp
mesajele ce nu sunt prelucrate de functia
fereastra sunt transmise functie DefWin- În programul scris în limbaj de asamblare
dowProc. Prototipul functiei DefWindow nu are importanta daca numele functiei
Proc este: fereastra este WndProc sau altul, acest
lucru fiind la latitudinea programatorului.
LRESULT DefWindowProc(
HWND hWnd, // identificatorul ferestrei
UINT Msg, // mesajul Bibliografie
WPARAM wParam, // 1-l param. al mesajului
LPARAM lParam // al 2-lea param. al mesj. [PETZ98] Petzold, Charles, Yao, Paul -
); Programare în Windows 95, Editura Teora,
Un mesaj ce trebuie tratat este WM_DES- Bucuresti, 1998
TROY care este trimis atunci când utiliza- [HOLZ96] Holzner, Steve – Advanced
torul doreste sa închida fereastra. Mesajul Visual C++ 4, M&T Books, New York
este tratat standard, prin apelul functiei 1996
PostQuitMessage , ce are prototipul: http://win32asm.cjb.net, " Iczelion's Win32
VOID PostQuitMessage( Assembly HomePage"
int nExitCode // codul de iesire
); http://www.pbq.com.au/home/hutch/masm.
htm, "MASM32"