Asembler x86/Pierwszy program/GNU AS: Różnice pomiędzy wersjami
Usunięta treść Dodana treść
zmiana kolejności segmentów |
m rewert - błędny kod asemblera |
||
Linia 1:
<noinclude>
{{
=== Hello world! (POSIX) ===
Oto przykład programu, napisanego w asemblerze GNU, wyświetlającego napis "Hello World!" w systemie zgodnym z normą POSIX, uruchomionym na komputerze typu i386:
<source lang="asm">
.data▼
napis:▼
.string "Hello World!\10"▼
len = . - napis▼
.text
.
_start:
movl $4, %eax
Linia 16 ⟶ 12:
movl $napis, %ecx
movl $len, %edx
int $
movl $1, %eax
int $
▲ .data
▲ napis:
▲ len = . - napis
</source>
Aby skompilować powyższy program musisz wydać następujące polecenia. Najpierw trzeba kod zasemblować aby uzyskać plik obiektowy '''*.o''':
<source lang="bash">▼
as hello.s -o hello.o
</source>▼
Tak otrzymany kod wynikowy, musisz poddać działaniu linkera '''ld''':
ld hello.o -o hello
Teraz dopiero program jest wykonywalny. Możesz go uruchomić w konsoli wydając polecenie w katalogu w którym jest program:
./hello
Omówię teraz po kolei kod tego programu:
.data▼
Oznacza, że dalsza część programu będą stanowiły dane, potrzebne do wykonania instrukcji.▼
napis:▼
.string "Hello World!\10"▼
Tworzymy napis, który będzie widoczny pod adresem etykiety "napis", o treści "Hello World!" zakończonej znakiem nowej linii 10 (0A szesnastkowo).▼
len = . - napis▼
Jest to zmienna, która zawiera długość napisu. Kropka oznacza "aktualny adres" w pamięci (w naszym przypadku koniec napisu), a "napis" - adres etykiety, pod którą zawarto początek napisu. Różnica koniec - początek daje długość napisu, która jest niezbędna, aby program wypisał na ekranie dokładnie tyle znaków, ile liczy sobie napis.▼
.text
.
Ten fragment informuje asembler, że informacje tutaj zawarte są kodem programu, a etykieta _start ma być etykietą globalną (umożliwi to m.in. wykorzystanie tej etykiety jako głównej funkcji programu).
_start:
"Zawartość" etykiety _start.
<source lang="asm">
Linia 68 ⟶ 43:
movl $napis, %ecx
movl $len, %edx
int $
</source>
Instrukcja mov (l na końcu to informacja, że zapisujemy dane do 32-bitowego rejestru) przenosi dane do odpowiednich rejestrów - w EAX znajdzie się numer funkcji systemowej (4 - write), EBX - plik docelowy (1 - standardowe wyjście), w ECX - adres, pod którym znajdują się dane do wyświetlenia oraz EDX - długość napisu. Instrukcja int powoduje wywołanie przerwania i realizację przez system operacyjny odpowiedniej czynności - w tym przypadku wypisanie na ekran "Hello
<source lang="asm">
movl $1, %eax
int $
</source>
Tym razem wywołamy funkcję exit, której argumentem będzie 0. W ten sposób "poprosimy" system operacyjny o zakończenie pracy programu.
▲ .data
▲Oznacza, że dalsza część programu będą stanowiły dane, potrzebne do wykonania instrukcji.
▲ napis:
Nie używamy .globl - etykieta napis ma być widoczna tylko dla kodu programu i nie jest istotna w procesie tworzenia pliku wykonywalnego.
▲</source>
▲Tworzymy napis, który będzie widoczny pod adresem etykiety "napis"
▲ len = . - napis
▲Jest to zmienna, która zawiera długość napisu. Kropka oznacza "aktualny adres" w pamięci (w naszym przypadku koniec napisu), a "napis" - adres etykiety, pod którą zawarto początek napisu. Różnica koniec - początek daje długość napisu, która jest niezbędna, aby program wypisał na ekranie dokładnie tyle znaków, ile liczy sobie napis.
=== Hello World! (wersja DOS) ===
Linia 83 ⟶ 70:
.data
napis:
.string "Hello World!\
.text
.globl _start
Linia 89 ⟶ 76:
movw $napis, %dx
movb $9, %ah
int $
movw $
int $
</source>
Przyglądając się składni GNU możesz zauważyć, jak bardzo różni się ona od składni NASM lub MASM.
Linia 97 ⟶ 84:
<noinclude>{{Nawigacja|Asembler X86|
[[Asembler
[[Asembler
}}</noinclude>
|