Little man computer
# Little man computer

El Little Man Computer (LMC, en inglés: "Computadora del hombre pequeño") es un modelo educativo de computadora, creado por Stuart Madnick en 1965. El LMC se utiliza normalmente en la enseñanza porque modela una computadora sencilla que utiliza la arquitectura de von Neumann, que tiene todas las características básicas de una computadora moderna. Puede ser programada con código máquina (aunque en lugar de usar un sistema binario, utiliza el decimal) o con código ensamblador.

## Arquitectura del sistema

El modelo LMC está basado en el concepto de un hombre pequeño encerrado en una habitación. En la habitación hay 100 cajas (memorias), numeradas del 0 al 99 y cada una puede contener una instrucción o dato de 3 dígitos (desde el 000 al 999). Además hay dos cajas al otro extremo etiquetadas ENTRADA y SALIDA que son utilizadas para recibir y enviar información.

En el centro de la habitación, existe una zona de trabajo que contiene una calculadora simple con dos funciones (suma y resta) denominada acumulador y un contador reprogramable denominado contador de programa. El Contador de Programa guarda la dirección de la próxima instrucción que el hombre pequeño va a realizar. Este contador de programa normalmente se incrementa en 1 después de que se ejecuta una instrucción, permitiéndole al hombre pequeño realizar su trabajo a lo largo del programa de manera secuencial.

Existen instrucciones de bifurcación que permiten realizar iteraciones (lazos) e incorporar al programa estructuras de programación condicionales. Colocando el contador de programa en una dirección de memoria no secuencial si se cumple una determinada condición (por lo general el valor almacenado en el acumulador es cero o positivo). Tal como establece la arquitectura de von Neumann, la memoria contiene tanto instrucciones como datos. Por lo tanto es preciso tener cuidado de detener el contador de programa antes de alcanzar una dirección de memoria que contenga datos o el hombrecillo intentará utilizarla como si fuera una instrucción. Para utilizar la LMC el usuario carga datos en las cajas y luego le indica al hombre pequeño que comience a trabajar, comenzando con la instrucción almacenada en la dirección de memoria (caja) cero. Restablecer el contador de Programa a cero hace que el programa comience nuevamente desde el principio.

## Ciclo de ejecución

Para ejecutar un programa, el hombre pequeño realiza los siguientes pasos:

* Comprueba el contador de programa, que tiene un número de caja que contiene una instrucción de programa (por ejemplo, cero).
* Busca qué instrucción hay en la caja con ese número.
* Incrementa el contador de programa (de forma que contenga el número de caja de la siguiente instrucción).
* Decodifica la instrucción (esto incluye encontrar el número de la caja que contiene los datos con los que trabajará, por ejemplo, que diga que hay que obtener los datos de la caja 42).
* Recupera los datos de la caja con el número encontrado en el paso anterior (por ejemplo, almacena los datos de la caja 42 en el acumulador).
* Ejecuta la instrucción.
* Almacena los nuevos datos en la caja desde donde se recuperaron los datos antiguos.
* Repite el ciclo o para.

## Comandos

Aunque el LMC sí refleja el funcionamiento real de los procesadores binarios, se eligió la simplicidad de los números decimales para minimizar la complejidad a los estudiantes, puesto que puede no resultar cómodo trabajar en un sistema binario o hexadecimal.

### Instrucciones

Algunos simuladores LMC se programan utilizando directamente instrucciones numéricas de 3 dígitos y otros con códigos mnemotécnicos de 3 letras y etiquetas. En cualquier caso, el conjunto de instrucciones es deliberadamente muy limitado (normalmente unas diez instrucciones) para simplificar la comprensión. Cuando el LMC utiliza códigos mnemotécnicos y etiquetas, después, se convierten en instrucciones numéricas de 3 dígitos cuando se ensambla el programa. El primer dígito de una instrucción numérica representa el comando a ejecutar y los dos últimos dígitos representan la dirección de memoria de la caja correspondiente a este comando.

La tabla de abajo muestra un conjunto típico de instrucciones numéricas y los códigos mnemotécnicos equivalentes.

Instrucciones :

