¿Cómo funciona una computadora? INTRODUCCiÓN A Lasdescripciones un programa forman hora se estudiará con cierto detalle el modus operandi de una computadora digital electrónica, sin emplear ningún tipo de terminología electrónica o de ingeniería. El hilo conductor será, sencillamente, una idea descriptiva de los procesos que en términos conceptuales deben suceder dentro de la máquina para lograr lo que se desea. De este modo, nos preocupará el concepto de necesidad lógica: lo que debe suceder, y los pasos necesarios y su orden, para llegar a obtener un resultado deseado. El desafío de este capítulo es llegar a inventar y "construir" la computadora, * partiendo de la sencilla idea de que en ciencia y tecnología las cosas son como son por alguna razón bien específica, y no por casualidad o por capricho de algún genio inventor. Como ejemplo inicial se propone pensar en los pasos necesarios para realizar con una calculadora común la operación de sumar 5 + 7. Para esto será necesario definir con cuidado dos tipos de objetos: los datos y las operaciones o funciones que actúan sobre éstos. En realidad la primera etapa no es difícil; cualquiera que haya usado una calculadora de bolsillo * En términos pedagógicos, el hecho de que las computadoras fueron en realidad inventadas hacia 1947 no debe desanimarnos. Lo importante es tener la capacidad de descubrirlo por medios propios. En su libro El miedo a la libertad (escrito en 1941), Erich Fromm (1900-1980) analiza los mecanismos psicológicos del acto creativo y descubrimiento de la verdad, y propone: "Por original no quiero significar, como ya se ha señalado, que una idea no haya sido pensada antes por algún otro, sino que se origina en el individuo, que es el resultado de su propia actividad y que en ese sentido representa su pensamiento." (Paidós, México, 1994, p. 233.) 42 Capítulo 2 ¿Cómo funciona una computadora'? sabe cómo hacerlo. El problema interesante consiste en indagar la forma de describir los pasos efectuados y de comunicárselo a la computadora después. y aquí aparece la necesidad de definir el concepto de programa, y es también aquí donde se gesta la concepción de las modernas computadoras programables y de la teoría de la programación que permite el modelado de la realidad. Es claro que para lograr esta suma hay que informar a la calculadora qué operaciones se desea hacer y sobre cuáles datos se van a aplicar. Normalmente se comunican los datos a la calculadora presionando las teclas que describen la operación por efectuarse. El siguiente es el proceso con detalle: 1. Presionar la tecla 5 (con esto se avisa a la calculadora que debe guardar este número en alguna memoria temporal, hasta decidir lo que se hará con éste). 2. Presionar la tecla + (ahora la calculadora traslada el 5 a un acumulador interno especial y está lista para recibir el segundo operando). 3. Presionar la tecla 7 (con lo que se efectúa la suma en el acumulador; la calculadora mantiene el resultado internamente). 4. Presionar la tecla = (esto indica a la. máquina que ha terminado la serie de operaciones y que debe liberar el resultado). 5. La máquina despliega el resultado: 12. Si ahora se decidiera hacer la operación 5/7 habría que volver a iniciar el proceso desde el paso 1, cambiando solamente la tecla + del paso 2 por la tecla correspondiente a la división. Un somero análisis revela que en realidad la calculadora "no se ha dado cuenta" de las operaciones que hizo, porque se realizaron como resultado de un proceso externo a la máquina misma; es decir, todo ha dependido del orden de los pasos (acciones) que decidimos efectuar con ésta, simplemente usándola como medio. Allí no hubo comunicación; sólo se utilizó el mecanismo. Para que la máquina "entienda" lo que se desea hacer (el proceso de la suma, de la división o cualquier otro) y lo pueda realizar de manera interna, debemos emplear las características únicas del lenguaje como medio de expresión, y escribir entonces un programa para que luego se ejecute. ¿Qué es un programa? La definición más elemental es que un programa es un conjunto explícito de pasos a seguir para lograr un fin determinado. En este caso, lo que interesa es lograr la suma de dos números, para lo cual hay que especificarle a la máquina las siguientes instrucciones: 1. 2. 3. 4. Observar el primer número. Llevarlo al acumulador para sumarlo con el número que sigue. Efectuar la suma usando este segundo número que ahora se observa. Mostrar el resultado. Pero hay todavía varios problemas por resolver para estar satisfechos con este programa. El primero de éstos consiste en que está escrito en español, y 2.2 FIGURA 6. El modelo de von Neumann 43 Esquema básico de una computadora. la máquina no entiende este lenguaje. * Otro problema es definir dónde se almacenarán los números 'que se desea que la máquina "observe". Uno más se refiere a dónde y cómo almacenar las instrucciones del programa. Para responder a estas cuestiones se definirá lo que se conoce como el modelo de von Neumann. Además, si logramos resolverlas, habremos convertido la calculadora en una verdadera computadora, porque la diferencia entre ambas consiste precisamente en la capacidad de seguir instrucciones escritas en un lenguaje. 2.2 EL MODELO DE VON NEUMANN La idea central del modelo de computación propuesto por John von Neumann es almacenar las instrucciones del programa de una computadora en su propia memoria, logrando con ello que la máquina siga los pasos definidos por su programa almacenado. En la figura 6 se observan las relaciones estructurales existentes entre las diversas unidades que configuran la máquina. Este esquema se sigue empleando en prácticamente todos los modelos de computadoras y presenta la configuración general de una computadora de programa almacenado, que es otra denominación para una máquina que funciona con el modelo de von Neumann. Como se decía en el capítulo anterior, es muy parecida al diseño original de Charles Babbage, aunque no está basada en ése. La unidad central de procesamiento (UCP -de aquí en adelante se le llamará así- aunque también es común referirse a ésta como CPU, por sus siglas en inglés) contiene a la unidad aritmética y lógica (hace los cálculos) ya la unidad-de control (define su orden y secuencia). Lafunción.de la UCP es clara: ejecutar instrucciones. Pero para ello necesariamente deben cumplirse estas condiciones: * Ni cualquier otro. El único lenguaje que una máquina es capaz de seguir -aunque lo pueden hacer- es el "lenguaje de máquina". no todas 44 Capítulo 2 ¿Cómo funciona una computadora? • • Que las instrucciones sean entendibles por la UCP. Que estén almacenadas en la memoria. Para cumplir con la primera condición se vuelve imprescindible codificarlas de alguna forma mediante números, para entonces construir circuitos electrónicos (Babbage intentó hacerlo con engranes) que se activen cuando reciban cada código numérico y efectúen la acción u operación codificada. Esto se hará más adelante. Para la segunda condición se abordará el problema del almacenamiento de números definiéndolo precisamente como la función de la memoria. Para nuestros propósitos, la memoria será un conjunto de celdas (o casillas electrónicas) con las siguientes características: • • Cada celda puede contener un (y sólo uno) valor numérico. Cada celda tiene la propiedad de ser "direccionable", es decir, se puede distinguir una de otra por medio de un número unívoco llamado su dirección. Esto implica que las celdas de la memoria deben estar organizadas de modo que faciliten la localización de cualquiera de ellas con un esfuerzo mínimo. El modo más sencillo de hacer esto es organizándolas en un conjunto numerado secuencialmente, para luego hacer referencia a las celdas por medio de su dirección. Se usará un apuntador para dirigirse a alguna celda, es decir, para especificar su dirección. Así, el conjunto de celdas de memoria se puede ver como se muestra en la figura 7. Cada celda tiene una dirección. Por ejemplo, la celda 2951 contiene un 23. Debe quedar clara la existencia de dos conceptos independientes: una cosa es la dirección de una celda y otra es su valor, aunque casualmente pudieran coincidir. Se dispone ya de una manera de almacenar (y recuperar) valores por medio de una dirección unívoca, como se verá a continuación cuando se definan dos operaciones elementales sobre la memoria: leer el contenido de una celda y escribir un valor en una celda. 2950 2951 2952 ! Apuntador FIGURA 7 Celdas de memoria y direcciones. 2953 2954 2.2 El modelo de von Neumann 45 Si se supone a la memoria de una computadora como una especie de almacén que funciona en forma autónoma del procesador, los siguientes deberán ser los pasos necesarios para efectuar las dos operaciones primitivas. Operaciones memoria sobre la Para leer: Especificar cuál celda se va a leer (esto es, proporcionar su dirección). Esperar un tiempo fijo para que los circuitos de la memoria traigan el valor depositado en esa celda (la celda no pierde ese valor; sólo se trae una copia del dato y no el dato mismo). e) Recoger el dato y dar por terminada la operación de lectura. a) b) y para escribir: a) Proporcionar a la memoria el dato que se desea depositar en una celda. b) Especificar la dirección de la celda sobre la que se desea hacer la escritu- ra del dato. e) Esperar un tiempo fijo para que los circuitos de la memoria depositen el dato en la celda designada y así terminar la operación de escritura. (Si la celda en cuestión tenía ya un valor, éste se pierde, pues es reemplazado por el nuevo.) Necesidad de la codificación Ahora hay que enfrentar el problema que se expresó antes: cómo almacenar las instrucciones en la memoria; es decir, debemos encontrar una forma de acomodar las instrucciones en las celdas. Esto lleva necesariamente al concepto de codificación. En efecto, si en las celdas de memoria sólo caben números, entonces habrá que convertir las instrucciones en números para poder emplearlas. Para codificarlas se debe considerar cuántas y cuáles habrá disponibles, así como el esquema de codificación a emplear. El primer factor depende fundamentalmente de la capacidad de la unidad de control del procesador central para hacer operaciones; cuanto más compleja -y costosa- sea la unidad central de procesamiento, tanto mayor será el número de instrucciones diferentes que podrá efectuar. De igual modo, debe encontrarse un código adecuado para que a cada instrucción definida corresponda un, y sólo uno, valor numérico. Para este propósito usaremos una especie de "diccionario electrónico" (que forma parte de la unidad de control: es lo que Babbage no pudo realizar con la tecnología de su tiempo) que especificará, por ejemplo, los siguientes códigosnuméricos. (Además, para nuestros fines pedagógicos escribimos a la izquierda una columna con el nombre de la instrucción, pero debe quedar claro que los circuitos de la máquina sólo están diseñados para reconocer los códigos, no sus nombres.) 46 Capítulo 2 ¿Cómo funciona una computadora'? De aquí en adelante se empleará el nombre lenguaje de máquina para referirse al código manejado por la unidad central de procesamiento de la computadora; los circuitos electrónicos de la unidad de control de la computadora "reconocen" Yejecutan precisamente las instrucciones codificadas en ese lenguaje de máquina. 2.2.1 Un primer programa Ahora es posible escribir un primer programa completo, usando el modelo recién descrito. Se continuará con el problema de sumar 5 + 7. Primera consideración: se requieren tres casillas, dos para los datos (5 y 7) Yuna para depositar el resultado. Se escogen las casillas 20, 21 Y22. (No hay ninguna razón especial para haberlas escogido; para nuestros fines, tres casillas cualesquiera son adecuadas.) Segunda consideración: hay que definir con detalle las operaciones por efectuar y su orden, así como obtener una codificación adecuada (o sea, escribirlas en lenguaje de máquina). Tercera consideración: hay que introducir todos los datos (e instrucciones) en la memoria. Trabajando con nuestro programa de la página 42, se detecta la necesidad de inventar varias operaciones de la máquina. Se requiere, por lo pronto, una instrucción para llevar el contenido de una celda al acumulador (que es una celda especial, o registro, contenido en la UCP), otra para hacer la suma y una más para devolver el contenido del acumulador a una celda de la memoria. La forma de la instrucción para llevar el contenido de una celda al acumulador es CARGA <dirección> donde CARGA es el nombre que dimos a la instrucción, y la <dirección> indica la celda de memoria cuyo valor se desea llevar al acumulador. Cabe aclarar que CARGA es el nombre simbólico (o mnemónico) de la instrucción, empleado para que éstas sean legibles por nosotros, pero primero fue necesario asignarle un código numérico interno. Sin importar ahora cuál sea éste, ocupará el contenido de una celda de la memoria. De la misma manera, la dirección será un número que ocupará un lugar en otra celda. Esto significa que la instrucción CARGA ocupará dos celdas en la memoria: una para el código de la operación y la otra para la dirección a la que hace referencia. Es decir, su longitud es dos. En términos generales, habrá instrucciones que ocupen una, dos y hasta tres o más celdas de memoria. (¿Podrá haber instrucciones de longitud cero? ¿Por qué?) Las demás instrucciones que se requerirán son: 2.2 GUARDA <dirección> SUMA <dirección> Deposita memoria Suma al memoria El modelo de von Neumann 47 el valor del acumulador en una celda de la (ésta es la inversa de la anterior), y acumulador el contenido de la celda de descrita por la dirección. Así que las instrucciones de nuestra máquina serán por lo pronto las siguientes: Nombre de la instrucción· Código interno Longitud de la instrucción (Los códigos internos para el lenguaje de máquina que se escogieron son arbitrarios, sin embargo, se debe tener cuidado de usarlos consistentemente.) Se escribirá el programa en forma tabular. En la parte izquierda del renglón se colocará el nombre simbólico de la instrucción, seguido de la dirección a la que haga referencia (si se da el caso); luego se describe brevemente el renglón (si se considera necesario) y, por último, se escribe su equivalente en el código interno que "entiende" el diccionario electrónico de la computadora. Para continuar, se supone que la celda 20 contiene un 5 y la celda 21 un 7, sin preocuparse por ahora de cómo se colocaron allí esos números. He aquí el programa para sumar 5 + 7. De este simplísimo programa se puede aprender varias cosas. Fue necesario inventar una nueva instrucción (ALTO) para lograr que la secuencia -cuando se ejecute- llegue a un fin. Obsérvese que esta nueva instrucción ocupa una sola casilla de memoria, pues no es necesario que haga referencia a alguna dirección. Otra cuestión importante es la aparición de dos programas: uno escrito en lenguaje simbólico y mnemónico (más fácil de reconocer para nosotros ya que es cercano a nuestro lenguaje), y otro -a la derecha- que está descrito en código numérico (el único que reconoce la computadora). Se llamará programa fuente al primero y programa objeto al segundo. Esto es, el programa fuente es aquel que está escrito en un lenguaje similar al nuestro (pero inaccesible para la computadora), mientras que el programa objeto ya está traducido al código que la máquina reconoce. En este caso fue la misma persona quien escribió ambos programas; por lo gene- 48 Capítulo 2 ¿Cómo funciona una computadora? ral será tarea del programador escribir el programa fuente, y la propia computadora lo traducirá a lenguaje objeto. El programa objeto, entonces, es: 20203021022270 que, obviamente, es por completo ininteligible para un ser humano. Otro aspecto fundamental es entender que este programa sirve para sumar cualquier par de números, siempre y cuando residan en las casillas 20 y 21. Esto es realmente importante, pues significa, ni más ni menos, que es una especie de "programa universal" para sumar dos números, sin importar cuáles sean. Claro que esto no resulta impresionante por ahora, pero si se piensa en un programa universal para calcular tablas de amortizaciones bancarias, u otro para invertir matrices de orden 90 x 90, se apreciarán las ventajas de esta nueva herramienta. Resta tan sólo introducir el programa objeto en la memoria de la computadora para que pueda ejecutarse luego. Aquí es crucial elegir las casillas de la memoria que se utilizarán para almacenar el programa; esto es, en qué sección de la memoria se va a cargar el programa. Se decidió hacerlo a partir de la celda 10. (se puede cargar a partir de cualquiera que se encuentre desocupada, siempre que se esté seguro de la existencia de suficientes celdas secuenciales vacías). Una vez cargado, el programa objeto se verá como se muestra en la figura 8. Cada celda contiene un solo número. La celda 22 contiene un número no especificado todavía -el resultado de la suma-, que se obtendrá una vez ejecutado el programa. Cada una de las dos primeras celdas contiene un número 20, pero en la primera éste representa el código de la instrucción CARGA, mientras que el mismo 20 representa, en la segunda celda, la dirección 20. Obsérvese cómo una celda puede contener un mismo número que significará dos cosas diferentes, dependiendo del orden en que aparezcan con respecto al inicio. Cuando se ha cargado el programa objeto a partir de la celda 10 de la memoria, debe encontrarse un procedimiento para lograr que la computadora comience a ejecutarlo y poder así obtener los resultados deseados. Aquí se hará un paréntesis para describir con cierto detalle cómo funciona la unidad de control del procesador central de la computadora. 2.2.2 La unidad de control La función principal de la unidad de control de la UCP es dirigir la secuencia de pasos de modo que la computadora lleve a cabo un ciclo completo de ejecu- ~~"llttLjr~??, l· 10 FIGURA 8 11 12 13 14 lS 16 Programa objeto cargado en memoria. 20 21 22 2.2 El modelo de von Neumann 49 11 IV FIGURA 9 III Modelo digital de la unidad de control. ción de una instrucción, y hacer esto con todas las instrucciones de que conste el programa. Los pasos para ejecutar una instrucción cualquiera son los siguientes: El ciclo de ejecución de la UCP l. Ir a la memoria y extraer el código de la subsecuente instrucción (que estará en la siguiente celda de memoria por leer). Esto se logra mediante un registro apuntador (que forma parte de los circuitos electrónicos de la unidad de control) que recibe el nombre de contador de programa (CP). Este paso se llama ciclo de fetch en la literatura computacional (to fetch significa traer, ir por). 11. Decodificar la instrucción recién leída (determinar de cuál se trata). 111.Ejecutar la instrucción. Iv. Prepararse para leer la siguiente casilla de memoria (es decir, actualizar el CP para que apunte a la celda que contiene la siguiente instrucción), y volver al paso I para continuar. La unidad de control ejecutará este ciclo de cuatro "instrucciones alambradas" a una velocidad enorme. * Se les llama así porque no residen en memoria, ni fueron escritas por ningún programador, sino que la máquina las ejecuta directamente por medios electrónicos, y lo hará mientras esté funcionando (mientras esté encendida). La ejecución de estos cuatro pasos (que forman un ciclo repetitivo) en una computadora es a razón de millones de veces por segundo. La unidad de control es una realización electrónica del modelo digital que se muestra en la figura 9. " Como se mencionó en el capítulo anterior, ésta es la diferencia principal entre hardware y software. El primer término denota todo lo referente a los circuitos electrónicos de una computadora, mientras que el segundo hace referencia a los programas, que no son parte física de la máquina, sino que residen en la memoria. 50 Capítulo 2 ¿Cómo funciona una computadora? Se ha definido ya el modelo de von Neumann, Ahora se pondrá a funcionar sobre nuestro pequeño programa de ejemplo (que suponemos ya cargado en la memoria). 2.2.3 Pasos en la ejecución de un programa Se describirán todos los pasos con detalle por única vez para que el lector pueda estudiarlos con detenimiento hasta estar seguro de haberlos comprendido. Le pedimos no seguir con la lectura si no cumple con esto. o. En virtud de que el programa comienza a partir de la celda número 10, se debe indicar a la unidad de control que esa celda contiene la primera instrucción. Para ello hay que colocar el número 10 en el registro contador de programa (es decir, apuntar a esa celda). Esto se representará por CP <--- 10. (Obsérvese que este paso es externo, esto es, no forma parte del programa, sino que se tiene que hacer "desde afuera" para iniciar la operación de la computadora.) 1. La unidad de control ejecutará el paso I e irá a la casilla 10 para leer su contenido, que es 20. 2. La unidad de control ejecuta el paso II, con lo que decodifica el 20 recién leído y determina que se trata de una operación CARGA. En este momento sucede algo de primordial importancia: como la instrucción 20 tiene una longitud de dos celdas, una para el código (20) y otra (la siguiente) para la dirección de la celda cuyo valor se cargará en el acumulador (que en este caso -de casualidad- también es 20), la máquina deberá ajustar el valor del contador de programa para que apunte a esa celda siguiente (i. e., la número 11 ). 3. La unidad de control ejecuta el paso III, con lo que efectivamente efectuará la operación de carga. Para esto, la computadora debe ir a la celda 11 y extraer su contenido, pero ahora ya no lo considerará como instrucción, sino como dirección, por lo cual irá a la celda 20 para extraer el valor que contenga (que es 5). En este momento hay que tener cuidado para que no haya confusión: el primer 20 (el de la celda 10) es la instrucción CARGA; el segundo 20 (el de la celda 11) es la dirección de la celda de memoria cuyo valor se desea cargar en el acumulador. Esta instrucción completa, 2020, puede leerse de la siguiente manera: "cargar el acumulador con el valor que esté contenido en la celda cuya dirección aparece a la derecha de donde se está leyendo ahora". Aunque parece innecesariamente elaborado, es imprescindible tener muy claro esto porque aquí reside la potencia del modelo de von Neumann. 4. La unidad de control ejecuta el paso IV, para luego reiniciar todo el ciclo. Obsérvese que se trata de una repetición ilimitada, que sólo terminará cuando se ejecute la instrucción ALTO. Por lo pronto, el contador de programa se hace igual a 12; esto es, apunta a la celda número 12. Interna- 2.2 El modelo de von Neumann 51 mente los circuitos de la unidad de control le añadieron la longitud de la instrucción recién ejecutada, que midió 2. 5. Se ejecuta, por segunda vez, el paso I de la unidad de control. Como CP = 12, se leerá esa celda, que contiene un 30. 6. Se decodifica esa instrucción, que es SUMA, por lo que el CP se prepara para apuntar a la siguiente celda. (Recuérdese que la instrucción SUMA ocupa dos celdas: una para el código de operación y otra para la dirección de la celda cuyo contenido se sumará al acumulador.) 7. Se ejecuta la instrucción 30, con lo que se añade al acumulador el contenido de la celda 21 (la dirección 21 reside en la celda 13, que está inmediatamente a la derecha de la que se está ejecutando). Ahora el acumulador contendrá un 12, es decir, 5 + 7. 8. El CP se actualiza para apuntar a la celda 14, en la cual (y no es casualidad, sino resultado del modelo) reside el código de la siguiente instrucción. Nuevamente en forma interna (paso IV) los circuitos de la unidad de control suman al contador de programa la longitud de la instrucción recién ejecutada. 9. Se lee la celda 14 y se extrae su contenido: 02. 10. Se decodifica la instrucción (GUARDA),por lo que se examina la siguiente celda, que contiene la dirección de la celda en donde se guardará el contenido del acumulador. 11. Al ejecutarse esta instrucción se deposita el valor del acumulador (12) en la celda número 22, o sea, se deja el resultado de la suma en la celda que previamente se había separado para tal fin. 12. La unidad de control regresa al paso I, no sin antes actualizar el contador de programa con la longitud de la instrucción recién ejecutada, y ahora apunta a la celda 16, que es donde reside la siguiente instrucción. 13. Se lee la celda 16 y se extrae su contenido: 70. 14. Se decodifica esta instrucción, que es ALTO. No se examina el dato de la siguiente celda porque la instrucción 70 tiene una longitud de uno. 15. Se ejecuta esta instrucción, lo que detiene a la unidad de control y a la máquina. De esta manera se rompe el ciclo de los cuatro pasos. El compromiso fue que el lector seguiría estos dieciséis pasos con cuidado (con ayuda del diagrama de la página 48), por lo cual habrá aprendido varias cosas sobre el lenguaje básico de las computadoras, entre las que sobresalen las siguientes: • Dado el contenido de una celda, la computadora no puede distinguir si se trata de una instrucción o de un dato o una dirección. • Debido a lo anterior, es responsabilidad de quien maneja la máquina indicar cuál es la celda en donde comienza el programa (esto se hizo por medio del paso O, que se describió como externo al programa). En algún capítulo posterior del libro se verá cómo la propia computadora, por medio del sistema operativo, será la que se encargue de esta tarea. • Una vez que el contador de programa apunta a la celda que contiene la primera instrucción, el resto del proceso ocurre de manera automática e 52 Capítulo 2 ¿Cómo funciona una computadora? invisible para el usuario. Esto se debe a los ajustes internos que se hacen al CP (en cada paso IV) que, a su vez, dependen de la longitud de la instrucción que se acaba de ejecutar. 2.3 EL LENGUAJE DE LA MÁQUINA Este apartado es relativamente largo y analiza con más detalle el comportamiento del modelo de von Neumann. Su lectura puede omitirse en primera instancia si sólo se está interesado en las consideraciones de tipo amplio o general. También es importante anotar que todo lo que aquí se propone funciona precisamente de esa forma en las computadoras reales, aunque nosotros dejamos de preocuparnos en un momento dado por cómo realizar los detalles. Por lo pronto, nuestra "máquina de papel" reconoce algunas pocas instrucciones, pues los circuitos electrónicos de su unidad de control así lo especifican, y sería deseable incrementar la cantidad y tipo de éstas para disponer de más poder de cómputo. En principio, la tarea es sencilla: basta con idear alguna instrucción y asignarle un código interno. Pero debe quedar claro que, en la vida real, cada nueva instrucción implica necesariamente la incorporación de nuevos circuitos especializados (y miles de nuevos microtransistores), por lo que existe un límite en la cantidad y complejidad de las instrucciones que un procesador puede realizar, como se analizará con más detalle en el capítulo 3. Evaluación de una fórmula Escribiremos a continuación un programa para sumar tres números cualesquiera y restar otro número al total anterior. Es decir, se evaluará la fórmula R = A + B + e - D (concediendo que tal cosa le pueda ser de utilidad a alguien). Supondremos que los cuatro números ya existen en memoria, en las celdas 770 a 773, y que el resultado va a quedar en la celda 774: CARGA SUMA SUMA RESTA GUARDA ALTO 770 771 772 773 774 La codificación de este programa fuente en lenguaje de nuestra máquina da como resultado el siguiente programa objeto equivalente: 20 770 30 771 30 772 33 773 02 774 70 Si se deseara posteriormente cargarlo a la memoria para ejecutarlo, habrá que seleccionar once celdas vacías secuenciales, que no incluyan de la 770 a la 774, porque ésas están reservadas para los datos. ,. 2.3 El lenguaje de la máquina S3 Programa para obtener un promedio Modos de direccionamiento Haremos ahora un programa para obtener el promedio de cuatro números previamente almacenados en la memoria. Se considerarán únicamente operaciones sobre números.,enteros, por lo que el promedio será también un número entero. Para obtener un promedio hay que hacer una suma y luego una división. Pero nuestra máquina aún no puede dividir, por lo cual prestamente inventamos, y comenzaremos a analizar, la instrucción para lograrlo, que tomará el número que en ese momento esté en el acumulador y lo dividirá entre otro. En general, las instrucciones aritméticas que el procesador puede realizar se efectúan sin punto decimal; es decir sólo con enteros. Los circuitos para manejo de operaciones con punto flotante son tan complicados que no todos los procesadores los incluyen; en capítulos posteriores se habla más sobre esto. Pero, ¿entre cuál número se hará la división de lo que contenga el acumulador? Existen dos posibilidades: entre el que resida en una celda de memoria cuya dirección se especifique, o bien entre un valor que a continuación se indique. Puede haber dos tipos de instrucciones de división, dependiendo del modo en que hagan el acceso a su operando. Una tiene la siguiente especificación: DIV <dirección> Divide lo que contenga el acumulador entre el contenido de la celda de memoria descrita por la dirección. y la otra efectuará la división ya no entre el número contenido en la celda cuya dirección se especifica, sino simplemente entre el número que se indique de inmediato a continuación: DIV-i <dato> Divide lo que contenga el acumulador entre el número que viene a continuación. El nombre simbólico de la segunda variante contiene una letra i, porque se trata de una división en modo inmediato. Ambas instrucciones tienen longitud 2: una celda para el código y la otra para la dirección del dato (en el primer caso), o para el dato mismo (en el segundo). Algunas instrucciones tienen variantes de direccionamiento en modo normal o en modo inmediato (u otros que luego se verán), dependiendo, como se acaba de ver en el ejemplo, si el dato con el que operan está contenido en una celda de memoria cuya dirección se indica, o bien si se encuentra inmediatamente después. Podría decirse que una operación en modo inmediato es menos general que la misma en modo normal, como se verá a continuación. Por ejemplo, las instrucciones CARGA SUMA GUARDA 7428 7429 7430 S4 Capitulo 2 ¡Cómo funciona una computadora? suman al número contenido en la celda 7428 el número que está en la 7429 Y dejan el resultado en la 7430. Es decir, realizan la operación R = A + B, llamando A, B YR a los contenidos de esas tres celdas, independientemente de cuáles sean sus valores. Pero la variante CARGA-i SUMA-i GUARDA Nuevas instrucciones 18 200 7430 únicamente hace la operaciónR = 18 + 200, con lo que siempre dejará el valor 218 en la celda que llamamos R (la 7430). En general, las instrucciones en modo inmediato son menos interesantes que las normales, porque están "comprometidas" con los valores que también forman parte del programa, mientras que las otras trabajan sobre las direcciones de los valores, por lo que estos últimos no forman parte del programa, sino que pueden ser datos independientes. Podemos entonces suponer que el diccionario electrónico de nuestra máquina ha crecido (y también, por supuesto, la complejidad de sus circuitos). Ahora se observa con nuevas instrucciones ya codificadas del siguiente modo: Obsérvese que se añadió un CARGA en modo inmediato, para poder decir, por ejemplo, CARGA-i GUARDA <valor> <dirección> y dejar un cierto valor preespecificado en alguna celda de memoria, para cubrir alguna necesidad posterior. 2.3 El lenguaje de la máquina 55 También se añadieron dos instrucciones de longitud 1, INCR y DECR, una que incrementa y la otra que decrementa en uno el contenido del acumulador, sin tener que hacer referencia a celdas de la memoria. Si se quiere aumentar en uno el contenido de la celda 2951, por ejemplo, resulta un poco más barato decir CARGA INCR GUARDA 2951 2951 cuyo código es 20 2951 32 02 2951 (5 celdas), que efectuar las operaciones CARGA SUMA-i GUARDA 2951 1 2951 porque el código de esto último ocupa 6 celdas: 20295131 01 02 2951 Las instrucciones INCR y DECR son útiles (y baratas) para el muy usual caso de incrementar o decrementar la unidad. Un programa más elaborado: búsqueda del máximo Analizaremos ahora una situación más compleja: leer tres valores y seleccionar el máximo entre éstos. Aunque el planteamiento del problema es sencillb, para resolverlo nos veremos obligados a inventar más instrucciones y a aprender más conceptos para seguir enriqueciendo las capacidades de cómputo de la máquina. La siguiente receta es una descripción de cómo resolver el problema: Leer los tres números. Considerar al primero como el mayor. Comparar el mayor (o sea, el primero) contra el segundo: si el segundo es mayor, entonces se le considerará como el mayor. (Y si no, no hay cambios.) Comparar el mayor (haya sido el primero o el segundo) contra el tercero: si el tercero es mayor, entonces se considerará a éste como el mayor. (Y si no, no hay cambios.) Mostrar el mayor. Alto. Si se hacen pruebas de ejecución de esta receta se verá que en efecto selecciona al mayor de tres números, independientemente de los valores con los que se trabaje, porque esta descripción es correcta desde un punto de vista lógico:se presupone que el primero es el mayor y luego secuencialmente 56 Capítulo 2 Instrucciones salida ,Cómo funciona una computadora? de entrada/ se va comparando contra cada uno de los restantes. Si en cualquier momento alguno de los nuevos números resulta mayor, sólo se abandona al antiguo mayor y se escoge al nuevo, y así hasta terminar. Al final del procedimiento el que haya sido el último mayor es efectivamente el máximo de todos. La computadora no puede todavía "entender" este programa fuente porque aún no está escrito en lenguaje de máquina, por lo cual nuestra tarea consiste en traducirlo y obtener un programa objeto equivalente. Lo primero que se antoja es revisar la documentación técnica del diccionario electrónico del procesador para simplemente escoger los códigos numéricos de las instrucciones requeridas. Pero sucede que nuestra máquina sólo dispone de las instrucciones hasta ahora especificadas, y en ningún lado aparece alguna instrucción para leer un número, ni para mostrarlo, ni para comparar, por lo que nos veremos obligados a seguir creando nuevas (y complicar el diseño del hardware encargado de ejecutarlas). Revisando el modelo de von Neumann (figura 6, de la página 43) se concluye que leer un número implica que el procesador central tome un valor del mundo exterior por medio de la unidad de entrada (usando un registro especialllamado puerto de entrada). Ese valor individual llega de afuera y es depositado en el acumulador como resultado de una instrucción de lectura, que llamaremos IN, a la que asignamos el código 10. Como esta instrucción no actúa sobre la memoria (sólo recoge un valor de la unidad de entrada y lo deja en el acumulador) su longitud será 1. IN Toma el valor individual que esté en el puerto de entrada y lo deposita en el acumulador. En la misma forma se diseña la instrucción contraria, para tomar un número del acumulador y dejarlo (una copia, en realidad) en la unidad de salida: OUT, con código 11 y longitud 1. Por fortuna en este libro no estamos preocupados por realizar todos los detalles de las operaciones que se están definiendo, y por ello dejaremos alegremente de lado las consideraciones requeridas para leer o escribir datos de tamaños diferentes. Es decir, simplemente supondremos que nuestras instrucciones IN y OUT son capaces de manejar datos individuales de longitud "razonable". Ya está resuelta una parte del problema, porque para leer un número y llevarlo a la memoria bastará con ejecutar la secuencia de instrucciones IN GUARDA Instrucciones comparación de <celda> donde <celda> especifica alguna dirección predefinida. Cada instrucción IN mete un solo número al puerto de entrada, por lo que si se desea leer 27 valores diferentes, por ejemplo, el mismo número de veces habrá que desocupar el puerto de entrada copiando su contenido a una celda de memoria diferente cada vez. Ahora se abordará el asunto de las comparaciones entre valores, y para ello pensamos en una instrucción que determine si el valor A es mayor, me- 2.3 El lenguaje de la máquina 57 nor O igual al valor B. Como A y B son direcciones de celdas, entonces la instrucción podría ser COMP 100 200 que compararía el valor contenido en la celda 100 con el contenido en la celda 200. Sólo que entonces esta instrucción mediría tres celdas de longitud (una para su código y dos más para las direcciones), lo cual resulta ser demasiado caro. Para reducir el costo de ejecución de la instrucción (o sea, su longitud) se efectuará la comparación entre el acumulador y el contenido de una sola celda, y antes deberá cargarse el acumulador con el primero de los datos para luego compararlos: CARGA COMP 100 200 La variante con modo de direccionamiento inmediato será COMP-i 8 para compararar el contenido del acumulador contra, por ejemplo, el valor 8. El procesador debe registrar de alguna forma el resultado de la comparación para permitir una posterior decisión si ésta fue como se esperaba, o bien al revés de lo que se esperaba. Lo que importa es tener la posibilidad de actuar de una o de otra forma, pero siempre bajo control del programa. ¿Qué significa actuar de una forma? En el contexto de un programa quiere decir ejecutar una cierta secuencia de instrucciones, por lo que actuar de otra forma simplemente indicará ejecutar otra secuencia (diferente) de instrucciones. Así, dentro del procesador debe existir un registro especial, que llamaremos bandera, para indicar el resultado de la última comparación entre dos valores. Los circuitos de la unidad de control de manera automática harán que la bandera asuma la o las posiciones resultantes de la comparación más reciente que se hubiera ejecutado. Las diversas posibilidades son IGUAL = DIFERENTE <> MAYORQUE > MENORQUE < MAYOR O IGUAL QUE MENOR O IGUAL QUE >= <= (No todas son mutuamente excluyentes: a la vez es cierto, por ejemplo, que 8 es mayor que 4; que 8 es mayor o igual que 4, y que 8 es diferente de 4.) De esta forma, la instrucción de comparación es entonces: COMP <dirección> Efectúa una comparación entre el contenido del acumulador y el de la celda cuya dirección se indica. Deja el resultado de la comparación en la bandera. 58 Capítulo 2 ¿Cómo funciona una computadora? Como el modelo de von Neumann especifica que la ejecución es secuencial (es decir, el contador de programa se incrementa para apuntar a la siguiente instrucción del programa objeto), entonces ejecutar una secuencia B en lugar de una A necesariamente implicará saltarse la primera de éstas; es decir, no ejecutarla. Para ello se requiere de una instrucción del siguiente tipo: BR> <dirección> Brinca directamente a la celda con la dirección especificada si es que la bandera indica MAYOR QUE. (Como la bandera puede estar en alguna(s) de las seis posibilidades ya mencionadas -más de una a la vez porque no todas son mutuamente excluyentes, como se dijo-, entonces habrá seis instrucciones de salto condicional diferentes: una para cada caso: BR=, BR<>, BR>, BR<, BR>=, BR<= ). Supongamos, por ejemplo, que la secuencia A abarca de la celda 1250 a la 1300, y la secuencia B va de la 1301 a la 1400. La decisión de si se ejecuta una u otra dependerá de una comparación anterior, por lo que en la celda 1248 habrá que colocar una de las instrucciones de bifurcación (o salto) condicional. El siguiente fragmento de programa no ejecuta la secuencia A si en la celda 650 hay un 10: Dirección Instrucción 1244 1246 1248 1250 CARGA 650 COMP-i 10 BR = 1301 Primera instrucción de la secuencia A 1300 1301 Última instrucción de la secuencia A Primera instrucción de la secuencia B 1400 Última instrucción de la secuencia B Pero si en la celda 650 hay cualquier valor que no sea igual a 10, entonces la instrucción BR= 1301 no tendrá ningún efecto, y el salto no se efectuará, por lo que la ejecución continúa en la forma secuencial normal y se procede a la ejecución de la secuencia A ...para continuar inmediatamente con las instrucciones de la secuencia B, que tal vez no era lo que se deseaba. 2.3 El lenguaje de la máquina 59 En efecto, resulta muy frecuente utilizar el resultado de una 'Comparación para escoger uno solo de dos caminos posibles: la secuencia' A o bien la secuencia B, pero no ambas. Si así fuera, entonces al final de la primera secuencia habría que insertar una instrucción para alterar el flujo normal y saltar directamente hacia el final de la segunda secuencia, sin ejecutarla. Esa nueva instrucción, de salto incondicional, tiene la siguiente forma: BR <dirección> Brinca inmediatamente a la celda con la dirección especificada. Como las seis instrucciones de salto condicional, esta nueva también tiene una longitud 2. A continuación se muestra el fragmento del programa anterior, ya modificado para obtener el efecto deseado de únicamente efectuar la secuencia de instrucciones A cuando la celda 650 no contenga un 10, y sólo ejecutar la secuencia B cuando ese valor sí sea 10 (o un caso o el otro, pero no ambos): 1244 1246 1248 1250 CARGA 650 COMP-i 10 BR=1303 Primera instrucción de la secuencia A 1300 1301 1303 Última instrucción de la secuencia A BR1401 Primera instrucción de la secuencia B 1400 Última instrucción de la secuencia B A continuación se muestra el conjunto actual de instrucciones de lenguaje de máquina que conforman el "diccionario electrónico" de la unidad de control de nuestra computadora. Aparecen en orden alfabético, aunque una vez más repetimos que los circuitos electrónicos sólo manejan los códigos numéricos; los nombres simbólicos no forman parte del diccionario y únicamente se emplean aquí por claridad en la exposición. 60 Caprtulo 2 ¿Cómo funciona una computadora? Con todos los nuevos elementos desarrollados ya no resulta tan difícil codificar el programa para encontrar el máximo entre tres números diseñado en la página 55, aunque no por ello carece de cierta complejidad. Cuando se trabaja con computadoras (y más aún tratándose de lenguaje de máquina), la atención a los detalles y minucias es enojosamente imprescindible. Se hará uso de cuatro celdas de memoria para los datos: una para cada uno de los tres números y otra para el valor mayor variable. Como la memoria consta de celdas numeradas secuencialmente, es forzoso definir desde ahora las direcciones para los datos y el código del programa objeto. Sin ningún motivo especial decidimos utilizar celdas a partir de la 3000. A continuación se muestran los programas fuente y objeto, escritos en renglones que incluyen información extra para auxiliar en la comprensión. Aparece subrayada la dirección de la primera instrucción ejecutable. Debe quedar claro que el código objeto es únicamente la última columna. 2.4 Sistemabinario 61 Si el lector verdaderamente desea comprender cómo funcionan las computadoras (dejando a un lado marcas y modelos), entonces no podrá estar satisfecho sino hasta haber "ejecutado" el programa anterior: le recomendamos tener cuidado y, para simular la ejecución, apuntar en una hoja los sucesivos contenidos del contador de programa, el acumulador, la bandera y las celdas de la memoria que contienen los datos. Pruebe los tres diferentes casos que puede haber: cuando el mayor es el primero, el segundo o el tercero de los números leídos. Por supuesto, el programa funciona para todos los casos y posibilidades, independientemente de los valores escogidos. Si no fuera así, no sería un "programa universal para determinar el mayor entre tres números cualesquiera" y tendría el poco interés que suele darse a los asuntos totalmente particulares y específicos, que sólo conciernen a sus dueños porque no son generales ni se refieren a situaciones amplias o abiertas. El alcance de este primer libro únicamente llega hasta estas ideas preliminares de la programación en lenguaje de máquina, por lo que con este ejemplo concluye por ahora el tema y se pasará a analizar otros conceptos. En un siguiente curso deben aprenderse las técnicas de programación en otro tipo de lenguajes con mayor capacidad expresiva. 2.4 SISTEMA BINARIO En una computadora real las celdas de la memoria no contienen números de la forma descrita aquí (lo cual se hizo por comodidad), sino que se almacenan en una forma más sencilla. 62 capítulo 2 ¿Cómo funciona una computadora? Qué implica almacenar un número Formas de representación de números Se ha visto que la unidad de memoria es el aparato cuya función es guardar (y recuperar) valores numéricos. Aunque la descripción física de la memoria no se dará sino hasta el siguiente capítulo, aquí debemos detenernos a examinar las implicaciones inherentes al hecho de almacenar un número. En efecto, almacenar un valor significa seleccionar (y mantener) uno de entre varios estados de un conjunto, en donde cada uno de esos estados tiene como función representar precisamente ese número. Desde esta perspectiva, un dado puede fungir como una unidad de memoria capaz de "recordar" un valor entre 1 y 6: basta con colocar alguna de sus seis caras hacia arriba, por ejemplo, y mantenerlo así. * Pero si se requiriera almacenar un número entre 1 y 400 habría entonces que construir un "hiperdado" con 400 caras. Es claro que mientras mayor sea la gama de posibles valores a almacenar, más compleja será la unidad de memoria para lograrlo. El truco que todos aprendimos en la escuela primaria consiste en descomponer el número en sus componentes más sencillos y manejar cada uno de éstos en forma individual. De esta forma bastaría con tres dados de diez caras cada uno para representar valores entre 1 y 1 000. Para ello habrá que asignar a cada dado una posición además de su valor y aprender a combinar ambos factores para lograr la representación buscada. Es decir, un sistema de numeración consta de dos componentes: una base numérica y un esquema posicional. Para nuestro caso, el dado de diez caras representa la base numérica (con diez diferentes valores: O a 9), y la posición de cada dado con respecto al anterior define si le toca tomar el papel de unidades, decenas o centenas. Si se desea reducir el grado de complejidad técnica de la unidad de memoria, habrá que reducir a su mínima expresión la cantidad de valores a representar con cada posición, pero se pagará el costo de tener que aumentar el número de posiciones, justamente porque entonces cada una vale menos. Para aclarar lo anterior construiremos una unidad de memoria empleando dados de sólo dos caras (ya no de diez) para representar valores. ** Si a las dos caras las llamamos Ay B, entonces con una moneda se podrán representar dos cosas diferentes: A o B (o una o la otra, pero no ambas a la vez, como con cualquier moneda normal). Pero si se desea representar tres cosas diferentes habrá forzosamente que utilizar una moneda adicional, para entonces poder escoger entre las siguientes cuatro posibilidades así: A A B B A B A B Ésta es la primera posibilidad Ésta es la cuarta Si se estuvieran utilizando dos dados de diez caras (la primera de éstas etiquetada con O,la segunda con 1 y así hasta la décima, etiquetada con 9), entonces la situación aparecería así: * En este contexto únicamente nos interesa la capacidad de mantener valores en sus caras, dejando por completo fuera las consideraciones de suerte o aleatoriedad. ** Los "dados de dos caras" también se conocen como monedas. 2.4 Sistemabinario o O O O 1 2 Ésta es la primera posibilidad: valor O Ésta es la segunda: valor 1 Ésta es la tercera: valor 2 2 7 Ésta es la vigésimo octava posibilidad: valor 27 9 9 8 9 Ésta es la nonagésimo novena: valor 98 Ésta es la centésima posibilidad: valor 99 63 Debe tenerse cuidado de no confundir las (cien diferentes) posibilidades con el valor numérico que se les asigna: lo único que sucede es que los valores que cada posibilidad representa comienzan desde cero, * y de allí la aparente irregularidad de que, por ejemplo, la vigésimo octava posibilidad represente el valor 27. Si por el contrario se escogieran dados de 27 caras para representar valores, con uno de ésos bastaría para numerar esa cantidad de posibilidades diferentes (una a la vez): Cara-1 Cara-2 Ésta es la primera posibilidad: valor O Ésta es la segunda: valor 1 Cara-26 Cara-27 Ésta es el vigésimo sexta: valor 25 Ésta es la vigésimo séptima posibilidad: 26 Es decir, el valor 11 se representaría así: Cara-12 porque a la Cara-1 se le asigna el valor cero, como ya se dijo. Si con este sistema de dados de 27 caras fuera necesario representar el valor 139, por ejemplo, habría que usar dos de éstos, y colocarlos uno al lado del otro así: Cara-6 Cara-5 * Recuérdese que no todas las culturas antiguas lograron comprender la enorme riqueza que ofrece el número cero. En efecto, es gracias al cero que los sistemas de numeración se sostienen. El cero no vale nada pero sí ocupa la primera cara de cada dado y puede simplemente separar las posiciones de cada dígito sin añadir nada. Su valía consiste precisamente en su falta de valor y en la presencia de la nada que implica. 64 Capítulo 2 ,Cómo funciona una computadora'? o bien FIGURA 10. Representación en sistema unario. El primer dado ("decenas de base 27") está en su sexta posición o cara -que vale 5, porque la primera vale 0-, y el segundo ("unidades de base 27") está en la quinta posición -que vale 4-. Es decir: 139 = (5 x 27) + (4 x 1) = 135 + 4 Cara-6 Cara-5 Aunque esto pueda parecer confuso (¿cómo que cada cara del dado vale uno menos que su posición?), en realidad emplea la misma lógica que todos aprendimos en la escuela primaria. En un sistema de numeración se escoge una base cualquiera (un dado con ese número de caras) y luego se combinan posicionalmente tantos de esos "dígitos" (o dados) como haga falta para llegar a representar el valor deseado, en el entendido de que cada uno vale base veces más que el que, está a su derecha. Por tanto, cada nuevo dígito (o sea, la cara de ese nuevo dado) representa sucesivas potencias del valor base. El sistema binario (í. e., con dados de dos caras) es casi el más sencillo que existe para representar números. Este "casi" es porque la manera más simple para representar, por ejemplo, el número cuatro, es con el sistema unario véase figura 10. ... pero habría algunos problemas técnicos al intentar representar el número diez millones. * Dicho de otra forma, en el sistema binario se escoge el número dos como la base de la numeración (así como en el decimal se escogió el diez), y se representa un número cualquiera descomponiéndolo en las sucesivas potencias de dos que, sumadas, den como resultado el número en cuestión. Por ejemplo, para escribir el valor 60 en binario habría que descomponerlo de la siguiente manera: una vez dos elevado a la quinta potencia, más una vez dos elevado a la cuarta potencia, más una vez dos elevado a la tercera * Esto se debe a que el sistema unario no es posicional, sino que cada "dígito" vale siempre lo mismo (1), independientemente de la posición que ocupe. El sistema de números romanos, como ejemplo similar, no es totalmente posicional, aunque sí representa un (pequeño) avance sobre el unario; el Imperio Romano no se caracterizó precisamente por su superioridad en las matemáticas o en las minucias del intelecto. 2.4 Sistema binario 65 potencia, más una vez dos elevado al cuadrado, más cero veces dos elevado a la primera potencia, más cero veces dos elevado a la cero potencia. En términos más sencillos sería: porque 60 = 32 + 16 + 8 + 4 Es decir: 60 = (111100)2 En el sistema decimal común y corriente se omite decir que la base es diez, cosa que sí se dijo para el caso 111100 encerrándolo entre paréntesis y poniendo el 2 como subíndice. Otra posibilidad es terminar la serie de unos y ceros con la letra b: (60)10= (111100)2= 111100b El bit Obsérvese que, para cada posición, el dígito binario puede tan sólo valer O (la primera cara del dado) o bien 1 (la segunda cara). Como se dijo en el capítulo anterior, la denominación "dígito binario" se abrevia comobit: binary digit.* El sistema de base 27 ya mencionado no es el más popular entre nosotros (¿será porque no tenemos 27 dedos?), pero algunos sistemas de mayor uso -además del decimal, por supuesto- son el binario (base 2), el octal (base 8) y el hexadecimal (base 16). En hexadecimal se emplean dados de 16 caras: O 1 Ésta es la primera posición: valor O Ésta es la segunda: valor 1 9 A B Ésta es la décima: valor 9 Así se llama la undécima posición: valor 10 Ésta es la duodécima: valor 11 Ésta es la décimo tercera: valor 12 Ésta es la décimo cuarta: valor 13 Ésta es la décimo quinta: valor 14 Ésta es la décimo sexta posición: valor 15 C D E F * La palabra bit significa partecita en inglés, por lo cual el nombre resulta además muy propio. El concepto matemático de bit como unidad de información es debido al doctor Claude Shannon, y el nombre se le ocurrió a su colega de los Laboratorios Bell, John Turkey. 66 Capítulo 2 ¿Cómo funciona una computadora? Por lo que el valor 12 se expresa como CH (suele escribirse una h (o H) al final de los números hexadecimales). Como antes, si se desea expresar el número 125, habrá que usar varios dados: 125::: 7DH::: (1X 161) + (13 x 16°)::: 112 + 13 Igualmente, 2951::: B87H porque 2951::: (11 X 162)+ (8.x 161)+ (1 X 161) ::: (11 x 256) + 128 + 7 ::: 2816 + 128 + 7 Además, como 16 es la cuarta potencia de 2, existe una relación directa que permite fácilmente convertir entre los números hexadecimales y los binarios, porque a cada dígito hexadecimal siempre corresponden cuatro dígitos binarios, acomodados como las sucesivas potencias 8-4-2-1. Es decir, combinando la opción de seleccionar (mediante un 1) o no (mediante un O) esa potencia, y haciendo luego la suma se puede pasar directamente entre la base 16 y la base 2, como se ve a continuación. Conversiones abreviadas entre algunas bases Potencias de dos Por ejemplo, 2951 :::B87H ::: 101110000111b. Se ve más claro cómo se obtuvo si se escriben los bits separados en grupos de cuatro comenzando por la derecha: 101110000111. 2.4 Sistema binario 67 El sistema octal emplea dados de ocho caras: la primera de éstas vale O, la segunda 1, y así hasta llegar a la octava, que vale 7. Por tanto, el valor 125 se representa en octal como 1750 (la letra o al final significa octal), porque 125 = (l x 82) + <1X 81) + (Q x 8°) 64 + 56 + 5 Como 8 es la tercera potencia de 2, se puede entonces convertir directamente entre números octales y números binarios acomodando los bits por la derecha en grupos de tres, de acuerdo con la serie de potencias 4-2-1, en forma parecida al acomodo de cuatro en cuatro para el sistema hexadecimal. Por tanto, 125 = 1750 = 1111101b De nuevo, si se separan los bits por la derecha en grupos de tres, se verá claramente cómo se obtuvieron: 001 111 101. (Los ceros a la izquierda se omiten, como es la costumbre.) Si ahora esos mismos bits se separan -siempre por la derecha para comenzar con las unidades- en grupos de cuatro (8-4-2-1), se llegará fácilmente al número 7D en hexadecimal: 125 = 0111 1101 7D Teoría de la información Existen diferentes métodos para convertir un valor numérico de una base a otra, aunque ya no se explicarán aquí, porque nuestro tema sigue siendo la memoria de la computadora. En [BROG95] y [TUCB94] se trata con más detalle estos temas, y además son textos recomendables sobre computación en general. Todoeste largo análisis surgió de la necesidad de almacenar números en la forma más sencilla posible, que resulta ser la binaria, porque emplea "dados" de dos caras (bits), que en una computadora pueden construirse con dispositivos eléctricos o electrónicos que asumen una sola de dos posiciones posibles: 0/1, o apagado/encendido, o no conduce/conduce, etcétera. En las computadoras se escogióel sistema binario para representar números justamente porque así se simplifica al máximo el diseño electrónico de sus componentes. Por otro lado, un resultado teórico debido a Shannon especifica que el sistema binario es suficiente para representar cualquier cantidad de información. Esta propuesta constituye la base del campo llamado teoría de la información, del que se dará un ejemplo sencillo. Si se considera el problema de averiguar la edad de una persona, en lugar de preguntárselo directamente, podría intentarse encontrar un método general y, al mismo tiempo, definir ciertos conceptos nuevos. Se podría preguntar: ¿tienes menos de cincuenta años?, y la respuesta sólo podría ser sí o no. A partir de esa respuesta podrían hacerse más "preguntas binarias" (cuya contestación sea sí o no) hasta encontrar el dato que se busca. Se dice que la cantidad de información que un dato contiene se mide por el número mínimo de preguntas binarias requeridas para averiguarlo con exactitud. 68 Capítulo 2 ,Cómo funciona una computadora'? Unidades binarias de medida Este número mínimo fue acotado y medido por Shannon, pero ya no tiene por qué preocuparnos aquí. Lo que sí interesa es entender que ese posible cero o uno (ese bit) será, de aquí en adelante, la unidad mínima de información. El artículo [BHAR87] contiene una explicación introductoria a la teoría de la información y a los resultados de Shannon. Por comodidad, los bits suelen trabajarse en grupos de ocho. Cada uno de estos pequeños grupos recibe el nombre de byte (binary term). Los bytes, a su vez, forman grupos de 1024,y cada uno de éstos se conocecomoun Kilobyte (KB). Se escogen esos números porque 8 = 23 Y 1024 = 210• Finalmente, cerca de un millón de bytes constituyen un Megabyte (MB). El número exacto es 220 = 1 048 576 bytes. Para terminar el capítulo es importante mencionar que prácticamente todas las computadoras comerciales (sin importar la marca o el tipo) en principio siguen el modelo de von Neumann aquí descrito. Esto no quiere decir, sin embargo, que la programación se haga de manera tan burda como la mostrada; de hecho, ningún programador trabaja así, sino que emplea los lenguajes de programación y las facilidades proporcionadas por la programación de sistemas mediante ensambladores, compiladores y sistemas operativos, que se estudiarán en los capítulos siguientes. PALABRAS Y CONCEPTOS CLAVE En esta sección se agrupan las palabras y conceptos de importancia estudiados en el capítulo, para que el lector pueda hacer una autoevaluación que consiste en ser capaz de describir con cierta precisión lo que cada término significa, y no sentirse satisfecho sino hasta haberlo logrado. Se muestran en el orden en que se describieron o se mencionaron. PROGRAMA INSTRUCCIONES MODELO DE VON NEUMANN PROGRAMA ALMACENADO CELDA DE MEMORIA VALOR DIRECCIÓN EN MEMORIA APUNTADOR CODIFICACIÓN "DICCIONARIO ELECTRÓNICO" MNEMÓNICOS LENGUAJE DE MÁQUINA PROGRAMA FUENTE PROGRAMA OBJETO CARGA EN MEMORIA CICLO DE FETCH HARDWARE SOFTWARE CONTADOR DE PROGRAMA EJECUCIÓN DE UN PROGRAMA
© Copyright 2024 ExpyDoc