Proyecto de Software de Base

El objetivo del proyecto es el de escribir un ensamblador simple para el microprocesador Intel 8085. El ensamblador se irá construyendo en diversas etapas. Cada etapa estará especificada en esta página y tendrá una fecha de entrega. La evaluación de la etapa se hará en base a que lo entregado satisfaga exactamente las especificaciones requeridas, es decir, ni más ni menos. Cada una de las etapas tendrá un valor que será anunciado junto con la especificación. Finalmente, los nombres de los programas serán de la forma nombreZZ donde ZZ es un código de dos dígitos que será entregado por el profesor junto con sus cuentas.

Primera etapa: Códigos de operación : 10 puntos : 23 de octubre de 2008 a las 10pm

Deberá escribir un programa llamado codigoZZ.c o codigoZZ.cpp o codigoZZ.java que lea un archivo con nemónicos y que escriba un archivo con los códigos de operación correspondientes. Como podrá ver en las páginas 18 a 20 del manual del Intel 8085, todos sus instrucciones tienen códigos de operación que caben en un entero de 8 bits. El archivo nemonico.txt consistirá de una sucesión de líneas de texto con un máximo de 80 caracteres y terminará con el fin de archivo. Cada línea de texto podrá:
  1. Estar en blanco (los caracteres definidos por isspace).
  2. Contener además de blancos una cadena alfanumérica.
Las cadenas alfanuméricas que correspondan con nemónicos serán construídas de la siguiente manera a partir de los nemónicos que aparecen en el manual:
  1. Aquellos nemónicos cuyos códigos de operación aparezcan completamente escritos con 0 y 1 simplemente se tomarán tal cual eliminando cualquier espacio que aparezca. Ejemplo: el nemónico MVI M se convertirá en MVIM con código de operación 00110110.
  2. Aquellos nemónicos en cuyos códigos de operación aparezcan D o S se expandirán para producir tantos nemónicos como sea necesario, reemplazando r, r1 y r2 por el nombre abreviado del registro correspondiente. Ejemplo: el nemónico MVI r se deberá convertir en 8 nemónicos diferentes MVIB, MVIC, MVID, MVIE, MVIH, MVIL, MVIM y MVIA con códigos de operación 00000110, 00001110, ..., 00111110, respectivamente.
  3. Aquellos nemónicos en cuyos códigos de operación aparezca A se expandirán para producir tantos nemónicos como sea necesario. El único caso es el del nemónico RST que se deberá convertir en 8 nemónicos diferentes RST0, RST1, ..., RST7 con códigos de operación 11000111, 11001111, ..., 11111111, respectivamente.
Observe que es posible que un nemónico aparezca repetido en este proceso, pero en este caso los códigos de operación también coincidirán así que sólo debe considerarse una vez. Las cadenas alfanuméricas que no hayan aparecido en este proceso no serán nemónicos. Nota: Aparentemente, el listado de nemónicos y códigos de operación del manual del Intel 8085 contiene algunos errores que hacen que dos nemónicos aparentemente diferentes tengan el mismo código de operación. Nosotros simplemente ignoraremos esos errores, es decir, si su programa encuentra cualquiera de estos nemónicos entonces deberá de entregar el código de operación mostrado en el manual aunque sea erróneo.

El programa ejecutable codigoZZ deberá leer cada una de las líneas del archivo nemonico.txt y para cada una de ellas deberá escribir una línea en el archivo codigoop.txt como sigue:
  1. Si la línea de la entrada está en blanco entonces la línea de la salida deberá consistir únicamente del caracter '\n'.
  2. Si la línea de la entrada contiene blancos y un nemónico entonces la línea de la salida deberá consistir únicamente del código de operación correspondiente representado con 8 bits seguido de un espacio seguido del mismo código representado como dos dígitos hexadecimales (con letras mayúsculas) seguido del caracter '\n'.
  3. En cualquier otro caso la línea de la salida deberá consistir únicamente de la cadena "ERROR\n".
Abajo encontrará un ejemplo del funcionamiento de este programa:

Ejemplo de entrada nemonico.txt
Explicación del ejemplo
Ejemplo de salida codigoop.txt
CALL
Call
CALL ME

MVIM
RST1
Un nemónico válido
Una cadena alfanumérica que no es un nemónico
Una línea que contiene más de una cadena alfanumérica
Una línea en blanco
Un nemónico válido
Un nemónico válido
11001101 CD
ERROR
ERROR

00110110 36
11001111 CF

Segunda etapa: Operandos : 10 puntos : 5 de noviembre de 2008 a las 10pm

