Asembler x86

Z Wikipedii, wolnej encyklopedii
Skocz do: nawigacja, szukaj

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

Język jest dodatkowo komplikowany przez obecność dwóch składni: Intela i AT&T (istnieją automatyczne translatory), oraz przez fakt, że możliwości i zasady wykorzystania tego języka są mocno zależne od systemu operacyjnego oraz kompilatora, różne są także sposoby komunikacji asemblera z innymi językami programowania.

Rejestry[edytuj | edytuj kod]

32-bitowe rejestry ogólnego przeznaczenia to:

  • EAX – Accumulator (akumulator - jego pamięć wykorzystuje arytmometr; używa się go do przechowywania wyników wielu operacji)
  • EBX – Base Register (rejestr bazowy - służy do adresowania)
  • ECX – Counter Register (rejestr licznikowy - służy jako licznik w pętli)
  • EDX – Data Register (rejestr danych - umożliwia przekaz/odbiór danych z portów wejścia/wyjścia)
  • ESP – Stack Pointer (przechowuje wskaźnik wierzchołka stosu)
  • EBP – Base Pointer (rejestr bazowy - służy do adresowania)
  • ESI – Source Index (rejestr źródłowy - trzyma źródło łańcucha danych)
  • EDI – Destination Index (rejestr przeznaczenia - przetrzymuje informacje o miejscu docelowym łańcucha danych)

Możliwy jest też dostęp do ich 16-bitowych mniej znaczących części – AX, BX, CX, DX, SP, BP, SI, DI, a w przypadku czterech pierwszych także do młodszego (Low) i starszego bajta (High) – odpowiednio AL, AH, BL, BH, CL, CH, DL, DH.

W procesorach 64-bitowych do rejestrów o długości 64 bitów odwołuje się poprzez nazwę z przedrostkiem R zamiast E - np. RAX, RBX.

Są też dostępne rejestry segmentów, określające położenie segmentów pamięci w przestrzeni adresowej (gdy procesor pracuje w trybie rzeczywistym lub wirtualnym) lub deskryptory segmentów (w trybie chronionym):

  • CS – Code Segment (segment kodu);
  • DS – Data Segment (segment danych);
  • ES – Extra Segment (dodatkowy segment danych);
  • SS – Stack Segment (segment stosu);
  • FS – dodatkowy rejestr segmentu;
  • GS – dodatkowy rejestr segmentu.

Ponadto istnieją:

  • EFLAGSrejestr flag procesora, składający się z pojedynczych bitów określających stan procesora;
  • EIP – wskaźnik adresowy na aktualnie wykonywaną instrukcję. Za jego pomocą procesor realizuje m.in. skoki, pętle, przejścia do podprogramów;
  • rejestry koprocesora arytmetycznego:
    • osiem rejestrów stosu koprocesora, oznaczanych w zależności od kompilatora jako ST0... ST7, 0... 7 lub ST(0)... ST(7);
    • rejestr stanu koprocesora;
    • rejestr stanu stosu koprocesora;
    • rejestr sterujący koprocesora;
  • rejestry kontrolne procesora CRn (n – numer rejestru);
  • rejestry debugera DRn (n – numer rejestru);
  • rejestry MMX (rozszerzenie) – 8 rejestrów 64-bitowych nazywanych mm0 ... mm7 (zamapowane na rejestry FPU);
  • rejestry SSE (rozszerzenie):
    • 8 rejestrów 128-bitowych nazywanych xmm0 ... xmm7; w trybie 64-bitowym dostępne jest 8 kolejnych rejestrów 128-bitowych xmm8 ... xmm15;
    • rejestr kontrolno-sterujący mxcsr.

Konwencje[edytuj | edytuj kod]

W składni i metodach programowania za pomocą asemblera x86 wykorzystuje się kilka ogólnie przyjętych (bądź sprzętowo narzuconych) konwencji, 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.
  • kolejność bajtów w procesorach zgodnych z x86 to little-endian (mniej znaczący bajt pierwszy).

Przykłady[edytuj | 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 elf -o beer.o beer.asm && gcc -s -o beer beer.o

Kompilacja drugiego:

gcc -s -o beer beer.s

Przykład składni Intela – program "99 Bottles of Beer" (ang. 99 butelek piwa)[edytuj | 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 | 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
Wikibooks-logo.svg
Zobacz publikację na Wikibooks:
Asembler X86

Zobacz też[edytuj | edytuj kod]