Sección especial: Construya su propia computadora1
En los siguientes problemas nos alejaremos temporalmente del mundo de la programación en lenguajes de alto nivel.
Vamos a "destripar" una computadora y examinar su estructura interna. Presentaremos la programación en lenguaje de
máquina y escribiremos varios programas en lenguaje de máquina. A fin de que esta experiencia sea especialmente
valiosa, construiremos una computadora (empleando la técnica basada software de la simulación) para que usted pueda
ejecutar sus programas.

5.42 (Programación en lenguaje de máquina) Vamos a crear una computadora a la que llamaremos Simpletron. Como su
nombre indica, se trata de una máquina sencilla. Sin embargo, también es potente, como habremos de ver. La Simpletron
ejecuta programas escritos en el único lenguaje que entiende directamente: Simpletron Machine Language (lenguaje de
máquina de Simpletron), abreviado SML.

La Simpletron contiene un acumulador: un "registro especial" en el que se coloca información antes de que la máquina
utilice dicha información en cálculos o la examine de diversas maneras. Toda la información se maneja en la Simpletron en
términos de palabras. Una palabra es un número decimal de cuatro dígitos con signo, como -3364, -1293, +0007, -0001,
etc. La Simpletron está equipada con una memoria de 100 palabras, a las cuales hace referencia por su número de
posición: 00, 01, ..., 99.

Antes de ejecutar un programa en SML, debemos cargar o colocar el programa en la memoria. La primera ejecución (o
enunciado) de un programa en SML siempre se coloca en la posición 00. El simulador iniciará la ejecución en esta posición.
Cada instrucción escrita en SML ocupa una palabra de la memoria de la Simpletron (de modo que las instrucciones son
números decimales de cuatro dígitos con signo). Supondremos que el signo de una instrucción SML les positivo, pero el
signo de una palabra de datos puede ser más o menos, Cada posición de la memoria de Simpletron puede contener una
instrucción, un valor de datos utilizado por un programa, o un área de memoria no utilizada (y por tanto no definida). Los
primeros dos dígitos de cada instrucción SML son el código de operación que especifica la operación por realizar. Los
códigos de operación SML se resumen en la siguiente tabla:

           Código de operación                                               Significado
Operaciones de Entrada y salida
const int READ = 10;                        Leer una palabra de la terminal colocándola en una posición específica de la
                                            memoria.
const int WRITE = 11;                       Escriba una palabra en la posición de memoria específica en la terminal.
Operaciones de carga/almacenamiento
const int LOAD = 20;                        Cargar una palabra de una posición de memoria específica al acumulador.
const int STORE = 21;                       Almacenar una palabra del acumulador a una posición específica de la
                                            memoria
Operaciones Aritméticas
const int ADD = 30;                         Sumar una palabra en una posición específica de la memoria a la palabra que
                                            está en el acumulador. (dejar el resultado en el acumulador)
const int SUBSTRACT = 31;                   Restar una palabra en una posición específica de la memoria de la palabra
                                            que está en el acumulador. (dejar el resultado en el acumulador)
const int DIVIDE = 32;                      Dividir una palabra en una posición específica de la memoria entre la palabra
                                            que está en el acumulador. (dejar el resultado en el acumulador)
const int SUBSTRACT = 31;                   Restar una palabra en una posición específica de la memoria por la palabra
                                            que está en el acumulador. (dejar el resultado en el acumulador)
Operaciones de transferencia de Control
const int BRANCH = 40;                      Bifurcar a una posición específica de la memoria.
const int BRANCHNEG = 41;                   Bifurcar a una posición específica de la memoria si el acumulador es negativo.
const int BRANCHZERO = 42;                  Bifurcar a una posición específica de la memoria si el acumulador es cero.
const int HALT = 43;                        Alto. El programa completó su tarea.

Los dos últimos dígitos de una instrucción SML son el operando: la dirección de la posición de memoria que contiene la
palabra a la que se le aplica el operando. Consideremos varios programas SML Sencillos.

El primer programa SML (ejemplo 1) lee 2 números de teclado y calcula e imprime su suma. La instrucción +1007 lee el
primer número del teclado y lo coloca en la posición 07 (que se ha inicializado con cero). Luego la instrucción +1008 lee el
siguiente número y lo coloca en la posición 08. La instrucción cargar. +2007, coloca el primer número en el acumulador, y la
instrucción sumar, +3008 suma el segundo número que está en el acumulador. Todas la instrucciones SML dejan el
resultado en el acumulador. La instrucción de almacenar, +2109, coloca el resultado en la memoria, en la posición 09. La
instrucción de escribir: +1009. toma el resultado de esa posición y lo imprime (como numero decimal de cuatro dígitos con
signo). La Instrucción de alto, +4300, termina la ejecución.




