  Assembly HOWTO
  Franois-Ren Rideau rideau@ens.fr
  v0.4l, 16 Novembre 1997

  Questo  il Linux Assembly HOWTO.  Questo documento descrive come pro
  grammare in assembly utilizzando strumenti di programmazione _L_I_B_E_R_I,
  concentrandosi sullo sviluppo per o sul sistema operativo Linux su
  piattaforme i386.  Il materiale incluso potrebbe essere o meno appli
  cabile ad altre piattaforme hardware e/o software.  Contributi
  riguardo a queste sarebbero ben accetti.  _p_a_r_o_l_e _c_h_i_a_v_e: assembly,
  assembler, libero, macro, preprocessore, asm, inline, 32-bit, x86,
  i386, gas, as86, nasm.  Traduzione di Matteo De Luigi
  (giotto@maya.dei.unipd.it).
  ______________________________________________________________________

  Indice Generale



  1. INTRODUZIONE
     1.1 Legal Blurp
     1.2 NOTA IMPORTANTE
     1.3 Prima di cominciare
        1.3.1 Come usare questo documento
        1.3.2 Documenti correlati
     1.4 Storia
     1.5 Ringraziamenti

  2. AVETE BISOGNO DELL'ASSEMBLY?
     2.1 Pro e contro
        2.1.1 I vantaggi dell'assembly
        2.1.2 Gli svantaggi dell'assembly
        2.1.3 Valutazioni
     2.2 Come NON usare l'assembly
        2.2.1 Procedura generale per ottenere codice efficiente
        2.2.2 Linguaggi con compilatori ottimizzanti
        2.2.3 Procedura generale per accelerare il vostro codice
        2.2.4 Ispezione del codice generato dal compilatore

  3. ASSEMBLATORI
     3.1 Assembly inline di GCC
        3.1.1 Dove trovare GCC
        3.1.2 Dove trovare documentazione per l'assemblatore inline di GCC
        3.1.3 Invocare GCC per fargli trattare correttamente l'assembly inline
     3.2 GAS
        3.2.1 Dove trovarlo
        3.2.2 Cos' la sintassi AT&T
        3.2.3 Modo a 16 bit limitato
     3.3 GASP
        3.3.1 Dove trovare GASP
        3.3.2 Come funziona
     3.4 NASM
        3.4.1 Dove trovare NASM
        3.4.2 Cosa fa
     3.5 AS86
        3.5.1 Dove procurarsi AS86
        3.5.2 Come invocare l'assemblatore?
        3.5.3 Dove trovare documentazione
        3.5.4 E se non riesco pi a compilare Linux con questa nuova versione?
     3.6 ALTRI ASSEMBLATORI
        3.6.1 L'assemblatore Win32Forth
        3.6.2 Terse
        3.6.3 Assemblatori non liberi e/o non a 32 bit.

  4. METAPROGRAMMAZIONE E MACRO
     4.1 Cosa  integrato nei pacchetti menzionati
        4.1.1 GCC
        4.1.2 GAS
        4.1.3 GASP
        4.1.4 NASM
        4.1.5 AS86
        4.1.6 ALTRI ASSEMBLATORI
     4.2 Filtri esterni
        4.2.1 CPP
        4.2.2 M4
        4.2.3 Macro con i vostri filtri
        4.2.4 Metaprogrammazione
           4.2.4.1 Backend da compilatori esistenti
           4.2.4.2 Il New-Jersey Machine-Code Toolkit
           4.2.4.3 Tunes

  5. CONVENZIONI DI CHIAMATA
     5.1 Linux
        5.1.1 Linking a GCC
        5.1.2 ELF ed a.out : problemi.
        5.1.3 Linux: chiamate di sistema dirette
        5.1.4 I/O sotto Linux
        5.1.5 Accedere a driver a 16 bit da Linux/i386
     5.2 DOS
     5.3 Winzozz e compagnia bella
     5.4 Un sistema operativo tutto vostro.

  6. COSE DA FARE E RIFERIMENTI


  ______________________________________________________________________

  11..  IINNTTRROODDUUZZIIOONNEE

  11..11..  LLeeggaall BBlluurrpp

  Copyright  1996,1997 by Franois-Ren Rideau.  This document may be
  distributed under the terms set forth in the LDP license at
  <http://sunsite.unc.edu/LDP/COPYRIGHT.html>.


  11..22..  NNOOTTAA IIMMPPOORRTTAANNTTEE

  C' da aspettarsi che questo sia l'ultimo rilascio di questo documento
  da parte mia.

  C' un candidato al ruolo di curatore, ma finch l'HOWTO non diventa
  ufficialmente suo, accetter suggerimenti e critiche.

  Siete in particolare invitati a porre domande, a rispondere alle
  domande, a correggere le risposte date, ad aggiungere nuove risposte
  alle FAQ, a fornire riferimenti ad altro software, ad indicare errori
  o lacune nelle pagine al responsabile attuale.  Se qualcuno di voi 
  motivato, potrebbe perfino _D_I_V_E_N_T_A_R_E _I_L _R_E_S_P_O_N_S_A_B_I_L_E _D_E_L_L_E _F_A_Q.  In
  una parola, contribuite!

  Per contribuire, per favore contattate chiunque sembri curare
  l'Assembly-HOWTO.  I curatori attuali sono: Franois-Ren Rideau
  <mailto:rideau@clipper.ens.fr> ed ora Paul Anderson
  <mailto:paul@geeky1.ebtech.net>.



  11..33..  PPrriimmaa ddii ccoommiinncciiaarree

  Questo documento intende rispondere alle domande pi frequenti delle
  persone che programmano o vogliono programmare in assembly a 32 bit
  per x86 utilizzando assemblatori _l_i_b_e_r_i, specialmente sotto il sistema
  operativo Linux.  Potrebbe inoltre rimandare ad altri documenti circa
  assemblatori non liberi, non per x86 o non a 32 bit, anche se questo
  non  il suo scopo principale.

  Poich l'interesse principale della programmazione in assembly
  consiste nel realizzare le viscere dei sistemi operativi, degli
  interpreti, dei compilatori e dei giochi, laddove un compilatore C non
  riesce a fornire l'espressivit richiesta ( abbastanza raro che si
  tratti di una questione di prestazioni), ci interesseremo
  principalmente di questo tipo di software.



  11..33..11..  CCoommee uussaarree qquueessttoo ddooccuummeennttoo

  Questo documento contiene risposte ad alcune domande poste di
  frequente.  In molte occasioni, vengono forniti URL di alcuni archivi
  di software o documentazione.  Per favore, notate che gli archivi di
  maggiore utilit hanno dei mirror e che accedendo ad un mirror pi
  vicino da un lato evitate ad Internet traffico non necessario e
  dall'altro risparmiate tempo prezioso.  In particolare, ci sono dei
  grandi depositi sparsi per tutto il mondo che fanno il mirror anche di
  altri archivi di pubblico interesse.

  Dovreste imparare ad annotarvi quali sono questi posti vicino a voi
  (dal punto di vista della rete).

  Talvolta, la lista dei mirror si trova in un file o in un messaggio di
  login. Siete pregati di seguire i consigli.  Altrimenti, dovreste
  interrogare archie circa il software di cui siete alla ricerca...

  La versione pi recente di questi documenti risiede ad

  <http://www.eleves.ens.fr:8080/home/rideau/Assembly-HOWTO> oppure
  <http://www.eleves.ens.fr:8080/home/rideau/Assembly-HOWTO.sgml>

  ma anche ci che si trova negli archivi degli HOWTO di Linux _d_o_v_r_e_b_b_e
  essere abbastanza aggiornato (io non ho modo di saperlo):

  <ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO/> (?)

  Una traduzione in francese di questo HOWTO pu essere trovata dalle
  parti di:

  <ftp://ftp.ibp.fr/pub/linux/french/HOWTO/>



  11..33..22..  DDooccuummeennttii ccoorrrreellaattii


    Se non sapete cos' il software _l_i_b_e_r_o, siete pregati di leggere
     _a_t_t_e_n_t_a_m_e_n_t_e la Licenza Pubblica Generale GNU, che viene usata in
     tantissimo software libero ed  un modello per la maggior parte
     delle licenze per questo tipo di programmi.  Si trova di solito in
     un file chiamato COPYING, con una versione per le librerie in un
     file chiamato COPYING.LIB.  Anche qualche pubblicazione della FSF
     (free software foundation) potrebbe esservi d'aiuto.

    In particolare, il software libero pi interessante  disponibile
     con sorgenti che possono essere consultati e corretti.  Talvolta 
     persino possibile prendere in prestito del codice.  Leggete con
     cura le licenze specifiche ed agite in conformit ad esse.

    C' una FAQ per comp.lang.asm.x86 che risponde a domande generiche
     circa la programmazione in assembly su x86 e a domande circa alcuni
     assemblatori commerciali in ambiente DOS a 16 bit.  Alcune
     riguardano la programmazione libera in asm a 32 bit, cos potreste
     essere interessati a leggere queste FAQ...

     <http://www2.dgsys.com/~raymoon/faq/asmfaq.zip>

    Esistono FAQ e documentazione riguardanti la programmazione sulla
     vostra piattaforma preferita, qualunque essa sia, che dovreste
     consultare per questioni specifiche alla piattaforma stessa non
     direttamente correlate alla programmazione in assembler.


  11..44..  SSttoorriiaa

  Ogni versione contiene alcune correzioni e rettifiche di poco conto
  che non  necessario menzionare ogni volta.


     VVeerrssiioonnee 00..11    2233 aapprr 11999966
        Francois-Rene Far Rideau <rideau@ens.fr> crea e pubblica il
        primo mini-HOWTO, perch Non ne posso pi di rispondere sempre
        alle stesse domande su comp.lang.asm.x86

     VVeerrssiioonnee 00..22    44 mmaagg 11999966
        *

     VVeerrssiioonnee 00..33cc   1155 ggiiuu 11999966
        *

     VVeerrssiioonnee 00..33ff   1177 ootttt 11999966
        Trovata l'opzione -fasm per abilitare l'assemblatore inline di
        GCC senza le ottimizzazioni -O

     VVeerrssiioonnee 00..33gg   22 nnoovv 11999966
        Creata la storia del documento. Aggiunti i riferimenti nella
        sezione sulla compilazione incrociata.  Aggiunta la sezione
        circa la programmazione dell'I/O sotto Linux (video in
        particolare).

     VVeerrssiioonnee 00..33hh   66 nnoovv 11999966
        maggiori informazioni sulla compilazione incrociata. Vedere
        devel/msdos su sunsite.

     VVeerrssiioonnee 00..33ii   1166 nnoovv 11999966
        NASM sta diventando molto affidabile.

     VVeerrssiioonnee 00..33jj   2244 nnoovv 11999966
        Riferimento alla traduzione in francese.

     VVeerrssiioonnee 00..33kk   1199 ddiicc 11999966
        Cosa? Mi ero dimenticato di fare riferimento a Terse???

     VVeerrssiioonnee 00..33ll   1111 ggeenn 11999977
        *

     VVeerrssiioonnee 00..44pprree11        1133 ggeenn 11999977
        Il mini-HOWTO in formato testo viene trasformato in un completo
        HOWTO linuxdoc-sgml, per vedere come sono gli SGML tools.

     VVeerrssiioonnee 00..44    2200 ggeenn 11999977
        Primo rilascio dell'HOWTO come tale.

     VVeerrssiioonnee 00..44aa   2200 ggeenn 11999977
        Aggiunta la sezione ringraziamenti.

     VVeerrssiioonnee 00..44bb   33 ffeebb 11999977
        Spostato NASM: ora  prima di AS86

     VVeerrssiioonnee 00..44cc   99 ffeebb 11999977
        Aggiunta la sezione avete bisogno dell'assembly?

     VVeerrssiioonnee 00..44dd   2288 ffeebb 11999977
        Annuncio prematuro di un nuovo responsabile dell'Assembly-HOWTO.

     VVeerrssiioonnee 00..44ee   1133 mmaarr 11999977
        Rilascio per DrLinux

     VVeerrssiioonnee 00..44ff   2200 mmaarr 11999977
        *

     VVeerrssiioonnee 00..44gg   3300 mmaarr 11999977
        *


     VVeerrssiioonnee 00..44hh   1199 ggiiuu 11999977
        ancora aggiunte a come NON usare l'assembly; aggiornamenti su
        NASM, GAS.

     VVeerrssiioonnee 00..44ii   1177 lluugglliioo 11999977
        informazioni sull'accesso al modo a 16 bit da Linux.

     VVeerrssiioonnee 00..44jj   77 sseetttteemmbbrree 11999977
        *

     VVeerrssiioonnee 00..44kk   1199 oottttoobbrree 11999977
        *

     VVeerrssiioonnee 00..44ll   1166 nnoovveemmbbrree 11999977
        rilascio per LSL, sesta edizione.

        Questo  ancora un altro ultimo-rilascio-di-Far-prima-che-un-
        altro-curatore-gli-subentri (?)



  11..55..  RRiinnggrraazziiaammeennttii

  Vorrei ringraziare le seguenti persone, in ordine di apparizione:

    Linus Torvalds <mailto:sepolto.vivo@nella.posta> per Linux

    Bruce Evans <mailto:bde@zeta.org.au> per bcc da cui  estratto as86

    Simon Tatham <mailto:anakin@poboxes.com> e Julian Hall
     <mailto:jules@earthcorp.com> per NASM

    Jim Neil <mailto:jim-neil@digital.net> per Terse

    Tim Bynum <mailto:linux-howto@sunsite.unc.edu> perch mantiene gli
     HOWTO

    Raymond Moon <mailto:raymoon@moonware.dgsys.com> per le sue FAQ

    Eric Dumas <mailto:dumas@excalibur.ibp.fr> per la sua traduzione in
     francese del mini-HOWTO ( una cosa triste per l'autore originale
     essere francese e scrivere in inglese)

    Paul Anderson <mailto:paul@geeky1.ebtech.net> e Rahim Azizarab
     <mailto:rahim@megsinet.net> per l'aiuto, se non per aver rilevato
     l'HOWTO.

    Tutte le persone che hanno dato il loro contributo con idee,
     commenti e supporto morale.



  22..  AAVVEETTEE BBIISSOOGGNNOO DDEELLLL''AASSSSEEMMBBLLYY??

  Beh, non vorrei interferire con ci che state facendo, ma ecco alcuni
  consigli derivanti da una esperienza ottenuta faticosamente.



  22..11..  PPrroo ee ccoonnttrroo



  22..11..11..  II vvaannttaaggggii ddeellll''aasssseemmbbllyy

  L'assembly pu esprimere cose molto a basso livello:

    potete accedere a registri e ad I/O dipendenti dalla macchina.

    potete controllare l'esatto comportamento di codice in sezioni
     critiche che potrebbe comportare il bloccarsi di hardware o I/O.

    potete trasgredire le convenzioni del vostro compilatore abituale,
     il che potrebbe permettere alcune ottimizzazioni (come ad esempio
     violare temporaneamente le regole per il garbage collecting,
     threading, ecc).

    ottenere accesso a modi di programmazione insoliti del vostro
     processore (ad esempio codice a 16 bit per l'avvio o l'interfaccia
     BIOS sui PC Intel).

    potete costruire interfacce tra frammenti di codice che usano
     convenzioni incompatibili (ad esempio prodotti da compilatori
     diversi o separati da una interfaccia a basso livello).

    potete produrre codice ragionevolmente veloce per cicli stretti per
     far fronte ad un compilatore non-ottimizzante di qualit scadente
     (ma dopotutto sono disponibili compilatori ottimizzanti liberi!).

    potete produrre codice ottimizzato a mano che risulta ottimo per la
     vostra particolare configurazione hardware, ma non per quella di
     chiunque altro.

    potete scrivere del codice per il compilatore ottimizzante del
     vostro nuovo linguaggio ( qualcosa che poche persone fanno, ed
     anche loro non lo fanno molto spesso).



  22..11..22..  GGllii ssvvaannttaaggggii ddeellll''aasssseemmbbllyy

  L'assembly  un linguaggio molto a basso livello (pi in basso c'
  solo la codifica a mano delle istruzioni in codice binario).

  Ci significa:

    All'inizio  lungo e tedioso da scrivere.

     notevolmente soggetto ad errori.

    Gli errori saranno molto difficili da scovare.

     molto difficile da comprendere e modificare, in altre parole da
     mantenere.

    Il risultato  decisamente non portabile verso altre architetture,
     esistenti o future.

    Il vostro codice verr ottimizzato solo per una certa
     implementazione di una stessa architettura: ad esempio, tra le
     piattaforme compatibili Intel, avere CPU diverse o differenti
     configurazioni (ampiezza del bus, velocit e dimensioni relative di
     CPU/cache/RAM/bus/dischi, presenza di FPU, estensioni MMX, ecc.)
     pu richiedere tecniche di ottimizzazione radicalmente diverse.  I
     tipi di CPU comprendono gi Intel 386, 486, Pentium, PPro, Pentium
     II; Cyrix 5x86, 6x86; AMD K5, K6.  Inoltre, continuano ad apparire
     nuovi tipi, perci non aspettatevi che questo elenco o il vostro
     codice siano aggiornati.
    Il vostro codice potrebbe inoltre non essere portabile verso
     piattaforme con sistemi operativi differenti ma con la stessa
     architettura per la mancanza di strumenti adeguati (beh, GAS pare
     funzionare su tutte le piattaforme; a quanto sembra, NASM funziona
     o pu essere reso funzionante su tutte le piattaforme Intel).

    Perdete pi tempo su pochi dettagli e non potete concentrarvi sulla
     progettazione algoritmica su piccola e grande scala che, come 
     noto, porta il maggior contributo alla velocit del programma.  Per
     esempio, potresete perdere del tempo per scrivere in assembly delle
     primitive molto veloci per la manipolazione di liste o matrici,
     quando sarebbe bastato utilizzare una tabella hash per accelerare
     molto di pi il vostro programma. Magari, in un altro contesto,
     sarebbe servito un albero binario, o qualche struttura ad alto
     livello distribuita su un cluster di CPU.

    Un piccolo cambiamento nell'impostazione algoritmica potrebbe far
     perdere ogni validit a tutto il codice assembly gi esistente.
     Perci o siete pronti a (ed in grado di) riscriverlo tutto, oppure
     siete vincolati ad una particolare impostazione algoritmica.

    Per quanto riguarda il codice che non si scosta troppo da quello
     che  presente nei benchmark convenzionali, i compilatori
     ottimizzanti commerciali permettono di ottenere prestazioni
     migliori rispetto all'assembly manuale (beh, ci  meno vero
     sulle architetture x86 rispetto alle architetture RISC e forse meno
     vero per compilatori largamente disponibili/liberi; comunque, per
     codice C tipico, GCC se la cava discretamente).

    E in ogni caso, come dice il moderatore John Levine su
     comp.compilers, i compilatori rendono decisamente pi facile
     utilizzare strutture dati complesse, non si stancano a met strada
     e ci si pu aspettare che generino codice abbastanza buono.
     Inoltre provvederanno a propagare _c_o_r_r_e_t_t_a_m_e_n_t_e trasformazioni di
     codice attraverso tutto il (lunghissimo) programma quando si
     tratter di ottimizzare codice tra i confini delle procedure e dei
     moduli.



  22..11..33..  VVaalluuttaazziioonnii

  Tutto sommato, potreste notare che nonostante l'uso dell'assembly sia
  talvolta necessario (o semplicemente utile, in alcuni casi), sar il
  caso che:

    minimizziate l'uso del codice assembly;

    incapsuliate questo codice in interfacce ben definite;

    facciate generare automaticamente il vostro codice assembly da
     strutture espresse in un linguaggio a pi alto livello rispetto
     all'assembly stesso (ad esempio le macro dell'assembly inline di
     GCC);

    facciate tradurre in assembly questi programmi da strumenti
     automatici;

    facciate ottimizzare questo codice, se possibile;

    tutti i punti di cui sopra, cio scriviate (un'estensione ad) un
     backend per un compilatore ottimizzante.

  Anche nei casi in cui l'assembly  necessario (ad esempio, nello
  sviluppo di sistemi operativi), scoprirete che non ne serve poi molto
  e che i principi precedenti continuano a valere.
  A questo riguardo, date un'occhiata ai sorgenti del kernel di Linux:
  poco assembly, giusto lo stretto necessario, il che ha come risultato
  un sistema operativo veloce, affidabile, portabile e mantenibile.
  Anche un gioco di successo come DOOM  stato scritto quasi
  completamente in C, con solo una minuscola parte scritta in assembly
  per renderlo pi veloce.



  22..22..  CCoommee NNOONN uussaarree ll''aasssseemmbbllyy



  22..22..11..  PPrroocceedduurraa ggeenneerraallee ppeerr ootttteenneerree ccooddiiccee eeffffiicciieennttee

  Come dice Charles Fiterman su comp.compilers circa il confronto tra
  codice assembly generato a mano o automaticamente,

  L'uomo dovrebbe sempre vincere, ed eccone i motivi:

    Primo passo: l'uomo scrive il tutto in un linguaggio ad alto
     livello.

    Secondo passo: provvede ad un profiling per trovare i punti in cui
     si perde pi tempo.

    Terzo passo: fa produrre al compilatore codice assembly per quelle
     piccole sezioni di codice.

    Quarto passo: le perfeziona a mano cercando piccoli miglioramenti
     rispetto al codice generato dalla macchina.

  L'uomo vince perch sa usare la macchina.



  22..22..22..  LLiinngguuaaggggii ccoonn ccoommppiillaattoorrii oottttiimmiizzzzaannttii

  I linguaggi quali ObjectiveCAML, SML, CommonLISP, Scheme, ADA, Pascal,
  C, C++, tra gli altri, dispongono di compilatori ottimizzanti liberi
  che ottimizzeranno il grosso dei vostri programmi (e spesso otterranno
  risultati migliori rispetto all'assembly manuale anche per cicli
  stretti), permettendovi nel frattempo di concentrarvi su dettagli pi
  ad alto livello, il tutto senza vietarvi di ottenere qualche punto
  percentuale di prestazioni in pi nella maniera espressa sopra, una
  volta che il vostro progetto avr raggiunto un'impostazione stabile.

  Certo, ci sono anche compilatori ottimizzanti commerciali per la
  maggior parte di quei linguaggi!

  Alcuni linguaggi hanno compilatori che producono codice C, che pu
  essere ulteriormente ottimizzato da un compilatore C.  LISP, Scheme,
  Perl e molti altri fanno parte di questa categoria.  La velocit 
  abbastanza buona.



  22..22..33..  PPrroocceedduurraa ggeenneerraallee ppeerr aacccceelleerraarree iill vvoossttrroo ccooddiiccee

  Per quanto riguarda l'accelerazione del vostro codice, dovreste
  restringerla alle parti di un programma che uno strumento di profiling
  ha decisamente identificato come un collo di bottiglia.

  Perci, se identificate qualche porzione di codice come troppo lenta,
  dovreste:
    prima di tutto provare ad usare un algoritmo migliore;

    poi provare a compilarla invece di interpretarla;

    poi provare ad abilitare e raffinare l'ottimizzazione per il vostro
     compilatore;

    poi dare al compilatore dei consigli su come ottimizzare
     (informazione sui tipi in LISP; uso di register con GCC; un mucchio
     di opzioni nella maggior parte dei compilatori, ecc.);

    infine, se  il caso, ripiegate sulla programmazione assembly.

  Come ultima cosa, prima che vi riduciate a scrivere assembly, dovreste
  ispezionare il codice generato, per controllare che il problema
  risieda proprio nella cattiva generazione del codice, visto che
  potrebbe anche non essere cos: il codice generato dal compilatore
  potrebbe essere migliore di quanto avreste potuto fare voi,
  specialmente sulle moderne architetture multi-pipelined!  Le parti
  lente di un programma potrebbero essere intrinsecamente tali.  I pi
  grossi problemi sulle architetture moderne con processori veloci sono
  dovuti a ritardi di accesso alla memoria, cache-miss, TLB miss, e page
  fault; l'ottimizzazione sui registri diventa inutile, ed otterrete
  risultati migliori riprogettando le strutture dati ed il threading per
  ottenere una miglior localit nell'accesso alla memoria.  Potrebbe
  forse essere d'aiuto un approccio completamente diverso al problema.


  22..22..44..  IIssppeezziioonnee ddeell ccooddiiccee ggeenneerraattoo ddaall ccoommppiillaattoorree

  Ci sono molte ragioni per ispezionare il codice assembly generato dal
  compilatore.  Ecco cosa potete fare con tale codice:

    controllate se il codice generato pu essere migliorato in maniera
     ovvia con assembly manuale (o con le opportune opzioni per il
     compilatore).

    Quando  il caso, partite da codice generato e modificatelo, invece
     di ripartire da zero.

    Pi in generale, utilizzate il codice generato come stub da
     modificare. In questo modo, almeno, viene gestito correttamente il
     modo in cui le vostre routine assembly si interfacciano col mondo
     esterno.

    Rintracciare dei bug nel vostro compilatore (raramente, si spera).

  Il modo canonico per far generare codice assembly  invocare con il
  flag -S il vostro compilatore.  Ci funziona con la maggior parte dei
  compilatori UNIX, compreso il compilatore C di GNU (GCC), ma nel
  vostro caso le cose potrebbero andare diversamente.  Nel caso di GCC,
  con l'opzione -fverbose-asm verr prodotto codice assembly pi
  comprensibile.  Certo, se volete ottenere buon codice assembly, non
  dimenticate di dare i soliti consigli e le solite opzioni per
  l'ottimizzazione!



  33..  AASSSSEEMMBBLLAATTOORRII



  33..11..  AAsssseemmbbllyy iinnlliinnee ddii GGCCCC

  Il noto compilatore GNU C/C++ (GCC), un compilatore ottimizzante a
  32-bit alla base del progetto GNU, supporta l'architettura x86
  abbastanza bene, e fornisce la possibilit di inserire codice assembly
  nei programmi C, in modo tale che l'allocazione dei registri pu
  essere o specificata o lasciata a GCC.  GCC funziona sulla maggior
  parte delle piattaforme disponibili, tra le quali sono degne di nota
  Linux, *BSD, VSTa, OS/2, *DOS, Win*, ecc.


  33..11..11..  DDoovvee ttrroovvaarree GGCCCC

  Il sito originale di GCC  il sito FTP di GNU
  <ftp://prep.ai.mit.edu/pub/gnu/> in cui si trova anche tutto il
  software applicativo del progetto GNU che  stato rilasciato.

  Versioni configurate e precompilate per Linux possono essere trovate
  in <ftp://sunsite.unc.edu/pub/Linux/GCC/>.  Esistono un sacco di
  mirror FTP di entrambi i siti in tutte le parti del mondo, cos come
  copie su CD-ROM.

  Recentemente, lo sviluppo di GCC si  biforcato.  Maggiori notizie
  sulla versione sperimentale, egcs, presso
  <http://www.cygnus.com/egcs/>.

  Dovreste trovare dei sorgenti adattati per il vostro sistema operativo
  preferito e dei binari precompilati ai soliti siti FTP.

  La versione pi comune per DOS si chiama DJGPP e pu essere trovata
  nelle directory con questo nome nei siti FTP.  Vedere:

  <http://www.delorie.com/djgpp/>


  C' anche una versione di GCC per OS/2 chiamata EMX, che funziona
  anche sotto DOS ed include molte routine di libreria per l'emulazione
  di UNIX.  Date un'occhiata dalle parti di:

  <http://www.leo.org/pub/comp/os/os2/gnu/emx+gcc/>

  <http://warp.eecs.berkeley.edu/os2/software/shareware/emx.html>

  <ftp://ftp-os2.cdrom.com/pub/os2/emx09c/>



  33..11..22..  DDoovvee ttrroovvaarree ddooccuummeennttaazziioonnee ppeerr ll''aasssseemmbbllaattoorree iinnlliinnee ddii GGCCCC

  La documentazione di GCC include file di documentazione in formato
  texinfo.  Potete compilarli con TeX e poi stampare il risultato,
  oppure convertirli in .info e sfogliarli con emacs, oppure ancora
  convertirli in .html o (con gli strumenti appropriati) in tutto ci
  che volete, oppure semplicemente leggerli cos come sono.

  Di solito i file .info si trovano in ogni buona installazione di GCC.

  La sezione corretta da cercare : C Extensions::Extended Asm::

  La sezione Invoking GCC::Submodel Options::i386 Options:: potrebbe
  anch'essa rivelarsi utile.  In particolare, d i vincoli sui nomi dei
  registri specifici per l'i386: abcdSDB corrispondono rispettivamente
  a: %eax, %ebx, %ecx, %edx, %esi, %edi, %ebp (nessuna lettera per
  %esp).

  La DJGPP Games resource (non solo per hacker dei giochi) ha questa
  pagina apposta per l'assembly:

  <http://www.rt66.com/~brennan/djgpp/djgpp_asm.html>

  Infine, c' una pagina web chiamata DJGPP Quick ASM Programming
  Guide che tratta URL, FAQ, sintassi asm AT&T per x86, alcune
  informazioni sull'asm inline e la conversione dei file .obj/.lib:

  <http://remus.rutgers.edu/~avly/djasm.html>

  GCC dipende da GAS per l'assembling e segue la sua sintassi (vedere in
  seguito); se usate l'asm inline, badate bene:  necessario che i
  caratteri percento siano protetti dall'espansione per poter essere
  passati a GAS.  Vedere la sezione su GAS in seguito.

  Potete trovare _u_n _s_a_c_c_o di esempi utili nella sottodirectory
  linux/include/asm-i386/ dei sorgenti del kernel di Linux.



  33..11..33..  IInnvvooccaarree GGCCCC ppeerr ffaarrggllii ttrraattttaarree ccoorrrreettttaammeennttee ll''aasssseemmbbllyy
  iinnlliinnee

  Assicuratevi di invocare GCC con il flag -O ( oppure -O2, -O3, ecc.)
  per abilitare le ottimizzazioni e l'assembly inline.  Se non lo fate,
  il vostro codice potrebbe venire compilato ma non essere eseguito
  correttamente!!!  In realt (lodi smisurate a Tim Potter,
  timbo@mohpit.air.net.au)  sufficiente utilizzare il flag -fasm (e
  forse -finline-functions) che attiva solo una parte di tutte le
  funzionalit abilitate da -O.  Cos, se avete problemi a causa di bug
  nelle ottimizzazioni della vostra particolare versione/implementazione
  di GCC, potete comunque usare l'asm inline.  In maniera analoga, usate
  -fno-asm per disabilitare l'assembly inline (perch dovreste?).

  Pi in generale, buoni flag di compilazione per GCC sulla piattaforma
  x86 sono

  ______________________________________________________________________
          gcc -O2 -fomit-frame-pointer -m386 -Wall
  ______________________________________________________________________



  -O2  il giusto livello di ottimizzazione. Ottimizzare oltre produce
  codice che  parecchio pi grande, ma solo di poco pi veloce; tale
  sovraottimizzazione potrebbe essere utile solo per cicli stretti (se
  ce ne sono), che potreste comunque realizzare in assembly; se ne
  sentite la necessit, fatelo solo per le poche routine che ne hanno
  bisogno.

  -fomit-frame-pointer consente al codice generato di evitare la stupida
  gestione del frame pointer, il che rende il codice pi piccolo e
  veloce e libera un registro per ulteriori ottimizzazioni.  Ci
  preclude il comodo utilizzo degli strumenti per il debugging (gdb), ma
  nel momento in cui usate questi strumenti, non  che vi importi poi
  molto delle dimensioni e della velocit.

  -m386 produce codice pi compatto, senza alcun rallentamento
  misurabile (notate che codice piccolo significa anche meno I/O per il
  disco ed esecuzione pi rapida), ma forse sui suddetti cicli stretti
  potreste apprezzare -mpentium per il GCC speciale che ottimizza per
  pentium (sempre che abbiate come obiettivo proprio una piattaforma
  pentium).

  -Wall abilita tutti gli avvisi e vi aiuta a scovare errori stupidi ed
  ovvii.

  Per ottimizzare ancora di pi, l'opzione -mregparm=2 e/o il
  corrispondente attributo per le funzioni vi potrebbero essere utili<,
  ma potrebbero porre un sacco di problemi qualora doveste fare un link
  con codice estraneo...

  Notate che potete rendere questi flag quelli predefiniti modificando
  il file /usr/lib/gcc-lib/i486-linux/2.7.2.2/specs o dovunque esso si
  trovi nel vostro sistema (meglio non aggiungere -Wall in quella sede,
  comunque).



  33..22..  GGAASS

  GAS  l'assemblatore GNU, su cui fa affidamento GCC.



  33..22..11..  DDoovvee ttrroovvaarrlloo

  Lo trovate nello stesso posto dove avete trovato GCC, in un pacchetto
  denominato binutils.



  33..22..22..  CCooss'' llaa ssiinnttaassssii AATT&&TT

  Poich GAS  stato concepito per supportare un compilatore UNIX a 32
  bit, esso utilizza la notazione standard AT&T, che assomiglia molto
  alla sintassi degli assemblatori standard per m68k ed  standard nel
  mondo UNIX.  Questa sintassi non  n peggiore n migliore della
  sintassi Intel.   semplicemente diversa.  Una volta che ci si 
  abituati, la si trova molto pi regolare della sintassi Intel, anche
  se un po' noiosa.

  Ecco le cose a cui prestare maggiore attenzione quando si ha a che
  fare con la sintassi di GAS:

    I nomi dei registri hanno % come prefisso, cosicch i registri sono
     %eax, %dl e cos via invece di solo eax, dl, ecc.  Ci fa s che
     sia possibile includere simboli C esterni direttamente nel sorgente
     assembly, senza alcun rischio di confusione e senza alcun bisogno
     di orribili underscore anteposti.

    L'ordine degli operandi  la sorgente (o sorgenti) per prima e la
     destinazione per ultima, che  l'opposto della convenzione Intel di
     avere prima la destinazione e le sorgenti per ultime.  Quindi, ci
     che nella sintassi intel  mov ax,dx (carica il contenuto del
     registro dx nel registro ax) diventer mov %dx, %ax nella sintassi
     AT&T.

    La lunghezza dell'operando  specificata tramite un suffisso al
     nome dell'istruzione.  Il suffisso  b per byte (8 bit), w per word
     (16 bit) e l per long (32 bit). Ad esempio, la sintassi corretta
     per l'istruzione menzionata poco fa sarebbe stata movw %dx,%ax.
     Comunque, gas non richiede una sintassi AT&T rigorosa, quindi il
     suffisso  opzionale quando la lunghezza pu essere ricavata dai
     registri usati come operandi, altrimenti viene posta a 32 bit per
     default (con un avviso).

    Gli operandi immediati sono indicati con il prefisso $, come in
     addl $5,%eax (somma il valore long 5 al registro %eax).

    L'assenza di prefisso in un operando indica che  un indirizzo di
     memoria; perci movl $pippo,%eax mette l'_i_n_d_i_r_i_z_z_o della variabile
     pippo nel registro %eax, mentre movl pippo,%eax mette il contenuto
     della variabile pippo nel registro %eax.


    L'indicizzazione o l'indirezione  ottenuta racchiudendo il
     registro indice o l'indirizzo della cella di memoria di indirezione
     tra parentesi, come in testb $0x80,17(%ebp) (esegue un test sul bit
     pi alto del valore byte all'offset 17 dalla cella puntata da
     %ebp).


  Esiste un programma per aiutarvi a convertire programmi dalla sintassi
  TASM alla sintassi AT&T. Date un'occhiata a

  <ftp://x2ftp.oulu.fi/pub/msdos/programming/convert/ta2asv08.zip>

  GAS ha una documentazione esauriente in formato TeXinfo, che trovate
  nella distribuzione dei sorgenti (e forse altrove).  Potete sfogliare
  le pagine .info estratte con emacs o con ci che pi vi aggrada.
  C'era un file chiamato gas.doc o as.doc dalle parti del pacchetto
  sorgente di GAS, ma  stato incorporato nella documentazione in
  TeXinfo.  Certo, in caso di dubbio, la documentazione definitiva sono
  i sorgenti stessi!  Una sezione che vi interesser particolarmente 
  Machine Dependencies::i386-Dependent::


  Ancora, i sorgenti di Linux (il kernel del sistema operativo) si
  rivelano buoni esempi; date un'occhiata ai seguenti file sotto
  linux/arch/i386:

  kernel/*.S, boot/compressed/*.S, mathemu/*.S

  Se state scrivendo qualcosa tipo un linguaggio, un pacchetto per i
  thread, ecc.  potreste anche guardare come si comportano altri
  linguaggi (OCaml, gforth, ecc.) o pacchetti per i thread
  (QuickThreads, MIT pthreads, LinuxThreads, etc), o quel che .

  Infine, limitarsi a compilare un programma C in assembly potrebbe
  mostrarvi la sintassi del genere di istruzioni che vi interessano.
  Vedere la precedente sezione ``Avete bisogno dell'assembly?''.



  33..22..33..  MMooddoo aa 1166 bbiitt lliimmiittaattoo

  GAS  un assemblatore a 32 bit, il suo compito  quello di supportare
  un compilatore a 32 bit.  Attualmente ha solo un supporto limitato per
  il modo a 16 bit, che consiste nell'anteporre i prefissi per i 32 bit
  alle istruzioni, cosicch scrivete codice a 32 bit che gira nel modo a
  16 bit su una CPU a 32 bit.  In entrambi i modi supporta l'uso dei
  registri a 16 bit, ma non l'indirizzamento a 16 bit.

  Utilizzate le direttive .code16 e .code32 per passare da un modo
  all'altro.  Notate che un'istruzione di assembly inline
  asm(".code16\n") consentir a GCC di produrre codice a 32 bit che
  girer in real mode!

  Mi  stato detto che la maggior parte del codice necessario per
  supportare pienamente la programmazione nel modo a 16 bit  stata
  aggiunta a GAS da Bryan Ford (si prega di confermare), tuttavia non si
  trova in nessuna delle distribuzioni che ho provato, fino a
  binutils-2.8.1.x ... sarebbero gradite maggiori informazioni su questo
  argomento.

  Una soluzione economica  quella di definire macro (vedere in seguito)
  che in qualche modo producono la codifica binaria (con .byte) solo per
  le istruzioni del modo a 16 bit di cui avete bisogno (quasi nessuna se
  usate il codice a 16 bit come sopra e se potete supporre con certezza
  che il codice girer su una CPU x86 in grado di gestire i 32 bit).
  Per trovare la codifica corretta, potete ispirarvi ai sorgenti degli
  assemblatori in grado di gestire i 16 bit.


  33..33..  GGAASSPP

  GASP (GAS Preprocessor)  il Preprocessore per GAS.  Aggiunge macro e
  dei costrutti sintattici carini a GAS.



  33..33..11..  DDoovvee ttrroovvaarree GGAASSPP

  GASP si trova assieme a GAS nell'archivio binutils di GNU.



  33..33..22..  CCoommee ffuunnzziioonnaa

  Funziona come un filtro, in modo molto simile a cpp e programmi
  analoghi.  Non ho alcuna idea sui dettagli, ma assieme ad esso trovate
  documentazione relativa in texinfo, perci limitatevi a sfogliarla (in
  .info), stamparla, sviscerarla.  GAS con GASP mi sembra un comune
  assemblatore con macro.


  33..44..  NNAASSMM

  Il progetto Netwide Assembler sta producendo un ulteriore
  assemblatore, scritto in C, che dovrebbe essere abbastanza modulare
  per supportare eventualmente tutte le sintassi ed i formati di oggetto
  conosciuti.


  33..44..11..  DDoovvee ttrroovvaarree NNAASSMM

  <http://www.cryogen.com/Nasm>

  Le release binarie, nel vostro solito mirror di sunsite, sotto
  devel/lang/asm/.  Dovrebbero inoltre essere disponibili come .rpm o
  .deb nei contrib delle vostre distribuzioni RedHat/Debian.


  33..44..22..  CCoossaa ffaa

  Nel momento in cui questo HOWTO viene scritto, la versione corrente di
  NASM  0.96.

  La sintassi  in stile Intel.   integrato del supporto per le macro.
  I formati di file oggetto supportati sono bin, aout, coff, elf, as86,
  (DOS) obj, win32, rdf (il loro formato specifico).

  NASM pu essere usato come backend per il compilatore libero LCC (sono
  inclusi i file di supporto).

  Di certo NASM si evolve troppo rapidamente perch questo HOWTO possa
  essere aggiornato.  A meno che voi stiate usando BCC come compilatore
  a 16 bit (il che esula dagli scopi di questo HOWTO sulla
  programmazione a 32 bit), dovreste usare NASM invece di, ad esempio,
  ASM o MASM, perch  attivamente supportato online e gira su tutte le
  piattaforme.

  Nota: con NASM trovate anche un disassemblatore, NDISASM.

  Il suo parser scritto a mano lo rende molto pi veloce di GAS anche
  se, ovviamente, non supporta tre fantastiliardi di architetture
  differenti.  Se volete generare codice per x86, dovrebbe essere
  l'assemblatore da scegliere.


  33..55..  AASS8866

  AS86  un assemblatore 80x86 a 16 e 32 bit, parte del compilatore C di
  Bruce Evans (BCC).  Segue fondamentalmente la sintassi Intel, anche se
  ne discosta leggermente per quanto riguarda le modalit di
  indirizzamento.


  33..55..11..  DDoovvee pprrooccuurraarrssii AASS8866

  Una versione decisamente superata di AS86  distribuita da HJLu
  semplicemente per compilare il kernel di Linux, in un pacchetto
  chiamato bin86 (versione corrente: 0.4), disponibile in ogni archivio
  di GCC per Linux.  Tuttavia non consiglio a nessuno di usarlo per
  qualcosa che non sia compilare Linux. Questa versione supporta solo
  una versione modificata del formato per file oggetto di minix, che non
   supportata dalle binutils GNU o altro e che ha qualche bug nel modo
  a 32 bit, quindi fareste proprio meglio a tenerla solo per compilare
  Linux.

  Le versioni pi recenti realizzate da Bruce Evans (bde@zeta.org.au)
  sono pubblicate assieme alla distribuzione FreeBSD.  Beh, lo erano:
  non sono riuscito a trovare i sorgenti dalla distribuzione 2.1 in poi
  :( Quindi, metto i sorgenti da me:

  <http:///www.eleves.ens.fr:8080/home/rideau/files/bcc-95.3.12.src.tgz>

  Il progetto Linux/8086 (conosciuto anche come ELKS) sta in qualche
  modo mantenendo bcc (anche se non credo che abbiano incluso le patch
  per i 32 bit).  Date un'occhiata dalle parti di
  <http://www.linux.org.uk/Linux8086.html> <ftp://linux.mit.edu/>.

  Tra l'altro, queste versione pi recenti, contrariamente a quelle di
  HJLu, supportano il formato GNU a.out per Linux, cosicch  possibile
  il linking tra il vostro codice ed i programmi Linux e/o l'utilizzo
  dei soliti strumenti dal pacchetto GNU binutil per manipolare i vostri
  dati.  Questa versione pu coesistere senza alcun danno con quella
  precedente (vedere la domanda relativa in seguito).

  BCC, versione del 12 marzo 1995 e precedenti, esegue i push ed i pop
  di segmenti soltanto a 16 bit, il che  non poco seccante quando si
  programma nel modo a 32 bit.

  Una patch  disponibile nel progetto Tunes
  <http://www.eleves.ens.fr:8080/home/rideau/Tunes/> alla sottopagina
  files/tgz/tunes.0.0.0.25.src.tgz nella directory decompressa LLL/i386/
  La patch dovrebbe anche essere disponibile direttamente da
  <http://www.eleves.ens.fr:8080/home/rideau/files/as86.bcc.patch.gz>
  Bruce Evans ha accettato questa patch, cos se un giorno ci sar da
  qualche parte una versione pi recente di bcc, la patch dovrebbe
  essere stata inclusa.


  33..55..22..  CCoommee iinnvvooccaarree ll''aasssseemmbbllaattoorree??

  Ecco la voce nel Makefile di GNU per usare bcc allo scopo di
  trasformare asm .s in oggetto .o ed ottenere un listato .l :



  ______________________________________________________________________
  %.o %.l:        %.s
          bcc -3 -G -c -A-d -A-l -A$*.l -o $*.o $<
  ______________________________________________________________________



  Togliete %.l, -A-l e -A$*.l se non volete alcun listato.  Se volete
  qualcos'altro invece di un a.out GNU, potete consultare la
  documentazione di bcc circa gli altri formati supportati e/o
  utilizzare objcopy dal pacchetto delle GNU binutils.


  33..55..33..  DDoovvee ttrroovvaarree ddooccuummeennttaazziioonnee

  La documentazione  quella che  inclusa nel pacchetto bcc.  Da
  qualche parte nel sito di FreeBSD sono inoltre disponibili le pagine
  di manuale.  In caso di dubbi, i sorgenti stessi sono spesso una buona
  documentazione: non  molto ben commentata, ma lo stile di
  programmazione  chiaro.  Potreste provare a vedere come as86 
  utilizzato in Tunes 0.0.0.25...



  33..55..44..  EE ssee nnoonn rriieessccoo ppii aa ccoommppiillaarree LLiinnuuxx ccoonn qquueessttaa nnuuoovvaa vveerr
  ssiioonnee??

  Linus  sepolto vivo nella posta e la mia patch per compilare Linux
  con as86 a.out per Linux non ce l'ha fatta ad arrivargli (!).  Ora,
  questo non dovrebbe avere importanza: limitatevi a tenere il vostro
  as86 dal pacchetto bin86 in /usr/bin e lasciate che bcc installi
  l'as86 buono come /usr/local/libexec/i386/bcc/as dove dovrebbe
  risiedere.  Non avrete mai bisogno di chiamare esplicitamente questo
  as86 buono, perch bcc fa tutto come si deve, compresa la
  conversione dal formato a.out di Linux quando viene invocato con le
  opzioni corrette; limitatevi perci ad assemblare usando bcc come
  frontend, non fatelo direttamente con as86.



  33..66..  AALLTTRRII AASSSSEEMMBBLLAATTOORRII

  Queste sono altre scelte possibili, non convenzionali, nel caso in cui
  le precedenti non vi abbiano soddisfatto (perch?).  Non le consiglio
  nei casi comuni (?), ma potrebbero rivelarsi molto utili se
  l'assemblatore deve essere integrato nel software che state
  progettando (ad esempio un sistema operativo o un ambiente di
  sviluppo).



  33..66..11..  LL''aasssseemmbbllaattoorree WWiinn3322FFoorrtthh

  Win32Forth  un sistema ANS FORTH a 32 bit _l_i_b_e_r_o che gira sotto
  Win32s, Win95, Win NT.  Include un assemblatore libero a 32 bit (con
  sintassi prefissa o postfissa) integrato nel linguaggio FORTH.  La
  gestione delle macro  realizzata con la piena potenza del linguaggio
  FORTH; comunque, l'unico contesto di input e di output supportato 
  Win32Forth stesso (nessuna creazione di file .obj ; certo, potreste
  aggiungerla voi stessi).  Lo trovate qui:
  <ftp://ftp.forth.org/pub/Forth/win32for/>



  33..66..22..  TTeerrssee

  Terse  uno strumento di programmazione con _L_A sintassi
  dell'assemblatore pi compatta per la famiglia x86!

  Vedere  <http://www.terse.com>.  Si dice che ce ne sia un clone libero
  da qualche parte.  Sarebbe stato abbandonato in seguito a pretese
  infondate secondo le quali la sintassi apparterrebbe all'autore
  originale.  Vi invito a continuarne lo sviluppo, nel caso la sintassi
  vi interessi.



  33..66..33..  AAsssseemmbbllaattoorrii nnoonn lliibbeerrii ee//oo nnoonn aa 3322 bbiitt..

  Potete trovare pi informazioni a riguardo, assieme alle basi della
  programmazione assembly per x86, nelle FAQ di Raymond Moon per
  comp.lang.asm.x86 <http://www2.dgsys.com/~raymoon/faq/asmfaq.zip>

  Va notato che tutti gli assemblatori che si basano sul DOS dovrebbero
  funzionare sotto l'emulatore di DOS per Linux ed altri emulatori
  analoghi cosicch, se ne possedete gi uno, potete continuare ad
  usarlo in un vero sistema operativo.  Alcuni assemblatori recenti per
  DOS supportano anche COFF e/o altri formati di file oggetto che sono
  supportati dalla libreria GNU BFD, cos potete usarli insieme ai
  vostri strumenti liberi a 32 bit, magari usando GNU objcopy (che fa
  parte delle binutils) come filtro di conversione.



  44..  MMEETTAAPPRROOGGRRAAMMMMAAZZIIOONNEE EE MMAACCRROO

  La programmazione in assembly  una scocciatura, tranne che per
  sezioni critiche dei programmi.

  Dovreste usare gli strumenti appropriati per il compito giusto, quindi
  non scegliete l'assembly quando non  adatto; C, OCAML, perl, Scheme
  potrebbero essere una scelta migliore per la maggior parte della
  vostra programmazione.

  Comunque, ci sono casi in cui questi strumenti non consentono un
  controllo sufficientemente accurato della macchina e l'assembly
  risulta utile o addirittura necessario.  In questi casi, vi sar utile
  un sistema di macro e metaprogrammazione che permetter di ridurre
  ogni struttura ricorrente in una definizione riutilizzabile molte
  volte, il che consente una programmazione pi sicura, la propagazione
  automatica delle modifiche alla struttura stessa, ecc.

  Un assemblatore liscio  spesso insufficiente, anche quando si
  sviluppano semplicemente piccole routine per un linking con il C.


  44..11..  CCoossaa  iinntteeggrraattoo nneeii ppaacccchheettttii mmeennzziioonnaattii

  S, lo so che questa sezione non contiene molte informazioni
  aggiornate.  Sentitevi liberi di contribuire ci che scoprite sulla
  vostra pelle...


  44..11..11..  GGCCCC

  GCC permette (e richiede) che voi specifichiate vincoli sui registri
  nel vostro codice assembly inline cosicch l'ottimizzatore ne  sempre
  al corrente; perci il codice assembly inline, in realt, non  per
  forza costituito da codice esatto, ma da strutture.
  Potete poi inserire il vostro assembly in macro di CPP ed in funzioni
  C inline, cos si pu usare come una qualsiasi macro o funzione C.  Le
  funzioni inline assomigliano molto alle macro, ma il loro uso risulta
  talvolta pi pulito.  Badate che in tutti questi casi si avr una
  duplicazione di codice, quindi in questo codice asm dovrebbero essere
  definite solo etichette locali (del tipo 1:).  Comunque, una macro
  permetterebbe che il nome di una etichetta non definita localmente
  venga passato come parametro (oppure utilizzate metodi aggiuntivi di
  metaprogrammazione).  Inoltre, propagare codice asm inline diffonder
  potenziali bug presenti in esso, state quindi doppiamente attenti ai
  vincoli sui registri in situazioni simili.

  Infine, il linguaggio C stesso pu essere considerato una buona
  astrazione rispetto al linguaggio assembly, il che vi solleva dalla
  maggior parte dei problemi legati all'assembling.

  Fate attenzione: alcune ottimizzazioni riguardanti il passaggio di
  argomenti a funzioni tramite registri possono rendere dette funzioni
  inadatte ad essere chiamate da routine esterne (ed in particolare da
  quelle scritte a mano in assembly) nel modo standard; l'attributo
  asmlinkage potrebbe impedire ad una routine di preoccuparsi di tale
  flag di ottimizzazione; guardatevi i sorgenti del kernel per gli
  esempi.



  44..11..22..  GGAASS

  GAS fornisce del supporto per le macro, come  spiegato in dettaglio
  nella documentazione texinfo.  GCC, oltra a riconoscere i file .s come
  assembly grezzo da inviare a GAS, riconosce anche i file .S come
  file da passare attraverso CPP prima di mandarli a GAS.  Ancora una
  volta, guardate i sorgenti di Linux per gli esempi.


  44..11..33..  GGAASSPP

  Aggiunge tutti i tipici trucchetti delle macro a GAS.  Consultate la
  sua documentazione texinfo.


  44..11..44..  NNAASSMM

  Anche NASM ha del supporto per le macro.  Date un'occhiata alla
  documentazione relativa.  Se avete qualche idea brillante, potreste
  voler contattare gli autori, dal momento che lo stanno sviluppando
  attivamente.  Nel frattempo, date un'occhiata ai filtri esterni
  presentati in seguito.


  44..11..55..  AASS8866

  Ha un po' di semplice supporto per le macro, ma non sono riuscito a
  trovare della documentazione.  I sorgenti sono molto chiari perci se
  siete interessati dovreste capirli facilmente.  Se le capacit di base
  non vi bastano, dovreste usare un filtro esterno (vedere in seguito).



  44..11..66..  AALLTTRRII AASSSSEEMMBBLLAATTOORRII


    Win32FORTH: CODE ed END-CODE sono delle macro che non commutano dal
     modo interpretazione al modo compilazione, cosicch avete pieno
     accesso alla potenza del FORTH durante l'assembling.

    TUNES: non funziona ancora, ma Scheme  un vero linguaggio ad alto
     livello che consente metaprogrammazione arbitraria.



  44..22..  FFiillttrrii eesstteerrnnii

  Qualunque sia il supporto per le macro del vostro assemblatore, o
  qualunque linguaggio utilizziate (perfino il C!), se secondo voi il
  linguaggio non  sufficientemente espressivo, potete far passare i
  file attraverso un filtro esterno con una regola come questa nel
  Makefile:


  ______________________________________________________________________
  %.s:    %.S altre_dipendenze
              $(FILTRO) $(OPZIONI_DEL_FILTRO) < $< > $@
  ______________________________________________________________________



  44..22..11..  CCPPPP

  CPP non  molto espressivo, ma  sufficiente per le cose facili, 
  standard ed  chiamato in modo trasparente da GCC.

  Per fare un esempio delle sue limitazioni, non si possono dichiarare
  oggetti in modo tale che i distruttori vengano chiamati
  automaticamente al termine del blocco di dichiarazione; non avete
  diversion o regole di visibilit (scoping), ecc.

  CPP si trova assieme ad ogni compilatore C. Se ve la siete cavata
  senza averne uno, non preoccupatevi di procurarvi GCC (anche se mi
  chiedo come abbiate fatto).


  44..22..22..  MM44

  M4 vi d tutta la potenza delle macro, con un linguaggio Turing-
  equivalente, ricorsione, espressioni regolari, ecc.  Potete farci
  tutto ci che CPP non riesce a fare.

  Date un'occhiata a macro4th/This4th da
  <ftp://ftp.forth.org/pub/Forth/> in Reviewed/ ANS/ (?), o le sorgenti
  di Tunes 0.0.0.25 come esempi di un utilizzo avanzato delle macro con
  m4.  Comunque, il suo scomodo sistema di protezione dall'espansione vi
  obbliga ad utilizzare per le macro uno stile basato sulla ricorsione
  in coda con passaggio di continuazione esplicito (explicit
  continuation-passing) se volete una uso _a_v_a_n_z_a_t_o delle macro (il che
  ricorda TeX. A proposito, qualcuno ha provato ad usare TeX per le
  macro di qualcosa di diverso dalla composizione tipografica?).  Questo
  comunque NON  peggio di CPP, il quale non permette n il quoting n
  la ricorsione.  La versione giusta di m4 da procurarsi  GNU m4 1.4 (o
  successiva, se esiste), la quale ha il maggior numero di funzionalit
  ed il minor numero di bug o limitazioni rispetto alle altre.  m4 
  progettato per essere lento per tutto tranne gli utilizzi pi
  semplici, il che potrebbe andare ancora bene per la maggior parte dei
  programmi assembly (non state scrivendo programmi in assembly da
  milioni di righe, vero?).



  44..22..33..  MMaaccrroo ccoonn ii vvoossttrrii ffiillttrrii

  Potete scrivervi dei semplici filtri per l'espansione delle macro con
  i soliti strumenti: perl, awk, sed, ecc.  Si fa in fretta ed avete il
  controllo su tutto.  Ma ovviamente, la potenza nella gestione delle
  macro bisogna guadagnarsela con fatica.



  44..22..44..  MMeettaapprrooggrraammmmaazziioonnee

  Invece di usare un filtro esterno che espande le macro, un modo
  alternativo di procedere  quello di scrivere programmi che scrivono
  parti di altri programmi (o interi programmi).

  Ad esempio, potreste utilizzare un programma che dia in uscita codice
  sorgente

    per generare tavole precalcolate di seno/coseno/quant'altro,

    per estrarre una rappresentazione in forma sorgente di un file
     binario,

    per inserire le vostre bitmap nel codice compilato di routine di
     visualizzazione rapide,

    per estrarre documentazione, codice di
     inizializzazione/conclusione, tabelle di descrizione cos come
     codice ordinario dagli stessi file sorgenti,

    per avere codice assembly personalizzato, generato da uno script
     perl/shell/scheme che si occupa di elaborazione generica.

    per propagare dati definiti in un punto solo verso vari pezzi di
     codice e tabelle con riferimenti incrociati.

    ecc.

  Pensateci!



  44..22..44..11..  BBaacckkeenndd ddaa ccoommppiillaattoorrii eessiisstteennttii

  Compilatori come SML/NJ, Objective CAML, MIT-Scheme, ecc.  hanno il
  loro backend generico per gli assemblatori che potreste o meno voler
  usare se intendete generare semiautomaticamente del codice partendo
  dai linguaggi relativi.



  44..22..44..22..  IIll NNeeww--JJeerrsseeyy MMaacchhiinnee--CCooddee TToooollkkiitt

  C' un progetto per costruire, usando il linguaggio di programmazione
  Icon, una base per produrre codice che manipola l'assembly. Date
  un'occhiata dalle parti di <http://www.cs.virginia.edu/~nr/toolkit/>



  44..22..44..33..  TTuunneess

  Il progetto Tunes OS sta sviluppando il suo assemblatore come
  un'estensione al linguaggio Scheme, come parte del suo processo di
  sviluppo.  Al momento non  ancora in grado di girare, tuttavia ogni
  aiuto  bene accetto.

  L'assemblatore manipola alberi di sintassi simbolici, cos pu
  ugualmente servire come base per un traduttore di sintassi assembly,
  un disassemblatore, un backend comune per assemblatore/compilatore,
  ecc.  Inoltre tutta la potenza di un vero linguaggio, Scheme, lo rende
  insuperato per quanto riguarda le macro e la metaprogrammazione.

  <http://www.eleves.ens.fr:8080/home/rideau/Tunes/>



  55..  CCOONNVVEENNZZIIOONNII DDII CCHHIIAAMMAATTAA



  55..11..  LLiinnuuxx



  55..11..11..  LLiinnkkiinngg aa GGCCCC

   il modo preferito.  Controllate la documentazione di GCC e gli
  esempi dai file .S del kernel di Linux che passano attraverso gas (non
  quelli che passano attraverso as86).

  Gli argomenti a 32 bit vengono posti sullo stack (push) in ordine
  inverso rispetto alla sintassi (per cui vi si accede prelevandoli
  nell'ordine corretto) sopra l'indirizzo di ritorno a 32 bit.  %ebp,
  %esi, %edi, %ebx sono salvati dalla funzione chiamata, gli altri dalla
  funzione chiamante; per contenere il risultato si usa %eax, oppure
  %edx:%eax per risultati a 64 bit.

  Stack FP: non ne sono certo, ma penso che il risultato vada in st(0) e
  che l'intero stack sia salvato dalla funzione chiamante.  Notate che
  GCC ha delle opzioni per modificare le convenzioni di chiamata
  riservando registri, per mettere argomenti nei registri, per non fare
  supposizioni sulla presenza dell'FPU, ecc.  Controllate le pagine
  .info i386 .

  Fate attenzione: in questo caso dovete dichiarare l'attributo decl per
  una funzione che seguir le convenzioni di chiamata standard di GCC
  (non so cosa faccia con le convenzioni di chiamata modificate).
  Leggete le pagine info di GCC nella sezione: C Extensions::Extended
  Asm::



  55..11..22..  EELLFF eedd aa..oouutt :: pprroobblleemmii..

  Alcuni compilatori C antepongono un underscore prima di ogni simbolo,
  mentre altri non lo fanno.

  In particolare, GCC a.out per Linux effettua questa anteposizione,
  mentre GCC ELF per Linux no.

  Se avete bisogno di gestire insieme entrambi i comportamenti, guardate
  come fanno i pacchetti esistenti.  Ad esempio, procuratevi dei vecchi
  sorgenti di Linux, Elk, qthreads, o OCAML...

  Potete inoltre far ignorare la rinominazione implicita C->asm
  inserendo istruzioni come


  ______________________________________________________________________
          void pippo asm("pluto") (void);
  ______________________________________________________________________


  per essere sicuri che la funzione C pippo venga chiamata davvero
  pluto in assembly.

  Notate che il programma di utilit objcopy, dal pacchetto binutils,
  dovrebbe permettervi di trasformare i vostri oggetti a.out in oggetti
  ELF e forse anche viceversa, in alcuni casi.  Pi in generale,
  effettuer un gran numero di conversioni di formato dei file.



  55..11..33..  LLiinnuuxx:: cchhiiaammaattee ddii ssiisstteemmaa ddiirreettttee

  Ci  espressamente _N_O_N consigliato, poich le convenzioni cambiano di
  tanto in tanto o tra varianti del kernel (vedere L4Linux), inoltre si
  perde la portabilit, comporta un lavoro di scrittura massiccio, si ha
  ridondanza con gli sforzi di libc ED INOLTRE preclude estensioni e
  correzioni apportate a libc come, ad esempio, il pacchetto zlibc, che
  provvede ad una trasparente decompressione al volo di file compressi
  con gzip.  Il metodo convenzionale e consigliato per chiamare i
  servizi di sistema di Linux , e rimarr, quello di passare attraverso
  la libc.

  Gli oggetti condivisi dovrebbero mantenere la vostra roba entro
  dimensioni contenute.  E se proprio volete binari pi piccoli,
  utilizzate #!  e scaricate sull'interprete il fardello che volete
  togliere dai vostri binari.

  Ora, se per qualche ragione non volete fare un link alla libc,
  procuratevi la libc stessa e capite come funziona!  Dopotutto,
  aspirate a sostituirla, no?

  Potreste inoltre dare un'occhiata a come il mio eforth 1.0c
  <ftp://ftp.forth.org/pub/Forth/Linux/linux-eforth-1.0c.tgz> lo fa.

  Anche i sorgenti di Linux tornano utili, in particolare l'header file
  asm/unistd.h, che descrive come effettuare le chiamate di sistema...

  Fondamentalmente, generate un int $0x80, con il numero associato a
  __NR_nomedellasyscall (da asm/unistd.h) in %eax, ed i parametri (fino
  a cinque) in %ebx, %ecx, %edx, %esi, %edi rispettivamente.  Il
  risultato viene restituito in %eax, dove un numero negativo  un
  errore il cui opposto  ci che libc metterebbe in errno.  Lo stack
  utente non viene toccato, cos non  necessario averne uno valido
  quando effettuate una chiamata di sistema.



  55..11..44..  II//OO ssoottttoo LLiinnuuxx

  Se volete effettuare dell'I/O sotto Linux, o si tratta di qualcosa di
  molto semplice che non richiede l'arbitraggio del sistema operativo, e
  allora dovreste consultare l'IO-Port-Programming mini-HOWTO, oppure ha
  bisogno di un driver di periferica nel kernel, nel qual caso dovreste
  provare ad approfondire le vostre conoscenze sull'hacking del kernel,
  sullo sviluppo di driver di periferica, sui moduli del kernel, ecc.,
  per i quali ci sono altri eccellenti HOWTO e documenti del LDP.

  In particolare, se ci che vi interessa  la programmazione della
  grafica, allora partecipate al progetto GGI:
  <http://synergy.caltech.edu/~ggi/> <http://sunserver1.rz.uni-
  duesseldorf.de/~becka/doc/scrdrv.html>

  Comunque, in tutti questi casi, fareste meglio ad usare l'assembly
  inline di GCC con le macro da linux/asm/*.h piuttosto che scrivere
  file sorgenti completamente in assembly.


  55..11..55..  AAcccceeddeerree aa ddrriivveerr aa 1166 bbiitt ddaa LLiinnuuxx//ii338866

  Ci  teoricamente possibile (dimostrazione: guardate come DOSEMU
  riesca a garantire ai programmi un accesso a porte hardware in modo
  selettivo), ed ho anche sentito voci secondo le quali qualcuno da
  qualche parte ci sarebbe di fatto riuscito (nel driver PCI?  Roba per
  l'accesso VESA? ISA PnP? Non so).  Se avete informazioni pi precise a
  riguardo, siate i benvenuti.  Comunque, buoni posti in cui cercare
  maggiori informazioni sono i sorgenti del kernel di Linux, i sorgenti
  di DOSEMU (ed altri programmi nel DOSEMU repository
  <ftp://tsx-11.mit.edu/pub/linux/ALPHA/dosemu/>), e sorgenti di vari
  programmi a basso livello sotto Linux...  (forse GGI se supporta
  VESA).  Fondamentalmente, dovete usare la modalit protetta a 16 bit o
  il modo vm86.

  Il primo  pi semplice da mettere in piedi, ma funziona solamente con
  codice educato (well-behaved) che non utilizza l'aritmetica dei
  segmenti o indirizzamento assoluto degli stessi (segmento 0 in
  particolare), a meno che non ci si trovi nel caso in cui tutti i
  segmenti utilizzati possano essere preparati in anticipo nella LDT.

  Il secondo permette pi compatibilit con i comuni ambienti a 16
  bit, ma richiede una gestione pi complessa.

  In entrambi i casi, prima di poter saltare al codice a 16 bit, dovete

    fare un mmap di tutti gli indirizzi assoluti utilizzati nel codice
     a 16 bit (come ROM, buffer video, zone su cui agir il DMA ed I/O
     memory-mapped) da /dev/mem allo spazio indirizzi del vostro
     processo.

    preparare la LDT e/o il monitor per il modo vm86

    ottenere gli opportuni permessi di I/O dal kernel (vedere sopra)

  Ancora una volta, leggete con cura i sorgenti dei contributi al DOSEMU
  repository menzionato sopra, in particolare quei mini-emulatori per
  far girare ELKS e/o semplici programmi .COM sotto Linux/i386.


  55..22..  DDOOSS

  La maggior parte dei DOS extender viene fornita con
  dell'interfacciamento a servizi DOS.  Leggete la loro documentazione a
  riguardo, ma spesso si limitano a simulare int $0x21 e simili, cos vi
  comportate come se foste in modo reale (dubito che abbiano qualcosa
  di pi di stub ed estensioni per lavorare con operandi a 32 bit; molto
  probabilmente si limiteranno a riportare l'interrupt nel gestore del
  modo reale o del vm86).

  Documentazione su DPMI e affini (e molto pi) pu essere trovata in
  <ftp://x2ftp.oulu.fi/pub/msdos/programming/>

  Anche DJGPP viene fornito con il proprio
  derivato/sottoinsieme/sostituto di glibc.

   possibile la compilazione incrociata da Linux a DOS, guardate nella
  directory devel/msdos/ del vostro mirror locale dell'area FTP di
  sunsite.unc.edu Date anche un'occhiata al DOS extender MOSS dal
  progetto Flux in Utah.

  Altri documenti e FAQ sono molto DOS-centrici.  Noi non consigliamo di
  sviluppare per DOS.



  55..33..  WWiinnzzoozzzz ee ccoommppaaggnniiaa bbeellllaa

  Ehi, questo documento riguarda solo il software libero.  Telefonatemi
  quando Winzozz diventa libero, o ci si possono usare strumenti di
  sviluppo liberi!

  Beh, dopotutto ci sono: Cygnus Solutions <http://www.cygnus.com> ha
  sviluppato la libreria cygwin32.dll per far girare i programmi GNU su
  piattaforme Micrashoft.  Cos potete usare GCC, GAS, tutti gli
  strumenti di GNU e molte altre applicazioni UNIX.  Date un'occhiata
  alla loro homepage.  Io (Far) non intendo dilungarmi sulla
  programmazione di WinnaNanna ma sono certo che potete trovare un sacco
  di documentazione a riguardo praticamente ovunque...



  55..44..  UUnn ssiisstteemmaa ooppeerraattiivvoo ttuuttttoo vvoossttrroo..

  Essendo il controllo ci che attrae molti programmatori all'assembly,
  il desiderio di sviluppare sistemi operativi  spesso ci che li porta
  all'(o deriva dall') hacking in assembly.  Va notato che ogni sistema
  che permette lo sviluppo di se stesso potrebbe essere considerato un
  sistema operativo, anche se magari gira sopra ad un sistema
  sottostante che fornisce multitasking o I/O (in modo molto simile a
  Linux sopra Mach o OpenGenera sopra UNIX), ecc.

  Quindi, per rendere pi facile il debugging, potreste voler sviluppare
  il vostro sistema operativo prima come processo che gira sopra a
  Linux (nonostante la lentezza), quindi usare il Flux OS kit
  <http://ww.cs.utah.edu/projects/flux/> (che consente l'utilizzo di
  driver di Linux e BSD nel vostro OS) per renderlo autonomo.  Quando il
  vostro sistema  stabile, resta ancora del tempo per scrivere dei
  driver per l'hardware tutti vostri, se la cosa vi fa proprio piacere.

  Questo HOWTO non si occuper di argomenti quali il codice per il boot
  loader ed entrare nel modo a 32 bit, gestire gli interrupt, i
  fondamenti degli orrori intel modo protetto o V86/R86, la
  definizione di un vostro formato per i file oggetto e le convenzioni
  di chiamata.  Il luogo principale in cui trovare informazioni
  attendibili a riguardo sono i sorgenti di sistemi operativi o
  bootloader gi esistenti.  Ci sono un sacco di riferimenti in questa
  pagina WWW:
  <http://www.eleves.ens.fr:8080/home/rideau/Tunes/Review/OSes.html>



  66..  CCOOSSEE DDAA FFAARREE EE RRIIFFEERRIIMMEENNTTII



    riempire le sezioni incomplete.

    aggiungere ulteriori riferimenti a software e documentazione.

    aggiungere esempi facili dal mondo reale per illustrare la
     sintassi, la potenza e le limitazioni di ogni soluzione proposta.

    chiedere aiuto in giro per questo HOWTO.

    trovare qualcuno che ha del tempo per subentrarmi nel mantenimento.

    che sia il caso di spendere qualche parola sull'assembly su altre
     piattaforme?

    Alcuni riferimenti (in aggiunta a quelli gi presenti nel resto
     dell'HOWTO)

       i manuali del pentium
        <http://www.intel.com/design/pentium/manuals/>

       bug nelle CPU della famiglia x86
        <http://www.xs4all.nl/~feldmann>

       hornet.eng.ufl.edu per programmatori assembly
        <http://www.eng.ufl.edu/ftp>

       ftp.luth.se <ftp://ftp.luth.se/pub/msdos/demos/code/>

       FAQ del modo protetto <ftp://zfja-
        gate.fuw.edu.pl/cpu/protect.mod>

       Pagina dell'assembly 80x86
        <http://www.fys.ruu.nl/~faber/Amain.html>

       Courseware <http://www.cit.ac.nz/smac/csware.htm>

       programmazione di giochi
        <http://www.ee.ucl.ac.uk/~phart/gameprog.html>

       esperimenti di programmazione solo in assembly sotto Linux
        <http://bewoner.dma.be/JanW>

    E ovviamente, utilizzate i vostri strumenti di ricerca su Internet
     per cercare ulteriori informazioni e ragguagliatemi su qualunque
     cosa interessante troviate!


  .sig dell'autore:

  --    ,                                         ,           _ v    ~  ^  --
  -- Fare -- rideau@clipper.ens.fr -- Francois-Rene Rideau -- +)ang-Vu Ban --
  --                                      '                   / .          --
  Join the TUNES project for a computing system based on computing freedom !
                   TUNES is a Useful, Not Expedient System
  WWW page at URL: http://www.eleves.ens.fr:8080/home/rideau/Tunes/



