Asembler x86/Pierwszy program/MASM

Pierwszy program

GNU As
FASM
MASM
NASM

Hello World! edytuj

Zacznijmy od dawki kodu, żeby mieć pojęcie jak w ogóle wygląda kod asemblera. Będzie to tradycyjny już program Hello World, który można napotkać w niemal każdym podręczniku do nauki programowania w dowolnym języku (za zadanie ma po prostu wyświetlenie napisu Hello World!).

.model SMALL
.386

.data
	tekst db "Hello World!\n"
.stack 100h
.code
	.startup
        mov eax, 4
        mov ebx, 1
	mov ecx, offset tekst
	mov edx, 13
	int 80h
        .exit
end

Wygląda strasznie? Na pewno. Postaram się zrozumiale wyjaśnić o co w nim chodzi.

 .model SMALL

Dyrektywa .model pozwala zdefiniować z jakiego modelu pamięci ma korzystać nasz program. Model SMALL oznacza segmentowy model pamięci z jednym segmentem kodu i jednym segmentem danych.

 .386

Ta dyrektywa określa z jakiego zbioru instrukcji będzie korzystać nasz program. W tym przypadku określamy oczywiście, że chodzi nam o zbiór instrukcji procesorów 80386.

 .data

Określa, że od tego miejsca w dół definiowany jest segment z danymi.

 tekst db "Hello World!\n"

Wrzuca do segmentu z danymi ciąg znaków "Hello World!" zakończony znakiem nowej linii. tekst jest to nazwa dla naszego ciągu, zaś słowo db oznacza, że ma być on ciągiem bajtów.

 .stack 100h

Dyrektywa tworzy segment stosu o wielkości 100h. Umieszczenie literki h za liczbą oznacza, że jest zapisana szesnastkowo (100h = 256 dziesiętnie).

 .code

Początek definiowania segmentu z kodem.

 .startup

Jest to makroinstrukcja, która w procesie kompilacji zastępowana jest w tym miejscu kodem wykonującym standardowe początkowe czynności (nadaje odpowiednie wartości rejestrom segmentowym, które są konieczne do poprawnego działania naszego programu).

 mov ecx, offset tekst

Jeśli zdeasemblujesz dowolny program, prawdopodobnie ujrzysz instrukcje podobne do tej umieszczone jedna za drugą. Każdej instrukcji asemblera używa się wg schematu:

instrukcja argumentA, argumentB, argumentC...

Jeśli chodzi o akurat tą instrukcję - mov kopiuje zawartość B do A. A w tym przypadku to rejestr procesora dx, zaś B (offset tekst) to adres naszego ciągu znaków, wydobyty dzięki słowu offset (użycie samej nazwy zmiennej nie odnosiłoby się do jej adresu a o niego nam w tym przypadku chodzi).

 mov eax, 4
 mov edx, 13
 mov ebx, 1

Kopiuje wartość 4 do naszego rejestru eax, 1 do ebx, i 13 do edx.

 int 80h

Instrukcja int wywołuje podprogram obsługi przerwania (dokładnie co to są przerwania opisane jest w rozdziale Instrukcje) o numerze podanym jako A (w tym przypadku chodzi o numer 21h). Podprogram obsługujący przerwanie o tym numerze wywołuje określoną funkcję o numerze przekazanym w rejestrze eax (przerwanie 80h, funkcja przerwania numer 4).

 .exit

Jest to makroinstrukcja wywołująca przerwanie 21h, funkcję 4Ch (dla ćwiczenia spróbuj zastąpić ją właściwym kodem przy użyciu instrukcji mov oraz int), która nie przyjmuje żadnych argumentów (tzn. makroinstrukcja ta nie przypisuje żadnych wartości rejestrom innym niż ah określającemu numer funkcji). Funkcja ta kończy działanie programu.

 end

Określa że w tym miejscu kończy się kod. Asembler po napotkaniu tego słowa kończy proces asemblacji, niezależnie od tego, czy znajduje się jakiś kod jeszcze dalej.

Goodbye world... edytuj

Powyższy kod początkowo może trochę odstraszać, lecz jeśli masz pierwszy raz styczność z asemblerem prawdopodobnie spodziewałeś się czegoś znacznie gorszego. O asemblerze krąży wiele nieprawdziwych informacji, iż jest to trudny do nauki język. Tak naprawdę nie jest trudny - jest nieczytelny. Po kilku godzinach od napisania nie rozumie się swojego własnego kodu, dlatego nawet jeśli nie przejmowałeś się komentarzami programując w innych językach programowania (bo można w nich sobie radzić bez komentarzy), staraj się pokonać nieco swoje przyzwyczajenia i dopisywać w kodzie komentarze w kluczowych miejscach. Niestety luksus ten dotyczy nas jedynie przy pisaniu własnych programów. Jeśli uczysz się asemblera głównie pod kątem zrozumienia zdeasemblowanych plików, tam jest to o tyle utrudnione, że rzuceni jesteśmy w tysiące linii kodu, o którego strukturze nie mamy zielonego pojęcia, dodatkowo nie mamy do pomocy żadnych komentarzy a język asemblera jest bardzo nieczytelny. Zaczynaj od prostych programów, nie rzucaj się na głęboką wodę. Następnie przechodź do coraz większych starając się zmodyfikować w nich konkretną rzecz (np. pozamieniać znaczenie przycisków itp.) - przede wszystkim nie poddawaj się! Dzięki znajomości asemblera Twoje możliwości będą znacznie szersze.