Simpletron
Home Práctica PAR Big Num Amigos Números Romanos Simpletron Classes Ejercicios Tic Tac Prime

 

OPCODES
UI
Ejemplo
Hints

Nombre:

Simpletron

Fecha de Entrega:

Primera Entrega:        4 Noviembre
Segunda Entrega:    25 Noviembre
Entrega Final:             12 Diciembre

Motivación:

Como ya se ha discutido, las computadoras solo entienden lenguaje máquina. Para que la computadora pueda ejecutar los programas que nosotros elaboramos en lenguajes de alto nivel (C++ o ADA) es necesario que un programa los compile (traduzca a lenguaje máquina). Por medio de este proyecto podrán experimentar con un lenguaje máquina sencillo llamado SML (Simpletron Machine Language), la manera en que este funciona, y como ejecuta programas. También pondrán en práctica los conocimientos adquiridos durante el curso.

Descripción:

Funcionamiento

El programa que se va a desarrollar deberá ser capaz de leer código SML y ejecutarlo, el interfaz que deberá tener se describe más adelante. Las operaciones que deberá ejecutar el programa serán las siguientes:

  • Operaciones Aritméticas sobre enteros y reales
  • Operaciones de Entrada/Salida para Enteros, Reales y Cadenas de Caracteres

Las características técnicas que tendrá el Simulador serán:

  1. 8 Registros
    1.1    7 Registros de Uso General
    1.2    1 Registro de Status
  2. 1 Acumulador de 16 bits
  3. 1 Pila de 256 Bytes
  4. Operaciones de Enteros, Reales y Cadenas de Caracteres
  5. Guardar, Abrir, Correr desde línea de comando
  6. Memoria de Uso 4096 Bytes
  7. Vaciado de Memoria

Distribución de bits en las Instrucciones

A continuación se describen la distribución de bits para las instrucciones:

Cada línea de código constará de 3 bytes (24 bits).

Ejemplo:

Para utilizar la instrucción MOD con la posición 60 en memoria se vería así:
00000100000000011110000 = 0x200F0 = 0x0200F0

Reservado (siempre 0) Instrucción (08) Dirección de Memoria (3C) Número de Registro
000 001000 000000111100 000

En el editor uno escribiría lo siguiente:

083C0

Las instrucciones básicamente tienen 3 partes:

  • Instrucción
  • Dirección de Memoria
  • Registro que afectan

La mayor parte de las instrucciones no necesitan utilizar el número de registro, excepto las instrucciones MOVR (0x24) y MOVA (0x25)  las cuales se encargan de colocar una dirección en algún registro específico, o colocar el valor de un registro en una dirección específica, respectivamente.

Manejo de los Registros

Registros de Uso General

El simulador deberá manejar 7 registros de uso general cada uno de 32 bits, los cuales se llamarán de la siguiente manera:

Número Nombre Acceso a LOW Acceso a HOW
0 PX PL PH
1 OX OL OH
2 QX QL QH
3 RX RL RH
4 SX SL SH
5 TX TL TH
6 UX UL UH

LOW = Low Order Word
HOW = High Order Word

Por medio de los accesos especiales, se podrá acceder a solamente a los primeros 16 bits o a los últimos 16 bits, así como se describe en la siguiente figura:

Registro de Status

Este es un registro de 8 bits en el cual los bits representan lo siguiente:

bit Significado
0 Reservado
1 Zero (si es uno el acumulador tiene 0)
2 Reservado
3 Neg (si es uno el acumulador almacena un número negativo)
4 Reservado
5 Reservado
6 Division by Zero (si es uno hubo división por cero)
7 Overflow (si es uno hubo overflow)

Los registros son utilizados para especificar direcciones de memoria o para recibir datos. Son especialmente utilizados para las operaciones de entrada / salida (IO), las cuales necesitan de la ejecución de un interrupto especial (el único).

Esto se debe a que normalmente los procesadores sólo pueden accesar a los registros en cada instrucción, y los registros guardan la dirección a la cual se quiere enviar o recibir la información. Un ejemplo, si desearamos imprimir un entero que se encuentra en la posición 75 de memoria tendríamos que escribir el siguiente código:

