Asembler x86


Asembler x86 w encyklopedii

Z Wikipedii, wolnej encyklopedii Przejdź do nawigacji Przejdź do wyszukiwania

Asembler x86 – język programowania z rodziny asemblerów do komputerów klasy PC, które posiadają architekturę głównego procesora zgodną z x86.

W rzeczywistości jest to kilka różnych języków używanych do zapisu tych samych instrukcji i dyrektyw, różniących się składnią.

Trzy najpopularniejsze składnie to:

  • składnia Intel/Microsoft - używana w asemblerze MASM firmy Microsoft i w przykładach zamieszczonych w dokumentacji firmowej procesorów Intel rodziny x86; dawniej korzystała z niej większość narzędzi programistycznych dla systemów DOS i Windows.
  • składnia NASM - używana w asemblerze NASM, podobna do składni Intel/Microsoft, ale uproszczona i pozbawiona niejednoznaczności zapisu
  • składnia AT&T - używana w systemach UNIX i uniksopodobnych.

Ponieważ kod w języku asemblera jest niskopoziomowy, istnieją automatyczne translatory między obydwoma składniami.

Spis treści

Konwencje | edytuj kod

W składni i metodach programowania za pomocą danej składni asemblera x86 wykorzystuje się kilka ogólnie przyjętych (bądź sprzętowo narzuconych) konwencji. Przykładowo dla składni Intel/Microsoft i NASM są to m.in.:

  • operand docelowy instrukcji jest podawany jako pierwszy z operandów, np. instrukcja:
mov ax, bx 
spowoduje wpisanie zawartości rejestru BX do rejestru AX. (w przypadku „składni AT&T” jest odwrotnie)
  • kolejność bajtów w procesorach zgodnych z x86 to little-endian (mniej znaczący bajt pierwszy).

Różnice pomiędzy NASM a Intel/Microsoft | edytuj kod

Oprócz prostszego zapisu dyrektyw i atrybutów, NASM eliminuje niejednoznaczności zapisu składni Intel/Microsoft.

MASM (Intel/Microsoft) | edytuj kod

W składni MASM interpretacja argumentu operacji przez asembler zależy od sposobu jego wcześniejszego zdefiniowania - w przykładzie poniżej argumenty x i y mają różną interpretację, a zapis [x] jest interpretowany podobnie do zapisu y.

x equ 1000 ; definicja symbolu x o wartości 1000 y dd 123 ; definicja zmiennej y o wartości początkowej 123, zajmującej 32 bity mov eax, x ; ładuje stałą 1000 mov ebx, [x] ; ładuje wartość danej spod adresu 1000 mov edx, y ; ładuje WARTOŚĆ zmiennej y mov edx, [y] ; ładuje wartość zmiennej y, tak samo, jak linia powyżej mov ecx, offset y ; ładuje adres zmiennej y movzx eax, byte ptr y ; ładuje bajt spod adresu y z rozszerzeniem zerami do 32 bitów mov eax, 8[ebp] ; ładuje daną spod adresu ebp+8 

NASM | edytuj kod

Każde odwołanie do danej w pamięci jest w składni NASM oznaczone nawiasami kwadratowymi. Brak nawiasów oznacza stałą lub adres.

x equ 1000 ; definicja symbolu x o wartości 1000 y dd 123 ; definicja zmiennej y o wartości początkowej 123, zajmującej 32 bity mov eax, x ; ładuje stałą 1000 mov ebx, [x] ; ładuje wartość danej spod adresu 1000 mov edx, y ; ładuje ADRES zmiennej y mov edx, [y] ; ładuje wartość zmiennej y movzx eax, byte [y] ; ładuje bajt spod adresu y zrozszerzeniem zerami do 32 bitów mov eax, [ebp+8] ; ładuje daną spod adresu ebp+8 

Przykłady programów | edytuj kod

Poniżej dwa przykłady, możliwe do skompilowania w systemie Linux: pierwszy można skompilować przy użyciu nasm, drugi – asemblerem z binutils (lub samym gcc, jeśli ma on rozszerzenie .s). Linkowanie w obu przypadkach gcc lub ręcznie.

Kompilacja pierwszego:

nasm -f elf32 beer.asm && gcc -s -o beer beer.o 

Kompilacja drugiego:

gcc -s -o beer beer.s 

Przykład składni NASM – program "99 Bottles of Beer" (ang. 99 butelek piwa) | edytuj kod

global main extern printf section .data beer db "%d bottles of beer on the wall, %d bottles of beer." db 0x0a db "Take one down and pass it around, %d bottles of beer." db 0x0a db 0 main: mov ecx, 99 _loop: dec ecx push ecx push ecx inc ecx push ecx push ecx push beer call printf add esp,16 pop ecx or ecx, ecx jne _loop xor eax,eax ret 

Przykład składni AT&T – ten sam program - "99 Bottles of Beer" (ang. 99 butelek piwa) | edytuj kod

.section .rodata .beer: .ascii "%d bottles of Beer on the wall, %d bottles of Beer.\n" .asciz "Take one down and pass it around, %d bottles of Beer.\n" .text .global main main: mov $99, %ecx loop: dec %ecx push %ecx push %ecx inc %ecx push %ecx push %ecx pushl $.beer call printf add $16,%esp pop %ecx or %ecx, %ecx jne loop xorl %eax,%eax ret 


Zobacz też | edytuj kod

Na podstawie artykułu: "Asembler x86" pochodzącego z Wikipedii
OryginałEdytujHistoria i autorzy