Deberá escribir un programa llamado operanZZ.c o operanZZ.cpp o operanZZ.java que lea un archivo con nemónicos y operandos y que escriba un archivo con los códigos de operación y los operandos correspondientes. El archivo nemonico.txt consistirá de una sucesión de líneas de texto con un máximo de 80 caracteres y terminará con el fin de archivo. Cada línea de texto podrá:
  1. Estar en blanco (los caracteres definidos por isspace).
  2. Contener además de blancos una cadena alfanumérica.
  3. Contener además de blancos dos cadenas alfanuméricas.
Como podrán ver aquí, el Intel 8085 tiene tres tipos de instrucciones según su longitud en bytes:
  1. Instrucciones de 1 byte: el único byte de la instrucción es su código de operación. Ejemplo: XCHG.
  2. Instrucciones de 2 bytes: el primer byte de la instrucción es su código de operación y el segundo byte de la instrucción es una constante de 8 bits (la cual puede ser un número de puerto). Ejemplo: IN nr.
  3. Instrucciones de 3 bytes: el primer byte de la instrucción es su código de operación y los otros dos bytes forman una constante de 16 bits (la cual puede ser una dirección). Ejemplo: LDA adr.
El tipo al que pertenece cada instrucción se puede tomar de aquí. La primera columna de esa tabla contiene al nemónico y a su posible operando. Usted debe ignorar los operandos que digan r1, r2, M, rp porque son operandos implícitos (esto es lo que hizo cuando expandió los nemónicos en la primera etapa del proyecto). Para esta etapa del proyecto debe considerar los operandos que digan nr (de 8 bits), adr (de 16 bits) y konst (de 8 bits). Todos los operandos se representarán como constantes numéricas en binario, decimal o hexadecimal.
  1. Un número binario quedará representado por el caracter '%' seguido de uno o más dígitos binarios '0' o '1'.
  2. Un número decimal quedará representado por uno o más dígitos decimales '0' a '9'.
  3. Un número hexadecimal quedará representado por el caracter '$' seguido de uno o más dígitos hexadecimales '0' a 'F'.
El programa ejecutable operanZZ deberá leer cada una de las líneas del archivo nemonico.txt y para cada una de ellas deberá escribir una línea en el archivo codigoop.txt como sigue:
  1. Si la línea de la entrada está en blanco entonces la línea de la salida deberá consistir únicamente del caracter '\n'.
  2. Si la línea de la entrada contiene blancos y un nemónico entonces:
    1. Si el nemónico corresponde con una instrucción de 1 byte la línea de la salida deberá consistir únicamente del código de operación escrito en hexadecimal seguido del caracter '\n'.
    2. En cualquier otro caso la línea de la salida deberá consistir únicamente de la cadena "ERROR\n".
  3. Si la línea de la entrada contiene blancos, un nemónico y una constante entonces:
    1. Si el nemónico corresponde con una instrucción de 2 bytes y la constante cabe en 8 bits la línea de la salida deberá consistir del código de operación escrito en hexadecimal, seguido de un espacio, seguido de la constante escrita en hexadecimal, seguido del caracter '\n'.
    2. Si el nemónico corresponde con una instrucción de 3 bytes y la constante cabe en 16 bits la línea de la salida deberá consistir del código de operación escrito en hexadecimal, seguido de un espacio, seguido de los 8 bits bajos de la constante escritos en hexadecimal, seguidos de un espacio, seguido de los 8 bits altos de la constante escritos en hexadecimal, seguido del caracter '\n'.
    3. En cualquier otro caso la línea de la salida deberá consistir únicamente de la cadena "ERROR\n".
  4. En cualquier otro caso la línea de la salida deberá consistir únicamente de la cadena "ERROR\n".
Abajo encontrará un ejemplo del funcionamiento de este programa:

Ejemplo de entrada nemonico.txt
Explicación del ejemplo
Ejemplo de salida codigoop.txt
HOLA
XCHG
XCHG $5
IN
IN %101
%101 IN
IN %2
IN $F 5
LDA
LDA 123
LDA 12345
LDA 123456
LDA 123 456
No es un nemónico
Instrucción de 1 byte
Sobra operando
Falta operando
Instrucción de 2 bytes
Línea en desorden
Constante errónea
Sobra operando
Falta operando
Instrucción de 3 bytes
Instrucción de 3 bytes
Operando demasiado grande
Sobra operando
ERROR
EB
ERROR
ERROR
DB 05
ERROR
ERROR
ERROR
ERROR
3A 7B 00
3A 39 30
ERROR
ERROR

Tercera etapa: Símbolos : 10 puntos : 24 de noviembre de 2008 a las 10pm