2600B0    ;Colocar el valor constante 0x00B (Operación de Escritura) en el Registro PL
2604B2    ;Colocar el valor constante 0x04B (Dirección del Entero) en el Registro QX
3F0000    ;Llamar al interrupto para que ejecute la instrucción que se encuentra en PL

Manejo de Cadenas de Caracteres

Las cadenas de caracteres se manejarán de la siguiente manera, los caracteres se almacenarán uno a uno en cada posición de memoria. Para poder determinar el tamaño de una cadena habrá que leer el HOB (High Order Byte) de la memoria (el cual es los últimos 8 bits de cada posición de memoria). En esa posición deberá estar almacenado el tamaño, en el siguiente byte estará el caracter. Por ejemplo si quisieramos almacenar la cadena Hola!, a partir de la dirección 00F, lo haríamos de la siguiente manera:

Dirección HOB
(High Order Byte)
(Últimos 8 bits)
MOB
(Medium Order Byte)
(8 bits de enmedio)
LOB
(Low Order Byte)
(Primeros 8 bits)
00F 4 H 0
010 3 o 0
011 2 l 0
012 1 a 0
013 0 ! 0

El Acumulador

El Acumulador es un lugar en el procesador donde se guarda el primer operando de una operación aritmética, así mismo ahí se guarda el resultado.

Manejo de Números Reales (float)

Los números de punto flotante serán de 4 bytes (32 bits) por lo tanto se utilizará el tipo float de C para simularlo. Ahora el manejo de los mismos es diferente al de los enteros, dado que no cabe en el acumulador, se utilizan los registros TX y SX para el manejo de los mismos.

Para almacenar un float en memoria, habrá que partirlo en 4 bytes, y manipular estos bytes independientemente. Los primeros dos bytes se almacenarán en la posición de memoria indicada, los últimos dos bytes se almacenarán en la siguiente posición de memoria. El funcionamiento interno de los números de punto flotante es indiferente para este proyecto. 

A continuación se coloca un segemento de código que parte el número real en cuatro bytes y almacena los primeros dos en la posición 1 de un arreglo, y los siquientes dos en la posición 2 del arreglo.

union f2_4b
{
    float f;
    char c[4];
};

float x = 5.5455234;
f2_4b Z;
Z.f = x;

int arreglo[3];
arreglo[1] = Z.c[1];
arreglo[1]<<=8;
arreglo[1]|=Z.c[0];
arreglo[2] = Z.c[3];
arreglo[2]<<=8;
arreglo[2]|=Z.c[2];

// voilá en el arreglo se encuentra introducido el float en forma de enteros...

Uso de Línea de Comando

El programa deberá tener la habilidad de poder ser llamado desde la línea de comando, dependiendo de las opciones, el programa ejecutará en modo normal, o ejecutará un programa especificado.

simplet [-r archivo.asm] [-h]

Si solo se ejecuta simplet, entonces se podrá ver el entorno definido en la interfaz del proyecto.

Si se coloca -r archivo.asm entonces el programa empezará a leer las instrucciones contenidas en el archivo de texto archivo.asm y las ejecutará.

Si se coloca -h desplegará un pequeño mensaje de ayuda.

Manejo de la Pila

El simpletron manejará una pila de 256 bytes de memoria, la cual deberá ser programada completamente utilizando objetos. Las pilas tienen dos operaciones básicas que son PUSH y POP, estas operaciones están definidas en los OPCODES del simpletron. El funcionamiento de la pila, básicamente será para el manejo de operaciones aritméticas con enteros, utilizando notación postfija. El programa desarrollado no tiene que hacer ningún tipo de conversión, sólo deberá manejar correctamente la pila para poderla utilizar en operaciones aritméticas.

Operaciones con Archivos

El programa deberá tener la habilidad de guardar archivo, abrir archivo, o empezar uno nuevo. El manejo de archivos se hará enteramente en archivos de texto.

Vaciado

En el interfaz de usuario se mira que hay una opción para hacer vaciado de memoria, por medio de esto lo que se logra es que se despliegue en pantalla o a un archivo el contenido total de la memoria.

Requerimientos:

El programa a entregar deberá cumplir con lo siguiente:

  • Escrito en C++
  • Modular, capaz de ser utilizado con otros programas
  • Chequeo de errores (overflow, mal formato, etc)
  • Programas de prueba