MIX (lenguaje de programación)
# MIX (lenguaje de programación)

MIX es una computadora hipotética usada en la monografía de Donald Knuth, El Arte de Programar Computadoras (en inglés, The Art of Computer Programming o TAOCP), MIX es el modelo numérico 1009, que deriva de modelos numéricos y nombres contemporáneos, máquinas comerciales influyentes para el autor. (“MIX” también es el valor 1009 en numeración romana.)

En la década de los '60s MIX fue superado por una nueva (también hipotética) arquitectura computacional, MMIX (2009), incorporada en las siguientes ediciones de TAOCP. Las implementaciones de software tanto para arquitecturas MIX como MMIX, han sido desarrolladas y liberadas por Knuth como “MIXware” y “MMIXware,” respectivamente.

Existen también muchos derivados de los emuladores MIX/MMIX de Knuth. GNU MDK, por ejemplo, es un paquete de software liberado y corre sobre una gran variedad de plataformas.

Su propósito para la educación es similar a la Arquitectura DLX desarrollada por John L. Hennessy y David A. Patterson, para la Arquitectura de computadoras: Una Aproximación Cuantitativa (en inglés, Computer Architecture: A Quantitative Approach).

## Arquitectura

MIX es una computadora híbrida binaria/decimal. Cuando se programa en binario, cada byte contiene 6 bits (valores de rango de 0 a 63). En el decimal, cada byte tiene 2 dígitos decimales (valores del rango 0 a 99). Los bytes se agrupan en palabras de cinco bytes además de un signo. Muchos de los programas escritos para MIX trabajan indistintamente en binario o decimal, siempre y cuando el almacenamiento no supere el valor de 63 en un simple byte.

Una palabra puede contener valores en un rango de −1.073.741.823 a 1.073.741.823 en modo binario y −9.999.999.999 a 9.999.999.999 en modo decimal. la representación de valores integrales de signo y Magnitud distinguen en la arquitectura MIX entre “−0” y “+0.”, esto contrasta con la computadoras modernas, para quienes las representaciones de cantidades integrales de complemento a dos incluyen una representación única para el cero, pero para quien el rango mayor de valores pertenece a los números negativos y no a los positivos.

### Registradores

Hay 9 tipos de registros en MIX:

* rA: Acumulador (palabra completa, cinco bytes y un signo).
* rX: Extensión (palabra completa, cinco bytes y un signo).
* rI1, rI2, rI3, rI4, rI5 rI6: Registro índice (dos bytes y un signo).
* rJ: Salto de dirección (dos bytes, siempre positivos).

Se asume como un byte a 6 bits. La mayoría puede especificar la posición de los campos (bytes) del registro que serán modificados, usando un sufijo con la forma (primero:último) ((first:last)). El campo de orden cero es el bit de signo.