| Código numérico | Código mnemotécnico | Instrucción | Descripción |
| - | - | - | - |
| 1xx | ADD | ADD | Suma el valor almacenado en la caja xx a cualquier valor que se encuentre actualmente en el acumulador (calculadora) Nota: El contenido de la caja no cambia, y las acciones en el acumulador (calculadora) no están definidas para instrucciones de suma con resultados de más de 3 dígitos. |
| 2xx | SUB | SUBTRACT | Resta el valor almacenado en la caja xx de cualquier valor que se encuentre actualmente en el acumulador (calculadora). Nota: El contenido de la caja no cambia, y las acciones en el acumulador no están definidas para instrucciones de resta con resultados negativos (pero, se establecerá un registro de estado negativo de forma que 8xx (BRP) se pueda utilizar correctamente). |
| 3xx | STA | STORE | Almacena el contenido del acumulador en la caja xx (destructivo). Nota: El contenido del acumulador (calculadora) no se modifica (no destructivo), pero el contenido de la caja se sustituye independientemente de lo que hubiera antes (destructivo). |
| 5xx | LDA | LOAD | Carga el valor de la caja xx (no destructivo) y lo introduce en el acumulador (destructivo). |
| 6xx | BRA | BRANCH (incondicional) | Establece la dirección indicada (valor xx) en el contador de programa. Es decir, el valor xx será la siguiente instrucción ejecutada. |
| 7xx | BRZ | BRANCH IF ZERO (condicional) | Si el acumulador (calculadora) contiene el valor 000, establece el valor xx en el contador de programa. En caso contrario no hace nada. Nota: Puesto que el programa se almacena en la memoria, todos los datos y las instrucciones del programa tienen el mismo formato de dirección/ubicación. |
| 8xx | BRP | BRANCH IF POSITIVE (condicional) | Si el acumulador (calculadora) es 0 o positivo, establece el valor xx en el contador de programa. En caso contrario no hace nada. Nota: Puesto que el programa se almacena en la memoria, todos los datos y las instrucciones del programa tienen el mismo formato de dirección/ubicación. |
| 901 | INP | INPUT | Va a la ENTRADA, obtiene el valor que ha introducido el usuario y lo pone en el acumulador (calculadora). Nota: Esto sobreescribe cualquier valor que se encuentre en el acumulador (destructivo) |
| 902 | OUT | OUTPUT | Copia el valor del acumulador (calculadora) en la SALIDA. Nota: El contenido del acumulador no cambia (no destructivo). |
| 0XX | HLT/COB | HALT/COFFEE BREAK | Deja de trabajar. |
| | DAT | DATA | Esta es una instrucción de ensamblador que únicamente carga el valor en la siguiente caja disponible. DAT también se puede utilizar en conjunción con etiquetes para declarar variables. Por ejemplo, DAT 984 almacena el valor 984 en una caja, en la dirección de la instrucción DAT. |

### Ejemplos

**Uso de códigos de instrucciones numéricas**

Este programa de ejemplo se ha escrito usando códigos numéricos (las instrucciones 901,... 000). El programa pide dos números como ENTRADA y devuelve la resta como SALIDA. Obsérvese que la ejecución comienza en la posición 00 y acaba en la 07. Las desventajas de la programación con LMC con códigos de instrucción numéricos se verán después.

| Caja | Código numérico | Operación | Comentarios |
| - | - | - | - |
| 00 | 901 | ENTRADA → ACUMULADOR | Introducir (INPUT) el primer número, en la calculadora (borra todo lo que había) |
| 01 | 308 | ACUMULADOR → MEMORIA[08] | Almacena (STORE) el valor actual de la calculadora (se prepara para el siguiente paso...) |
| 02 | 901 | ENTRADA → ACUMULADOR | Introduce (INPUT) el segundo número, en la calculadora (y borra el primer número) |
| 03 | 309 | ACUMULADOR → MEMORIA[09] | Almacena (STORE) el valor actual de la calculadora (de nuevo, se prepara para el siguiente paso...) |
| 04 | 508 | MEMORIA[08] → ACUMULADOR | (Ahora que los dos valores de entrada están almacenados en las cajas 08 y 09...) Carga (LOAD) el primer valor, de nuevo, en la calculadora (y borra lo que había) |
| 05 | 209 | ACUMULADOR = ACUMULADOR - MEMORIA[09] | Resta (SUBTRACT) el segundo número al valor actual de la calculadora (que era el primer número) |
| 06 | 902 | ACUMULADOR → SALIDA | Devuelve (OUTPUT) el resultado de la calculadora como SALIDA |
| 07 | 000 | (no hace ninguna operación) | Para (HALT) el LMC |

**Uso de códigos mnemotécnicos y etiquetas**