Deberá escribir un programa llamado simbolZZ.c o simbolZZ.cpp o simbolZZ.java que lea un archivo con etiquetas, nemónicos, directivas y operandos y que escriba un archivo con las direcciones, los códigos de operación y los operandos correspondientes. El archivo nemonico.txt consistirá de una sucesión de líneas de texto con un máximo de 80 caracteres y terminará con el fin de archivo. Cada línea de texto podrá:
  1. Estar en blanco (los caracteres definidos por isspace).
  2. Contener además de blancos una cadena alfanumérica.
  3. Contener además de blancos dos cadenas alfanuméricas.
  4. Contener además de blancos tres cadenas alfanuméricas.
Su programa deberá ser capaz de mantener el valor del contador de localidades (inicialmente igual a 0) y de procesar tres directivas:
  1. La directiva ORG tiene un operando, el cual es el nuevo valor del contador de localidades.
  2. La directiva EQU tiene un operando, el cual se usará para darle valor a un símbolo.
  3. La directiva END no tiene operandos e indica que no se debe procesar más código fuente.
Además, su programa deberá ser capaz de usar un operando previamente definido en lugar de un operando numérico.

El programa ejecutable operanZZ deberá leer cada una de las líneas del archivo nemonico.txt y para cada una de ellas deberá escribir una línea en el archivo codigoop.txt como sigue:
  1. Si la línea de la entrada está en blanco entonces la línea de la salida deberá consistir únicamente del caracter '\n'.
  2. Si la línea de la entrada contiene blancos y un nemónico entonces:
    1. Si el nemónico corresponde con la directiva END se deberá terminar la ejecución del programa.
    2. Si el nemónico corresponde con una instrucción de 1 byte la línea de la salida deberá consistir del valor del contador de localidades escrito en hexadecimal, seguido de un espacio, seguido del código de operación escrito en hexadecimal seguido del caracter '\n'. El contador de localidades se deberá incrementar en 1.
    3. En cualquier otro caso la línea de la salida deberá consistir únicamente de la cadena "ERROR\n".
  3. Si la línea de la entrada contiene blancos, un nemónico y un operando entonces:
    1. Si el nemónico corresponde con la directiva ORG entonces el valor del operando es el nuevo valor del contador de localidades y la línea de la salida deberá consistir únicamente del caracter '\n'.
    2. Si el nemónico corresponde con una instrucción de 2 bytes y el operando cabe en 8 bits la línea de la salida deberá consistir del valor del contador de localidades escrito en hexadecimal, seguido de un espacio, seguido del código de operación escrito en hexadecimal, seguido de un espacio, seguido del valor del operando escrito en hexadecimal, seguido del caracter '\n'. El contador de localidades se deberá incrementar en 2.
    3. Si el nemónico corresponde con una instrucción de 3 bytes y el operando cabe en 16 bits la línea de la salida deberá consistir del valor del contador de localidades escrito en hexadecimal, seguido de un espacio, seguido del código de operación escrito en hexadecimal, seguido de un espacio, seguido de los 8 bits bajos del operando escritos en hexadecimal, seguidos de un espacio, seguido de los 8 bits altos del operando escritos en hexadecimal, seguido del caracter '\n'. El contador de localidades se deberá incrementar en 3.
    4. En cualquier otro caso la línea de la salida deberá consistir únicamente de la cadena "ERROR\n".
  4. Si la línea de la entrada contiene blancos y al menos dos cadenas alfanuméricas y la primera no es un nemónico entonces ésta será un símbolo y:
    1. Si el nemónico corresponde con la directiva EQU entonces el valor del operando es el valor del símbolo y la línea de la salida deberá consistir únicamente del caracter '\n'. No se modifica el contador de localidades. En el caso de que el operando sea un símbolo y éste no esté definido previamente entonces la línea de la salida deberá consistir únicamente de la cadena "ERROR\n".
    2. Si además del símbolo el resto de la línea es como en los casos (2) y (3) de arriba entonces la línea se procesa como se indica arriba además de que el valor del contador de localidades es el valor del símbolo.
    3. Si en cualquiera de los casos (4.1) y (4.2) el símbolo al que se le debe dar valor ya tenía un valor asignado entonces la línea de la salida deberá consistir únicamente de la cadena "ERROR\n".
    4. En cualquier otro caso la línea de la salida deberá consistir únicamente de la cadena "ERROR\n".
  5. En cualquier otro caso la línea de la salida deberá consistir únicamente de la cadena "ERROR\n".
Cada vez que se imprima el contador de localidades se hará con 4 dígitos hexadecimales. Su programa se deberá detener en cuanto localize el primer error.

Abajo encontrará un ejemplo del funcionamiento de este programa:

