CZĘŚĆ 1. - PODSTAWY

Autor nie ponosi odpowiedzialności za jakiekolwiek szkody wynikłe z niewłaściwego użytkowania zarówno Macro Assemblera, jak i programów przykładowych użytych w tym kursie. Został on napisany wyłącznie w celach edukacyjnych. Mam nadzieje, że "kursanci" wybaczą mi również brak polskich liter w niektórych wyrazach (nie jestem w stanie sprawdzić wszystkiego, a bez "krzaczków" piszę z przyzwyczajenia).

1. Co jest potrzebne?

2. Co się może przydać? 3. Dlaczego warto pisać programy w Asemblerze?

4. Rejestry procesora

Każdy 32-bitowy procesor posiada rejestry 32-bitowe (czyli 4-bajtowe), które dzielą się na 16-bitowe, a te z kolei na 8-bitowe (aczkolwiek nie wszystkie).

4.1 Rejestry danych (ogólnego przeznaczenia)
Zasadniczo rejestry danych są 4 (EAX, EBX, ECX, EDX), ale jak pisałem wyżej - można je jeszcze podzielić. Poniższy rysunek zawiera nazwy wszystkich rejestrów danych:



Czyli - jak widać - mniej znacząca połowa rejestru EAX nosi nazwę AX, a AX dzieli się na AH i AL. Podobnie jest z rejestrami EBX, ECX i EDX. W rejestrach ośmiobitowych można zapisać liczby od 0 do 255, 16-bitowych - od 0 do 65535, a w 32-bitowych - od 0 do 4294967295 (ale naprawdę nie ma sensu tego pamiętać).
Mogą się za to przydać nazwy rejestrów:

4.2 Rejestry indeksowe
Czyli EDI i ESI (dzielą się jeszcze na DI i SI, podobnie jak przy rejestrach danych) stosuje się przy operacjach na ciągach oraz jako rejestry ogólnego przeznaczenia. Warto zaznaczyć, że Windows używa ich do swoich (niecnych ;-)) celów i zmiania ich zawartości _może_ spowodować (znany wszystkim skądinąd) komunikat "Program wykonał...". Dlatego też po każdej modyfikacji tych rejestrów należy przywrócić ich poprzednią wartość.

4.3 Niektóre rejestry zostały celowo pominięte w tym opisie, ze względu na rzadkość ich stosowania w aplikacjach Windows.

5 Pierwszy program (!)
Jak to zwykle w tego typu kursach bywa, zaczniemy od programu wyświetlającego prosty komunikat tekstowy.

5.1 Struktura programu
W każdym programie napisanym w Macro Assemblerze powtarzają się te same fragmenty kodu (nazwane tutaj przeze mnie "strukturą"). Tak więc pisanie programu zaczynamy od następującego fragmentu (ktory musi występować w prawie każdej aplikacji):

.386
.model flat, stdcall
option casemap:none

include \masm32\include\windows.inc
;deklaracje bibliotek, które chcemy uzyć

.const
;stałe

.data
;zmienne, które są dane od początku działania programu

.data?
;zmienne niezdefiniowane (podajemy tylko typ zmiennej)

.code
start:
;kod assemblerowy
end start

W pierwszej linii okreslamy zestaw instrukcji ktore chcemy uzyc. 386 jest najbardziej popularny i daje gwarancje ze napisane programy będą "chodzić" na każdym komputerze z Windows. Zamiast 386 moze byc 486, 586 itp.

5.2
Aby wyświetlić komunikat, musimy wiedzieć która funkcja API jest za to odpowiedzialna i w jakiej bibliotece się znajduje. Te informacje można wziąc z WINAPI.HLP. Ponieważ jest to pierwsza częśc kursu, oszczedze wam szukania - ta funkcja to MessageBox. W opisie do niej (winapi.hlp) czytamy:

HWND hWnd, handle of owner window
LPCTSTR lpText, address of text in message box
LPCTSTR lpCaption, address of title of message box
UINT uType style of message box

Są to parametry, które należy podać przy wywoływaniu tej funkcji. hWnd to tzw. "uchwyt okna", który pozwala Windzie określić o które okno nam chodzi. My jeszcze nie mamy okna, więc będziemy musieli wpisać tam 0 (czyli NULL). lpText to adres w pamięci do tekstu, który ma się wyświetlić w okienku. lpCaption to adres w pamięci do tekstu, który ma się wyświetlić w polu tytułowym okienka z komunikatem. uType zawiera informację o tym, jakie przyciski i ikona mają się znaleźć w oknie.
A więc tworzymy plik tekstowy z rozszerzeniem ASM i wpisujemy do niego strukture programu (powyżej).
Funkcje, których bedziemy używać znajdują się w bibliotekach kernel32 i user32, musimy wiec je zadeklarować, aby kompilator wiedział skąd wziąć informacje o nich:

include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib


W sekcji data definiujemy zmienne zawierające to, co chcemy wyświetlić w okienku, np.

msgTytul db "MASM Tutorial",0
msgTekst db "Assembler jest wspaniały!",0


Pare słów wyjaśnienia: msgTytul i msgTekst to nazwy zmiennych, db oznacza typ zmiennej (w tym przypadku byte), natomiast 0 musi konczyc kazdą zmienną tekstową.
W miejscu gdzie ma byc kod należałoby wywołać funkcję MessageBox. Macro Assembler posiada specjalną instrukcję służącą do wywoływania funkcji API - invoke. Parametry do funkcji podaje się wtedy po przecinku. Piszemy więc:

invoke MessageBox,0,addr msgTekst,addr msgTytul,MB_OK

"Addr" przed nazwami zmiennych jest potrzebny po to, by kompilator zamienił to na adres, a nie na zawartość zmiennej. Skąd wiemy, że jako parametr należy podać adres? Z winapi.hlp (patrz wyżej - jest tam napisane np. address of text in message box).
Aby program działał prawidłowo, należy go zakończyć. Służy do tego funkcja ExitProcess. Dopisujemy więc jeszcze fragment:

invoke ExitProcess,0

Sekcje ".const" oraz ".data?" są puste więc można je spokojnie usunąć. Cały kod wygląda więc tak:

.386
.model flat, stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib

.data
msgTytul db "MASM Tutorial",0
msgTekst db "Assembler jest wspaniały!",0

.code
start:
  invoke MessageBox,0,addr msgTekst,addr msgTytul,MB_OK
  invoke ExitProcess,0
end start


Po kompilacji programik ten wyświetli okienko z komunikatem i przyciskiem OK. Jeżeli chcemy, aby zamiast OK były inne przyciski, wpisujemy odpowiednie wartości zamiast MB_OK:

Gdy chcemy dodatkowo wyswietlic ikonkę, dopisujemy do kodu przycisku "or" oraz odpowiednią wartość z listy poniżej.

Przykład - wyświetlanie komunikatu z przyciskami przerwij, ponów próbę, zignoruj i znakiem zapytania:

invoke MessageBox, 0, addr msgTekst, addr msgTytul, MB_ABORTRETRYIGNORE or MB_ICONQUESTION

Okienku z komunikatem można nadać jeszcze kilka innych właściwości. Zainteresowanych odsyłam do winapi.hlp. Przykładowy program do tej części kursu znajduje się tutaj.

Arkadiusz "Czajnick" Robiński
arekrob@kki.net.pl
http://www.antywin.ko.pl