Internet Info, s.r.o. Lupa Měšec Podnikatel Root Zdroják DigiZone Slunečnice Vitalia TopDrive KupDnes Navrcholu NovýTarif Dobrý web Weblogy Woko Jagg Computer.cz SK: MojeLinky

Hlavní navigace

Když céčko nestačí: GAS

Potřebujeme-li v kritické sekci programu napsaném v jazyce C nebo C++ maximální výkon, jako poslední možnost se jeví přepsat tuto kritickou část do assembleru, tedy přímo do jazyka symbolických instrukcí dané platformy. V následujícím článku se podíváme na to, jaké máme na Linuxu možnosti, použijeme-li assembler vkládaný přímo do kódu jazyka C překladače gcc, tedy GNU Assembler.

Tweetni to Twitter Jaggni to! Jagg Del.icio.us Delicious

Než se odhodnáte k tomuto odvážnému kroku, je nutno zvážit, zdali je opravdu nutné assembler použít. Jistě, s trochou šikovnosti můžete skutečně urychlit vykonávaný kód, zejména tam, kde se zpracovávají větší množství dat (audio, video atd). Je dobré se na to ale podívat z jiné stránky.

Programování v assembleru je značně nebezpečné a pracné. Zatímco kompilátor jazyka C odhalí při překladu spoustu chyb, jazyk symbolických instrukcí spolyká všechno, co je syntakticky správně. Odhalování následných chyb je pak noční můrou všech programátorů. Další značnou nevýhodou je nepřenositelnost kódu, a to i v případě, že zůstává cílová platforma (např. Intel) stejná. Pokud budete chtít program přeložit na jiné platformě, počítejte s tím, že budete někdy muset vynaložit nemalé úsilí, aby se program úspěšně přeložil. Navíc, optimalizační algoritmy jsou dnes na tak vysoké úrovni, že assembler v normálním případě takřka potřebovat nebudete.

Jelikož platí, že budete muset přepisovat do assembleru jen malé části aplikace, je proto nejvhodnější použít inline assembler. Je to takový assembler, který se mixuje přímo s jazykem C a kompilátor mu rozumí a správně jej vloží do generovaného kódu. Evidentně tedy záleží na kompilátoru jazyka C, který chcete použít. Nejpoužívanějším kompilátorem v Linuxu je překladač jazyka C z balíku GCC (GNU Compiler Collection) s příhodným názvem gcc, který podporuje assembler GAS (GNU Assembler).

Programátoři zvyklí na programování v systémech DOS/Windows pravděpodobně zažijí malý šok (já sám jsem začínal v DOSu). Hned první ranou bylo pro mě zjištění, že GAS používá syntaxi AT&T, která se od intelovské syntaxe značně liší. Druhé zjištění však bylo ještě horší. Vkládání assembleru do kódu C/C++ je implementováno dosti nemotorně, pravděpodobně z důvodů přenositelnosti.

Svět UNIXu tu byl dávno před firmami Intel nebo Microsoft. Tehdejší UNIXy se provozovaly zřejmě hodně na procesorech Motorola, které podporovaly právě tuto syntaxi, vyvinutou v laboratořích AT&T. Od intelovské se liší zejména v těchto věcech:

  • parametry všech instrukcí jsou obráceně (zdroj, cíl)
  • registry musí být uvozeny pomocí znaku % (procento)
  • každé konstantě nebo číslu musí předcházet znak $ (dolar)
  • většina instrukcí končí znaky b, w, l, které udávají šířku parametru (byte, word, longword)
  • syntaxe adresování paměti je zcela odlišná (kulaté závorky místo složených)

