Proyecto para Software de Base

El objetivo del proyecto es la escritura de un ensamblador para un procesador simple de 8 bits. Las opciones de procesadores son el MOS Technologies 6502, el Motorola 6800, el Intel 8085 y el Zilog 80. La distribución de los procesadores se hará de forma aleatoria. Abajo listo quiénes quedaron con cuál procesador [número de equipo - integrantes]:
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. Finalmente, cada una de las etapas tendrá un valor que será anunciado junto con la especificación.

Primera Etapa : Códigos de Operación y nemónicos : 5 puntos : 9 de mayo de 2006 a las 10pm

Cada equipo deberá averiguar los códigos de operación, los nemónicos y los modos de direccionamiento de cada una de las instrucciones del procesador con el que está trabajando. Observe que cada instrucción puede tener diversos códigos de operación según el tipo de direccionamiento. Esto resultará en un problema más adelante, así que su labor será la de modificar los nemónicos de modo que cada modo de direccionamiento de cada instrucción tenga un nemónico distinto propuesto por ustedes. Equivalentemente, cada código de operación y modo de direccionamiento deberá tener un nemónico distinto. Ustedes deben de entregar un archivo de texto con el siguiente formato: El primer renglón debe de contener un número entero N escrito en decimal que sea la cantidad de nemónicos distintos. Cada uno de los siguientes N renglones debe de contener la información correspondiente a cada uno de los nemónicos: Una cadena formada exclusivamente por letras mayúsculas y dígitos, que comience con una letra y que representa un nemónico, seguida de un espacio, seguida de un número entero escrito en decimal que representa el código de operación.

Por ejemplo, el SIC tiene una instrucción de suma cuyo nemónico es ADD y su código de operación es 18 en hexadecimal, es decir, 24 en decimal. Como casi todas las instrucciones del SIC, esta instrucción tiene dos modos de direccionamiento (directo e indexado). Por lo tanto, podríamos remplazar el nemónico ADD por los dos nemónicos ADDD y ADDX. En el archivo pedido, esto equivaldría a tener dos renglones como sigue:
ADDD 24
ADDX 24
Otra opción podría ser que los nemónicos fueran SUMADIR y SUMAIND, etc.

Segunda Etapa: Instrucciones y operandos : 5 puntos : 16 de mayo de 2006 a las 10pm

En esta etapa van a modificar el archivo que entregaron en la primera etapa para resolver algunos detalles. El primero de ellos (y que ya se notaba desde el ejemplo con el SIC) es que en ocasiones más de un nemónico parece tener el mismo código de operación. Eso no puede ser cierto, pues el procesador requiere saber cuál es cuál. Lo que ocurre es que en ocasiones el procesador lee algunos bits adicionales para distinguir entre las instrucciones correspondientes. Por ejemplo, el SIC distingue entre las dos instrucciones ADDD y ADDX fijándose en el bit más alto del siguiente byte. El segundo detalle a resolver es el de cuántos bytes ocupa cada instrucción (en el SIC todas las instrucciones ocupan 3 bytes, pero eso no es cierto en el SIC/XE). El tercer detalles es cuántos bits ocupan los operandos de las instrucciones y en qué formato están escritos (particularmente con o sin signo). Finalmente, el último detalles es que todos los números mencionados arriba se suelen escribir en hexadecimal. En esta ocasión, ustedes deben de entregar un archivo de texto con el siguiente formato: El primer renglón debe de contener un número entero N escrito en hexadecimal que sea la cantidad de nemónicos distintos. Cada uno de los siguientes N renglones debe de contener la información correspondiente a cada uno de los nemónicos: Una cadena formada exclusivamente por letras mayúsculas y dígitos, que comience con una letra y que representa un nemónico, seguida de un espacio, seguida de un número entero L escrito en hexadecimal que representa la longitud de la instrucción en bytes, seguida de un espacio, seguida de L números enteros escritos en hexadecimal separados por espacios representando el código de operación y todos los bits adicionales requeridos y donde los bits del operando valgan 0, seguidos de L números enteros escritos en hexadecimal separados por espacios donde los bits del operando valgan 1 y todos los demás cero, seguidos de un número entero escrito en hexadecimal que vale 0 si el operando es sin signo (absoluto) y 1 si el operando es con signo (relativo al contador de programa).

Por ejemplo, las líneas correspondientes a ADDD y ADDX del SIC se deben ver en el archivo pedido como sigue:
ADDD h3 h18 h0 h0 h0 h7f hff h0
ADDX h3 h18 h80 h0 h0 h7f hff h0
ya que lo que distingue a ADDD de ADDX es el valor del bit más alto del segundo byte. Observe que los números hexadecimales están escritos según el formato descrito en la tarea 1. Si le parece más conveniente, también puede escribir los números en cualquier otro de los formatos descritos allí (es decir, binario, cuaternario, octal o decimal).

Tercera Etapa : Generación de código objeto : 15 puntos : 2 de junio de 2006 a las 10pm