1
 Extraído del libro “Como programar en Java” Autores Deitel y Deitel, © 1998 Prentice Hall Hispanoamericana, p. 265-271.
Tomada con fines didácticos.
Ejemplo 1

Posición                                  Número                                    Instrucción
00                                        +1007                                     (Leer A)
01                                        +1008                                     (Leer B)
02                                        +2007                                     (Cargar A)
03                                        +3008                                     (Sumar B)
04                                        +2109                                     (Almacenar C)
05                                        +1109                                     (Escribir C)
06                                        +4300                                     (Alto)
07                                        +0000                                     (Variable A)
08                                        +0000                                     (Variable B)
09                                        +0000                                     (Resultado C)

Ejemplo 2
Posición                                  Número                                    Instrucción
00                                        +1009                                     (Leer A)
01                                        +1010                                     (Leer B)
02                                        +2009                                     (Cargar A)
03                                        +3110                                     (Restar B)
04                                        +4107                                     (Bifurcar si negativo a 07)
05                                        +1109                                     (Escribir A)
06                                        +4300                                     (Alto)
07                                        +1110                                     (Escribir B)
08                                        +4300                                     (Alto)
09                                        +0000                                     (Variable A)
10                                        +0000                                     (Variable B)

Este programa en SML lee dos números del teclado y determina e imprime el mayor de ellos. Observe el empleo de la
instrucción +4107 como transferencia condicional del control, muy similar al enunciado if de Java. Ahora escriba programas
SML para realizar las siguientes tareas.
      a) Utilice un ciclo controlado por centinela para leer 10 números positivos y calcular e imprimir su suma.
      b) Utilice un ciclo controlado por contador para leer siete números, algunos positivos y otros negativos, y calcular e
          imprimir su promedio.
      c) Lea una serie de números y determine e imprima el número más grande. El primer número leído indica cuántos
          números deben procesarse.
5.43 (Un simulador de computadora) Tal vez le parezca descabellado, pero en este problema usted va a construir su propia
computadora. Y no, no va a soldar componentes para formar circuitos. Más bien, utilizara la potente técnica de simulación
basada en software para crear un modelo de software orientado a objetos de la Simpletron. Le aseguramos que no se
decepcionará. Su simulador de Simpletron convertirá la computadora que usted está usando en una Simpletron, y usted
podrá realmente ejecutar, probar y depurar los programas SML que escribió para el ejercicio 5.42. Su Simpletron será Un
programa C que corra en su PC


Cuando ejecute su simulador de Simpletron, deberá comenzar por desplegar:

                          *** ¡Bienvenido a Simpletron! ***
                          *** Introduzca su programa una instrucción ***
                          *** (o palabra de datos) a la vez en el campo ***
                          *** de texto de entrada. Yo indicaré el número ***
                          *** de posición y una interrogación (?). Usted ***
                          *** tecleará entonces la palabra para esa ***
                          *** posición. Haga clic en el botón LISTO para ***
                          *** dejar de introducir su programa. ***

El programa deberá exhibir una posición de memoria junto con un signo de interrogación (?) en el que el usuario tecleará
las instrucciones una por una y mediante el código “9999”, Simpletrón sabrá que ha introducido el programa SML completo.
Simule la memoria de la Simpletron con un arreglo memory de un solo sub índice con 100 elementos. Ahora suponga que el
simulador está funcionando y examinemos el diálogo conforme introducimos el programa del ejemplo 2 del ejercicio 5.42:

               00 ? +1009
               01 ? +1010
               02 ? +2009
               03 ? +3110
               04 ? +4107
               05 ? +1109
               06 ? +4300
               07 ? +1110
               08 ? +4300
               09 ? +0000
               10 ? +0000

Su programa deberá usar un printf() para exhibir la posición de memoria seguida de una interrogación. Los valores a la
derecha de cada signo de interrogación son tecleados por el usuario. Cuando se introduzca un 9999, el programa deberá
exhibir:

       *** Se terminó de cargar el programa ***
       *** Comienza la ejecución del programa ***

El programa SML ya se ha colocado (o cargado) en el arreglo memory. La ejecución se iniciará con la instrucción que está
en la posición 00 y, al igual que en C, continuará secuencialmente, a menos que una transferencia de control haga que
continúe en alguna otra parte del programa.

