Rozdział I - Podstawy


Kurs ten zakłada, iż wiesz, jak korzystać z asemblera MASM. Jeśli nie znasz MASM'a, pobierz plik winasm32.exe i przestudiuj tekst zawarty w tym pakiecie zanim zaczniesz przerabiać mój kurs (polecam również zapoznanie się z artykułem Kodowanie Liczb - J.W.). Jeśli wiesz, jak korzystać z MASM'a, to jesteś już gotowy. Zaczynajmy!.

 

Teoria

Programy Win32 pracują w trybie chronionym dostępnym już od modelu procesora 80286. Lecz 80286 jest dzisiaj historią. Dlatego powinniśmy się troszczyć jedynie o model 80386 i jego następców. System Windows uruchamia każdy program Win32 w oddzielnej, wirtualnej przestrzeni. Zatem każdy program Win32 będzie posiadał własną przestrzeń adresową o rozmiarze 4GB. Jednakże nie oznacza to, iż każdy program Win32 posiada 4GB fizycznej pamięci, a jedynie możliwość zaadresowania dowolnej komórki w tym zakresie. Windows zajmie się tym, aby adresowana przez program pamięć stała się dostępna. Oczywiście program pracujący w takim środowisku musi się podporządkować panującym zasadom, w przeciwnym razie powstanie straszny błąd Naruszenia Zasad Ochrony (GPF - General Protection Fault). W swojej przestrzeni adresowej każdy program przebywa samotnie. Stanowi to zatem przeciwieństwo sytuacji spotykanej w 16 bitowych Windows. Wszystkie programy Win16 mogą się nawzajem "widzieć". W Win32 to się nie zdarza. Zmniejsza to szansę zapisania danych przez jeden z programów w obszarze danych lub kodu innego programu.

Model pamięci również drastycznie różni się od modeli stosowanych w czasach systemów 16 bitowych. W Win32 nie musimy się już martwić podziałem pamięci na segmenty! Istnieje tylko jeden model pamięciowy. Model Flat Memory (Płaska Pamięć). Nie ma już segmentów 64KB. Pamięć jest dużą, ciągłą przestrzenią o rozmiarze 4GB. Oznacza to również, iż nie musisz bawić się rejestrami segmentowymi. Możesz zastosować dowolny rejestr segmentowy do zaadresowania dowolnej komórki wewnątrz tej przestrzeni pamięciowej. To WSPANIAŁA pomoc dla programistów sprawiająca, iż programowanie w asemblerze Win32 jest tak proste jak programowanie w języku C.

Programując w Win32 musisz znać kilka ważnych zasad. Jedną z nich jest to, iż system Windows wykorzystuje dla swoich wewnętrznych potrzeb rejestry esi, edi, ebp i ebx. Więc zapamiętaj najpierw taką zasadę: jeśli używasz dowolnego z tych rejestrów w swojej funkcji zwrotnej (callback), nie zapomnij go odtworzyć przed powrotem do Windows. Funkcja zwrotna (callback function) jest twoją własną funkcją, którą wywołuje system Windows. Oczywistym przykładem jest procedura okna (window procedure). Nie oznacza to, iż nie możesz korzystać z tych czterech rejestrów - możesz. Po prostu upewnij się, iż odtworzyłeś ich zawartość przed powrotem do Windows.

 

Praktyka

Oto szkielet programu. Jeśli nie rozumiesz niektórych kodów, nie panikuj. Wyjaśnię za chwilę każdy z nich.

 

.386 
.MODEL FLAT, STDCALL 

.DATA 
    <Twoje zainicjowane dane> 
    ... 

.DATA? 
    <Twoje nie zainicjowane dane> 
    ... 

.CONST 
    <Twoje stałe> 
    ... 

.CODE 
    <etykieta> 
    <Twój kod> 
    ... 
END <etykieta>

 

To wszystko! Przeanalizujmy ten szkieletowy program.

 

.386

To jest dyrektywa asemblera, która informuje go, aby korzystać z instrukcji procesora 80386. Możesz również zastosować .486, .586, lecz najbezpieczniej będzie pozostać przy .386. Właściwie istnieją dwa prawie identyczne formy każdego z modeli mikroprocesora. 386/.386p, .486/.486p. Wersje "p" są konieczne jedynie w przypadku, gdy twój program korzysta z instrukcji uprzywilejowanych. Instrukcje takie są zarezerwowane dla systemu operacyjnego pracującego w trybie chronionym. Mogą być wykonywane jedynie przez uprzywilejowany kod, taki jak wirtualne sterowniki urządzeń. Przez większość czasu twoje programy będą pracowały w trybie nieuprzywilejowanym, więc bezpiecznie możemy pominąć wersje z "p".

 

