Proyecto de Software de Base

El objetivo del proyecto es el de escribir un ensamblador simple para el microprocesador Zilog Z80. 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 de 8 bits : 10 puntos : 23 de junio de 2009 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 49 a 60 del manual del Zilog Z80, todas sus instrucciones tienen códigos de operación que caben en un entero de 8 bits o en un entero de 16 bits. En esta primera sólo trabajaremos con las instrucciones cuyo código de operación mide 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 y coma que aparezca. Ejemplo: el nemónico LD (HL) se convertirá en LD(HL) con código de operación 00110110.
  2. Aquellos nemónicos en cuyos códigos de operación aparezcan r o s se expandirán para producir tantos nemónicos como sea necesario, reemplazando r y s por el nombre abreviado del registro correspondiente. Ejemplo: el nemónico LD r se deberá convertir en 7 nemónicos diferentes LDB, LDC, LDD, LDE, LDH, LDL y LDA con códigos de operación 00000110, 00001110, ..., 00111110, respectivamente.
  3. No se tomarán en cuenta ninguno de los nemónicos que tienen un cuadrito en la descripción de su código de operación.
  4. Es posible que haya otros casos que describiré luego.
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
LDA
lda
LDB ME

LDC
LDD
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
00111110 3E
ERROR
ERROR

00001110 0E
00010110 16

Segunda etapa: Operandos : 20 puntos : 9 de julio de 2009 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 en el manual, el Z80 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: LDAB.
  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: LDB.
  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: LDBC.
El tipo al que pertenece cada instrucción se puede tomar del manual. La primera columna de esa tabla contiene al nemónico y a su posible operando. Usted debe ignorar los operandos que digan r o s (o también dd o qq) 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 n (de 8 bits), n (de 16 bits) y d (de 8 bits). Si una instrucción tiene a d y a n simultaneamente como parámetros, debe ignorarla también. 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
LDAB
LDAB $5
LDBC
LDBC %101
%101 LDBC
LDBC %2
LDBC $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

ERROR
ERROR

ERROR
ERROR
ERROR
ERROR


ERROR
ERROR

Tercera etapa: Símbolos : 20 puntos : 3 de agosto de 2009 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.
  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.

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:Abajo encontrará un ejemplo del funcionamiento de este programa:

Ejemplo de entrada nemonico.txt
Explicación del ejemplo
Ejemplo de salida codigoop.txt
LDAB
HOLA LDAB
ORG 20
COSA LDBC HOLA
LDBC COSA
ORG $10
NADA EQU HOLA
LDBC NADA
AZCA EQU 30
ORG AZCA
LDAB
LDBC $1234
END
LDAB
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 xx
0001 xx

0014 yy 01 00
0017 yy 14 00


0010 yy 01 00


001E xx
001F yy 34 12

No habrá cuarta etapa del proyecto.