Utilice la variable acumulator (acumulador) para representar el registro acumulador. Use la variable instructionCounter
(contador de instrucciones) para seguir la pista a la posición de memoria que contiene la instrucción que se está ejecutando.
Utilice la variable operationCode (código de operación) para indicar la operación que se está realizando, es decir, los dos
dígitos de la izquierda de la palabra de instrucción. Emplee la palabra operand (operando) para indicar la posición de
memoria sobre la cual opera la instrucción en curso (operand será a los dos dígitos de la derecha de la instrucción que se
está ejecutando.) No ejecute las instrucciones directamente de la memoria. Más bien, transfiera de la memoria la siguiente
instrucción por realizar a una variable llamada instructionRegister (registro de instrucción). Luego "separe" los dos dígitos de
la izquierda y colóquelos en operationCode, y "separe" los dos dígitos de la derecha y colóquelos en operand. Cada uno de
los registros anteriores deberá tener un campo de texto correspondiente en el que el valor actual se pueda exhibir en todo
momento. Cuando Simpletron inicie su ejecución, todos los registros especiales deberán inicializarse en 0.
Sigamos ahora paso por paso la ejecución de la primera instrucción SML, +1009, que está en la posición de memoria 00.
Esto es un ciclo de ejecución de instrucción.

El instructionCounter nos indica la ubicación de la siguiente instrucción por ejecutar. Traemos de memory el contenido de
esa posición empleando el enunciado de Java:

       instructionRegister = memory[instructionCounter ]

El código de operación y el operando se extraen del registro de instrucciones con los enunciados:


       operationCode = instructionRegister /100;
operand = instructionRegister % 100;

Ahora la Simpletron debe determinar que el código de operación es un leer (no un escribir, ni un cargar, etc.). Un switch
diferenciará entre las doce operaciones de SML. En la estructura switch, simulamos el comportamiento de diversas
instrucciones SML como sigue (dejamos las demás para el lector):

leer:                                                           Exhibir la solicitud "Teclee un entero". Habilitar el campo de
                                                                texto input para que el usuario pueda introducir un valor.
                                                                Leer el valor introducido, convertirlo en entero y
                                                                almacenarlo en la posición memory [ operand ].
cargar:                                                         accumulator = memory [ operand ] ;
sumar:                                                          accumulator += memory [ operand ] ;
bifurcar:                                                       Explicaremos las instrucciones de bifurcación en breve
alto:                                                           Esta instrucción imprime el mensaje
                                                                *** Terminó la ejecución de Simpletron ***

Cuando el programa SML termina su ejecución, deben exhibirse el nombre y el contenido de cada registro, así como el
contenido de la memoria completa. Semejante impresión se conoce como vaciado de computadora (lo que no quiere decir
que la computadora quede hueca). Para facilitar la programación de su método de vaciado (dump, en inglés), mostramos un
ejemplo de formato de vaciado en la figura 5.23. Observe que un vaciado después de la Ejecución de un programa
Simpletron mostraría los valores reales de las instrucciones y los datos en el momento en que terminó la ejecución. El
ejemplo de vaciado supone que las salidas se envían a la pantalla con una serie de llamadas a los métodos printf().

Continuemos con la ejecución de la primera instrucción de nuestro programa, a saber, la +1009 de la Posición 00. Como
hemos señalado, el enunciado switch simula esto solicitando al usuario que teclee un valor usando un scanf(), leyendo así
el valor, convirtiendo el valor en entero y almacenándolo en la posición de memoria memory[operand] .Dado que nuestra
Simpletron está controlada por teclado, esperará a que el usuario capture un y oprima la tecla Enter. Entonces, el valor se
leerá y se colocará en la posición 09. En este punto, habrá terminado la simulación de la primera instrucción. Lo único que
resta es preparar la Simpletron para que ejecute la siguiente instrucción. Puesto que la instrucción recién ejecutada no era
una transferencia de control, basta con incrementar el registro contador de instrucciones como sigue:

        ++instructioncounter:

Esto completa la ejecución simulada de la primera instrucción. Cuando el usuario haga clic en el botón de Ejecutar siguiente
instrucción, se iniciará de nuevo todo el proceso (es decir, el ciclo de ejecución de instrucción) con la obtención de la
siguiente instrucción por ejecutar. Consideremos ahora cómo se simulan las instrucciones de bifurcación (las transferencias
de control). Todo lo que tenemos que hacer es ajustar el valor del contador de instrucciones de forma apropiada. Por tanto,
la instrucción de bifurcación incondicional (40) se simula dentro del switch con:

        instructionCounter = operand;