Esta es la primera etapa en la cual se deberá de entregar un programa. Deberán escribir un programa de nombre ensambla que lea de la entrada estándar un programa escrito en lenguaje ensamblador y que escriba en la salida un programa escrito en código objeto. En esta etapa, el código fuente consistirá de una sucesión de líneas de texto y terminará con el fin de archivo. Cada línea de texto podrá (1) estar en blanco (los definidos por isspace), (2) contener además de blancos el nemónico de una instrucción sin parámetro, (3) contener además de blancos el nemónico de una instrucción separada por blancos de su parámetro numérico o (4) contener además de blancos la pseudoinstrucción ORIGEN separada por blancos de su parámetro numérico. Los nemónicos deberán ser aquellos definidos en las etapas previas del proyecto y deberán de estar contenidos en una tabla de símbolos implementada como una tabla de dispersión. Los parámetros numéricos podrán estar escritos en cualquiera de los formatos numéricos definidos en la tarea 1. El parámetro de ORIGEN es la dirección de la siguiente instrucción en el código fuente (si éste no comienza con ORIGEN se debe considerar que la primera instrucción tiene dirección 0) y por lo tanto debe de estar en el rango 0 a 65535. Los parámetros de las instrucciones deben de estar en los rangos que les correspondan (es decir, en ocasiones deberán ser de 8 bits, en otras ocasiones de 16 bits, etc.) Su programa deberá detectar los siguientes tipos de errores, los cuales deberá señalar en el error estándar (stderr) junto con el número y contenido de la línea fuente en que ocurren: (1) instrucción desconocida, (2) falta parámetro, (3) sobra parámetro, (4) parámetro fuera de rango, (5) parámetro sin instrucción y (6) formato desconocido de parámetro. Las líneas que contengan errores no afectarán al contador de programa. Cada línea de la entrada estándar deberá producir una línea en la salida estandar según sea el caso: (1) una línea vacía si la de entrada estaba en blanco o si la entrada era una instrucción ORIGEN legal, (2) una línea que comienza con la letra M seguida de una dirección escrita con cuatro dígitos hexadecimales seguida de una sucesión de parejas de dígitos hexadecimales separados por espacios y correspondientes al código objeto de una instrucción legal, (3) una línea que comienza con el caracter ? seguida de un mensaje de error adecuado (INSTRUCCION, FALTA, SOBRA, RANGO, PARAMETRO, FORMATO). Abajo mostramos un ejemplo de funcionamiento de este programa con el SIC:

Entrada estándar
Salida estándar
Error estándar
ORIGEN  h1000
 STL  h1033
JSUB
h1036
COMP  h1015
JEQ ENDFIL

M1000 14 10 33
?FALTA
?PARAMETRO
M1003 30 10 15
?FORMATO
FALTA 3 JSUB
PARAMETRO 4 h1036
FORMATO 6 JEQ ENDFIL

Si quieren probar su programa con el código fuente en fuente.txt, mandando el código objeto a objeto.txt y los errores a error.txt con redirección bajo Linux lo pueden hacer con la instrucción ensambla <fuente.txt 1>objeto.txt 2>error.txt y para enviar algo al error estándar desde un programa en C pueden usar fprintf(stderr, ...), en C++ pueden usar cerr << ..., etc. Nota: Ustedes pueden incluir la tabla de nemónicos dentro del código fuente de su programa o también pueden hacer que su programa la lea de algún archivo adicional que se entregue junto al código.

Cuarta Etapa: Definición de símbolos : 10 puntos : 30 de junio de 2006 a las 10pm

Debarán escribir un programa de nombre pasouno que lea de la entrada estándar un programa escrito en lenguaje ensamblador y que escriba en la salida un programa escrito en código objeto. En esta etapa, el código fuente consistirá de una sucesión de líneas de texto y terminará con el fin de archivo. Cada línea de texto podrá ser de cualquiera de los cuatro tipos definidos en la tercera etapa del proyecto además de los siguientes casos: (5) contener además de blancos la pseudoinstrucción DEFINE separada por blancos de una etiqueta y de un parámetro numérico en los formatos definidos en la tarea 1, (6) contener además de blancos la pseudoinstrucción IGNORA seguida de cualquier texto, (7) antes de cualquier nemónico (y separada por blancos de él) podrá aparecer una etiqueta en el formato definido en la tarea 1 y (8) en lugar de cualquier parámetro numérico podrá aparecer una etiqueta en el formato definido en la tarea 1. Los parámetros de DEFINE serán un símbolo no definido previamente y el valor que se le está asignando a ese símbolo. El texto que sigue a IGNORA se considerará un comentario y puede ignorarse. Si aparece una etiqueta antes de un nemónico entonces ésta debe ser un símbolo no definido previamente y tomará el valor del contador de localidades. Si aparece una etiqueta como parámetro de un nemónico o como segundo parámetro de DEFINE entonces ésta deberá estar definida previamente (es decir, no se permiten referencias hacia adelante). Su programa deberá detectar los seis tipos de errores definidos en la tercera etapa del proyecto además de los siguientes: (7) redefinición de símbolo y (8) símbolo no definido. Las líneas que contengan errores no afectarán al contador de programa ni definirán símbolos. Cada línea de la entrada estándar deberá producir una línea en la salida estandar según sea el caso: (1) una línea vacía si la de entrada estaba en blanco o si la entrada era una instrucción ORIGEN, DEFINE o IGNORA legal, (2) una línea que comienza con la letra M seguida de una dirección escrita con cuatro dígitos hexadecimales seguida de una sucesión de parejas de dígitos hexadecimales separados por espacios y correspondientes al código objeto de una instrucción legal, (3) una línea que comienza con el caracter ? seguida de un mensaje de error adecuado (INSTRUCCION, FALTA, SOBRA, RANGO, PARAMETRO, FORMATO, CONOCIDO, DESCONOCIDO). Abajo mostramos un ejemplo de funcionamiento de este programa con el SIC:

