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

Usunięta treść Dodana treść
poprawki
Nie podano opisu zmian
Linia 6:
 
====DOS/Windows====
<sourcesyntaxhighlight lang="asm">
segment .data
tekst db "Hello World!",0Dh,0Ah,"$"
Linia 22:
mov ax, 4C00h
int 21h
</syntaxhighlight>
</source>
Program ten po uruchomieniu w konsoli wyświetla na ekranie tekst "Hello World!". Postaram się zrozumiale wyjaśnić, o co w nim chodzi.
<sourcesyntaxhighlight lang="asm">segment .data</sourcesyntaxhighlight>
Oznacza, że od tego miejsca w dół definiowany jest nowy segment o nazwie ".data".
 
<sourcesyntaxhighlight lang="asm">tekst db "Hello World!",0Dh,0Ah,"$"</sourcesyntaxhighlight>
Ta linijka dodaje zmienną do obecnie definiowanego segmentu (w tym przypadku chodzi o segment ".data"). ''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 0D0A (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 $.
 
<sourcesyntaxhighlight lang="asm">segment stosik stack</sourcesyntaxhighlight>
Tworzy segment stosu (''stack'') o nazwie ''stosik'' i...
 
<sourcesyntaxhighlight lang="asm">resb 64</sourcesyntaxhighlight>
... 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.
 
<sourcesyntaxhighlight lang="asm">segment .text</sourcesyntaxhighlight>
Analogicznie do pierwszej linijki w naszym programie, tworzy segment o nazwie ''.text''. Poniżej znajduje się jego definicja.
 
<sourcesyntaxhighlight lang="asm">
mov ax, .data
mov ds, ax
mov ax, stosik
mov ss, ax
</syntaxhighlight>
</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 ''.data'' 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.
 
<sourcesyntaxhighlight lang="asm">
mov dx, tekst
mov ah, 9
int 21h
</syntaxhighlight>
</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 (zakończenie go przyrostkiem h 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 21h'' 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!''. </br>'''Uwaga''': należy zaznaczyć, że ''przerwanie 21h'' oraz opisana funkcja obsługiwane są przez MS-DOS, przez co kod nie jest przenośny na inne platformy niż Windows.
 
<sourcesyntaxhighlight lang="asm">
mov ax, 4C00h
int 21h
</syntaxhighlight>
</source>
 
Wywołuje funkcję przerwania 21 o numerze 4C00h. Odpowiada ona za zakończenie działania programu i oddanie sterowania do systemu.
Linia 64:
====Linux====
Poniżej znajduje się źródło programu działającego pod systemem operacyjnym Linux.
<sourcesyntaxhighlight lang="asm">
;; hello.asm
;; Wypisuje określony ciąg 14 znaków
Linia 87:
int 0x80
; KONIEC PROGRAMU
</syntaxhighlight>
</source>
 
{{RightBox|
Linia 98:
Aby skompilować program należy wcześniej upewnić się, ża posiadamy zainstalowany kompilator NASM. Następnie należy wydać polecenie:
 
<sourcesyntaxhighlight lang=bash>
nasm -f elf hello.asm
</syntaxhighlight>
</source>
 
Otrzymamy wówczas plik '''hello.o''', który należy zlinkować do postaci wykonywalnej poleceniem:
 
<sourcesyntaxhighlight lang=bash>
ld hello.o -o hello
</syntaxhighlight>
</source>
 
Aby uruchomić tak przygotowany program należy wprowadzić:
 
<sourcesyntaxhighlight lang=bash>
./hello
</syntaxhighlight>
</source>
 
=== Goodbye world... ===