La instrucción condicional "bifurcar si el acumulador es cero" se simula con:
:
        if { accumulator == 0 }
           instructionCounter = operand;

Implemente ahora su simulador de Simpletron y ejecute los programas SML que escribió en el ejercicio 5.42. Puede adornar
SML con características adicionales e incluir código para implementarlas en su simulador.

El simulador deberá verificar la ocurrencia de diversos tipos de errores. Durante la fase de carga del programa, cada
número que el usuario teclee en la "memoria" (el arreglo memory) de la Simpletron deberá estar en el intervalo de -9999 a
+9998. El simulador deberá comprobar que todos los números introducidos estén en este intervalo y, en caso contrario,
seguir solicitando al usuario que reintroduzca el número hasta que el usuario teclee un número correcto.

Durante la fase de ejecución, su simulador deberá detectar diversos errores graves, como intentos por dividir entre cero,
intentos de ejecutar códigos de operación no válidos, desbordamientos del acumulador (es decir, operaciones aritméticas
que tengan como resultado valores mayores que +9999 o menores que -9999) y demás. Estos errores graves se
denominan errores fatales. Cuando se detecte un error fatal, el simulador deberá imprimir un mensaje de error de este tipo:

*** Intento de dividir entre cero *** I
*** La ejecución de Simpletron terminó anormalmente ***

e imprimir un vaciado de computadora completo en el formato que describimos antes. Esto ayudará al usuario a encontrar la
causa del error en el programa.
REGISTROS
Acumulador                        +0000
instructioncounter                   00
Instructionregister               +0000
operationcode                        00
operand                              00

MEMORIA
            1         2       3       4       5       6       7       8       9      10
   1    +0000     +0000   +0000   +0000   +0000   +0000   +0000   +0000   +0000   +0000
   2    +0000     +0000   +0000   +0000   +0000   +0000   +0000   +0000   +0000   +0000
   3    +0000     +0000   +0000   +0000   +0000   +0000   +0000   +0000   +0000   +0000
   4    +0000     +0000   +0000   +0000   +0000   +0000   +0000   +0000   +0000   +0000
   5    +0000     +0000   +0000   +0000   +0000   +0000   +0000   +0000   +0000   +0000
   6    +0000     +0000   +0000   +0000   +0000   +0000   +0000   +0000   +0000   +0000
   7    +0000     +0000   +0000   +0000   +0000   +0000   +0000   +0000   +0000   +0000
   8    +0000     +0000   +0000   +0000   +0000   +0000   +0000   +0000   +0000   +0000
   9    +0000     +0000   +0000   +0000   +0000   +0000   +0000   +0000   +0000   +0000
  10    +0000     +0000   +0000   +0000   +0000   +0000   +0000   +0000   +0000   +0000


Fig. 5.23 Muestra de vaciado.

5.44 ( Modificaciones al simulador de Simpletron) En el ejercicio 5.43 usted escribió un simulador en software de una
computadora que ejecuta programas escritos en el lenguaje de máquina Simpletron Machine Language (SML). En este
ejercicio proponemos varias modificaciones y mejoras al simulador de Simpletron.
...
     a) Extienda la memoria del simulador de Simpletron de modo que contenga 1000 posiciones de memoria y permita a
           la Simpletron manejar problemas mayores.
     b) Permita al simulador que realice cálculos de residuo. Esto requerirá una instrucción SML adicional.
     c) Permita al simulador que realice cálculos de exponenciación. Esto requerirá una instrucción SML adicional.
     d) Modifique el simulador de modo que use valores hexadecimales en lugar de enteros para representar
     1. las instrucciones de SML.
     e) Modifique el simulador para contemplar el envío a la salida de un carácter de nueva línea. Esto requerirá una
           instrucción SML adicional.
     f)    Modifique el simulador para procesar valores de punto flotante además de valores enteros.
     g) Modifique el simulador para manejar entradas que sean cadenas. Sugerencia: cada palabra de Simpletron se
           puede dividir en dos grupos, cada uno de los cuales contiene un entero de dos dígitos. Cada entero de dos dígitos
           representa el equivalente decimal ASCII de un carácter. Agregue una instrucción de lenguaje de máquina que
           introduzca una cadena y almacene la cadena a partir de una posición específica en la memoria de la Simpletron.
           La primera mitad de la palabra de esa posición será una cuenta del número de caracteres que comprende la
           cadena (esto es, la longitud de la cadena). Cada media palabra subsecuente contendrá un carácter ASCII
           expresado como dos dígitos decimales. La instrucción de lenguaje de máquina convertirá cada carácter en su
           equivalente ASCII y lo asignará a una mitad de palabra.
     h) Modifique el simulador de modo que maneje la salida de cadenas almacenadas en el formato de la parte.
           Sugerencia: Agregue una instrucción de lenguaje de máquina que imprima una cadena que comience en una
           posición de memoria específica de la Simpletron. La primera mitad de la palabra en esa posición es una cuenta
           del numero de caracteres que comprende la cadena (esto es, la longitud de la cadena). Cada media palabra
           subsecuente contendrá un carácter ASCII expresado como dos dígitos decimales. La instrucción de lenguaje de
           máquina verificará la longitud e imprimirá la cadena traduciendo cada número de dos dígitos al carácter
           equivalente.