.MODEL FLAT, STDCALL

.MODEL jest dyrektywą asemblera określającą model pamięci twojego programu. Pod Win32 istnieje tylko jeden model, FLAT.

STDCALL informuje MASM'a o konwencji przekazywania parametrów dla procedur i funkcji. Konwencja przekazywania parametrów określa kolejność umieszczania ich na stosie, od lewa na prawo lub od prawa na lewo, oraz również kto wyczyści ramkę stosu po wywołaniu funkcji.

Pod Win16 istniały dwa rodzaje konwencji wywołania - C oraz PASCAL.

Konwencja wywołania typu C przekazuje parametry od strony prawej do lewej, parametr najbardziej na prawo zostanie umieszczony na stosie jako pierwszy. Procedura wywołująca jest odpowiedzialna za usunięcie ramki stosu po wywołaniu. Na przykład w celu wywołania funkcji o nazwie foo(int p1, int p2, int p3) w konwencji wywołania typu C kod asemblera wygląda następująco:


    push [p3]     ; Umieść na stosie trzeci parametr 
    push [p2]     ; Następnie drugi 
    push [p1]     ; I pierwszy 
    call foo 
    add  sp, 12   ; Usuń ze stosu parametry po wywołaniu funkcji


Konwencja wywołania typu PASCAL jest odwrotnością konwencji wywołania typu C. Przekazuje ona parametry od lewej do prawej i wywoływana procedura/funkcja jest odpowiedzialna za usuwanie ramki stosu po wywołaniu. Win16 zaadoptowało konwencję PASCAL z uwagi na mniejszy rozmiar kodu wynikowego. Konwencja C jest użyteczna, gdy nie znamy liczby przekazywanych parametrów do funkcji, jak jest w przypadku wsprintf(), gdzie wywoływana funkcja nie ma sposobu bezpośredniego określenia liczby przekazanych na stosie parametrów, więc nie może usunąć z niego ramki stosu.

STDCALL jest połączeniem konwencji C i PASCAL. Przekazuje ona parametry od strony prawej do lewej, lecz za usuwanie ramki stosu odpowiedzialna jest wywoływana funkcja. Platforma Win32 stosuje wyłącznie stdcall. Jedynym wyjątkiem jest wsprintf(), gdzie musi być zastosowana konwencja wywołania typu C.

 

.DATA
.DATA?
.CONST
.CODE

Wszystkie cztery dyrektywy określają tzw. sekcję. W Win32 nie ma segmentów, pamiętasz? Za to można podzielić całą przestrzeń adresową na sekcje logiczne. Początek jednej sekcji oznacza koniec poprzedniej. Istnieją dwie grupy sekcji: danych i kodu. Sekcje danych dzielą się na trzy kategorie:

Nie musisz wykorzystywać w swoim programie wszystkich trzech sekcji naraz. Zadeklaruj tylko te, które chcesz użyć.

Dla kodu istnieje tylko jedna sekcja: .CODE. To tutaj trafia twój kod programu.

 

<etykieta>
...
END <etykieta>

gdzie <etykieta> jest dowolną etykietą wykorzystywaną do określenia zasięgu twojego kodu. Obie etykiety muszą być identyczne. Wszystkie twoje kody muszą być umieszczone pomiędzy <etykieta> a END <etykieta>.

 

Autorem kursu jest Iczelion. Kurs programowania Windows znalazł się na serwerze I LO w Tarnowie za pisemną zgodą autora.
Tłumaczenie z języka angielskiego, opracowanie HTML i konwersję przykładów programów wykonał mgr Jerzy Wałaszek.


   I Liceum Ogólnokształcące   
im. Kazimierza Brodzińskiego
w Tarnowie

©2024 mgr Jerzy Wałaszek

Dokument ten rozpowszechniany jest zgodnie z zasadami licencji
GNU Free Documentation License.

Pytania proszę przesyłać na adres email: i-lo@eduinf.waw.pl

W artykułach serwisu są używane cookies. Jeśli nie chcesz ich otrzymywać,
zablokuj je w swojej przeglądarce.
Informacje dodatkowe