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ň