Samozřejmě, že rozdílů je více, ale tyto jsou ty nejmarkantnějsí. Na ostatní narazíte méně často. Současné verze GASu již umožňují zapnout Intel syntaxi, ovšem vzhledem k tomu, že intelovská syntaxe je v GASu mizerně dokumentována, a s přihlédnutím na to, že veškeré tutoriály, návody či dokonce zdrojové kódy programů (či jádra) jsou v AT&T syntaxi, doporučuji raději tu od Intelu v GASu nepoužívat. Zvyk je zvyk a bývá to leckdy velmi těžké se přizpůsobit.

Další překážkou však může být způsob, jakým se tento assembler vkládá do zdrojového kódu C. Všechno se totiž děje nepříjemným způsobem – pomocí řetězcových literálů. Co řádek, to symbolická instrukce, takže je oddělujete pomocí \n. Pokud budete používat normální odřádkování, kompilátor vás bude varovat, že se odřádkování v řetězci nemá používat. Můžete alternativně použít středník, pokud programujete pro Intel. Programátoři zvyklí na tasm nebo masm si musejí navíc dávat pozor na to, že musejí vrátit stav registrů na konci bloku tak, jak byl na začátku, a odkazy na proměnné v C musejí explicitně zadávat ručně. Překladač gcc navíc kontroluje syntaxi minimálně (resp. vůbec, gas minimálně), jakékoliv překlepy jsou ztrestány množstvím ilegálního kódu a nesmyslných chybových hlášení. Jejich případné dohledávání je hotové peklo. Takové nepřepnutí na konci bloku zpět na AT&T syntaxi je opravdovou lahůdkou.

Samotná syntaxe inline assembleru v  gcc je následující:
asm ("assembler kód"
: mapování výstupních proměnných
:
mapování vstupních proměnných
: seznam modifikovaných registrů, případně paměti);

Za klíčovým slovem asm (resp. __asm__) následuje vlastní kód v GAS assembleru. Pokud hodláte použít proměnné z Céčka (to dělat nemusíte, poslední tři „parametry“ jsou totiž nepovinné), musíte je vyjmenovat v další části příkazu a říci optimalizátoru, jak je umístit. Nakonec je nutno dodat seznam registrů, které hodláte měnit, aby kompilátor zajistil jejich odložení na zásobníku. Ještě bych dodal, že na vstupní/výstupní proměnné se odkážete pomocí %1...%n a znaky procenta, které uvozují registry, musíte zdvojit.

Dalo by se říci, že programování v inline GASu se doporučuje zkušenějším jedincům. Pokud tedy s assemblerem začínáte nebo přecházíte-li z Windows, doporučuji spíše assemblery basm nebo nasm, o kterých bude řeč později. Následuje malá ochutnávka, co od inline assembleru GAS můžete očekávat.

Tabulka č. 389
#include <stdio.h>

int att_faktorial(int n) {
int result;

asm ("
    movl $1, %%eax      /* a = 1*/
    movl %1, %%ecx      /* c = n */
    cmp $0, %%ecx       /* if (c == 0) */
    jne aiter           /*   goto iter */
    incl %%ecx          /* c++ */
    aiter:              /* do { */
    imull %%ecx, %%eax  /*   c *= a */
    loop aiter          /* } while (c >= 0) */
    movl %%eax, %0"     /* result = a */
    : "=g" (result)
    : "g" (n)
    : "%eax", "%ecx", "memory"
  );

return result;
}

int intel_faktorial(int n) {
int result;

asm volatile ("
    .intel_syntax noprefix
    .arch i386
    xor eax, eax
    inc eax         /* eax = 1*/
    mov ecx, %1     /* ecx = n */
    cmp ecx, 0      /* if (ecx == 0) */
    jne iiter       /*   goto iter */
    inc ecx         /* ecx++ */
    iiter:          /* do { */
    imul eax, ecx   /*   ecx *= eax */
    loop iiter      /* } until (ecx >= 0) */
    mov %0, eax     /* result = eax */
    .att_syntax"    /* NUTNE PREPNOUT ZPET! */
    : "=&r" (result)
    : "r" (n)
    : "%eax", "%ecx", "memory"
  );

return result;
}

