Program
Początek sekcji danych (segment data*). W cpp zmienne deklarować można bezpośrednio w kodzie:
int main()
{
//kod
int x;
//kod
return 0;
}
W asemblerze tak nie jest. Wszystkie zmienne deklaruje się w sekcji danych.
section .data
napis db "Hello world", 0ah
dnapis equ $-napis
db oznacza, ze chcemy zadeklarować bajt. Jednak db jest na tyle wyjatkowe, ze pozwala deklarować nie tylko pojedyncze bajty, ale też całe łańcuchy znaków, co zresztą można dostrzec w powyższym przykładzie. Można także deklarować innych rozmiarów zmienne:
db (byte) 1bajt
dw (word) 2 bajty
dd (dword) 4 bajty
pw 6 bajtów
dq 8 bajtów
dt 10 bajtów
Tajemniczy ciąg znaków 0ah (lub inaczej zapisane 0xa), to zapisana wartość w systemie szesnastkowym (hexadecymalnym, hex), w ascii oznacza ona, uwaga: enter. Czyli 0ah to po prostu zwykły koniec linii.
No dobra, ale co jest w zmiennej dnapis? Długość napisu. Dyrektywa equ oznacza, że jest to stała (const, wartość się nie zmienia). $-napis to długość napisu.
section .text
global _start
_start:
Section .text to sekcja kodu (segment code*). Umieszcza się tu kod programu, czyli wywołania funkcji, pętle, itp., itd.
global _start to informacja, ktorej wymaga linker ld. Jest to symbol globalny, który pokaże linkerowi, gdzie jest start programu. Linijka _start: służy właśnie do takiego pokazania.
mov eax, 4
mov ebx, 1
mov ecx, napis
mov edx, dnapis
int 80h
Eax, ebx, ecx i edx to rejestry ogólnego przeznaczenia. Instrukcja mov służy do kopiowania wartości. W pierwszej linijce do rejestru eax jest kopiowana wartość 4. Dlaczego kopiowana a nie przypisywana? Bo bezpośrednio do rejestru nie można wpisać wartosci. Dlatego się ją kopiuje. Ale co to za wartości 4, 1 (bo napis dnapis chyba oczywiste)? Otóż to spójrz na ostatnią linijkę. Int 80h. Jest to wywołanie przerwania systemowego. Czyli tak jakby wywołanie funkcji. Funkcji, która ma 3 argumenty (od ebx do edx). Eax "mówi", którą funkcję systemową wywołać. W tym przypadku jest to 4 (sys_write), czyli zapis do pliku. Zapis do pliku? Przecież to miał być tradycyjny hello world, piszący tekst na ekranie... Bo będzie. Otóż to rejestr ebx zawiera wartość 1, czyli standardowe wyjście (std out), w tym przypadku ekran (konsoli). Ecx zawiera napis, który ma zostać wyswietlony, a edx jego długość. Wszystko pięknie, ale program trzeba jeszcze zamknąć...
mov eax, 1
mov ebx, 0
int 80h
Eax- funkcja nr 1 to sys_exit
Ebx- wyzerowany, aby nie było komplikacji...
To teraz kod całego programu:
section .data
napis db "Hello world", 0ah
dnapis equ $-napis
section .text
global _start
_start:
mov eax, 4
mov ebx, 1
mov ecx, napis
mov edx, dnapis
int 80h
mov eax, 1
mov ebx, 0
int 80h
Całość zapisujemy (np. hello.asm), następnie kompilujemy:
I do linkera:
ld hello.o -o hello
I uruchamiamy:
./hello
I widzimy radosny komunukat:
Mam nadzieję że dzięki temu poradnikowi polubicie asembleraZachęcam do eksperymentowania z rożnymi napisami i nazwami zmiennych
*elementy zaznaczone gwiazdką nie są konieczne do skumania na tym etapie