_____________________________________________________________________________________
En los siguientes problemas nos desviaremos temporalmente del mundo de la programación en lenguajes de alto nivel para "abrir de par en par" una computadora y ver su estructura interna. Presentaremos la programación en lenguaje máquina y escribiremos varios programas en este lenguaje. Para que ésta sea una experiencia valiosa, crearemos también una computadora (mediante la técnica de la simulación basada en software) en la que pueda ejecutar sus programas en lenguaje máquina.
_____________________________________________________________________________________
5.18 (Programación en Lenguaje Máquina) Crearemos una computadora a la que llamaremos Simpletron. Como su nombre lo indica, es una máquina simple, pero poderosa. Simpletron sólo ejecuta programas escritos en el único lenguaje que entiende directamente: el lengaje máquina de Simpletron, o LMS.
Simpletron contiene un acumulador, un registro especial en el cual se coloca la información antes de que Simpletron la utilice en los cálculos, o que la analice de distintas maneras. Toda la información dentro de Simpletron se manipula en términos de palabras. Una palabra es un número decimal con signo de cuatro dígitos, como +3364, -1293, +0007 y -0001. Simpletron está equipada con una memoria de 100 palabras, y se hace referencia a estas palabras mediante sus números de ubicación 00, 01, ..99.
Antes de ejecutar un programa LMS debemos cargar, o colocar, el programa en la memoria. La primera instrucción de cada programa LMS se coloca siempre en la ubicación 00. El simulador empezará a ejecutarse en esta ubicación. Cada instrucción escrita en LMS ocupa una palabra de la memoria de Simpletron (y, por lo tanto, las instrucciones son números decimales de cuatro dígitos con signo). Supondremos que el signo de una instrucción LMS siempre será positivo, pero el signo de una palabra de información puede ser positivo o negativo. Cada una de las ubicaciones en la memoria de Simpletron puede contener una instrucción, un valor de datos utilizado por un programa o un área no utilizada (y, por lo tanto, indefinida) de memoria. Los primeros dos dígitos de cada instrucción LMS son el código de operación que especifica la operación a realizar. Los códigos de operación de LMS se sintetizan en la figura siguiente.
_________________________________________________________________________________________________________ CÓDIGO DE OPERACIÓN SIGNIFICADO _________________________________________________________________________________________________________ Operaciones de entrada/salida _________________________________________________________________________________________________________ final int LEE = 10; Lee una palabra desde el teclado y la introduce en una ubicación específica de memoria. final int Escribe = 11: Escribe una palabra de una ubicación específica de memoria y la imprime en la pantalla. _________________________________________________________________________________________________________ Operaciones de carga/almacenamiento _________________________________________________________________________________________________________ final int CARGA = 20; Carga una palabra de una ubicación específica de memoria y la coloca en el acumulador. final int ALMACENA = 21; Almacena una palabra del acumulador dentro de una ubicación específica de memoria. _________________________________________________________________________________________________________ Opoeraciones aritméticas _________________________________________________________________________________________________________ final int SUMA = 30; Suma una palabra de una ubicación específica de memoria a la palabra en el acumulador (deja el resultado en el acumulador). final int RESTA = 31; Suma una palabra de una ubicación específica de memoria a la palabra en el acumulador (deja el resultado en el acumulador). final int DIVIDE = 32; Divide una palabra de una ubicación específica de memoria a la palabra en el acumulador (deja el resultado en el acumulador). final int MULTIPLICA Multiplica una palabra de una ubicación específica de memoria a la palabra en el acumulador (deja el resultado en el acumulador). _________________________________________________________________________________________________________ Operaciones de transferencia de control _________________________________________________________________________________________________________ final int BIFURCA = 40; Bifurca hacia una ubicación específica de memoria. final int BIFURCANEG = 41; Bifurca hacia una ubicación específica de memoria si el acumulador es negativo. final int BIFURCACERO = 42; Bifurca hacia una ubicación específica de memoria si el acumulador es cero. const int ALTO = 43; Alto. El programa completó su tarea. __________________________________________________________________________________________________________
Los dos últimos dígitos de una instrucción LMS son el operando (la dirección de la ubicación en memoria que contiene la palabra a la cual se aplica la operación). Consideremos varios programas simples en LMS.
El primer programa en LMS, figura siguiente, lee dos números del teclado, cualcula e imprime su suma. La instrucción +1007 lee el primer número del teclado y lo coloca en la ubicación 07 (que se ha inicializado con 0). Después, la instrucción +1008 lee el siguiente número y lo coloca en la ubicación 08. La instrucción carga, +2007, coloca el primer número en el acumulador y la instrucción suma, +3008, suma el segundo número al número en el acumulador. Todas las instrucciones LMS aritméticas dejan sus resultados en el acumulador. La instrucción almacena, +2109, coloca el resultado de vuelta en la ubicación de memoria 09, desde la cual la instrucción escribe, +1109, toma el número y lo imprime (como un número decimal de cuatro dígitos con signo). La instrucción alto, +4300, termina la ejecución.
Ubicación Número Instrucción 00 +1007 (Lee A) 01 +1008 (Lee B) 02 +2007 (Carga A) 03 +3008 (Suma B) 04 +2109 (Almacena C) 05 +1109 (Escribe C) 06 +4300 (Alto) 07 +0000 (Variable A) 08 +0000 (Variable B) 09 +0000 (Resultado C)
El segundo programa en LMS (figura siguiente) lee dos números desde el teclado, determina e imprime el valor más grande. Observe el uso de la instrucción +4107 como una transferencia de control condicional, en forma muy similar a la instrucción if de Java.
Ubicación Número Instrucción 00 +1009 (Lee A) 01 +1010 (Lee B) 02 +2009 (Carga A) 03 +3110 (Resta B) 04 +4107 (Bifurcación negatuva a 07) 05 +1109 (Escribe A) 06 +4300 (Alto) 07 +1110 (Escribe B) 08 +4300 (Alto) 09 +0000 (Variable A) 10 +0000 (Variable B)
Ahora escriba un programa en LMS para realizar cada una de las siguientes tareas:
a) Usar un ciclo controlado por centinela para leer 10 números positivos. Calcular e imprimir la suma.
b) Usar un ciclo controlado por contador para leer siete números, algunos positivos y otros negativos, y calcular e imprimir su promedio.
c) Leer una serie de números, determinar e imprimir el número más grande. El primer número leído indica cuántos números deben procesarse.
_____________________________________________________________________________________
SOLUCIÓN:
a) Usar un ciclo controlado por centinela para leer 10 números positivos. Calcular e imprimir la suma.
Ubicacion Numero Instruccion 00 +1015 Lee el primer numero y lo almacena en la localidad 15 01 +2015 Carga el numero almacenado en 15 02 +4004 Bifurcacion positiva a la localidad 04 03 +4300 Para 04 +1016 Lee un segundo numero y lo almacena en la localidad 16 05 +2016 Carga el numero de la localidad 16 06 +4009 Bifurcacion positiva a 09 07 +1115 Imprime el numero de la localidad 15 08 +4300 Para 09 +3015 Suma el numero de la localidad 15 10 +2115 Almacena la suma en la localidad 15 11 +1016 Lee otro numero y lo almacena en la localidad 16 12 +4009 Bifurcacion positiva a 09 13 +1115 Imprime el numero almacenado en 15 14 +4300 Para 15 +0000 Variable 16 +0000 Variable
1) Recibe un número y para si es negativo (00 a 03) Si el número es positvivo, se guarda en la variable Suma.
2) Recibe un segundo número y si es negativo, se imprime Suma y se para (04-08) Si el número es positivo, se suma a la variable Suma.
3) Se realiza el ciclo hasta que se recibe un número negativo (09-12)
4) Se imprime la suma y se detiene la ejecución (13-14)
5) Variables (15 y 16)
b) Usar un ciclo controlado por contador para leer siete números, algunos positivos y otros negativos, y calcular e imprimir su promedio.
Ubicacion Numero Instruccion 00 +1020 Lee un numero y lo almacena en la localidad 20 01 +2020 Carga el numero almacenado en 20 02 +4100 Bifurcacion negativa a la localidad 00 03 +2020 Carga el numero almacenado en 20 04 +4200 Bifurcacion 0 a la localidad 00 05 +1024 Lee un numero y lo almacena en la localidad 24 06 +2024 Carga el valor almacenado en la localidad 24 07 +3023 Suma el valor de la localidad 23 al acumulador 08 +2123 Almacena la suma en la localidad 23 09 +2121 Carga el valor almacenado en 21 10 +2022 Suma el valor de la localidad 22 11 +2121 Almacena la suma en la localidad 21 12 +2021 Se carga el valor de la localidad 21 13 +3120 Se resta el valor almacenado en la localidad 20 14 +4005 Si la diferencia es positiva, bifurca a la localidad 05 15 +2021 Carga la variable de la localidad 21 16 +3223 Se divide el contenido de 18 entre el contenido en el acumulador 17 +2125 Se almacena el resultado en la localidad 25 18 +1125 Se Imprime el resultado 19 +4300 Para 20 +0000 Limite 21 +0000 Contador (Inicializado en 0) 22 +0000 Uno (Inicializado en uno) 23 +0000 Suma (Inicializado en 0) 24 +0000 Variable
Éste es el programa. No recibe 7 números, sino cualquiera que el usuario introduzca al principio. Por lo demás, el procedimiento es igual para 7 o para cualquier número N. Se requiere una variable que haga las veces de contador, en la localidad 21, inicializada en 0. Esta variable se incrementa cada vez que se realiza el ciclo. El incremento es siempre en uno, y se hace sumando la constante uno almacenada en la localidad 22. También es necesaria otra variable más, llamada suma, localizada en la localidad 23, la cual se inicia con el valor 0 y se incrementa cada vez con el valor del número recibido.
El programa consta de 6 partes, separadas por espacios para hacer más visible esta división. Éstas partes son:
1) Recepción del límite ( de la localidad 00 a la 04) Verifica que el primer número (el que indica cuántos enteros se recibirán) sea positivo. Para ésto, primero se revisa que no sea negativo; si lo es, el control se regresa al inicio, a la localidad 00. Después de ésto, se verifica que el número sea distinto de 0. Si lo es, de nuevo se regresa el control a la localidad 00.
2) Suma del número. (De las localidades 05 a 08) Recibe un número y lo suma al contenido de la variable suma, la cual, inicialmente tiene el valor 0.
3) Incremento del contador (De las localidades 09 a 11) Para incrementar la viariable Contador, almacenada en la localidad 21, se hace uso de la constante Uno, almacenada en la localidad 22.
4) Verificación de la condición para verificar que Contador no haya superado a Límite, se resta el primero del segundo. En caso de que el resultado no sea positivo (esto incluye 0 o un número negativo), se termina el ciclo, de lo contrario, se transfiere el control a 05.
5) Impresión de los resultados (de la localidad 15 a la 19) En estas instrucciones se divide la Suma entre el Límite y se presenta el resultado.
6) Variables (Localidades 20 a 25) En esta sección se almacenan las variables a las que se hace referencia en el programa.
c) Leer una serie de números, determinar e imprimir el número más grande. El primer número leído indica cuántos números deben procesarse.
Ubicacion Numero Instruccion 00 +1026 Lee un numero y lo almacena en la localidad 26 01 +2026 Carga el numero almacenado en 26 02 +4100 Bifurcacion negativa a la localidad 00 03 +2026 Carga el numero almacenado en 26 04 +4200 Bifurcacion 0 a la localidad 00 05 +1024 Lee un numero y lo almacena en la localidad 24 06 +2025 Carga el valor almacenado en la localidad 25 07 +3126 Resta el valor almacenado en 26 08 +4221 Bifurcacion cero (transferencia de control) a la localidad 21 09 +1023 Recibe un número y lo almacena en 23 10 +2024 Carga el numero de la localidad 24 11 +3123 Resta el número de la localidad 23 12 +4015 Bifurca positivo a la localidad 15 13 +2023 Carga el número almacenado en la localidad 23 14 +2124 Almacena el número en la localidad 24 15 +2025 Carga la variable de la localidad 25 16 +3027 Suma el contenido de la localidad 27 17 +2125 Se almacena el resultado en la localidad 25 18 +2025 Se carga el contenido de la localidad 25 19 +3126 Se resta el contenido de la localidad 26 20 +4109 Bifurca negativo a la lodalidad 09 21 +1124 Imprime la localidad 24 22 +4300 Para 23 +0000 Numero 24 +0000 Mayor 25 +0000 Contador (Inicializado a 1) 26 +0000 Limite 27 +0000 Uno (Inicializado a 1) (Inicializado en 0)
También éste programa ha sido dividido en partes para su mejor comprensión.
1) Recepción del límite ( 00 a 04) Ésta variable indica cuántos números se recibirán. No se aceptan negativos ni 0.
2) Recepción del primer número (05) Éste número, por ser el primero, se almacena en la variable Mayor, localidad 24.
3) Primera verificación del límite (06-08) En caso de que el límite sea sólo 1 número, éste condicional lleva el control a la localidad 21.
4) Recepción de número (09) Si el límite es 2 o más, se recibe el siguiente número y se almacena en la variable Número (localidad 23).
5) ¿Es más grande Mayor o Número? (10 a 12) Si Mayor - Número > 0, entonces el control se transfiere a la localidad 15, de lo contrario se lleva a cabo las instrucciones siguientes.
6) Mayor = Número (13-14) Estas líneas asignan un nuevo valor a la variable Mayor.
7) Incremento del contador (15-17) Éste incremento hace uso de la variable Uno, la cual se inicializa en 1.
8) Verificación del contador (18- 20) Si Contador - limite es negativo, se transfiere el control a la localidad 9. De lo contrario (una diferencia igual a 0), se realiza la siguiente instrucción.
9) Se imprime el número Mayor y se termina el programa (21-22) Esta instrucción se realiza cualesquiera que sean las transferencias de control anteriores.
10) Variables (23-27) La variable Número almacena los sucesivos números que se introducen. La variable Mayor almacena siempre el mayor, Contador debe ser inicializado a 0, Límite se recibe del usuario al principio, y Uno debe inicializarse a 1.