Asembler x86/Pierwszy program/GNU AS

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.