Little man computer
# Little man computer

Il Little Man Computer (LMC, letteralmente L'omino-computer) è un modello di computer a istruzioni, creato dal dottor Stuart Madnick nel 1965. Viene generalmente usato come mezzo di istruzione, perché rappresenta un semplice computer con Architettura di von Neumann, la base di ogni computer contemporaneo. Può essere programmato sia in linguaggio macchina sia in linguaggio Assembly.

## Architettura di sistema

L'idea di base del LMC è la seguente: si immagina un omino chiuso in una stanzetta (o direttamente dentro il computer). Da un lato della stanza, ci sono 100 buche delle lettere (che rappresentano la memoria del computer), numerate da 0 a 99. Ognuna di esse può contenere un'istruzione oppure un dato, codificati con 3 caratteri numerici, dal valore 000 al valore 999. Dall'altro lato della stanza ci sono invece due ulteriori buche delle lettere, chiamate INBOX e OUTBOX, usate per ricevere dati e trasmetterli in uscita. Al centro della stanza c'è una sorta di scrivania da lavoro con un calcolatrice che ha solo due semplici funzioni: addizione e sottrazione. La calcolatrice rappresenta l'accumulatore. Assieme alla calcolatrice è presente un contatore azzerabile, che rappresenta il Program Counter. Il Program Counter contiene l'indirizzo della prossima istruzione che l'Omino dovrà portare a termine. In condizioni normali, non appena tale istruzione viene eseguita, il Program Counter viene incrementato di 1: in questo modo l'Omino svolgerà tutte le istruzioni in sequenza. È però possibile attraverso istruzioni di salto codificare istruzioni di iterazione (cicli), o anche strutture di selezione condizionata del tipo if-else, queste ultime semplicemente settando il Program Counter a una specifica istruzione se qualche particolare condizione è verificata, ad esempio se il valore mostrato dalla calcolatrice è zero oppure è positivo. Proprio come nell'Architettura di von Neumann, la memoria contiene sia istruzioni sia dati, bisogna quindi fare attenzione a fermare il contatore quando si raggiunge un indirizzo contenente dei dati, o l'Omino li considererà istruzioni e tenterà di trattarli come tali. Per utilizzare l'LMC, l'utente immette dei dati nelle buche delle lettere e poi segnala all'Omino di cominciare l'esecuzione. L'Omino comincerà dall'istruzione contenuta nell'indirizzo di memoria numero zero: in questo modo, resettando il Program Counter a zero si riavvia il programma.

## Ciclo d'esecuzione

Per eseguire un programma, l'Omine svolge i seguenti passi:

* Guarda il Program Counter per capire quale buca delle lettere contiene l'istruzione da eseguire (ad esempio, la numero zero)
* recupera l'istruzione dalla buca con il numero corrispondente
* incrementa il Program Counter, in questo modo esso conterrà il numero dell'istruzione seguente
* decodifica l'istruzione, ottenendo anche il numero delle buche delle lettere che contengono i dati necessari allo svolgimento dell'istruzione stessa
* recupera i dati dalla buca delle lettere corrispondente al numero trovato nel passaggio precedente e li immagazzina nell'accumulatore
* esegue l'istruzione
* immagazzina i nuovi dati nella buca delle lettere da cui aveva ottenuto i vecchi dati
* ripete il ciclo o si ferma

## Comandi

Anche se l'LMC in realtà rappresenta il lavoro di un processore binario, è stato scelto di utilizzare numeri decimali per semplicità e per venire incontro agli studenti che potrebbero non essere accostumati a lavorare con il sistema binario o esadecimale.

### Istruzioni

Alcuni simulatori di LMC sono programmati direttamente con istruzioni numeriche a tre cifre, altri con codici o etichette mnemoniche (sempre di 3 caratteri). In entrambi i casi, il numero di istruzioni è comunque molto limitato (circa dieci istruzioni) per semplificarne la comprensione. Se l'LMC è del tipo che utilizza etichette mnemoniche, queste sono convertite in codici a tre cifre durante la compilazione del programma. La prima cifra di un'istruzione numerica rappresenta il comando da eseguire, e le ultime due cifre l'indirizzo di memoria della buca delle lettere legata a quel comando

La tabella sottostante mostra un insieme di istruzioni numeriche tipico e le relative etichette mnemoniche.

Istruzioni :

| Codice numerico | Codice mnemonico | Istruzione | Descrizione |
| - | - | - | - |
| 1xx | ADD | ADD | Somma il valore immagazzinato nella casella xx a quello contenuto nell'accumulatore. Il risultato è memorizzato nell'accumulatore. Nota: il contenuto della casella non viene cambiato. L'azione non è definita per istruzioni che causerebbero somme non codificabili in tre cifre (overflow). |
| 2xx | SUB | SUBTRACT | Sottrai il valore immagazzinato nella casella xx da quello contenuto nell'accumulatore. Il risultato è memorizzato nell'accumulatore. Nota: il contenuto della casella non viene cambiato. L'azione non è definita per istruzioni che causerebbero risultati della sottrazione negativi (underflow); in ogni caso, viene impostato un flag di negatività cosicché l'istruzione 8xx (BRP) possa essere eseguita correttamente. |
| 3xx | STA | STORE | Immagazzina il contenuto dell'accumulatore nella casella xx, cancellandone il contenuto precedente. Nota: il contenuto dell'accumulatore non cambia, mentre quello della casella xx sì, a prescindere dal contenuto precedente. |
| 5xx | LDA | LOAD | Carica il valore contenuto nella casella xx nell'accumulatore, cancellandone il contenuto precedente. Nota: il contenuto della casella xx non cambia, mentre quello dell'accumulatore sì, a prescindere dal contenuto precedente. |
| 6xx | BRA | BRANCH (incondizionale) | Imposta il Program Counter all'indirizzo xx. Quindi, l'istruzione contenuta nella casella xx sarà la prossima a essere eseguita. |
| 7xx | BRZ | BRANCH IF ZERO (condizionale) | Se l'accumulatore contiene il valore 000, imposta il Program Counter al valore xx, altrimenti, non fare nulla. Nota: Il Program Counter potrebbe essere modificato anche se l'accumulatore riporta valore 000 a causa del comportamento indefinito dell'istruzione SUBTRACT quando il risultato è negativo. |
| 8xx | BRP | BRANCH IF POSITIVE (condizionale) | Se il flag di negatività non è impostato, modifica il Program Counter al valore xx, altrimenti non fare nulla. Nota: Il flag di negatività è impostato quando il risultato dell'istruzione SUBTRACT è negativo. Di conseguenza, BRP modifica il Program Counter quando il risultato della sottrazione è maggiore o uguale a zero. |
| 901 | INP | INPUT | Acquisisci dalla casella INBOX il valore digitato dall'utente e memorizzalo nell'accumulatore. Nota: questa istruzione sovrascrive qualunque valore sia presente nell'accumulatore. |
| 902 | OUT | OUTPUT | Emetti nella casella OUTBOX il valore presente nell'accumulatore. Nota: Il contenuto dell'accumulatore non cambia. |
| 000 | HLT/COB | HALT/COFFEE BREAK | Termina il programma. |
| | DAT | DATA | Questa istruzione assembly carica il valore nella prima casella disponibile. DAT si usa anche in combinazione con delle etichette per dichiarare delle variabili. Per esempio, DAT 984 immagazzina il valore 984 nella casella di destinazione dell'istruzione di DAT. |

### Esempi

**Uso dei codici di istruzione numerici**

Questo semplice programma (dall'istruzione 901 all'istruzione 000) è stato scritto usando solo codici numerici. Il programma accetta due numeri come input e produce la loro differenza come output. L'esecuzione comincia alla casella 00 e finisce alla casella 07. Successivamente verranno discussi gli svantaggi di usare istruzioni a codice numerico per programmare l'LMC.

| Casella | Codice numerico | Operazione | Commenti |
| - | - | - | - |
| 00 | 901 | INBOX --> ACCUMULATOR | INPUT del primo numero, che viene scritto sull'accumulatore (cancellando qualunque cosa vi fosse memorizzata prima) |
| 01 | 308 | ACCUMULATOR --> MEMORY[08] | STORE (Immagazzina nella casella 08) il valore corrente dell'accumulatore, in preparazione al passaggio successivo. |
| 02 | 901 | INBOX --> ACCUMULATOR | INPUT del secondo numero, che viene scritto sull'accumulatore (cancellando qualunque cosa vi fosse memorizzata prima, in questo caso il primo input) |
| 03 | 309 | ACCUMULATOR --> MEMORY[09] | STORE (Immagazzina nella casella 09) il valore corrente dell'accumulatore, sempre in preparazione al passaggio successivo. |
| 04 | 508 | MEMORY[08] --> ACCUMULATOR | Ora che entrambi i numeri in INPUT sono immagazzinati nelle caselle 08 e 09... LOAD (carica) il primo valore di nuovo nell'accumulatore (sempre cancellandone il contenuto) |
| 05 | 209 | ACCUMULATOR = ACCUMULATOR - MEMORY[09] | SUBTRACT (sottrae) il secondo numero al contenuto dell'accumulatore, che contiene il primo numero |
| 06 | 902 | ACCUMULATOR --> OUTBOX | OUTPUT (produce) il risultato del calcolo immagazzinato nell'accumulatore sull'OUTBOX |
| 07 | 000 | (nessuna operazione eseguita) | HALT (ferma) il Little Man Computer |

**Uso di istruzioni con etichette e codici mnemonici**

L'Assembly è un linguaggio di programmazione a basso livello che usa codici mnemonici ed etichette al posto di codici numerici. Nonostante l'LMC faccia ne faccia un uso limitato, si nota subito la convenienza di utilizzare tali codici dall'esempio sottostante, che è il programma appena presentato (sottrazione di due numeri) riscritto in linguaggio assembly: non è più necessario che il programmatore memorizzi un insieme di codici numerici anonimi, ma può programmare usando dei codici mnemonici più facili da ricordare. Se tali codici rappresentano istruzioni che coinvolgono indirizzi di memoria (ad esempio istruzioni di salto o di caricamento e salvataggio dei dati), un'etichetta viene impiegata per identificare l'indirizzo di memoria.

    Questo programma d'esempio può essere compilato ed eseguito sul simulatore di LMC, disponibile sul sito internet della York University (Toronto, Canada) o sull'applicazione desktop scritta da Mike Coley. Questi simulatori includono istruzioni complete e programmi d'esempio, il compilatore assembler per convertire il codice assembly in codice macchina, interfacce di controllo per eseguire e osservare i programmi e descrizioni passo passo dettagliate di ogni istruzione dell'LMC.

## Etichette

Senza le etichette il programmatore dovrebbe calcolare manualmente gli indirizzi di memoria: nell'esempio fatto usando i codici numerici, se una nuova istruzione venisse inserita prima dell'ultima istruzione (HLT), l'istruzione di HLT, attualmente situata all'indirizzo 07, verrebbe spostata all'indirizzo 08 (gli indirizzi vengono etichettati a partire dallo 00). Supponendo che l'utente inserisca 600 come primo input, l'istruzione 308 farebbe sì che questo valore venisse immagazzinato alla casella di indirizzo 08 e sovrascriverebbe l'istruzione 000 (l'HLT). Dal momento che l'istruzione 600 significa "salta alla casella di indirizzo 00", il programma, anziché fermarsi, finirebbe in un ciclo infinito, ricominciando dall'istruzione iniziale (alla casella 00) e tornandoci sempre alla fine (grazie all'istruzione 600, erroneamente memorizzata al posto dell'HLT). Per sopperire a questa eventualità, molti linguaggi assembly (compreso il modello LMC) combinano i codici mnemonici con delle etichette. Un'etichetta è semplicemente una parola usata sia per identificare un indirizzo di memoria dove è immagazzinata un'istruzione o dei dati, sia per riferirsi a tale indirizzo all'interno di un'istruzione.

Quando il programma è compilato dall'assembler:

* Le etichette a sinistra di un'istruzione mnemonica sono convertite nell'indirizzo di memoria in cui l'istruzione o i dati sono immagazzinati, per esempio loopstart INP
* Le etichette a destra di un'istruzione mnemonica prendono il valore dell'indirizzo di memoria indicato sopra, per esempio BRA loopstart
* Un'etichetta combinata con una dichiarazione DAT funziona da variabile e indica l'indirizzo di memoria in cui i dati sono immagazzinati per esempio uno DAT 1 o numero1 DAT 1

Nell'esempio in assembly che usa codici mnemonici ed etichette, se una nuova istruzione venisse inserita prima dell'istruzione finale di HLT allora l'indirizzo di memoria etichettata FIRST diventerebbe 09 anziché 08 e l'istruzione STA FIRST verrebbe convertita in 309 (STA 09) anziché in 308 (STA 08) quando il programma verrebbe compilato.

Quindi le etichette vengono usate per:

* identificare un'istruzione particolare, bersaglio di un'istruzione di salto(BRANCH).
* identificare un indirizzo di memoria utilizzando una variabile (per mezzo dell'istruzione DAT) e nel caso caricare i dati nel programma nel momento di compilazione (questo uso potrebbe non apparire scontato se non si considera che ad esempio non c'è modo di sommare 1 all'accumulatore, a parte chiedere all'utente di inserire il valore 1 all'inizio del programma, ma è chiaramente molto meglio avere già l'1 presente in memoria, usando one DAT 1)

### Esempio

Questo programma riceve un numero in input dall'utente e lo decrementa di uno fino ad arrivare a zero.

Questo programma riceve un numero in input dall'utente, lo eleva al quadrato e lo emette come output, poi ripete richiedendo un nuovo numero. Inserire 0 farebbe terminare il programma. (Nota: un input che producesse in output un valore superiore a 999 causerebbe un errore nel programma a causa del limite di cifre consentito dal modello LMC).

Nota: Se nessun valore è specificato dopo un'istruzione DAT, di default viene immagazzinato 0.

