Ľudmila Jánošíková | |||||||||||||||||||||||||||||||||||||||||
Programovanie v jazyku symbolických adries | |||||||||||||||||||||||||||||||||||||||||
pre 32-bitové procesory Intel | |||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||
Služby operačného systému Windows 95/98/NT/XP
32-bitový operačný systém Windows (Windows 95/98/NT/XP) implementuje funkcie aplikačného programového rozhrania (API) Win32 a poskytuje ich aplikačným programom. Pomocou týchto funkcií aplikačný program používa prostriedky výpočtového systému, predovšetkým pamäť a vstupné a výstupné zariadenia. Funkcií je asi tisíc. Podrobný popis všetkých funkcií nájdete napr. v súbore win32.hlp, ktorý je súčasťou softvérových balíkov firmy Borland. Funkcie sú umiestnené v dynamicky pripájaných knižniciach. Z programu ich vyvoláme menom. Meno funkcie deklarujeme v programe ako externý symbol typu PROC. Pri linkovaní potom musíme k preloženému programu pripojiť knižnicu import32.lib, ktorá obsahuje odkazy na dynamicky pripájané funkcie operačného systému. V rámci kurzu o JSA budeme hovoriť len o niektorých funkciách. Zameriame sa na tie funkcie, ktoré predstavujú analógiu k službám operačného systému MS-DOS. Podstatná časť predchádzajúcej kapitoly bola venovaná operáciám so súbormi pod operačným systémom MS-DOS. V tejto kapitole vymenujeme funkcie, ktoré na prístup k súborom poskytuje operačný systém Windows. Rovnaké funkcie však možno použiť aj pri prístupe k adresáru a k rôznym zariadeniam, ako je napr. paralelný a sériový port. Postup práce so súborom je rovnaký ako pod DOS-om: najprv treba súbor vytvoriť alebo otvoriť, potom doňho môžeme zapisovať alebo z neho čítať, napokon musíme súbor zatvoriť. Funkcie pre prácu so súbormi sú však pod Windows oveľa zložitejšie než pod DOS-om. Hlavnou príčinou je to, že Windows je viacúlohový operačný systém. Viac úloh súčasne môže požadovať prístup k zariadeniu. Okrem toho Windows umožňuje vykonávať asynchrónne operácie vstupu a výstupu. V operačnom systéme MS-DOS sme mohli so súbormi vykonávať len synchrónne operácie. To znamená, že pri čítaní dát zo súboru alebo zápise dát do súboru bol volajúci program pozastavený a čakal na prenos požadovaných údajov. Po ukončení prenosu získal späť riadenie a mohol pokračovať vo svojej práci. Pretože operácie so súbormi a s ostatnými zariadeniami prístupnými pomocou súborových funkcií sú pomalé, umožňuje Windows komunikovať s týmito zariadeniami asynchrónne. Znamená to, že aplikácia povie systému, aby vykonal čítanie alebo zápis a potom pokračuje v činnosti, zatiaľ čo súbežne prebieha operácia vstupu alebo výstupu. V ďalšom texte si popíšeme funkcie, ktoré slúžia na otvorenie súboru, čítanie, zápis, zatvorenie súboru a nastavenie ukazovateľa v súbore. Hodnota NULL, ktorú môžu nadobúdať niektoré parametre funkcií, má význam nulového smerníka a je implementovaná ako nulový 32-bitový offset. Funkčná hodnota sa vracia v registri EAX. Niektoré funkcie vracajú logické hodnoty. Hodnota TRUE je implementovaná ako 1, FALSE ako 0. Volaním funkcie CreateFileA oznamuje náš program operačnému systému, s akým súborom, prípadne zariadením chce pracovať. Funkcia CreateFileA vytvorí súbor a zároveň ho otvorí pre požadovaný spôsob prístupu (čítanie a/alebo zápis), alebo otvorí už existujúci súbor. Funkcia vráti 32-bitový popisovač (handle) súboru v registri EAX. V prípade chyby vráti hodnotu INVALID_HANDLE_VALUE (-1). Funkcia má nasledujúce parametre (všetky typu dword):
Prvý parameter funkcie CreateFileA (popisovač súboru s atribútmi) môže byť buď popisovač otvoreného súboru, alebo môže mať hodnotu NULL. Ak parameter obsahuje popisovač súboru, funkcia ignoruje atribúty odovzdané v nasledujúcom parametri a použije atribúty súboru určeného týmto popisovačom. Ak funkcia CreateFileA otvára existujúci súbor (a nevytvára nový), parameter popisovač súboru s atribútmi sa ignoruje. Druhý parameter obsahuje v nižšom slove atribúty súboru, vo vyššom príznaky. Atribúty môžeme nastaviť na hodnotu FILE_ATTRIBUTE_NORMAL (00000080h), alebo použiť kombináciu nasledujúcich preddefinovaných konštánt:
Význam prvých piatich atribútov už poznáme z operačného systému MS-DOS. Atribút FILE_ATTRIBUTE_COMPRESSED pre súbor znamená, že dáta v súbore budú komprimované. Ak vytvoríme adresár s týmto atribútom, budú všetky novo vytvorené súbory a podadresáre komprimované. Atribút FILE_ATTRIBUTE_TEMPORARY znamená, že súbor sa bude používať relatívne krátky čas. Keď funkcia CreateFileA vytvorí súbor s týmto atribútom, snaží sa ho udržiavať v pamäti a neukladať ho na disk. Tým sa výrazne zrýchľuje prístup k súboru. Atribút FILE_ATTRIBUTE_TEMPORARY sa často používa v kombinácii s príznakom FILE_FLAG_DELETE_ON_CLOSE (04000000h), ktorý oznamuje systému, že po zatvorení súboru sa má tento z disku vymazať. Ďalšie príznaky sa väčšinou týkajú využitia cache pamäti pri prístupe k súboru. Operačný systém za normálnych okolností používa pri prístupe k súboru cache pamäť. Tým sa výrazne zvyšuje rýchlosť načítania údajov, ktoré s najväčšou pravdepodobnosťou budú v okamihu potreby v cache pamäti. Režim spätného zápisu („write back“) zase zrýchľuje ukladanie dát do súboru, pretože na disk sa pristupuje len občas a prednostne vtedy, keď procesor nemá inú robotu. Na druhej strane použitie cache pamäti znamená, že časť súboru bude v pamäti dvakrát: v cache pamäti a vo vyrovnávacej pamäti, ktorú program používa pri čítaní a zápise do súboru. Príznakmi môžeme zmeniť štandardné využitie cache pamäti, aby sme prístup k súboru čo najviac zefektívnili s ohľadom na potreby našej aplikácie. Príznak FILE_FLAG_WRITE_THROUGH (80000000h) prikazuje operačnému systému, aby pri zápise do súboru použil režim „write through“ (súčasný zápis do cache pamäti aj na disk). Príznak FILE_FLAG_NO_BUFFERING (20000000h) oznamuje operačnému systému, že čítanie a zápis do súboru sa nebude uskutočňovať cez cache pamäť, ale že dáta zo súboru sa budú ukladať rovno do vyrovnávacej pamäti definovanej v programe. Podľa toho, čo presne robíte, môže viesť použitie tohto príznaku k zvýšeniu výkonu aplikácie a k úspore pamäti. Príznaky FILE_FLAG_SEQUENTIAL_SCAN a FILE_FLAG_RANDOM_ACCESS majú význam len v prípade, keď operačný systém používa cache pamäť štandardným spôsobom. Ak použijete príznak FILE_FLAG_NO_BUFFERING, obidva príznaky sa budú ignorovať. Príznak FILE_FLAG_SEQUENTIAL_SCAN (08000000h) oznamuje systému, že k údajom v súbore hodláte pristupovať sekvenčne. Systém bude vykonávať dopredné čítanie zo súboru, aby údaje, ktoré chcete načítať, boli v okamihu potreby k dispozícii v cache pamäti. Tým sa znižuje počet nutných prístupov k disku a zvyšuje sa rýchlosť aplikácie. Ak však mienite používať náhodný prístup k súboru pomocou ukazovateľa v súbore, je výhodnejšie nastaviť príznak FILE_FLAG_RANDOM_ACCESS (10000000h). Systém potom nebude údaje zo súboru načítať dopredu. Príznak FILE_FLAG_BACKUP_SEMANTICS (02000000h) sa používa najmä v aplikáciách pre zálohovanie dát. Systém kontroluje, či volajúci proces je oprávnený vykonávať zálohovanie súboru. Použitím príznaku FILE_FLAG_POSIX_SEMANTICS (01000000h) oznamujete systému, aby pri prístupe k súboru používal pravidlá systému POSIX, ktoré rozlišujú veľké a malé písmená v mene súboru. Tento príznak používajte opatrne, pretože sa môže stať, že súbor vytvorený s týmto príznakom nebude dostupný z aplikácie vytvorenej pre MS-DOS alebo Windows NT. Posledný príznak FILE_FLAG_OVERLAPPED (40000000h) oznamuje systému, že požadujete asynchrónny prístup k zariadeniu. Význam ďalšieho parametra je zrejmý z nasledujúcej tabuľky.
V štruktúre SECURITY_ATTRIBUTES nastavujete práva prístupu k súboru (zariadeniu) a tiež môžete určiť, či popisovač zariadenia bude dedičný (čím by prístup k zariadeniu získali aj synovské procesy). Pokiaľ chcete použiť implicitné hodnoty zabezpečenia1 a popisovač nemá byť dedičný, môžete na mieste tohto parametra odovzdať hodnotu NULL. Režim zdieľania definuje, či a akým spôsobom budú procesy zdieľať súbor. Parameter
môže nadobúdať nasledujúce hodnoty:
Spôsob prístupu je jedna zo štyroch hodnôt:
Meno súboru môže obsahovať špecifikáciu disku a cestu. Funkcia predpokladá, že meno je zadané v znakovej sade ANSI, obsahuje maximálne 260 znakov a je ukončené nulou. Ak je meno súboru zadané v znakovej sade Unicode, treba použiť funkciu CreateFileW. V ďalšom texte sa zameriame na synchrónne operácie vstupu a výstupu. Na čítanie zo súboru slúži funkcia ReadFile. Funkcia číta údaje zo súboru od pozície danej hodnotou ukazovateľa v súbore. Po skončení operácie čítania sa ukazovateľ upraví o počet skutočne prečítaných bajtov. Funkcia má nasledujúce parametre (všetky typu dword):
Ak čítanie zo súboru prebehlo bez chyby, vráti funkcia ReadFile hodnotu TRUE. Ak vrátená hodnota je TRUE a počet načítaných bajtov je nula, potom to znamená, že v okamihu požadovanej operácie čítania bol ukazovateľ za aktuálnym koncom súboru. V prípade neúspešnej operácie vráti ReadFile hodnotu FALSE. Funkcia WriteFile zapisuje dáta do súboru od pozície danej hodnotou ukazovateľa. Po ukončení zápisu sa ukazovateľ upraví o počet skutočne zapísaných bajtov. Funkcia má nasledujúce parametre (všetky typu dword):
Ak zápis do súboru prebehol bez chyby, vráti funkcia WriteFile hodnotu TRUE. V prípade neúspešnej operácie vráti WriteFile hodnotu FALSE. Funkcia CloseHandle zatvorí súbor. Má jediný parameter – popisovač súboru (typu dword). V prípade úspechu vráti TRUE, v prípade neúspechu FALSE. Napokon spomenieme funkciu SetFilePointer, ktorá mení polohu ukazovateľa v otvorenom súbore. Funkcia má nasledujúce parametre (všetky typu dword):
Počet bajtov, o ktorý sa má posunúť ukazovateľ, sa pripočíta k počiatočnému bodu. Pre väčšinu súborov postačuje možnosť posúvať sa dopredu či dozadu o 32-bitovú hodnotu. V tom prípade má druhý parameter hodnotu NULL. V prípade, že relatívna vzdialenosť musí byť vyjadrená 64-bitovou hodnotou, zadáme jej nižšiu časť v treťom parametri a vyššiu časť v premennej, ktorej adresa je druhým parametrom funkcie. Prvý parameter udáva, ku ktorému miestu v súbore sa relatívne posunutie vzťahuje. Môže nadobúdať jednu z nasledujúcich hodnôt:
Ak funkcia SetFilePointer prebehla v poriadku, vráti novú hodnotu ukazovateľa, a to nižšie dvojslovo v registri EAX, vyššie dvojslovo v premennej, ktorej adresa je druhým parametrom funkcie. Ak došlo ku chybe, nasledujúce volanie funkcie GetLastError vráti hodnotu rôznu od NO_ERROR. Na záver tejto kapitoly ukážeme príklad, ktorý vytvorí nový súbor a zapíše doňho obsah premennej IOBuffer. Meno súboru je v premennej MenoSub2. Do programu je včlenený súbor win32.inc, ktorý obsahuje definíciu konštánt spomínaných v predchádzajúcom texte. Program (nech sa volá winfile.asm) treba preložiť prekladačom tasm32 s nastavenou voľbou pre rozlišovanie malých a veľkých písmen: \tasm\bin\tasm32 /ml winfile Pri linkovaní treba tiež rozlišovať malé a veľké písmená, ďalej musíme zadať prepínače, ktoré vytvoria EXE súbor pre Windows, a napokon musíme prilinkovať knižničný súbor import32.lib: \tasm\bin\tlink32
/c /Tpe /aa winfile,,,\tasm\lib\import32
.386 include win32.inc
.DATA .CODE Výstup na obrazovku sa v operačnom systéme Windows uskutočňuje volaním jeho funkcií. V ďalšom texte budeme hovoriť o aplikačnej úrovni vstupu, pretože tá je založená na inej filozofii, než sme boli zvyknutí pod DOS-om. Na rozdiel od aplikácií bežiacich pod operačným systémom MS-DOS, aplikácie napísané pre operačný systém Windows nezískavajú vstupné údaje volaním služieb operačného systému. Namiesto toho čakajú, kým im operačný systém pošle vstupné údaje. Pokiaľ v DOS-ovských programoch bola hlavným vstupným zariadením klávesnica, pod Windows sa ním stáva myš. Každý pohyb myšou, kliknutie tlačidla myši alebo stlačenie klávesu predstavuje vstupnú udalosť, ktorú Windows oznamuje aplikačnému programu tak, že volá tzv. oknovú procedúru (window procedure). Každé okno aplikácie má svoju oknovú procedúru, ktorú Windows volá vtedy, keď podľa polohy kurzora zistí, že vstup je adresovaný danému oknu. Windows odovzdáva oknovej procedúre správu (message). Správa je údajová štruktúra s nasledujúcimi položkami (typu dword):
Oknová procedúra podľa kľúča rozhodne, ako má správu spracovať. Napr. kľúč WM_PAINT hovorí oknovej procedúre, že užívateľská oblasť okna (client area) sa zmenila a musí sa prekresliť. Myš generuje správy WM_MOUSEMOVE, WM_LBUTTONDOWN, WM_RBUTTONDOWN a iné. Oknová procedúra vykoná potrebnú činnosť, nastaví funkčnú hodnotu na nulu a vráti riadenie do Windows. Oknová procedúra musí pred návratom zavolať procedúru DefWindowProc, ktorá štandardným spôsobom spracuje správy, ktoré nespracovala oknová procedúra. Oknová procedúra sa obvykle nazýva WndProc, ale nie je to podmienkou. Meno oknovej procedúry musí aplikácia oznámiť operačnému systému. Slúži na to príkaz EXPORTS v definičnom súbore (.def), ktorý sa prilinkuje k aplikácii. Bližšie informácie o definičnom súbore nájdete v elektronickej dokumentácii k Turbo Assembleru 5.0 (súbor tlink.txt). Aj aplikácia môže generovať správy a posielať ich vlastným oknám alebo inej aplikácii. Posielanie správ sa však neuskutočňuje tak priamočiaro, ako sme naznačili. Napr. vznik vstupnej udalosti neznamená, že Windows volá oknovú procedúru automaticky. Každá aplikácia má vlastný front správ, do ktorého sa ukladajú všetky správy určené pre danú aplikáciu. Aplikácia sama správu z frontu vyberie (pričom môže správy filtrovať) a dá pokyn operačnému systému, aby ju poslal oknovej procedúre. Správy sa z frontu vyberajú v tzv. slučke správ (message loop), ktorá v najjednoduchšom prípade vyzerá takto:
while GetMessage(msg,NULL,0,0) do
begin
TranslateMessage(msg);
DispatcheMessage(msg)
end; Funkcia GetMessage vyberá správy z frontu a kopíruje ich do štruktúry msg. GetMessage vráti TRUE pri všetkých správach okrem správy WM_QUIT, kedy vráti FALSE. Prijatím správy WM_QUIT sa slučka správ ukončí. Ukončenie slučky správ je obvykle prvým krokom k uzavretiu aplikácie. Druhý parameter funkcie GetMessage je handle okna, ktorého správy sa majú vyberať z frontu správ. Ak má tento parameter hodnotu NULL, znamená to, že z frontu sa majú vyberať správy pre všetky okná patriace danej aplikácii. GetMessage môže z frontu vyberať len správy, ktorých kľúče sú v stanovenom intervale (určenom tretím a štvrtým parametrom). Ak tieto parametre majú nulové hodnoty, GetMessage vyberá všetky správy. Ak aplikácia mieni akceptovať vstup z klávesnice, musí slučka správ obsahovať funkciu TranslateMessage. Windows generuje správy WM_KEYDOWN, WM_SYSKEYDOWN, WM_KEYUP a WM_SYSKEYUP pri každom stlačení klávesu. Tieto správy obsahujú scan kód a virtuálny kód klávesu a ďalšie informácie, napr. počet opakovaní ako dôsledok podržania klávesu. Scan kód je jedinečné číslo priradené klávesu. Závisí od typu klávesnice. Virtuálny kód je od zariadenia nezávislá hodnota, ktorú prideľuje klávesom Windows a ktorá určuje význam jednotlivých klávesov. Správy WM_KEYDOWN a WM_KEYUP sa generujú pri stlačení nesystémových klávesov3, správy WM_SYSKEYDOWN a WM_SYSKEYUP pri stlačení systémových klávesov. Správy WM_KEYDOWN a WM_SYSKEYDOWN identifikujú, ktorý kláves bol stlačený, ale neposkytujú informáciu o zodpovedajúcom znaku. Ak bol stlačený kláves mapovaný na ASCII znak, funkcia TranslateMessage preloží správu WM_KEYDOWN (WM_SYSKEYDOWN) na znakovú správu WM_CHAR a umiestni ju späť do frontu správ. Znaková správa sa potom z frontu vyberie v nasledujúcej iterácii slučky správ. Správa WM_CHAR obsahuje v najnižšom bajte prvého parametra ASCII kód klávesu a v druhom parametri scan kód (v bitoch 16 až 23) a ďalšie údaje o klávese (počet opakovaní znaku, súčasné stlačenie klávesu Alt, atď.). Funkcia DispatchMessage prikáže operačnému systému, aby správu poslal oknovej procedúre. Aplikácia začína vykonávať svoju slučku správ po tom, ako sa inicializovala a vytvorila aspoň jedno okno. Stačí, aby aplikácia mala len jednu slučku správ, aj keď má viacej okien. DispatchMessage pošle správu vždy tomu správnemu oknu, pretože súčasťou správy je handle okna, ktorému je správa určená. Správa, ktorá má handle okna NULL, je určená aplikácii ako takej, ale žiadnemu konkrétnemu oknu. S takouto správou neurobí DispatchMessage nič. Turbo Assembler 5.0 obsahuje demonštračný program Wap32.asm (v podadresári EXAMPLES). Na tejto jednoduchej 32-bitovej aplikácii môžete sledovať, ako sa inicializuje aplikácia pod Windows, ako sa vytvorí okno, ako je naprogramovaná jednoduchá slučka správ a oknová procedúra. 1 Implicitné zabezpečenie znamená, že administrátor a tvorca objektu majú k zariadeniu plný prístup, všetci ostatní majú prístup zakázaný. 2 Ak by sme chceli obsah premennej IOBuffer vypísať na tlačiareň, zadali by sme meno súboru 'LPT1'. 3 Nesystémové klávesy sú také, pri ktorých nebol súčasne stlačený kláves Alt. |
Načo je vám jazyk symbolických adries?
Architektúra moderných procesorov Služby operačného systému MS-DOS Služby operačného systému Windows 95/98/NT/XP |
||||||||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||||||
Vydala Žilinská univerzita v Žiline, 2000. ISBN 80-7100-723-4. Otázky a pripomienky môžete poslať autorke. Naposledy upravené 7.12.2011. |