Simpletron1

  • 1.
    Sección especial: Construyasu propia computadora1 En los siguientes problemas nos alejaremos temporalmente del mundo de la programación en lenguajes de alto nivel. Vamos a "destripar" una computadora y examinar su estructura interna. Presentaremos la programación en lenguaje de máquina y escribiremos varios programas en lenguaje de máquina. A fin de que esta experiencia sea especialmente valiosa, construiremos una computadora (empleando la técnica basada software de la simulación) para que usted pueda ejecutar sus programas. 5.42 (Programación en lenguaje de máquina) Vamos a crear una computadora a la que llamaremos Simpletron. Como su nombre indica, se trata de una máquina sencilla. Sin embargo, también es potente, como habremos de ver. La Simpletron ejecuta programas escritos en el único lenguaje que entiende directamente: Simpletron Machine Language (lenguaje de máquina de Simpletron), abreviado SML. La Simpletron contiene un acumulador: un "registro especial" en el que se coloca información antes de que la máquina utilice dicha información en cálculos o la examine de diversas maneras. Toda la información se maneja en la Simpletron en términos de palabras. Una palabra es un número decimal de cuatro dígitos con signo, como -3364, -1293, +0007, -0001, etc. La Simpletron está equipada con una memoria de 100 palabras, a las cuales hace referencia por su número de posición: 00, 01, ..., 99. Antes de ejecutar un programa en SML, debemos cargar o colocar el programa en la memoria. La primera ejecución (o enunciado) de un programa en SML siempre se coloca en la posición 00. El simulador iniciará la ejecución en esta posición. Cada instrucción escrita en SML ocupa una palabra de la memoria de la Simpletron (de modo que las instrucciones son números decimales de cuatro dígitos con signo). Supondremos que el signo de una instrucción SML les positivo, pero el signo de una palabra de datos puede ser más o menos, Cada posición de la memoria de Simpletron puede contener una instrucción, un valor de datos utilizado por un programa, o un área de memoria no utilizada (y por tanto no definida). Los primeros dos dígitos de cada instrucción SML son el código de operación que especifica la operación por realizar. Los códigos de operación SML se resumen en la siguiente tabla: Código de operación Significado Operaciones de Entrada y salida const int READ = 10; Leer una palabra de la terminal colocándola en una posición específica de la memoria. const int WRITE = 11; Escriba una palabra en la posición de memoria específica en la terminal. Operaciones de carga/almacenamiento const int LOAD = 20; Cargar una palabra de una posición de memoria específica al acumulador. const int STORE = 21; Almacenar una palabra del acumulador a una posición específica de la memoria Operaciones Aritméticas const int ADD = 30; Sumar una palabra en una posición específica de la memoria a la palabra que está en el acumulador. (dejar el resultado en el acumulador) const int SUBSTRACT = 31; Restar una palabra en una posición específica de la memoria de la palabra que está en el acumulador. (dejar el resultado en el acumulador) const int DIVIDE = 32; Dividir una palabra en una posición específica de la memoria entre la palabra que está en el acumulador. (dejar el resultado en el acumulador) const int SUBSTRACT = 31; Restar una palabra en una posición específica de la memoria por la palabra que está en el acumulador. (dejar el resultado en el acumulador) Operaciones de transferencia de Control const int BRANCH = 40; Bifurcar a una posición específica de la memoria. const int BRANCHNEG = 41; Bifurcar a una posición específica de la memoria si el acumulador es negativo. const int BRANCHZERO = 42; Bifurcar a una posición específica de la memoria si el acumulador es cero. const int HALT = 43; Alto. El programa completó su tarea. Los dos últimos dígitos de una instrucción SML son el operando: la dirección de la posición de memoria que contiene la palabra a la que se le aplica el operando. Consideremos varios programas SML Sencillos. El primer programa SML (ejemplo 1) lee 2 números de teclado y calcula e imprime su suma. La instrucción +1007 lee el primer número del teclado y lo coloca en la posición 07 (que se ha inicializado con cero). Luego la instrucción +1008 lee el siguiente número y lo coloca en la posición 08. La instrucción cargar. +2007, coloca el primer número en el acumulador, y la instrucción sumar, +3008 suma el segundo número que está en el acumulador. Todas la instrucciones SML dejan el resultado en el acumulador. La instrucción de almacenar, +2109, coloca el resultado en la memoria, en la posición 09. La instrucción de escribir: +1009. toma el resultado de esa posición y lo imprime (como numero decimal de cuatro dígitos con signo). La Instrucción de alto, +4300, termina la ejecución. 1 Extraído del libro “Como programar en Java” Autores Deitel y Deitel, © 1998 Prentice Hall Hispanoamericana, p. 265-271. Tomada con fines didácticos.
  • 2.
    Ejemplo 1 Posición Número Instrucción 00 +1007 (Leer A) 01 +1008 (Leer B) 02 +2007 (Cargar A) 03 +3008 (Sumar B) 04 +2109 (Almacenar C) 05 +1109 (Escribir C) 06 +4300 (Alto) 07 +0000 (Variable A) 08 +0000 (Variable B) 09 +0000 (Resultado C) Ejemplo 2 Posición Número Instrucción 00 +1009 (Leer A) 01 +1010 (Leer B) 02 +2009 (Cargar A) 03 +3110 (Restar B) 04 +4107 (Bifurcar si negativo a 07) 05 +1109 (Escribir A) 06 +4300 (Alto) 07 +1110 (Escribir B) 08 +4300 (Alto) 09 +0000 (Variable A) 10 +0000 (Variable B) Este programa en SML lee dos números del teclado y determina e imprime el mayor de ellos. Observe el empleo de la instrucción +4107 como transferencia condicional del control, muy similar al enunciado if de Java. Ahora escriba programas SML para realizar las siguientes tareas. a) Utilice un ciclo controlado por centinela para leer 10 números positivos y calcular e imprimir su suma. b) Utilice un ciclo controlado por contador para leer siete números, algunos positivos y otros negativos, y calcular e imprimir su promedio. c) Lea una serie de números y determine e imprima el número más grande. El primer número leído indica cuántos números deben procesarse.
  • 3.
    5.43 (Un simuladorde computadora) Tal vez le parezca descabellado, pero en este problema usted va a construir su propia computadora. Y no, no va a soldar componentes para formar circuitos. Más bien, utilizara la potente técnica de simulación basada en software para crear un modelo de software orientado a objetos de la Simpletron. Le aseguramos que no se decepcionará. Su simulador de Simpletron convertirá la computadora que usted está usando en una Simpletron, y usted podrá realmente ejecutar, probar y depurar los programas SML que escribió para el ejercicio 5.42. Su Simpletron será Un programa C que corra en su PC Cuando ejecute su simulador de Simpletron, deberá comenzar por desplegar: *** ¡Bienvenido a Simpletron! *** *** Introduzca su programa una instrucción *** *** (o palabra de datos) a la vez en el campo *** *** de texto de entrada. Yo indicaré el número *** *** de posición y una interrogación (?). Usted *** *** tecleará entonces la palabra para esa *** *** posición. Haga clic en el botón LISTO para *** *** dejar de introducir su programa. *** El programa deberá exhibir una posición de memoria junto con un signo de interrogación (?) en el que el usuario tecleará las instrucciones una por una y mediante el código “9999”, Simpletrón sabrá que ha introducido el programa SML completo. Simule la memoria de la Simpletron con un arreglo memory de un solo sub índice con 100 elementos. Ahora suponga que el simulador está funcionando y examinemos el diálogo conforme introducimos el programa del ejemplo 2 del ejercicio 5.42: 00 ? +1009 01 ? +1010 02 ? +2009 03 ? +3110 04 ? +4107 05 ? +1109 06 ? +4300 07 ? +1110 08 ? +4300 09 ? +0000 10 ? +0000 Su programa deberá usar un printf() para exhibir la posición de memoria seguida de una interrogación. Los valores a la derecha de cada signo de interrogación son tecleados por el usuario. Cuando se introduzca un 9999, el programa deberá exhibir: *** Se terminó de cargar el programa *** *** Comienza la ejecución del programa *** El programa SML ya se ha colocado (o cargado) en el arreglo memory. La ejecución se iniciará con la instrucción que está en la posición 00 y, al igual que en C, continuará secuencialmente, a menos que una transferencia de control haga que continúe en alguna otra parte del programa. Utilice la variable acumulator (acumulador) para representar el registro acumulador. Use la variable instructionCounter (contador de instrucciones) para seguir la pista a la posición de memoria que contiene la instrucción que se está ejecutando. Utilice la variable operationCode (código de operación) para indicar la operación que se está realizando, es decir, los dos dígitos de la izquierda de la palabra de instrucción. Emplee la palabra operand (operando) para indicar la posición de memoria sobre la cual opera la instrucción en curso (operand será a los dos dígitos de la derecha de la instrucción que se está ejecutando.) No ejecute las instrucciones directamente de la memoria. Más bien, transfiera de la memoria la siguiente instrucción por realizar a una variable llamada instructionRegister (registro de instrucción). Luego "separe" los dos dígitos de la izquierda y colóquelos en operationCode, y "separe" los dos dígitos de la derecha y colóquelos en operand. Cada uno de los registros anteriores deberá tener un campo de texto correspondiente en el que el valor actual se pueda exhibir en todo momento. Cuando Simpletron inicie su ejecución, todos los registros especiales deberán inicializarse en 0. Sigamos ahora paso por paso la ejecución de la primera instrucción SML, +1009, que está en la posición de memoria 00. Esto es un ciclo de ejecución de instrucción. El instructionCounter nos indica la ubicación de la siguiente instrucción por ejecutar. Traemos de memory el contenido de esa posición empleando el enunciado de Java: instructionRegister = memory[instructionCounter ] El código de operación y el operando se extraen del registro de instrucciones con los enunciados: operationCode = instructionRegister /100;
  • 4.
    operand = instructionRegister% 100; Ahora la Simpletron debe determinar que el código de operación es un leer (no un escribir, ni un cargar, etc.). Un switch diferenciará entre las doce operaciones de SML. En la estructura switch, simulamos el comportamiento de diversas instrucciones SML como sigue (dejamos las demás para el lector): leer: Exhibir la solicitud "Teclee un entero". Habilitar el campo de texto input para que el usuario pueda introducir un valor. Leer el valor introducido, convertirlo en entero y almacenarlo en la posición memory [ operand ]. cargar: accumulator = memory [ operand ] ; sumar: accumulator += memory [ operand ] ; bifurcar: Explicaremos las instrucciones de bifurcación en breve alto: Esta instrucción imprime el mensaje *** Terminó la ejecución de Simpletron *** Cuando el programa SML termina su ejecución, deben exhibirse el nombre y el contenido de cada registro, así como el contenido de la memoria completa. Semejante impresión se conoce como vaciado de computadora (lo que no quiere decir que la computadora quede hueca). Para facilitar la programación de su método de vaciado (dump, en inglés), mostramos un ejemplo de formato de vaciado en la figura 5.23. Observe que un vaciado después de la Ejecución de un programa Simpletron mostraría los valores reales de las instrucciones y los datos en el momento en que terminó la ejecución. El ejemplo de vaciado supone que las salidas se envían a la pantalla con una serie de llamadas a los métodos printf(). Continuemos con la ejecución de la primera instrucción de nuestro programa, a saber, la +1009 de la Posición 00. Como hemos señalado, el enunciado switch simula esto solicitando al usuario que teclee un valor usando un scanf(), leyendo así el valor, convirtiendo el valor en entero y almacenándolo en la posición de memoria memory[operand] .Dado que nuestra Simpletron está controlada por teclado, esperará a que el usuario capture un y oprima la tecla Enter. Entonces, el valor se leerá y se colocará en la posición 09. En este punto, habrá terminado la simulación de la primera instrucción. Lo único que resta es preparar la Simpletron para que ejecute la siguiente instrucción. Puesto que la instrucción recién ejecutada no era una transferencia de control, basta con incrementar el registro contador de instrucciones como sigue: ++instructioncounter: Esto completa la ejecución simulada de la primera instrucción. Cuando el usuario haga clic en el botón de Ejecutar siguiente instrucción, se iniciará de nuevo todo el proceso (es decir, el ciclo de ejecución de instrucción) con la obtención de la siguiente instrucción por ejecutar. Consideremos ahora cómo se simulan las instrucciones de bifurcación (las transferencias de control). Todo lo que tenemos que hacer es ajustar el valor del contador de instrucciones de forma apropiada. Por tanto, la instrucción de bifurcación incondicional (40) se simula dentro del switch con: instructionCounter = operand; La instrucción condicional "bifurcar si el acumulador es cero" se simula con: : if { accumulator == 0 } instructionCounter = operand; Implemente ahora su simulador de Simpletron y ejecute los programas SML que escribió en el ejercicio 5.42. Puede adornar SML con características adicionales e incluir código para implementarlas en su simulador. El simulador deberá verificar la ocurrencia de diversos tipos de errores. Durante la fase de carga del programa, cada número que el usuario teclee en la "memoria" (el arreglo memory) de la Simpletron deberá estar en el intervalo de -9999 a +9998. El simulador deberá comprobar que todos los números introducidos estén en este intervalo y, en caso contrario, seguir solicitando al usuario que reintroduzca el número hasta que el usuario teclee un número correcto. Durante la fase de ejecución, su simulador deberá detectar diversos errores graves, como intentos por dividir entre cero, intentos de ejecutar códigos de operación no válidos, desbordamientos del acumulador (es decir, operaciones aritméticas que tengan como resultado valores mayores que +9999 o menores que -9999) y demás. Estos errores graves se denominan errores fatales. Cuando se detecte un error fatal, el simulador deberá imprimir un mensaje de error de este tipo: *** Intento de dividir entre cero *** I *** La ejecución de Simpletron terminó anormalmente *** e imprimir un vaciado de computadora completo en el formato que describimos antes. Esto ayudará al usuario a encontrar la causa del error en el programa.
  • 5.
    REGISTROS Acumulador +0000 instructioncounter 00 Instructionregister +0000 operationcode 00 operand 00 MEMORIA 1 2 3 4 5 6 7 8 9 10 1 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 2 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 3 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 4 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 5 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 6 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 7 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 8 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 9 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 10 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 Fig. 5.23 Muestra de vaciado. 5.44 ( Modificaciones al simulador de Simpletron) En el ejercicio 5.43 usted escribió un simulador en software de una computadora que ejecuta programas escritos en el lenguaje de máquina Simpletron Machine Language (SML). En este ejercicio proponemos varias modificaciones y mejoras al simulador de Simpletron. ... a) Extienda la memoria del simulador de Simpletron de modo que contenga 1000 posiciones de memoria y permita a la Simpletron manejar problemas mayores. b) Permita al simulador que realice cálculos de residuo. Esto requerirá una instrucción SML adicional. c) Permita al simulador que realice cálculos de exponenciación. Esto requerirá una instrucción SML adicional. d) Modifique el simulador de modo que use valores hexadecimales en lugar de enteros para representar 1. las instrucciones de SML. e) Modifique el simulador para contemplar el envío a la salida de un carácter de nueva línea. Esto requerirá una instrucción SML adicional. f) Modifique el simulador para procesar valores de punto flotante además de valores enteros. g) Modifique el simulador para manejar entradas que sean cadenas. Sugerencia: cada palabra de Simpletron se puede dividir en dos grupos, cada uno de los cuales contiene un entero de dos dígitos. Cada entero de dos dígitos representa el equivalente decimal ASCII de un carácter. Agregue una instrucción de lenguaje de máquina que introduzca una cadena y almacene la cadena a partir de una posición específica en la memoria de la Simpletron. La primera mitad de la palabra de esa posición será una cuenta del número de caracteres que comprende la cadena (esto es, la longitud de la cadena). Cada media palabra subsecuente contendrá un carácter ASCII expresado como dos dígitos decimales. La instrucción de lenguaje de máquina convertirá cada carácter en su equivalente ASCII y lo asignará a una mitad de palabra. h) Modifique el simulador de modo que maneje la salida de cadenas almacenadas en el formato de la parte. Sugerencia: Agregue una instrucción de lenguaje de máquina que imprima una cadena que comience en una posición de memoria específica de la Simpletron. La primera mitad de la palabra en esa posición es una cuenta del numero de caracteres que comprende la cadena (esto es, la longitud de la cadena). Cada media palabra subsecuente contendrá un carácter ASCII expresado como dos dígitos decimales. La instrucción de lenguaje de máquina verificará la longitud e imprimirá la cadena traduciendo cada número de dos dígitos al carácter equivalente.