Assembler -=-=-=-=-=- "The C Programming Language -- A language which combines the flexibility of assembly language with the power of assembly language." Použití inline assembleru jsem už popsal ve výhni #8. Proto se teď budu zabývat linkováním assemblerových objetů. Pro psaní assembleru jde použít buď standardní program gas (GNU assembler). Ten používá AT&T syntax, kterou jsem už také popsal ve výhních #8 a #7, nebo program NASM, který má syntax (až na drobné vyjimky) shodnou s TASManem a proto asi bude lepší v případě, že máte nějaký assemblerový kód a chcete ho použít. Díky rozdílům mezí 16 a 32 bitovým kódem stejně ale zdroják asi bude chtít částečně upravit. Existuje také převadeč ta2as, který se stará o překlad z Intelí syntaxe do AT&T. Není ale příliš spolehlivý. Dál budu psát hlavně o gasu, protože NASM nepoužívám (nechtěl by o něm někdo napsat?). Hodně věcí ale asi bude stejných. Asi jeden z nejjedodušších způsobů, jak se naučit gas je vzít jednoduchý zdroják v C a přeložit ho do assembleru (pomocí -S). Základní struktura souboru je asi následující: .file "jméno" .data mojedato: .word 0 .text .globl __myasmfunc __myasmfunc: ... ret Vlastní GAS je velmi jednoduchý proram. Nemá žádnou podporu pro makra. Pokud ale použijete jako příponu .S (ne .s), prožene se nejprve zdroják preprocesorem. Proto lze použít makra a konstanty preprocesoru. DJGPP má standardně celkem šikovnou sadu maker v souboru libc/asmdefs.h #include <libc/asmdefs.h> .file "jmeno.S" .data .align 2 mojedata: .word 0 ... .text .align 4 FUNC(__mojefunkce) ENTER movl ARG1, %eax ... jmp label ... label: ... LEAVE Takto napsané funkce se potom chovájí jako standardní céčkové funkce. Prototyp vypadá asi takto: void mojefunkce(int p); Volací konvence jsou standardní céčkové - parametry jsou na zásobníku pospátku (první pop vyzvedne první parametr). O vrácení zásobníku se stará volající funkce. Pokud máte kód napsaný pro pascal, tedy funkce po sobě uklízí samy, je nutné k prototypu napsat: void mojefunkce(int p) __attribute((stdcall)); GCC také umí registrové volací konvence. Potom je prvních n parametrů uloženo v registrech (n<=3). To se deklaruje: void mojefunkce(int a, int b, int c) __attribute((regparm(3))); Použijí se registry EAX, EDX, ECX. Registrové volací konvence jsou často rychlejší, než zásobníkové, proto takové prototypy se občas vyplatí použít i u často volaných céčkových funkci. Nejdůležitější pseudoinstrukce GASu jsou: .allign n - zarovná adresu následující instrukce tak, aby byla dělitelná číslem n. Pseudoinstrukce pro určování segnetu .data datový segment .text kódový segment Scope: .globl symbol symbol je globální .comm symbol, délka následující symbol je common (takových symbolů může být v objektech víc se stejným jménem a linker je potom spojí za sebe. Pseudoinstrokce pro zadávání dat: .ascii .asciz jako .ascii ale přidá nakonec nulu .byte .short (16 bitů) .int (32 bitů) .quad (64 bitů) .double .float .fill kolikrát, velikost, hodnota Novější gasy podoporují i věci jako .ifdef, .macro atd. Zdá se mi ale lepší použít preprocesor. Více je v dokumentaci (info -f gas) výheň