int main(int argc, char* argv[])
{
  printf("Faktorial 6 je %d\n",
    att_faktorial(6));
  printf("Faktorial 6 je %d\n",
    intel_faktorial(6));
return 0;
}
faktorial.c: faktoriál v inline assembleru GAS s AT&T i Intel sntaxí

Pokusím se v krátkosti přiblížit, jak probíhá předávání proměnných z jazyka C do assembleru. Překladač zamění všechny výskyty %0 (jež nahradí proměnnou result) a %1 (nahrazuje proměnnou n). Musíte mu ale sdělit, jak to má udělat. Ve většině případů vás to moc zajímat nebude, použijete tedy modifikátor "g", který kompilátoru říká, udělej to nejrychleji, jak umíš. V tomto případě může kompilátor zástupný znak nahradit třeba adresou v paměti. Můžete také použít "r", čímž naznačujete, že to musí být registr, ale je vám jedno, který, což se hodí tehdy, pokud budete používat zástupný znak ( %1) ve smyčce. Pomocí "&" zajistíte, aby se registry pro jednotlivé proměnné lišily. Konečně pomocí "a", "b", "c", "d" můžete registr specifikovat konkrétně. Pro kompletní pochopení doporučuji přeložit s parametrem - S takto: gcc -S faktorial.c. Překladač vytvoří soubor faktorial.s , který obsahuje kompletní výpis celého programu. Sekce, které programátor vytvořil inline, jsou označeny.

Bývá zvykem kompilátoru sdělit, ať se blok v assembleru nepokouší optimalizovat. To se hodí tehdy, jsme-li si jisti, že náš kód je nejrychlejší možný. Právě k tomu slouží specifikátor volatile. Zbytek programu již nepotřebuje vysvětlení, zajistí totiž výpis faktoriálu na konzoli. Při experimentování doporučuji hojně používat parametr -S a následně si prohlížet vygenerovaný assembler.

GAS samozřejmě umí zpracovávat soubory i externě. Mívají obyčejně příponu .s, a jak sem nastínil výše, můžete si takový výpis nechat vygenerovat překladačem gcc pomocí parametru -S. Veliká výhoda je, že takto vygenerovaný kód lze pomocí GASu znovu přeložit, takže můžete směle experimentovat. Nutno podotknout, že v čistém assembleru voláte přímo služby operačního systému, jejichž čísla musíte zkrátka znát nebo použít sadu maker.

davame_internetu_obsah
       

GAS obsahuje vlastní preprocesor gasp, který umožňuje definovat makra, a tak usnadňuje psaní programů v čistém assembleru. Syntaxe je ale dost šílená. Mám za to, že byla vytvořena spíše pro stroje než pro lidi a vůbec bych se nedivil, kdyby GCC gasp přímo využíval při kompilaci kódu v jazyce C.

www.manualy.sk
ibm.com

Školení: Linux – Firewall, Samba, VPN

Na třídenním školení se naučíte nainstalovat a spravovat Firewall a Router, SAMBA Doménový a Souborový server. Dále si zprovozníte vlastní, zabezpečený VPN server.

Podrobnější informace a přihláška

Ohodnoťte jako ve škole:
Průměrná známka 3,15

Přehled názorů

pomoc
lama 25. 2. 2003 05:07
Nový
└ 
Re: pomoc
martin hassman 25. 2. 2003 11:40
Nový
Ad syscally
kvr 25. 2. 2003 07:27
Nový
└ 
Re: Ad syscally
lzap 25. 2. 2003 08:00
Nový
 
└ 
OT, nalezi k dalsimu threadu
kedluben 27. 2. 2003 00:16
Nový
 
 
├ 
Re: OT, nalezi k dalsimu threadu
Miloslav Ponkrác 27. 2. 2003 16:03
Nový
 
 
│
└ 
Re: OT, nalezi k dalsimu threadu
kedluben 27. 2. 2003 17:46
Nový
 
 
│
 
