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

Usunięta treść Dodana treść
Mythov (dyskusja | edycje)
przerzucono treść z rozdziału "Narzędzia"
 
Mythov (dyskusja | edycje)
Linia 1:
=== Hello World! ===
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>
segment dane
tekst db "Hello World!",0Ah,0Dh,"$"
Linia 21:
int 0x21
end
</presource>
Program ten po uruchomieniu w konsoli wyświetla na ekranie tekst "Hello World!". Postaram się zrozumiale wyjaśnić o co w nim chodzi.
<source lang="asm">segment dane</source>
Oznacza, że od tego miejsca w dół definiowany jest nowy segment o nazwie "dane".
 
<source lang="asm">tekst db "Hello World!",0Ah,0Dh,"$"</source>
Ta linijka dodaje zmienną do obecnie definiowanego segmentu (w tym przypadku chodzi o segment "dane"). ''tekst'' to nazwa naszej zmiennej, ''db'' to typ naszej zmiennej (db - 1 bajt) zaś wszystko co znajduje się dalej w tej linijce to wartość początkowa dla naszej zmiennej. Jak widać jest to ciąg znaków zakończony znakami 0A0D (określające przejście do nowej linii) oraz znakiem $ oznaczającym koniec naszego ciągu (dla migrantów z C/C++ - jest to odpowiednik znaku '\0'). Gdyby zabrakło tego znaku, instrukcje operujące na naszej zmiennej, nie mogłyby określić gdzie jest jej koniec, więc wyjechałyby poza przydzielony jej obszar pamięci dopóki nie znalazłyby znaku $.
 
<source lang="asm">segment stosik stack</source>
Tworzy segment stosu o nazwie ''stosik''...
 
<source lang="asm">resb 64</source>
resb 64
... i rozmiarze 64 bajtów. Dyrektywa ''resb'' jest podobna do poznanej przed chwilą dyrektywy ''db'', tyle że tworzy konkretną ilość zmiennych bez przydzielania im wartości początkowych.
 
<source lang="asm">segment kod</source>
Analogicznie do pierwszej linijki w naszym programie, tworzy segment o nazwie ''kod''. Poniżej znajduje się jego definicja.
 
Linia 41:
Nazywa obecną pozycję słówkiem "start". Poprzedzenie ''start:'' dwoma kropkami oznacza, że chcemy aby to miejsce było początkiem naszego programu.
 
<source lang="asm">
mov ax, dane
mov dsax, axdane
mov axds, stosikax
mov ssax, axstosik
mov ss, ax
</source>
Instrukcja [[Asembler X86/Instrukcje/Transferowe#mov|mov]] kopiuje wartość drugiego parametru do pierwszego. Jako, że po starcie programu, rejestry segmentowe są niezainicjowane, musimy ręcznie przydzielić im adresy odpowiednich segmentów. W pierwszej linijce kopiujemy adres segmentu ''dane'' do rejestru ax. Następnie z rejestru ax kopiujemy go do rejestru segmentowego ds (instrukcja mov nie pozwala na bezpośrednie przydzielanie wartości rejestrom segmentowym, dlatego musieliśmy użyć rejestru ax jako pośrednika). W następnych 2 linijkach powtarzamy operację, tyle że kopiujemy adres segmentu stosik (który jest stosem naszego programu) do rejestru ss.
 
<source lang="asm">
mov dx, tekst
mov ahdx, 9tekst
mov ah, 9
int 0x21
</source>
Ten fragment kodu zacznę tłumaczyć od końca. Instrukcja [[../Instrukcje/Różne#int|int]] wywołuje ''podprogram obsługi przerwania'' o podanym numerze (poprzedzenie go przedrostkiem 0x oznacza liczbę w zapisie szesnastkowym). Podprogram ów wywołuje odpowiednią funkcję o numerze podanym w rejestrze ah (wcześniej nadaliśmy temu rejestrowi wartość 9, więc instrukcja ''int 0x21'' wywołała funkcję numer 9 przerwania numer 21 w zapisie szesnastkowym). Wywołana w tym przypadku funkcja wyświetla w konsoli ciąg znaków, którego adres znajduje w rejestrze dx (przydzieliliśmy temu rejestrowi adres naszej zmiennej ''tekst''). W efekcie na ekranie pojawi się, więc napis ''Hello World!''
 
<source lang="asm">
mov ax, 0x4C00
mov ax, dane0x4C00
int 0x21
</source>
Wywołuje funkcję przerwania 21 o numerze 0x4C00. Odpowiada ona za zakończenie działania programu i oddanie sterowania do systemu.
 
<source lang="asm">end</source>
end
Dyrektywa określająca koniec naszego kodu. Nie ma ona znaczenia i jest ignorowana, lecz tradycyjnie powinna stać na końcu pliku z kodem.