A.D.Danilecki , 66-200 Świebodzin, Polska
W tej chwili szopen@aurora.put.poznan.pl
lub szopen@arrakis.cs.put.poznan.pl
Poznań, 61-142 Ul.Św Rocha 11b
Adres powyższy aktualny na pewno do wakacji 2000 roku
Krótki wstęp do programowania z wykorzystaniem inline assemblera x86

TO JEST WERSJA 0.6 TEGO TEKSTU - CZYLI WCIĄŻ BETA PROSZE O KOMENTARZE, TYCZĄCE STYLU, EWENTUALNYCH BŁEDOW ITD JEŻELI SAM DAŁBYŚ RADE LEPIEJ NAPISAĆ NINIEJSZY DOKUMENT, PROSZE O KONTAKT A PRZEKAŻE WSZYSTKIE MATERIAŁY W MOIM POSIADANIU
18 października 1999 . Wszystkie linki zamieszczone w tekście do tego dnia istniały (were valid) o ile nie jest podane inaczej w tekście avly@castle.net - adres nieaktualny, nie znam nowego adresu



3. Punkt drugi : Zasady ogólne


NEXT - Punkt 3: Moje pierwsze programki
PREV - Punkt1 : Dlaczego nie używać assemblera?

do spisu treści

Jeżeli w środku programu w C chcemy umieścić kod w assemblerze, powinniśmy stosować jedną z dwóch składni : pierwszą, prostą :
asm ( " instrukcje assemblerowe " )
lub drugą, rozszerzoną (ang. extended asm) :
asm ("instrukcje..."

: Zmienne "wyjściowe"
: Wartości "wejściosciowe"
: Lista zmodyfikowanych rejestrów/pamięci )

W najprostszej postaci nasz pierwszy program w assemblerze może wyglądać tak:
void main()
{
asm(" nop ");
}

Program ten nic nie robi. jego działanie sprowadza się do wykonania instrukcji assemblerowej nop która jest odpowiednikiem instrukcji pustej w C, czyli nie powoduje wykonania żadnej akcji.

Teraz kilka zasad ogólnych:

  • Używamy tzw. składni AT&T, która jest standardem w świecie UNIXA i różni się dość sporo od składni intelowskiej. Jeżeli wolisz składnię intela, musisz ściągnąć nasma i programować osobne programy w assemblerze a nie tylko wstawki. Gcc nie obsługuje notacji intelowskiej.
  • Jeżeli używamy postaci prostej instrukcji assemblerowej (ang. assembler statement), to nazwy rejestrów poprzedzamy zawsze znakiem '%'. W postaci rozszerzonej nazwy rejestrów poprzedzamy zawsze dwoma znakami '%', czyli piszemy : %eax, %ecx.. w postaci prostej i %%eax, %%ecx.. w postaci rozszerzonej. Skąd to się bierze, wyjaśni się wkrótce.
  • Stałe (immediate value) zaznaczamy przedrostkiem '$', czyli piszemy: np. mov $1, %eax
  • Każdą prawie komendę można zapisać z przyrostkiem określającym typ argumentu, dopuszczalne przyrostki to 'b' (byte) 'w' (word) i 'l' (long). Jeżeli przyrostek pominiemy, gcc będzie zgadywać za nas typ operandu i może zgadnąć źle.
  • porządek operandów zawsze jest'źródło', 'przeznaczenie' , czyli jeśli chcemy wpisać liczbę jeden do rejestru eax piszemy, jak wyżej :
    movb $1,%eax
    czyli nieco inaczej niż w klasycznym assemblerze znanym z DOS-a.
  • Jeżeli chcemy operować na adresie zmiennej, piszemy $zmienna, jeżeli na jej zawartości, piszemy zmienna. Zmienna musi być globalna w programie w C. Jeżeli np zadeklarowaliśmy globalną zmienną int a, to nastepujące instrukcje mają następujący efekt : asm ("mov $1,a") ; // a=1;
  • Jeżeli adres zmiennej ładujemy do rejestru, to możemy się do zawartości zmiennej odwoływać za pomocą nawiasów, np
    asm( "mov $a,%eax\n" "mov $1,(%eax)");// a=1
    Hej! co to za '\n'? Otóż jeśli używamy kilku intrukcji assemblera w ten sposób właśnie się je oddziela. Ten znak '\n' to znak końca linii.
  • Teraz jak operować na wskaźnikach? kod w c: *(p+1) w asmie 1(%eax) zakładając że w %eax znajduje się adres zmiennej p.
  • Zasady te znajdziesz w plikach ,,info'' do as-a i gcc. Szukaj info as-> Machine Dependencies->i386. Oraz info gcc->C Extensions->Extended Asm. Także info gcc->Machine Desc->Constraints->Machine Constraints.

    To byłoby tyle jeśli chodzi o ogólne zasady. Teraz przejdziemy do pisania krótkich programików z wykorzystaniem składni rozszerzonej.



    NEXT - Punkt 3: Moje pierwsze programki
    PREV - Punkt1 : Dlaczego nie używać assemblera?