CIAO MONDO, giocare con il CANE web al volo

Giovanni A. Cignoni, Giuliano Pacini - lavori in corso


Per mettersi nei panni degli studenti di TAMC degli anni ’70 si dovrebbe studiare, a partire dalla dispensa di Grasselli [23] per poi approfondire con la nota tecnica [17] e le tesi [18, 20]. Conosciamo però l’impazienza di vedere il CANE in funzione, quindi ecco qua il più classico degli esempi di introduzione alla programmazione pronto per essere provato al volo.

Piccola parentesi per dare la giusta prospettiva storica: gli studenti che usavano il CANE non conoscevano CIAO MONDO. Hello World comparve per la prima volta nel 1974 in un memorandum di Brian Kernighan rimasto interno ai Bell Labs. Fu poi ripreso in “The C Programming Language”, scritto con Dennis Ritchie e pubblicato nel 1978 per i tipi di Prentice-Hall. Negli anni a seguire, il libro divenne una pietra miliare, oltre che per il C, anche per lo stile dei testi sui linguaggi di programmazione: dalla formattazione tipografica, allo stile della scrittura, al programmino di primo contatto.
Anche l’essere CIAO MONDO tutto maiuscolo è un segno dei tempi: le minuscole non erano comprese nell’insieme dei caratteri che il CANE ereditava dalle periferiche dell’IBM 7090.

CIAO MONDO, minimale

Un programma per il CANE, fisicamente, sta in un pacco di schede perforate, ognuna contenente 4 parole di 18 bit. La prima scheda è per il caricatore minimo, il programmino (4 istruzioni) che carica nella memoria del CANE le schede successive, cioè il vero programma utente, anch’esso codificato in binario. CIAO MONDO si programma in 7 parole, 3 di istruzioni e 4 di dati (la stringa). Quindi 3 schede: il caricatore minimo e 2 di programma, la seconda non usata completamente.

Il CANE web legge le schede come sequenze di caratteri, questo infatti erano: le perforazioni su una colonna codificavano un carattere; il perforatore, per facilitare la lettura, stampava in alto il carattere corrispondente (esempio di scheda con tutti i caratteri del CANE). Le schede binarie avevano perforazioni solo sulle prime due righe. In pratica, CIAO MONDO è:

000111001111111000111010001000001100010100001000000100100000000000000001
111101000000000100111100000000000111000000000000000101010011011001010001
100110110000100100100110100101010100100110110000110000

Per caricare le schede copiate il testo sopra, premete il bottone Load Cards sul lettore di schede IBM 1402, incollate il testo e confermate con il bottone Carica. Le schede appaiono sul carrello e lo stato del lettore diventa Ready.
Sulla consolle del CANE, in basso a destra, c’è il bottone L: premetelo ed è fatta!

Cosa è successo? L attiva la sequenza di avvio; questa legge una scheda binaria, la carica in memoria a partire dalla locazione 0 e poi passa il controllo al programma che inizia da quella locazione. La prima scheda è il caricatore minimo; questo legge e carica in memoria le schede successive a partire dalla locazione 4, quindi passa il controllo al programma che inizia da quella locazione, cioè CIAO MONDO. Finito il programma il CANE si arresta.

L’istruzione che termina CIAO MONDO imposta il contatore di programma in modo che, riattivando l’esecuzione in continuo, riparte la stampa: assicuratevi che il commutatore S/C sia su C e premete Go.

Potete provare a premere Go due volte di seguito. Dato che la stampante è impegnata, la seconda stampa non parte subito; il CANE va in attesa e cicla sull’istruzione di stampa: si vede da rC, il contatore di programma, che oscilla fra 005 e 006.

CIAO MONDO, senza zeri

Perché la linea stampata è piena di brutti zeri? La IBM 1403 stampava sempre una linea intera, 120 caratteri presi da 40 locazioni consecutive nella memoria del CANE (la codifica dei caratteri era a 6 bit). Nel CIAO MONDO minimale la stringa è limitata all’essenziale, quindi dopo viene stampato quel che c’è in memoria, zeri se la macchina è appena accesa e CIAO MONDO il primo programma caricato (negli standard di allora la codifica del carattere ‘0’ era 0).

