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

Usunięta treść Dodana treść
zmiana kolejności segmentów
Przemub (dyskusja | edycje)
m rewert - błędny kod asemblera
Linia 1:
<noinclude>
{{Asembler X86Asembler_X86/Nawigacja|Pierwszy program}}</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
.globlglobal _start
_start:
movl $4, %eax
Linia 16 ⟶ 12:
movl $napis, %ecx
movl $len, %edx
int $80h0x80
movl $1, %eax
xorlmovl %ebx$0, %ebx
int $80h0x80
 
.data
napis:
.string "Hellohello Worldworld!\10n"
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''':
<source lang="bash">
ld hello.o -o hello
 
chmod +x hello
</source>
Teraz dopiero program jest wykonywalny. Możesz go uruchomić w konsoli wydając polecenie w katalogu w którym jest program:
<source lang="bash">
./hello
</source>
Omówię teraz po kolei kod tego programu:
<source lang="asm">
.data
</source>
Oznacza, że dalsza część programu będą stanowiły dane, potrzebne do wykonania instrukcji.
<source lang="asm">
napis:
</source>
Tworzymy etykietę napis.
<source lang="asm">
.string "Hello World!\10"
</source>
Tworzymy napis, który będzie widoczny pod adresem etykiety "napis", o treści "Hello World!" zakończonej znakiem nowej linii 10 (0A szesnastkowo).
<source lang="asm">
len = . - napis
</source>
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.
<source lang="asm">
.text
.globlglobal _start
</source>
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).
<source lang="asm">
_start:
</source>
"Zawartość" etykiety _start.
<source lang="asm">
Linia 68 ⟶ 43:
movl $napis, %ecx
movl $len, %edx
int $80h0x80
</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 Worldworld!".
<source lang="asm">
movl $1, %eax
xorlmovl %ebx$0, %ebx
int $80h0x80
</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 lang="bashasm">
.string "Hellohello Worldworld!\10n"
</source>
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.
 
=== Hello World! (wersja DOS) ===
Linia 83 ⟶ 70:
.data
napis:
.string "Hello World!\13\10n$"
.text
.globl _start
Linia 89 ⟶ 76:
movw $napis, %dx
movb $9, %ah
int $21h0x21
movw $4C00h0x4C00, %ax
int $21h0x21
</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 x86X86/Narzędzia|Narzędzia]]|
[[Asembler x86X86/Podstawy|Podstawy]]|
}}</noinclude>