1. Základy


Tutoriál 1: Základy



Tento tutoriál predpokladá, že čitateľ vie používať MASM (Microsoft Macro ASseMbler). Ak nepoznáte MASM, stiahnite si MASM napr. odtiaľto a preštudujte si dokumentáciu predtým ako začnete s týmto tutoriálom. Dobre! Teraz ste už pripravený! Tak poďme na to!

Teória:

Win32 programy bežia v chránenom režime, ktorý je dostupný od čias 80286. Ale 80286 je už história. My sa teda budme zaoberať 80386 a jeho potomkami. Win32 programy bežia v oddelených virtuálnych priestoroch. To znamená, že každý Win32 program má svoj 4 GB adresový priestor. Toto však neznamená, že by každý win32 program mal 4GB fyzickej pamäte, len že program môže adresovať pamäť z tohto rozsahu. Windows musí samozrejme zabezpečiť, aby boli všetky odkazy platné. Samozrejme, že programy musia dodržiavať pravidlá dané Windowsom, inak spôsobia toľko obávanú všeobecnú chybu ochrany (General Protection Fault). Každý program je sám vo svojom adresovom priestore. Toto je rozdiel od programov Win16. Všetky Win16 programy sa môžu navzájom vidieť. U Win32 programov je to inak. Táto vlastnosť pomáha znížiť pravdepodobnosť, ze jeden program prepíše svoj kód alebo dáta cez iný program.

Pamäťový model je teraz úplne odlišný od 16-bitového sveta. Pri Win32 programoch sa nemusíme zaoberať pamäťovým modelom alebo jeho segmentami. Teraz je len jeden model: Plochý pamäťový model (Flat memory model). Teda už žiadne 64K segmenty. Pamäť je veľký kontinuálny priestor o veľkosti 4 GB. To tiež znamená, že sa už programátori nemusia zaoberať segmentovými registrami. Môžu použiť ktorýkoľvek segmentový register na adresovanie akéhokoľvek bodu v adresovom priestore. Toto je VEĽKÁ POMOC pre programátorov. Toto robí Win32 assembler rovnako jednoduchým ako C.
Keď programujete pod Win32, vy musíte poznať niektoré dôležité pravidlá. Jedno také pravidlo je, že Windows používajú esi, edi, ebp and ebx vnútorne a teda neočakávajú sa zmeny hodnôt v týchto registroch. Teda si pamätajte toto pravidlo: Skôr ako vrátite po použití týchto registrov vo vašej spätnej funkcii (callback function) kontrolu Windows-om, nezabudnite obnoviť tieto registre. Spätná funkcia je vaša vlastná funkcia volaná Windows-om. Jasným príkladom je procedúra okna. To neznamená, že nemôžete používať tieto štyri registe. Môžete. Len ich nikdy nezabudnite obnoviť pred vrátením kontroly Windows-u.

Obsah:

Toto je kostra programu. Ak nerozumiete niektorým častiam kódu, nerobte paniku. Všetko bude vysvelené neskôr..

.386
.MODEL Flat, STDCALL
.DATA
    <Vaše inicializované dáta >
    ……
.DATA?
   <Vaše neinicializované dáta >
   ……
.CONST
   <Vaše konštanty >
   ……
.CODE
   <label>
    <Váš kód >
   …..
    end <label>

To je celé ! Ideme analyzovať kostru programu.

.386
Toto je direktíva assembleru , ktorá hovorí, aby sa použila 80386 inštrukčná sada. Vy môžete používať aj .486, .586 ale najbezpečnejšie je používať .386. Vlastne sú tam vždy po dve takmer tožné sady pre model CPU. .386/.386p, .486/.486p. Tie "p" verzie sú potrebné len keď Váš program používa privilegované inštrukcie. Privilegované inštrukcie sa používajú, keď CPU beží v chránenom režime. Oni môžu byť použité len privilegovaným kódom ako sú napríklad virtuálne ovládače zariadení. Väčšinu času bude Váš program bežať v neprivilegovanom režime, preto je bezpečnejšie používať nie "p" verzie.

