Asembler x86/Pierwszy program/MASM: Różnice pomiędzy wersjami

Usunięta treść Dodana treść
Mythov (dyskusja | edycje)
m nawigacja
Doles (dyskusja | edycje)
Linia 2:
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!'').
 
<source lang="asm">
<pre>
.model small
.386
Linia 16:
.exit
end
</presource>
 
Wygląda strasznie? Na pewno. Postaram się zrozumiale wyjaśnić o co w nim chodzi.
<source lang="asm">
.model small
</source>
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.
<source lang="asm">
.386
</source>
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.
<source lang="asm">
.data
</source>
Określa, że od tego miejsca w dół definiowany jest segment z danymi.
<source lang="asm">
tekst byte "Hello World!",0Ah,0Dh,"$"
</source>
Wrzuca do segmentu z danymi ciąg znaków "Hello World!" zakończony znakiem nowej linii (0A0D) oraz znakiem $ określającym, iż jest to koniec naszego ciągu (dla migrantów z C/C++ - jest to odpowiednik znaku '\0'). ''tekst'' jest to nazwa dla naszego ciągu, zaś słowo ''db'' oznacza, że ma być on ciągiem bajtów.
<source lang="asm">
.stack 100h
</source>
Dyrektywa tworzy segment stosu o wielkości 100h. Umieszczenie literki ''h'' za liczbą oznacza, że '''jest zapisana szesnastkowo''' (100h = 256 dziesiętnie).
<source lang="asm">
.code
</source>
Początek definiowania segmentu z kodem.
<source lang="asm">
.startup
</source>
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).
<source lang="asm">
mov dx, offset tekst
</source>
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).
<source lang="asm">
mov ah, 09h
</source>
Kopiuje wartość 09h do naszego rejestru ah.
<source lang="asm">
int 21h
</source>
Instrukcja int wywołuje podprogram obsługi przerwania (dokładnie co to są przerwania opisane jest w rozdziale [[Asembler X86/Przerwania|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 ah (przerwanie 21h, funkcja przerwania numer 09h).
<source lang="asm">
.exit
</source>
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.
<source lang="asm">
end
</source>
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.