spis tresci:
Programowanie pod Windows z uzyciem funkcji API
Wstep
Jak je wywolywac
Troche praktyki
Szkielet programu
Przyklad
Zaczne od wyjasnienia czym sa funkcje API(application programming interface), programowanie pod Windowsa jest bardzo trudne, dlatego spotykamy sie z odpowiedznikiem dosowego przerwania nr 21.
Procedury obslugujace te funkcje (api) zanjduja sie w roznych plikach dll (te najwazniejsze sa w kernel32.dll i user32.dll). Funkcje API dzielimy na dwa rodzaje:ANSI i Unicode, ansi to te z koncowkami "A" a Unicode to te z "W".Znak ANSI w kodzie zajmuje 1 bajt a Unicode 2 bajty i to wszystko co powinienes o tym wiedziec ;)).
Pod dosem przerwanie wywolywalo sie instrukcja int, pod windowsem bedziemy uzywali: call nazwa_funkcji.
Jeszcze jedna wazna rzecz wszystkie style... (np. mb_ok), powinny sie znajdowac w pliku .inc (dzial tools)
go up
Z naszych programow fukcje API bedziemy wywolywac uzywajac instrukcji call (chyba nie musze pisac co ona robi?!?), przed wywolaniem nalezy jeszcze podac rozne parametry (np. wyswietlenie okna- musimy podac wspolrzedne,rodzaj okna...) do tego celu uzyjemy instrukcji push.
Mozemy tez wywolywac: call nazwa, argumenty... , ale o tym pozniej.
Troche namotalem, chodzi o to aby funkcja API zaraz po wywolaniu mogla sobie wszystkie dane odnalezc bez trudu.Jezeli zaczniemy klasc na stos rozne rzeczy w ustalonej kolejnosci to wystarczy ze funkcja je zdejmnie ze stosu i "powklada" do odpowiednich rejestrow, z ktorych bedzie pozniej korzystala.
Tutaj jest napisane co i w jakiej kolejnosci potrzebuje funkcja CreateFile:
HANDLE CreateFile(
LPCTSTR lpFileName, // pointer to name of the file
DWORD dwDesiredAccess, // access (read-write) mode
DWORD dwShareMode, // share mode
LPSECURITY_ATTRIBUTES lpSecurityAttributes, // pointer to security attributes
DWORD dwCreationDistribution, // how to create
DWORD dwFlagsAndAttributes, // file attributes
HANDLE hTemplateFile // handle to file with attributes to copy
);
Tak wyglada opis funkcji "niesetety" zostal on napisaany z mysla o programistach piszacych w jezykach wyzszego poziomu tak wiec my bedziemy musieli sie troche nameczyc, no moze troche przesadzilem poprostu wszystkie argumenty musimy wywolywac w odwrotnej kolejnosci :))).
jezeli pierwsze jest: pointer to name of the file (czyli offset nazwy pliku)
to my musimy go odlozyc jako ostatniego.Jest to zwiazane ze stosem rzecz ktora kladziemy jako ostania, zdejmujemy jako pierwsza- mam nadzieje ze to rozumiesz.
Jeszcze jedno, wiekszosc ciagow znakow (gl. nazwy) musi byc zakonczona zerem np (ale bedzie to zaznaczone w opisie danej funkcji API): napis db 'hjsahjsahjsa',13,10
db 'nanananna',0
znaki sterujace 13 i 10 tak jak w dosie :)
go up
Dokladniej wyjasnie wywolywanie na przykladzie z wykorzystaniem funkcji API: MessageBoxA chyba wszyscy widzieli takie male okienka z dwoma albo trzema guzikami
Niestety nie ma jej w naszej sciadze z funkcjami Api :(((,
ale ja posiadam jej opis :)
Zaczynamy, pierwsza rzecza jaka funkcja musi przyjac to offset wyswietlonego napisu.ALE PAMIETAJ: DLA FUNKCJI PIERWSZE JEST TO CO TY POLOZYLES NA STOSIE OSTATNIE, DRUGIE TO CO TY POLOZYLES PRZEDOSTATNIE itd. Druga rzecza ktora funkcja potrzebuje to nazwa naszego box'a i trzecia to rodzaj box'a.Rodzaj to nic innego jak to ile i jakie guziki powinien posiadac, jaka ikonke wew. itp.
A teraz wszystko co musimy polozyc na stosie:
push rodzaj_pudelka
push offset nazwa_pudelka
push offset tekst_do_wyswietlenia
i aby narysowac pudelko ;)) call MessageBoxA.
Uff prawda ze prste.
Jeszcze jedno oba ciagi znakow nazwa_pudelka i tekst_do_wyswietlenia maja wygladac tak:
nazwa_pudelka db "nazwa jaka Ci sie podoba",0
;------------------------------------------^ ^zakonczona "zerem"
tekst_do_wyswietlenia db "tekst ktory bedzie wew. boxa",0 ;tez z zerem
Kolejna bardzo przydatna funkcja jest ExitProcess
funkcja konczy nam program cos jak funkcja 00h przerwania 21h
wywolujemy ja bez zadnego parametru.
Czyli na koncu programu trzeba zamiescic call ExitProcess
go up
Zaczniemy od ogolnego szkieletu programu:
.386P ;wybieramy procesor
Locals ;
jumps ;bedziemy uzywali dalekich skokow
;
.Model Flat ,StdCall ;specjalny model pamieci, czyli takiea ktora jest ciagla
;w tym miejscu powinnismy zdefiniowac nasze stale, zew.procedury oraz struktury (opisze je pozniej)
.data ; nasze zmienne
.code ;i kod wlasciw
Przejdzmy teraz do tych procedur zew., jezeli czytales rozdzial o proc. zew. to wiesz o co chodzi.W naszym przypadku procedurami zew. beda wszystkie uzyte funkcje API, definiujemy je tak: extrn MessageBoxA :PROC
Teraz BARDZO WAZNA rzecz zawsze przy definiowaniu proc pisz tak jak byc powinno czyli MessageBoxA a nie messageboxa (pozniej wyjasenie dlaczego).
Stale wygladaja tak: jaakas_stala equ 1322
stale moga zawirac nazwy rejestrow, liczby...(chyba wszystko).
Kolejna rzecza sa struktury, potrzebuja ich niektore funkcje.oglnie struktora wyglada tak:
WNDCLASS struc
clsStyle dd ? ; class style
clsLpfnWndProc dd ? ; pointer to the window procedure
clsCbClsExtra dd ? ; sort of size of buffer (0)
clsCbWndExtra dd ? ; sort of size of buffer too (0)
clsHInstance dd ? ; application instance handle
clsHIcon dd ? ; icon handle
clsHCursor dd ? ; cursor handle
clsHbrBackground dd ? ; background brush handle
clsLpszMenuName dd ? ; menu handle
clsLpszClassName dd ? ; far ptr to class name string,
WNDCLASS ends
Jest to prosto wyciete ze wspanialej szkolki o asmie napisanej przez HAKa
Teraz aby moc korzystac z tego w czesci .data musimy wstawic takie cos:
dowlona_nazwa WNDCLASS <?>
to chyba wszytko.
go up
Oto przyklad programu, z uzyciem funkcji MessageBoxA:
.386P ;
Locals ;
jumps ; dyrektywki kompilatora
;
.Model Flat ,StdCall ;
mb_ok equ 0 ;styl pudelka 0 to pudelko z jednym przyciskiem
hWnd equ 0 ;to jest identyfikator nadawany naszemu boxowi
extrn ExitProcess : PROC ;definiujemy zew. procedury
extrn MessageBoxA : PROC ;
.Data ; ateraz dane
text db "++t0udi++",13,10
db "hello ;))))",0
caption db "hello to znowu ja!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",0
.Code ; i kod
bcbc:
push mb_ok ;odkladamy na stos nasze dane - kolejnosc bardzo wazna
push offset caption ;
push offset text ;
push hWnd ;
call MessageBoxA ;wywolanie "MessageBoxA"
call exitprocess ;koniec programu
end bcbc
Fajnie ze mamy program ale jak go skompilowac?
TASM32 /m /ml nazwa
i
TLINK32 /Tpe /aa /c nawa,nazwa,,import32.lib
pewnie zastanawiasz sie co to ten plik import32.lib, jest to plik ktory wsakzuje adresy funkcji API.Potrzebujemu go aby nasz program mogl poprawnie chdzic, jak wspominalem wczesniej wszystkie API sa w plikach dll, i by moc sie z nimi komunikowac potrzebujemy ich adresy ;).
Plik zostanie zamieszczony na mojej stronie, a caly przyklad mozesz sciagnac z dzialy assembler.
go up
Chcialbym zaznaczyc ze strona nie powstala by gdyby nie rozne txt, glownie HAKa i Masty.Glowny powodem powstania tej stronki byl prawie calkowity brak materialow, po polsku, dotyczacych programowania pod winem
Zapraszam do dzialu z opisem niektorych funkcji API
przepraszam za to ze niektore rzeczy moga byc niezrozumiale, staralem sie tlumaczyc jak najlepiej, poza tym strona posawala glownie wieczorami :((
ale z uplywem czasu bede sie staral wszystko poprawiac.Jezli czegos nie rozumiesz to pisz
cdn...
na glowna
|