.MODEL FLAT, STDCALL
.MODEL
je direktíva, ktorá špecifikuje pamäťový model Vášho programu. Pod Win32, používa sa jediný model,
plochý (FLAT)model.

STDCALL určuje mená a volacie konvencie používané v assembleri. Volacie konvencie špecifikujú akým spôsobom sa volajú parametre (zľava do prava, zprava do ľava).
Pod Win16, sú dva typy volacej konvencie,
C a PASCAL

C volacia konvencia volá parametre zprava do ľava, t.j. , parameter najviac vpravo je použitý najskor.
Volajúci je zodpovedný za obnovenie zásobníka po volaní. Napríklad, funkcia foo(int prvy_parameter, int druhy_parameter,
int treti_parameter) v C volacej konvencii bude kód assembleru vyzerať takto:


push [treti_parameter]       ;ulož tretí parameter do zásobníka
push [druhy_parameter]     ;ulož druhý parameter do zásobníka
push [prvy_parameter]       ;ulož prvý parameter do zásobníka
call foo                 ;zavolaj funkciu foo


PASCAL

volacia konvencia je otočená (opačná) ako C volacia konvencia. Parametre sa volajú zľava do prava a za obnovenie zásobníka po volaní je zodpovedný volaný.

Win16 programy používajú
PASCALkonvenciu, pretože tá produkuje menší kód. C konvencia je užitočná vtedy, keď neviete koľko parametrov bude predané funkcii – to je napríklad funkcia wsprintf().
STDCALL je hybridná C and PASCAL konvenca. Použitie parametrov je zprava do ľava, ale za obnovenie je zodpovedný volaný.Win32 platforma používa výhradne STDCALL. Výnimka je funkcia wsprintf(). Tu musíte použiť C volaciu konvenciu.

.DATA
.DATA?
.CONST
.CODE

Tieto všetky štyri direktívy sú volacie sekcie. Ešte si pamätáte, že Win32 programy nemajú sekcie? Čo je potom toto? Len to, že si ten adresový priestor môžete rozdeliť do logických sekcií. Začiatok jednej sekcie označuje koniec predchádzajúcej sekcie. Máme dve skupiny sekcií: dátové sekcie (data) a sekcie kódu (code). Dátové sekcie sú rozdelené do troch kategórií:


  • .DATA    Toto je sekcia, ktorá obsahuje inicializované dáta Vášho programu.

  • .DATA?  Toto je sekcia, ktorá obsahuje neinicializované dáta Vášho programu. Niekedy potrebujete len predalokovať nejakú pamäť, ale nechcete ju hneď inicializovať. Táto sekcia je práve určená na tento účel. Výhoda neinicializovaných dát: nepotrebuje miesto v spustiteľnom súbore. Napríklad, ak alokujete 10,000 bajtov vo Vašej .DATA? sekcii, Váš spustiteľný súbor sa nezväčší o 10,000 bajtov. Jeho veľkosť zostane rovnaká. Vy len poviete, koľko priestoru potrebujete pri zavedení programu do pamäte. To je všetko.

  • .CONST  Táto sekcia obsahuje deklaráciu konštánt použitých vo Vašom programe. Konštanty nemôžete modifikovať Vašim programom. Preto sú to *konštanty*.

Vy nemusíte vo svojom programe použiť všetky sekcie . Použite len tie sekcie, ktoré skutočne potrebujete.

Pre kód je len jedna sekcia :
.CODE.
To je miesto, kde sa nachádza celý kód.

<label>
end <label>
značka <label> môže byť ľubovoľná. Len spolu s koncovou značkou (návestím) musia byť rovnaké.  Teda celý Váš kód sa musí achádzať medzi značkami <label> a end <label>





[Obsah]