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

Usunięta treść Dodana treść
Lethern (dyskusja | edycje)
m nawigacja
→‎Hello World!: pod linuxa
Linia 3:
 
=== Hello World! ===
Zacznijmy od dawki kodu, aby w ogóle mieć pojęcie, jak wygląda kod w języku Asembler. 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!). Uwaga: jak już wcześniej było wspomniane, konkretny kod zapisany w Asemblerze wykonuje się na konkretnej maszynie. Poniższy program uruchomi się tylko pod systemem WindowsLinux.
<source lang="asm">
format MZ
 
entry kod.text:start_start
 
segment dane.data
tekst db "Hello World!",0Ah,0Dh,"$\n"
 
segment kod.text
start_start:
mov ax, dane.data
mov ds, ax
mov dxecx, tekst
mov aheax, 94
intinc 0x21ebx
mov axedx, 0x4C0013
int 0x2180h
mov eax, 1
dec ebx
int 80h
</source>
A teraz postaram się zrozumiale wyjaśnić poszczególne fragmenty kodu.
Linia 28 ⟶ 31:
Informuje asemblera FASM, że ma utworzyć dosowy plik wykonywalny MZ.
 
<source lang="asm">entry kod.text:start_start</source>
Powiadamia gdzie znajduje się adres wejściowy dla pliku wykonywalnego (z którego adresu ma rozpocząć się wykonywanie kodu); ''kod.text'' jest to nazwa segmentu zaś po dwukropku znajduje się nazwa etykiety która jest przypisana do żądanego adresu (zarówno wykorzystany tu segment jak i etykieta są zdefiniowanie poniżej).
 
<source lang="asm">segment dane.data</source>
Tworzy segment o nazwie ''dane'' i przechodzi do jego definiowania.
 
<source lang="asm">tekst db "Hello World!",0Ah,0Dh,"\n$"</source>
Tworzy wewnątrz obecnie definiowanego segmentu (tj. segmentu ''dane'') ciąg "Hello World" zakończony znakiem nowej linii oraz znakiem dolara (znak dolara w funkcjach dosowych oznacza koniec ciągu znaków dlatego musi się tu znaleźć).
 
<source lang="asm">start:_start</source>
Definiuje etykietę o nazwie ''start_start''.
<source lang="asm">
mov ax, dane.data
mov ds, ax
</source>
Linia 47 ⟶ 50:
 
<source lang="asm">
mov dxecx, tekst
mov aheax, 94
mov ebx, 1
int 0x21
mov edx, 13
int 0x2180h
</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 (poprzedzeniezakończenie go przedrostkiemprzyrostkiem 0xh oznacza liczbę w zapisie szesnastkowym). Podprogram ów wywołuje odpowiednią funkcję o numerze podanym w rejestrze aheax (wcześniej nadaliśmy temu rejestrowi wartość 94, więc instrukcja ''int 0x2180h'' wywołała funkcję numer 94 przerwania numer ''2180 w zapisie szesnastkowym''). Wywołana w tym przypadku funkcja wyświetla w konsoli ciąg znaków, którego adres znajduje w rejestrze dxecx (przydzieliliśmy temu rejestrowi adres naszej zmiennej ''tekst'') do napotkania znaku o numerze w rejestrze edx. W efekcie na ekranie pojawi się więc napis ''Hello World!''. </br>'''Uwaga''': należy zaznaczyć, że ''przerwanie 21h80h'' oraz opisana funkcja obsługiwane są przez MS-DOSUnix, przez co kod nie jest przenośny na inne platformy nizniż WindowsLinux.
 
<source lang="asm">
mov axeax, 0x4C001
dec ebx
int 0x2180h
</source>
Wywołuje funkcję przerwania 2180 o numerze 0x4C001. Odpowiada ona za zakończenie działania programu i oddanie sterowania do systemu za pomocą kodu wyjścia w rejestrze EBX (instrukcja dec zmniejsza wartość o 1, przez co ebx jest teraz równy 0).
Jeszcze tylko na koniec taka mała ciekawostka na temat wartości zapisywanej do rejestru AX. Zapisujemy tutaj 0x4C00. Dolny bajt - 0x00 oznacza kod błędu jaki zwracamy systemowi operacyjnemu. Jeśli dalibyśmy np 0x4C13 to nasz program zwrócił by kod błędu równy własnie liczbie 0x13.
 
<noinclude>