MIX también registra también si la operación anterior se sobrecargó, y tiene un triple indicador de comparación (menor que'/less than, igual que/equal to, o mayor que/ greater than). En el siguiente diagrama se muestra como se dividen esos campos.

| ± | A1 | A2 | A3 | A4 | A5 |
| - | - | - | - | - | - |
| ± | X1 | X2 | X3 | X4 | X5 |
| + | J4 | J5 |

* OV?

| ± | I1.4 | I1.5 |
| - | - | - |
| ± | I2.4 | I2.5 |
| ± | I3.4 | I3.5 |
| ± | I4.4 | I4.5 |
| ± | I5.4 | I5.5 |
| ± | I6.4 | I6.5 |

### Memoria y entrada/salida

La máquina MIX tiene 4000 palabras de almacenamiento (cada una con 5 bytes y un signo), direcciones desde 0 a 3999. Una variedad de dispisitivo de entrada y salida también incluidas:

* Unidad de cinta (dispisitivo 0…7).
* Unidad de disco (dispisitivo 8…15).
* Lector de tarjeta (dispisitivo 16).
* Perfordor de tarjeta (dispisitivo 17).
* Impresora lineal (dispisitivo 18).
* Terminal de tipeado (dispisitivo 19).
* Cinta de papel (dispisitivo 20).

### Instructiones

Cada instrucción máquina en memoria ocupa una palabra, y consiste en cuatro elementos: la dirección (2 bytes y el signo de la palabra) en memoria a ser leída o escrita; una especificación de índice (1 byte, describiendo donde se usara el índice de registro rI) para agregar a la dirección; una modificación (1 byte) que especifica qué partes del espacio del registro o memoria será leída o alterada; y el código de la operación (1 byte). Todo el código de la operación tiene una asociación mnemónica.

Los programas en MIX frecuentemente usan código flexible, en particular para retornar desde una subrutina. ya que MIX carece de una pila de subrutina para el retorno automático. El código flexible facilita la modicación del byte, permitiendo que el programa almacene datos para, por ejemplo, la parte de una dirección de destino de instrucción, dejando sin modificar al resto de la instrucción.

Los programas MIX están generalmente construidos usando el Lenguaje Ensamblador MIX o MIXAL. El siguiente ejemplo fue tomado del tema códigos de programas hola mundo en diferentes lenguajes de programación:

| LDA ADDR,i(0:5) | rA := memoria[ADDR + rIi]; |
| - | - |
| LDX ADDR,i(0:5) | rX := memoria[ADDR + rIi]; |
| LD? ADDR,i(0:5) | rI? := memoria[ADDR + rIi]; |
| LDAN ADDR,i(0:5) | rA := - memoria[ADDR + rIi]; |
| LDXN ADDR,i(0:5) | rX := - memoria[ADDR + rIi]; |
| LD?N ADDR,i(0:5) | rI? := - memoria[ADDR + rIi]; |
| STA ADDR,i(0:5) | memoria[ADDR + rIi] := rA; |
| STX ADDR,i(0:5) | memoria[ADDR + rIi] := rX; |
| ST? ADDR,i(0:5) | memoria[ADDR + rIi] := rI?; |
| STJ ADDR,i(0:5) | memoria[ADDR + rIi] := rJ; |
| STZ ADDR,i(0:5) | memoria[ADDR + rIi] := 0; |
| ADD ADDR,i(0:5) | rA := rA + memoria[ADDR + rIi]; |
| SUB ADDR,i(0:5) | rA := rA - memoria[ADDR + rIi]; |
| MUL ADDR,i(0:5) | (rA, rX) := rA * memoria[ADDR + rIi]; |
| DIV ADDR,i(0:5) | rA := int( (rA, rX) / memoria[ADDR + rIi] ); rX := (rA, rX) % memoria[ADDR + rIi]; |
| ENTA ADDR,i | rA := ADDR + rIi; |
| ENTX ADDR,i | rX := ADDR + rIi; |
| ENT? ADDR,i | rI? := ADDR + rIi; |
| ENNA ADDR,i | rA := - ADDR - rIi; |
| ENNX ADDR,i | rX := - ADDR - rIi; |
| ENN? ADDR,i | rI? := - ADDR - rIi; |
| INCA ADDR,i | rA := rA + ADDR + rIi; |
| INCX ADDR,i | rX := rX + ADDR + rIi; |
| INC? ADDR,i | rI? := ADDR + rIi; |
| DECA ADDR,i | rA := rA - ADDR - rIi; |
| DECX ADDR,i | rX := rX -ADDR - rIi; |
| DEC? ADDR,i | rI? := rI? - ADDR - rIi; |
| CMPA ADDR,i(0:5) | comparar rA con memoria[ADDR + rIi]; |
| CMPX ADDR,i(0:5) | comparar rX con memoria[ADDR + rIi]; |
| CMP? ADDR,i(0:5) | comparar rI? con memoria[ADDR + rIi]; |
| JMP ADDR,i | rJ := dirección de la siguiente instrucción; ir a ADDR + rIi; |
| JSJ ADDR,i | ir a ADDR + rIi; |
| JOV ADDR,i | si (sobrecarga) entonces sobrecarga := falso; ir a ADDR + rIi; |
| JNOV ADDR,i | si (no sobrecarga) entonces ir a ADDR + rIi; sino sobrecarga := falso; |
| JL, JE, JG ADDR,i JGE, JNE, JLE ADDR,i | si (menor, igual, mayor) mientras ir a ADDR + rIi; si (no menor, desigual, no mayor) entonces ir a ADDR + rIi; |
| JAN/JAZ/JAP ADDR,i JANN/JANZ/JANP ADDR,i | si (rA<0 o rA==0 o rA>0) entonces ir a ADDR + rIi; si (rA>=0 o rA!=0 o rA<=0) entonces ir a ADDR + rIi; |
| JXN/JXZ/JXP ADDR,i JXNN/JXNZ/JXNP ADDR,i | si (rX<0 o rX==0 o rX>0) entonces ir a ADDR + rIi; si (rX>=0 o rX!=0 o rX<=0) entonces ir a ADDR + rIi; |
| J?N/J?Z/J?P ADDR,i J?NN/J?NZ/J?NP ADDR,i | si (rI?<0 o rI?==0 o rI?>0) ir a ADDR + rIi; si (rI?>=0 o rI?!=0 o rI?<=0) ir a ADDR + rIi; |
| MOVE ADDR,i(F) | para (n = 0; n < F; n++, rI1++) memoria[ADDR+rIi+n] := memoria[rI1]; |
| SLA/SRA ADDR,i SLAX/SRAX ADDR,i SLC/SRC ADDR,i | cmabiar rA a la izquierda/derecha por ADDR+rIi bytes cambiar (rA, rX) a la izquierda/derecha por ADDR+rIi bytes rotatar (rA, rX) a la izquierda/derecha por ADDR+rIi bytes |
| NOP | hacer nada; |
| HLT | concluir ejecución; |
| IN ADDR,i(F) | leer en un bloque desde la unidad de entrada F en la memoria[ADDR + rIi] adelante; |
| OUT ADDR,i(F) | imprimir un bloque para la unidad F desde la memoria[ADDR + rIi] adelante; |
| IOC ADDR,i(F) | enviar la instrucción de control e/s a la unidad F; |
| JRED ADDR,i(F) | si (la unidad de e/s F esta lista) entonces ir a ADDR + rIi; |
| JBUS ADDR,i(F) | si (la unidad de e/s F está ocupada) entonces ir a ADDR + rIi; |
| NUM | rA := el valor numérico de los caracteres en (rA, rX); |
| CHAR | (rA, rX) := valor de los código de carácter representado de rA; |