Entrada estándar
Salida estándar
Error estándar
IGNORA el programa!
DEFINE AQUI h1000
DEFINE ALLA h1033
ORIGEN AQUI
STL  ALLA
JSUB AQUI
IGNORA que es otro?
COMP OTRO
JEQ  AQUI
DEFINE OTRO h1015
DEFINE OTRA OTRO
IGNORA ya se alla!
ALLA STL AQUI




M1000 14 10 33
M1003 48 10 00

?DESCONOCIDO
M1006 30 10 00



?CONOCIDO
DESCONOCIDO 8 COMP OTRO
CONOCIDO 13 ALLA STL AQUI

Si quieren probar su programa con el código fuente en fuente.txt, mandando el código objeto a objeto.txt y los errores a error.txt con redirección bajo Linux lo pueden hacer con la instrucción pasouno <fuente.txt 1>objeto.txt 2>error.txt y para enviar algo al error estándar desde un programa en C pueden usar fprintf(stderr, ...), en C++ pueden usar cerr << ..., etc. Nota: Ustedes pueden incluir la tabla de nemónicos dentro del código fuente de su programa o también pueden hacer que su programa la lea de algún archivo adicional que se entregue junto al código.

Quinta Etapa: Ensamblador completo : 15 puntos : 10 de julio de 2006 a las 10pm

Debarán escribir un programa de nombre pasodos que lea de la entrada estándar un programa escrito en lenguaje ensamblador y que escriba en la salida un programa escrito en código objeto. En esta etapa, el código fuente consistirá de una sucesión de líneas de texto y terminará con el fin de archivo. Cada línea de texto podrá ser de cualquiera de los tipos definidos en la tercera y cuarta etapas del proyecto además de los siguientes casos: (9) contener además de blancos la pseudoinstrucción BYTE seguida de un parámetro numérico con valor N seguida de N parámetros numéricos separados por espacios. El primer parámetro de BYTE deberá ser un parámetro numérico constante en el rango 0 a 255, mientras que los demás parámetros podrán estar definidos por etiquetas y en cualquier caso deberán estar en el rango 0 a 255. En este caso, el contador de localidades deberá incrementarse en N unidades y el código objeto generado serán los N bytes definidos por los últimos N parámetros de BYTE. Si en cualquier lugar del código fuente aparece una etiqueta como parámetro numérico ésta deberá estar definida en exactamente un lugar (es decir, ahora sí se permiten referencias hacia adelante). Su programa deberá detectar los ocho tipos de errores definidos en la tercera y cuarta etapas del proyecto, aunque en esta ocasión el error de tipo (8) sólo se refiere a símbolos no definidos en ninguna parte. Además, cuando un símbolo se defina más de una vez se considerará que su valor correcto es el de la primera definición y que las demás líneas que lo definan contendrán un error de tipo (7). Abajo mostramos un ejemplo de funcionamiento de este programa con el SIC:

Entrada estándar
Salida estándar
Error estándar
IGNORA el programa!
DEFINE AQUI h1000
DEFINE ALLA h1033
DEFINE VALOR 10
ORIGEN AQUI
STL  ALLA
JSUB AQUI
IGNORA que es otro?
COMP OTRO
JEQ  AQUI
DEFINE OTRO h1015
DEFINE OTRA OTRO
IGNORA ya se alla!
ALLA STL AQUI
BYTE 4 h1 h2 h4 h8





M1000 14 10 33
M1003 48 10 00

M1006 28 10 15
M1009 30 10 00



?CONOCIDO
M100C 01 02 04 08
CONOCIDO 14 ALLA STL AQUI

Si quieren probar su programa con el código fuente en fuente.txt, mandando el código objeto a objeto.txt y los errores a error.txt con redirección bajo Linux lo pueden hacer con la instrucción pasodos <fuente.txt 1>objeto.txt 2>error.txt y para enviar algo al error estándar desde un programa en C pueden usar fprintf(stderr, ...), en C++ pueden usar cerr << ..., etc. Nota: Ustedes pueden incluir la tabla de nemónicos dentro del código fuente de su programa o también pueden hacer que su programa la lea de algún archivo adicional que se entregue junto al código.