Asembler x86/Pierwszy program/GNU AS

Z Wikibooks, biblioteki wolnych podręczników.

Pierwszy program

GNU As
FASM
MASM
NASM

Hello world! (POSIX)[edytuj]

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:

 .text
 .global _start
 _start:
        movl $4, %eax
        movl $1, %ebx
        movl $napis, %ecx
        movl $len, %edx
        int $0x80
 
        movl $1, %eax
        movl $0, %ebx
        int $0x80
 
 .data
 napis:
        .string "hello world!\n"
 len = . - napis

Aby skompilować powyższy program musisz wydać następujące polecenia. Najpierw trzeba kod zasemblować aby uzyskać plik obiektowy *.o:

 as hello.s -o hello.o

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:

.text
.global _start

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.

 movl $4, %eax
 movl $1, %ebx
 movl $napis, %ecx
 movl $len, %edx
 int $0x80

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 world!".

 movl $1, %eax
 movl $0, %ebx
 int $0x80

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.

 .string "hello world!\n"

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)[edytuj]

Analogiczny program, który kompiluje się pod systemem DOS(będąc emulowanym pod Windowsem) mógłby wyglądać np. tak:

 .data
 napis:
      .string "Hello World!\n$"
 .text
 .globl _start
 _start:
        movw $napis, %dx
        movb $9, %ah
        int $0x21
        movw $0x4C00, %ax
        int $0x21

Przyglądając się składni GNU możesz zauważyć, jak bardzo różni się ona od składni NASM lub MASM.