└ 
Re: OT, nalezi k dalsimu threadu
Miloslav Ponkrác 28. 2. 2003 12:56
Nový
 
 
│
 
 
└ 
Re: OT, nalezi k dalsimu threadu
Jerry 29. 11. 2006 19:02
Nový
 
 
└ 
Děkuji za reklamu
Miloslav Ponkrác 27. 2. 2003 16:07
Nový
Dojem
Miloslav Ponkrác 25. 2. 2003 08:40
Nový
└ 
Re: Dojem
anonymní uživatel 25. 2. 2003 09:23
Nový
 
├ 
Re: nasm
Miloslav Ponkrác 25. 2. 2003 10:06
Nový
 
└ 
Re: Dojem
Miloslav Ponkrác 25. 2. 2003 10:13
Nový
 
 
├ 
Re: Dojem
kato 25. 2. 2003 10:47
Nový
 
 
│
└ 
Re: Dojem
Miloslav Ponkrác 25. 2. 2003 11:41
Nový
 
 
│
 
└ 
Re: Dojem
MIroslav Kokrda 25. 2. 2003 13:03
Nový
 
 
│
 
 
└ 
Re: Dojem
Miloslav Ponkrác 25. 2. 2003 13:34
Nový
 
 
│
 
 
 
└ 
Re: Dojem... a spatny k tomu ;-)
Richard Richter 25. 2. 2003 14:52
Nový
 
 
│
 
 
 
 
└ 
Re: Dojem... a spatny k tomu ;-)
Miloslav Ponkrác 25. 2. 2003 15:30
Nový
 
 
│
 
 
 
 
 
└ 
Re: Dojem... a spatny k tomu ;-)
Pichi 25. 2. 2003 17:02
Nový
 
 
│
 
 
 
 
 
 
└ 
Re: Dojem... a spatny k tomu ;-)
Miloslav Ponkrác 26. 2. 2003 09:08
Nový
 
 
│
 
 
 
 
 
 
 
└ 
Re: Dojem... a spatny k tomu ;-)
anonymní uživatel 26. 2. 2003 09:28
Nový
 
 
│
 
 
 
 
 
 
 
 
└ 
Re: Dojem... a spatny k tomu ;-)
Miloslav Ponkrác 26. 2. 2003 09:57
Nový
 
 
│
 
 
 
 
 
 
 
 
 
├ 
Re: Dojem... a spatny k tomu ;-)
Pichi 26. 2. 2003 10:24
Nový
 
 
│
 
 
 
 
 
 
 
 
 
│
└ 
Re: Dojem... a spatny k tomu ;-)
Miloslav Ponkrác 26. 2. 2003 11:35
Nový
 
 
│
 
 
 
 
 
 
 
 
 
│
 
├ 
Re: Dojem... a spatny k tomu ;-)
anonymní uživatel 26. 2. 2003 17:14
Nový
 
 
│
 
 
 
 
 
 
 
 
 
│
 
└ 
Re: Dojem... a spatny k tomu ;-)
pharook 26. 2. 2003 22:28
Nový
 
 
│
 
 
 
 
 
 
 
 
 
│
 
 
└ 
Souhlasím
anonymní uživatel 27. 2. 2003 15:45
Nový
 
 
│
 
 
 
 
 
 
 
 
 
└ 
Re: Dojem... a spatny k tomu ;-)
anonymní uživatel 26. 2. 2003 17:10
Nový
 
 
│
 
 
 
 
 
 
 
 
 
 
└ 
Nebudeme blafovat, O.K.?
anonymní uživatel 27. 2. 2003 15:46
Nový
 
 
│
 
 
 
 
 
 
 
 
 
 
 