Per eliminare gli zeri dobbiamo completare la riga con degli spazi. Per estendere la stringa caricata servirebbero altre 9 schede: uno spreco di carta. Il CIAO MONDO che segue, con un ciclo, riempie di spazi le locazioni di memoria lette dalla stampante. È di 12 parole, 8 di istruzioni e 4 di dati, e sta in 3 schede (più ovviamente la prima con il caricatore minimo):

000111001111110100111010001000010000010100001000000100100000000000000001
000111010000100100111101000000000101000111001000000000110101010000001111
010101010000000001100000000000000111111100000000001100000000000000001010
010011011001010001100110110000100100100110100101010100100110110000110000

Per caricarlo sapete già come fare. Durante l’esecuzione, prima che sia lanciata la stampa, viene eseguito il ciclo: si può osservare dal contenuto del registro indice rX2. Perché rX2 e non rX1? Con rX1 si definivano le opzioni di MCA, un’istruzione per la manipolazione dei caratteri: con rX1 impostato a 0, MCA era usata proprio per riempire di spazi.

Cose toste: un altro caricatore e l’algoritmo di Euclide

Il caricatore minimo è un capolavoro di essenzialità, ma ha anche i suoi limiti: può caricare solo programmi contigui, il numero di schede da caricare è cablato nel codice del caricatore minimo, il programma caricato viene sempre lanciato a partire dalla locazione 4... Ma possiamo usare il caricatore minimo per caricare un caricatore più sofisticato che poi caricherà il programma utente. Il seguente pacco di schede è un esempio di quest’altro modo di usare il CANE:

000111001111100000111010001000100100010100001000000100100000000000000001
111111000000000101111010000000100010111101000000000110000101000000100010
010110000000100001001000000000100010000110111000100010011101000000010100
100101000000011111101001000000011111011101000000010000100101000000010001
000000000000000000011111111000100101100100000000010101000000100000000000
000000010000000000011111111111111101100100000000010011001011111000011010
000111010000000000000001010000100011001000010000000000010100010000000001
011111010000000011100011000000011001100000000000000100000000000000100000
100000111000000000000000000100000000
000100110         111011000001001011000111011000010001000111001000000000
000101001         110101011001100010010101011000000001100000000000101001
000101100         111101000000101100000001000001001011000101000001001100
000101111         110111000000000000001000000001001000000001000001001101
000110010         000101000001001110110111000000000000001000000001001001
000110101         000101000001001001000001000001001000001000000001001010
000111000         000011000000000000010111000001001010101000000000111110
000111011         000101000001001010001000000001001010100000000000111000
000111110         000001000001001010110110000000000000001000000001010001
001000001         001001000001010010000001000001000111001000000001010000
001000100         111111000000000000111100000001001011000000000000100110
001000111         100100010011010100
000100110      100
    15    12
   300   240
123456 34554

La prima scheda è il caricatore minimo, seguono 8 schede del caricatore binario (descritto alle pp. 22-25 di [17]). Le 13 schede successive sono del programma utente: si riconosce il formato diverso. Il primo campo di 9 bit è la locazione di memoria a partire dalla quale sono caricate in memoria le tre istruzioni codificate in binario nel resto della scheda. L’ultima scheda è una scheda di controllo: il codice “100” indica che il programma è terminato, i primi 9 bit specificano l’indirizzo dal quale lanciare il programma. Infine, le ultime 3 schede, in decimale, sono i dati per il programma utente.

Il programma calcola il massimo comun divisore fra due numeri applicando l’algoritmo di Euclide. Per vederlo in funzione dopo aver caricato il pacco di schede premete L, quando il CANE si ferma il programma utente è in memoria ed è pronto ad essere eseguito: premendo Go legge due valori decimali da una scheda, calcola il massimo comun divisore e stampa il risultato. Potete divertirvi ad aggiungere schede con altre coppie di valori, occhio alla sintassi però :)