Ejemplo de entrada nemonico.txt
Explicación del ejemplo
Ejemplo de salida codigoop.txt
XCHG
HOLA XCHG
ORG 20
COSA LDA HOLA
LDA COSA
ORG $10
NADA EQU HOLA
LDA NADA
AZCA EQU 30
ORG AZCA
XCHG
LDA $1234
END
XCHG
Comienza con CONTLOC=0 y se le suma 1
Se define HOLA=1 y se le suma 1 a CONTLOC
Se le asigna 20=$14 a CONTLOC
Se define COSA=20 y se le suma 3 a CONTLOC
Instrucción con parámetro simbólico
Se le asigna $10 a CONTLOC
Se define NADA=HOLA=1
Instrucción con parámetro simbólico
Se define AZCA=30
Se le asigna 30=$1E a CONTLOC
Instrucción sin parámetro
Instrucción con parámetro numérico
Termina el procesamiento
Esto ya no se lee
0000 EB
0001 EB

0014 3A 01 00
0017 3A 14 00


0010 3A 10 00


001E EB
001F 3A 34 12

Cuarta etapa: Código objeto : 10 puntos : 8 de diciembre de 2008 a las 10pm

Deberá escribir un programa llamado objetoZZ.c o objetoZZ.cpp o objetoZZ.java que lea un archivo con etiquetas, nemónicos, directivas y operandos y que escriba un archivo con código objeto. El archivo fuente.txt consistirá de una sucesión de líneas de texto con un máximo de 80 caracteres y terminará con el fin de archivo. Cada línea de texto podrá:
  1. Estar en blanco (los caracteres definidos por isspace).
  2. Contener además de blancos una cadena alfanumérica.
  3. Contener además de blancos dos cadenas alfanuméricas.
  4. Contener además de blancos tres cadenas alfanuméricas.
Además de todo lo que hacía la tercera etapa, su programa deberá ser capaz de procesar otras dos directivas:
  1. La directiva BYTE tiene un operando de 8 bits, el cual es un byte que se enviará a la salida. Una línea con esta directiva se deberá procesar de la misma forma que un nemónico que corresponda con una instrucción de un byte.
  2. La directiva RESB tiene un operando de 16 bits, el cual es una cantidad de bytes que se quieren reservar. Una línea con esta directiva se deberá procesar incrementando el valor del contador de localidades por la cantidad indicada en el operando.
Ahora, su programa deberá escribir un archivo objeto.txt que contendrá el código objeto correspondiente al código fuente. Cada línea del código objeto será un registro de texto formado como sigue:
  1. El primer caracter será la letra 'T'.
  2. Los siguientes cuatro caracteres serán la dirección del primer byte del código contenido en el registro.
  3. Los siguientes dos caracteres serán la cantidad de bytes contenidos en el registro (mínimo $01, máximo $20).
  4. Cada byte contenido en el registro corresponderá con dos caracteres.
  5. El último caracter será un '\n'.
Por supuesto, todos los números mencionados arriba deberán estar escritos en hexadecimal. Hay varias situaciones en las cuales se debe escribir un registro nuevo:
  1. Al principio.
  2. Cuando un registro se llene ($20 bytes = 32 bytes).
  3. Cuando el código fuente tenga una directiva ORG.
  4. Cuando el código fuente tenga una directiva RESB.
Su programa se deberá detener en cuanto localize el primer error. Abajo encontrará un ejemplo del funcionamiento de este programa:

Ejemplo de entrada fuente.txt
Explicación del ejemplo
Bytes generados
Ejemplo de salida objeto.txt
XCHG
HOLA XCHG
BYTE HOLA
ORG 20
COSA LDA HOLA
LDA COSA
ORG $10
NADA EQU HOLA
LDA NADA
AZCA EQU 30
RESB AZCA
BYTE AZCA
BYTE %10000
ORG AZCA
XCHG
LDA $1234
END
XCHG
Comienza con CONTLOC=0 y se le suma 1
Se define HOLA=1 y se le suma 1 a CONTLOC
Se emite el byte 1
Se le asigna 20=$14 a CONTLOC
Se define COSA=20 y se le suma 3 a CONTLOC
Instrucción con parámetro simbólico
Se le asigna $10 a CONTLOC
Se define NADA=HOLA=1
Instrucción con parámetro simbólico
Se define AZCA=30
Se le suma 30 a CONTLOC
Se emite el byte 30
Se emite el byte 16
Se le asigna 30=$1E a CONTLOC
Instrucción sin parámetro
Instrucción con parámetro numérico
Termina el procesamiento
Esto ya no se lee
0000 EB
0001 EB
0002 01

0014 3A 01 00
0017 3A 14 00


0010 3A 01 00


0031 1E
0032 10

001E EB
001F 3A 34 12
T000003EBEB01
T0014063A01003A1400
T0010033A0100
T0031021E10
T001E04EB3A3412


Quinta etapa: No habrá : 10 puntos : 8 de diciembre de 2008 a las 10pm

No deberá escribir un programa.