Esercitazioni del corso di Laboratorio di Calcolo
     n. 2
    12 e 19 novembre 2004
    uso di emacs, del precompilatore e del compilatore g++


  1. create un sottodirettorio ex2 (usando il comando mkdir)
  2. spostatevi in ex2 (usando il comando cd)
  3. usate emacs per creare il file nepero.cc  contenente il programma che trovate a questo indirizzo  (emacs nepero.cc, inserite il codice , salvate con Save Buffer dal menu File oppure  con C-x C-s). Non e' necessario che ricopiate tutti i commenti.

  4. NB: le tastiere italiane (che prevedono caratteri speciali come le lettere accentate) non prevedono caratteri quali { } e ~ che vi serviranno spesso. Chi dovesse avere una tastiera italiana utilizzi
                    AltGr insieme al tasto 7 per {
                    AltGr insieme al tasto 0 per }
                    AltGr insieme al tasto  ^ per ~
  5. invocate il precompilatore, ovvero date il comando g++     -E    nepero.cc : come potete vedere l'uscita di questo comando e` inviata direttamente allo schermo, per poter visualizzare il codice precompilato avete bisogno di ridirigere questa informazione su un file. Questa operazione si effettua in unix mediante il comando > . Provate quindi a dare il comando g++   -E     nepero.cc   > precompilato1.cc . Modificate nepero.cc levando le due barre di commento davanti alla direttiva #define USA_MATH e  ripetete la precompilazione ridirigendo l'uscita su un altro file mediante il comando g++   -E     nepero.cc   > precompilato2.cc
  6. Visualizzate il contenuto dei files precompilato1.cc e precompilato2.cc con il comando more seguito dal nome del file. Potete osservare che il precompilatore ha inserito, oltre a molte righe vuote, tantissimo codice in cima al vostro programma: si tratta di una copia del file iostream.h che definisce le classi di oggetti che gestiscono l'Input/Output (ed in particolare gli oggetti cin e cout). Potete verificarlo andando ad aprire, sempre con more, il file iostream.h che si trova in un direttorio del sistema: /usr/include/g++-3/. Nel secondo caso viene inserita anche una copia del file math.h che si trova in /usr/include.
  7. potete anche osservare che le righe di codice soggette alla direttiva #idef USA_MATH/#else/#endif inserite nei due file precompilati sono diverse
  8. potete nuovamente commentare la direttiva #define USA_MATH in nepero.cc e osservare che l'opzione -D del compilatore ha lo stesso effetto della direttiva #define usando g++   -D USA_MATH -E     nepero.cc   > precompilato3.cc e confrontando tra di loro precompilato2.cc e precompilato3.cc (potete confrontare due file con il comando unix diff    file1    file2 : se non ottenete risposta vuol dire che non ci sono differenze, le righe diverse sono indicate con > e < )
  9. a questo punto, ora che sapete come agisce il precompilatore, potete passare al compilatore vero e proprio. Potete invocarlo sia partendo dal file da precompilare che partendo dal file precompilato con i comandi g++     -S    nepero.cc  e g++    -S    precompilato1.cc (se #define USA_MATH e' commentato) o g++    -S    precompilato2.cc (se #define USA_MATH e' attivo) e potete verificare che si ottiene lo stesso file assembly in uscita (lo potete guardare con more e potete confrontare due file con il comando unix diff    file1    file2 ).
  10. dopo la compilazione avete bisogno dell'assembler, che si invoca col comando g++   -c    nomefile   e che puo` agire su uno qualunque dei files che avete creato fino ad ora (nepero.cc,precompilato1.cc,nepero.s,precompilato1.s ...) e che produce nomefile.o. Il comando more vi consente di sbirciare anche dentro a questo file senza far danni, ma come potete vedere e` scritto in un formato non visualizzabile.
  11. per ottenere un eseguibile invece dovete invocare g++, di nuovo su uno qualunque dei files precedenti, senza opzioni (o solo con l'opzione -o nomeeseguibile posta alla fine della riga di comando se volete dare un nome diverso da a.out al vostro eseguibile: g++ nepero.cc -o nepero).
  12. per eseguire il programma e` sufficiente scrivere il nome dell'eseguibile, eventualmente preceduto da ./ per indicare che l'eseguibile si trova nel direttorio corrente (.) qualora il sistema vi rispondesse "command not found" (vuol dire che la vostra SHELL non e' ben definita e il direttorio corrente non e' nella lista di quelli tra i quali cercare gli eseguibili).
Per chi dovesse effettuare questa esercitazione in ambiende Windows esistono funzionalita' analoghe anche in altri compilatori ed in particolare si consiglia l'uso del compilatore Borland C++ (istruzioni per la sua installazione e per il suo uso)