I computer rappresentano dati e istruzioni con sequenze di bit. Fra quello che scriviamo e quello che succede nei circuiti ci sono però parecchi livelli: applicazioni, sistema operativo, istruzioni macchina, componenti elettronici.
È il viaggio con cui apro Feel Geek, e parte da una domanda che continua ad affascinarmi: come fa un dito premuto su un tasto a diventare qualcosa che una macchina riesce a elaborare?
Il bit: due valori, moltissime combinazioni
Un bit assume due valori, che indichiamo con 0 e 1. Una sequenza di n bit ha 2ⁿ combinazioni possibili: con otto bit — un byte — sono 256.
Attenzione a un equivoco comune: non vuol dire che i numeri binari siano multipli di due. Vuol dire che usano due cifre e un sistema posizionale basato sulle potenze di due. Per esempio 101 in base due vale 1 × 4 + 0 × 2 + 1 × 1, cioè 5.
E la stessa sequenza può rappresentare cose completamente diverse a seconda della codifica. I bit da soli non dicono se appartengono a un testo, a un'immagine o a un'istruzione: quella informazione sta nella convenzione, non nei bit.
Byte e capacità: prefissi decimali e binari
Per abitudine si chiama kilobyte una quantità di 1024 byte. Per evitare ambiguità la distinzione corretta è questa:
| Unità | Quantità |
|---|---|
| 1 byte | 8 bit |
| 1 kilobyte, kB | 1000 byte |
| 1 kibibyte, KiB | 1024 byte |
| 1 megabyte, MB | 1.000.000 byte |
| 1 mebibyte, MiB | 1.048.576 byte |
I prefissi binari servono proprio a dire esplicitamente «potenze di due». Riferimento NIST sulle unità binarie. È anche il motivo per cui un disco «da 1 TB» sul computer ne mostra meno: nessuno ti sta imbrogliando, si stanno usando due scale diverse.
Come i circuiti rappresentano 0 e 1
L'immagine della lampadina accesa o spenta funziona per capire l'idea di due stati distinguibili. Nei circuiti digitali reali i valori logici corrispondono a condizioni elettriche definite dal progetto.
I transistor permettono di costruire circuiti che elaborano questi segnali. Non sono lampadine in miniatura, e non vale nessuna regola del tipo «otto transistor uguale un byte»: il numero di componenti dipende dal tipo di circuito e di memoria.
Anche la storia va letta distinguendo proposte teoriche, brevetti e dispositivi funzionanti. Un passaggio decisivo fu il transistor a contatto puntiforme realizzato da John Bardeen e Walter Brattain nel 1947. Computer History Museum.
Dal programma alle istruzioni macchina
Scrivere direttamente codici macchina sarebbe faticoso e legato a un'architettura precisa. I linguaggi di programmazione servono a descrivere le operazioni attraverso astrazioni più maneggevoli.
L'assembly dà una rappresentazione simbolica delle istruzioni di una determinata architettura, e un assembler la traduce in codice macchina. Non è uno strumento universale che assegna significato a qualunque numero binario.
Compilatori e interpreti stanno su un altro piano. Un compilatore traduce un programma in un'altra rappresentazione; un interprete ne esegue le operazioni con un proprio meccanismo. Le due tecniche convivono spesso, anche con compilazione durante l'esecuzione.
Ecco perché definire un linguaggio «compilato» o «interpretato» è una semplificazione: conta l'implementazione che stai usando, non il nome del linguaggio.
Il sistema operativo collega programmi e risorse
Quando premi un tasto, il sistema riceve un evento che un'applicazione può gestire. Il programma usa le interfacce disponibili per elaborarlo e produrre un risultato.
Non serve immaginare che a ogni gesto il programma venga ritradotto da capo. Molte istruzioni sono già pronte per essere eseguite, e altre attività le gestiscono librerie, runtime e servizi di sistema.
Questi livelli nascondono la complessità senza eliminarla. È il motivo per cui si può programmare e usare un computer senza ricostruire ogni volta il comportamento dei circuiti — il che è una fortuna.
Una memoria finita impone limiti
Con un numero fissato di bit rappresenti un numero finito di configurazioni. Intervallo dei valori e precisione dipendono dalla codifica scelta.
Quindi non tutti i numeri sono rappresentabili esattamente in uno spazio limitato. Arrotondamenti e limiti di grandezza sono conseguenze concrete con cui i programmi devono fare i conti, non dettagli che spariscono comprando una macchina più potente.
Un paio di correzioni storiche
Va corretta una sovrapposizione che si sente spesso, e che avevo fatto anch'io: Turing, Enigma e Colossus non stanno nella stessa storia. Il progetto di Colossus fu guidato da Tommy Flowers e riguardava le comunicazioni cifrate con Lorenz, non Enigma. The National Museum of Computing.
E Pascal appartiene al XVII secolo, non al XVI. Sono precisazioni che non tolgono niente al fascino del percorso: anzi, mostrano che l'informatica nasce da contributi diversi e non da una singola invenzione risolutiva.
Il punto d'arrivo resta quello che mi interessava di più: fra la tua intenzione e una risposta sullo schermo c'è una catena di rappresentazioni e meccanismi che qualcuno ha progettato. Capirne anche solo qualcuno rende tutto molto meno misterioso, e parecchio più interessante.