El lenguaje ensamblador es un lenguaje de programación de bajo nivel que utiliza la mnemotécnia y etiquetas en lugar de códigos de instrucciones numéricas. Aunque el LMC utiliza un conjunto limitado de mnemotécnicos, la conveniencia de usar una regla mnemotécnica para cada instrucción del lenguaje ensamblador se hace evidente en el mismo programa que se muestra a continuación (el programador ya no tiene que acordarse de una serie de códigos numéricos anónimos y puede programar con un conjunto de códigos mnemotécnicos más fáciles de memorizar). Si la sentencia es una instrucción que implica una dirección de memoria (ya sea una instrucción de salto o datos que se tienen que cargar o guardar), entonces utiliza una etiqueta para nombrar esa dirección.

    Este programa de ejemplo puede ser compilado y ejecutado en el simulador de LMC disponible en el sitio web de la Universidad de York (Toronto, Canadá) o en la aplicación de escritorio escrita por Mike Coley. Todos estos simuladores incluyen instrucciones completas y programas de ejemplo, un ensamblador para convertir el código ensamblador a código máquina, interfaces de control para ejecutar y supervisar los programas y una descripción paso a paso detallada de cada instrucción LMC.

## Etiquetas

Sin etiquetas el programador necesita calcular manualmente las cajas (direcciones de memoria) donde almacenar los datos.

En el ejemplo con código numéricos, si se añade una nueva instrucción antes de la instrucción HLT final, como resultado se moverá la instrucción HLT desde la caja 07 a la 08 (el etiquetado de direcciones del programa comienza en la posición 00). Supongamos que el usuario introduce 600 como primera entrada (en la instrucción 901 de la caja 00). La instrucción 308 (caja 01) hace que este valor se almacene en la caja 08, y sobreescribe la instrucción 000 (HLT) con el valor 600. La instrucción 600 significa saltar a la dirección (caja) 00 del programa, así, en lugar de pararse, el programa se queda atrapado en un bucle sin fin.

Para solucionar esta dificultad, la mayoría de los lenguajes ensambladores (incluyendo el LMC) combinan los códigos nemotécnicos con etiquetas. Una etiqueta no es más que una palabra que se utiliza para nombrar cualquier dirección de memoria donde se almacena una instrucción o un dato, o para referirse a esta dirección en una instrucción.

Cuando un programa se ensambla:

* Una etiqueta a la izquierda de una instrucción se convierte en la dirección de memoria donde se almacena la instrucción o los datos. Por ejemplo, iniciobucle INP
* Una etiqueta a la derecha de una instrucción toma el valor de la dirección de memoria antes mencionada. Por ejemplo, BRA iniciobucle
* Una etiqueta combinada con una declaración DAT funciona como una variable, hace que los datos se almacenen en la dirección de memoria de la etiqueta. Por ejemplo, one DAT 1 o numero1 DAT

En el ejemplo de lenguaje ensamblador que utiliza mnemotécnia y etiquetas, si una nueva instrucción se inserta antes de la instrucción HLT final, entonces la ubicación de la dirección marcada con la etiqueta PRIMERO estará ahora en la posición de memoria 09 en lugar de la 08, y la primera instrucción STA se convertirá en 309 (STA 09) en lugar de 308 (STA 08) cuando se ensamble el programa.

Por lo tanto, las etiquetas se utilizan para:

* Identificar una instrucción particular como destino de una instrucción de salto (BRANCH).
* Identificar una ubicación de memoria como una variable con un nombre (utilizando DAT) y, opcionalmente, cargar determinados datos cuando se ensambla el programa para su uso posterior cuando se ejecute. Este uso no se hace evidente hasta que uno se da cuenta de que no hay ninguna otra forma de sumarle 1 a un contador: Se le podría pedir al usuario que introdujera el 1 al inicio (INPUT), pero es mejor cargarlo cuando se ensambla el programa usando one DAT 1)

### Ejemplos

Este programa pide una ENTRADA al usuario, y hace una cuenta atrás hasta cero.

Este programa pide una ENTRADA al usuario, calcula el cuadrado, muestra la respuesta y vuelve a repetir. La introducción de un cero finaliza el programa. (Nota: una entrada que de un resultado superior a 999 producirá un error debido al límite de 3 dígitos del LMC)

Nota: Si no hay datos después de una declaración DAT, entonces se almacena en la dirección de memoria el valor predeterminado 0.

