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

Usunięta treść Dodana treść
błąd
ELF
Linia 5:
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 Linux.
<source lang="asm">
format ELF
 
entry .text:_start
Linia 13 ⟶ 14:
segment .text
_start:
movxor dsebx, axebx
mov ax, .data
mov ds, ax
mov ecx, tekst
mov eax, 4
inc ebx
mov edx, 13
int 80h80H
mov eax, 1
decxor ebx, ebx
int 80h80H
</source>
A teraz postaram się zrozumiale wyjaśnić poszczególne fragmenty kodu.
 
<source lang="asm">format ELF</source>
Informuje asembler, że ma utworzyć linuxowy plik wykonywalny ELF.
<source lang="asm">entry .text:_start</source>
Powiadamia gdzie znajduje się adres wejściowy dla pliku wykonywalnego (z którego adresu ma rozpocząć się wykonywanie kodu); ''.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 .data</source>
Tworzy segment o nazwie ''dane.data'' i przechodzi do jego definiowania.
 
<source lang="asm">tekst db "Hello World!\n$"</source>
Tworzy wewnątrz obecnie definiowanego segmentu (tj. segmentu ''dane.data'') ciąg "Hello World" zakończony znakiem nowej linii.
 
<source lang="asm">_start</source>
Definiuje etykietę o nazwie ''_start''.
<source lang="asm">
mov ax, .data
mov ds, ax
</source>
Kopiuje adres segmentu ''dane'' do rejestru AX a następnie z rejestru AX do rejestru DS (do rejestrów segmentowych nie można przypisywać bezpośrednio adresów dlatego musiał tu pośredniczyć jakiś inny rejestr).
 
<source lang="asm">xor ebx, ebx</source>
 
Wykonuje na rejestrze EBX operację [[w:XOR|XOR]]. Prawy operand to rejestr EBX.
Wynika że, następujące działanie (niech daszek ^ oznacza operację [[w:XOR|XOR]]):
EBX ^ EBX = 0
Tak więc <tt>xor ebx, ebx</tt> zeruje rejestr EBX.
<source lang="asm">
mov ecx, tekst
Linia 52 ⟶ 53:
int 80h
</source>
Ten fragment kodu zacznę tłumaczyć od końca. Instrukcja [[..Asembler X86/Instrukcje/Różne#int|int]] wywołuje ''podprogram obsługi przerwania'' o podanym numerze (zakończenie go przyrostkiem hH oznacza liczbę w zapisie szesnastkowym). Podprogram ów wywołuje odpowiednią funkcję o numerze podanym w rejestrze eax (wcześniej nadaliśmy temu rejestrowi wartość 4, więc instrukcja ''int 80h80H'' wywołała funkcję numer 4 przerwania numer ''80 w zapisie szesnastkowym''). Wywołana w tym przypadku funkcja wyświetla w konsoli ciąg znaków, którego adres znajduje w rejestrze ecx (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 80h'' oraz opisana funkcja obsługiwane są przez Unix, przez co kod nie jest przenośny na inne platformy niż Linux.
 
<source lang="asm">