└ 
Re: Nebudeme blafovat, O.K.?
Pichi 28. 2. 2003 08:03
Nový
 
 
└ 
Re: Dojem
anonymní uživatel 26. 2. 2003 17:01
Nový
fastcall
GF 25. 2. 2003 09:52
Nový
└ 
Re: fastcall
petrs 25. 2. 2003 13:12
Nový
 
├ 
Re: fastcall
GF 25. 2. 2003 16:50
Nový
 
│
└ 
Re: fastcall
petrs 26. 2. 2003 00:59
Nový
 
│
 
└ 
Re: fastcall
GF 26. 2. 2003 19:57
Nový
 
└ 
Re: fastcall
Michal Ludvig 26. 2. 2003 09:28
Nový
jezusku ;)
sd 25. 2. 2003 15:07
Nový
└ 
Re: jezusku ;)
lama 25. 2. 2003 21:29
Nový
!!! OPRAVA !!!
lzap 25. 2. 2003 16:32
Nový
Kdo to neumi tak to aspon uci...
Zdenek Kabelac 25. 2. 2003 16:54
Nový
├ 
Re: Kdo to neumi tak to aspon uci...
Pichi 25. 2. 2003 17:09
Nový
│
├ 
Re: Kdo to neumi tak to aspon uci...
tdx 25. 2. 2003 23:08
Nový
│
│
└ 
Díky za pochopení
Miloslav Ponkrác 26. 2. 2003 09:13
Nový
│
│
 
└ 
Re: Díky za pochopení
Pichi 26. 2. 2003 10:18
Nový
│
│
 
 
└ 
Re: Díky za pochopení
Miloslav Ponkrác 26. 2. 2003 11:35
Nový
│
│
 
 
 
└ 
Re: Díky za pochopení
Pichi 26. 2. 2003 12:03
Nový
│
│
 
 
 
 
└ 
Nazvěme to pravým jménem
Miloslav Ponkrác 26. 2. 2003 13:23
Nový
│
│
 
 
 
 
 
├ 
Re: Nazvěme to pravým jménem
kubik 26. 2. 2003 17:33
Nový
│
│
 
 
 
 
 
│
└ 
Re: Nazvěme to pravým jménem
Miloslav Ponkrác 27. 2. 2003 15:49
Nový
│
│
 
 
 
 
 
└ 
Re: Nazvěme to pravým jménem
jr 6. 3. 2003 12:09
Nový
│
└ 
Styl diskuse
Miloslav Ponkrác 26. 2. 2003 13:34
Nový
│
 
├ 
Re: Styl diskuse
michael 26. 2. 2003 17:25
Nový
│
 
└ 
Re: Styl diskuse
michael 26. 2. 2003 17:25
Nový
│
 
 
└ 
Re: Styl diskuse
Miloslav Ponkrác 27. 2. 2003 15:56
Nový
└ 
Re: Kdo to neumi tak to aspon uci...
lzap 26. 2. 2003 13:21
Nový
stydte se
bobo 26. 2. 2003 14:04
Nový
└ 
Re: stydte se
Pichi 26. 2. 2003 15:10
Nový
 
└ 
Re: stydte se
kubik 26. 2. 2003 17:35
Nový
 
 
└ 
Re: stydte se
tdx 26. 2. 2003 23:20
Nový
Nepochopeni
Zdenek Kabelac 27. 2. 2003 12:10
Nový
├ 
Re: Nepochopeni
Miloslav Ponkrác 27. 2. 2003 16:12
Nový
└ 
Re: Nepochopeni
lzap 1. 3. 2003 22:11
Nový
 
└ 
Re: Nepochopeni
x 27. 10. 2003 15:07
Nový
       

Tento text je již více než dva měsíce starý. Chcete-li na něj reagovat v diskusi, pravděpodobně vám již nikdo neodpoví. Pro řešení aktuálních problémů doporučujeme využít naše diskusní fórum.

Zasílat nově přidané příspěvky e-mailem