Exponsor

CURSO TÉCNICO INSTALADOR DE ENERGÍA SOLAR TÉRMICA

Visita el siguiente enlace: http://enersolartermica.blogspot.com.es/ ¡No pierdas esta magnifica oportunidad de poder formarte en esta profesión con gran demanda de empleo! Ahora por oferta de lanzamiento y por tiempo limitado puedes adquirir este curso por solo 9,95€, cuando su valor de mercado es de 49€.

martes, 21 de abril de 2009

PROGAMACIÓN DEL MICROPROCESADOR ( IV )

La conversión a código binario (usando algún estándard como ASCII) de los símbolos numéricos y alfabéticos de los que consta un programa como el programa BASIC mostrado en el artículo anterior es tan sólo el primer paso previo a la ejecución del programa escrito por un programador. Conforme va entrando este torrente de "unos" y "ceros" a una sección de la memoria RAM reservada para almacenar esta información preliminar, la información sigue sin tener significado alguno para la máquina. Aunque en formato binario, este conjunto de "unos" y "ceros" conocido como código fuente (source code) tiene que ser convertido al lenguaje de máquina que "entiende" el microprocesador, tiene que ser convertido a una secuencia de instrucciones en lenguaje de máquina que puedan ser ejecutadas por la misma máquina, tiene que ser convertido a código objeto (object code). Y esto tiene que ser llevado a cabo por un programa conversor independiente del programa ejecutor que va a llevar a cabo la ejecución del código objeto. Esto significa que, además del programa que se va a ejecutar en la máquina, el cual es un programa ejecutable desarrollado para procesar en un lenguaje como BASIC ó FORTRAN ó COBOL ó cualquiera de las muchas otras variedades existentes, la máquina debe contar también con un programa traductor que convierta al código fuente en código objeto. Y aquí lo que puede fijar un límite absoluto es el tamaño de la memoria RAM disponible. Aunque hoy estamos acostumbrados a memorias RAM que se miden en los gigabytes, hace varias décadas había que conformarse con memorias RAM muchísimo más modestas, a grado tal que una de las primeras memorias RAM construídas a base de ferritas magnéticas (conocida como magnetic core memory) rara vez excedía del medio megabyte para las computadoras más costosas y sofisticadas en el mercado fabricadas entonces por IBM, Honeywell y Burroughs. Inclusive, ante la falta de capacidad de muchas computadoras para poder tener residentes en la memoria RAM al mismo tiempo tanto un programa traductor como el programa ejecutor del código objeto, frecuentemente lo que hacían los administradores del sistema era acomodar las cosas de modo tal de que en vez de tener a varios programas residentes al mismo tiempo en la memoria RAM, lo que se hacía era cargar primero la memoria RAM con el programa traductor, el cual se encargaba de convertir el código fuente a código objeto, tras lo cual con el código objeto ya residente en la memoria RAM se sacaba fuera de la memoria el programa traductor con el fin de cargar el programa ejecutor encargado de procesar el código objeto. Y de hecho, para programas excesivamente grandes, esto es precisamente lo que se lleva a cabo en muchas computadoras de escritorio de uso actual, y quien se encarga de hacer tal cosa automáticamente es ese otro programa que está corriendo todo el tiempo desde el momento en que se enciende la computadora de escritorio hasta el momento en el que se apaga la máquina, ese otro programa conocido como el sistema operativo. Cuando abrimos un programa que requiere de un consumo enorme de memoria RAM, el sistema operativo "guarda" los demás programas en el disco duro hasta que se requiera utilizar uno de dichos programas, en cuyo caso lo vuelve a cargar. Esta es la razón por la cual un sistema multitareas que está corriendo varios programas a la vez en lugar de uno solo en ocasiones manifiesta tardanzas que nos parecen exasperantes.

Así pues, para poder usar ventajosamente cualquier microcomputadora, a menos de que queramos llevar a cabo la programación en lenguaje de máquina nosotros mismos debemos contar por los menos con tres programas: el programa "fuente" como el que hemos puesto arriba en lenguaje BASIC, el programa traductor que convierta las instrucciones del programa fuente en código objeto, y el programa ejecutor en sí (en este caso, BASIC), el cual tomará las instrucciones del código objeto procesándolas una por una en lenguaje de máquina para proporcionarle al usuario las respuestas deseadas. Esto no incluye ese cuarto programa que vendría siendo un sistema operativo, un programa que está corriendo todo el tiempo y el cual nos facilita enormemente las tareas más sencillas tales como el copiado y el almacenado de archivos. El sistema operativo es una gran comodidad para el uso de cualquier computadora, pero aún sin un sistema operativo es posible programas computadoras; y de hecho ninguna de las primeras computadoras contaba con sistema operativo alguno. En su esencia básica, el sistema operativo no tiene mucha ciencia: al encender la máquina el sistema operativo se va cargando en una buena parte de la memoria RAM; una vez que termina de cargarse comienza a ejecutarse esperando instrucciones del usuario. Si el usuario quiere correr un programa como Mathematica o como Photoshop, entonces al seleccionar dicho programa del menú visual el sistema operativo transfiere el control de la computadora a dicho programa. Una vez que el usuario ha terminado de usar la aplicación, el control de la computadora es transferido nuevamente al sistema operativo. De este modo, el día ordinario en cualquier computadora de escritorio transcurre transfiriendo el control de un programa a otro, hasta que llega el momento de apagar la máquina con la orden final en la cual el usuario le pide al sistema operativo que se encarge de "cerrar" todos los archivos pendientes de ser cerrados y llevar la computadora hasta el punto en el cual pueda ser apagada ya sea por el usuario o por el mismo sistema operativo.

El programa anteriormente proporcionado en lenguaje BASIC es en realidad demasiado elemental para lo que BASIC puede hacer. Por principio de cuentas, BASIC puede efectuar operaciones no sólo sobre números enteros sino inclusive sobre números reales en notación decimal, e inclusive es capaz de llevar a cabo algunas operaciones matemáticas sofisticadas. A manera de ejemplo, considérese el siguiente programa BASIC:
10 A=45.68
20 B=17.29
30 C=A+B
40 D=SQR(C)
50 PRINT D
60 END
Esto ya es algo más sofisticado, y está mucho más "en línea" con lo que los diseñistas de las primeras computadoras querían que sus máquinas lograran. La ejecución del programa hará que los números 45.68 y 17.29 sean asignados a localidades en la memoria RAM en las que puedan ser localizados. La presencia del punto decimal prácticamente garantiza que este lenguaje BASIC necesitará más de una sola localidad de memoria RAM para poder almacenar en formato binario cada uno de estos números decimales. Tras esto, los números serán sumados y el resultado será asignado a localidades en la memoria RAM identificados en conjunto como C en donde pueda ser localizado. A continuación, el número identificado como D será llamado por la computadora para sacarle la raíz cuadrada con la ayuda de una palabra reservada por BASIC para su uso exclusivo, SQR, lo cual requerirá de una buena cantidad de instrucciones en lenguaje de máquina que nos resultaría extremadamente tedioso escribir sin incurrir en equivocación alguna. Al final, se imprime el resultado en la pantalla o en alguna impresora con el comando PRINT. Es motivo de reflexión el pensar que el anterior programa, el cual ocupa tan sólo seis líneas de código fuente, para ser ejecutado tendrá que ser convertido por el mismo microprocesador a cientos de instrucciones en lenguaje de máquina.

El lenguaje BASIC que hemos descrito con ejemplos es un lenguaje BASIC en el cual la microcomputadora va "traduciendo" cada línea de código fuente conforme la va encontrando. Así, primero se encuentra con la línea 10, la traduce a lenguaje de máquina, y la ejecuta. Hecho esto, se topa con la siguiente línea, la línea 20, la traduce a lenguaje de máquina, y la ejecuta. La mecánica de traducción línea-por-línea se repite hasta que se llega a la instrucción final en la cual se le indica a la computadora que el procesamiento ha terminado. Este tipo de programas, en los cuales cada instrucción se va traduciendo paso-a-paso, es conocido como interpretadores.

Además de los lenguajes interpretadores como BASIC, existe otro tipo más sofisticado de lenguajes de alto nivel conocidos como compiladores. La diferencia principal entre un programa interpretador y un programa compilador estriba en que el programa compilador no va traduciendo y ejecutando cada instrucción conforme se la va encontrando, sino que primero traduce todas las instrucciones juntas a lenguaje de máquina, tomando el código fuente y produciendo un código objeto, y una vez hecho esto procede a ejecutar todas las instrucciones ya traducidas de un solo golpe. Este último procedimiento es mucho más eficiente porque permite identificar muchos patrones repetitivos eliminando una gran cantidad de redundancias. En castellano, esto significa que los programas de computadora basados en lenguajes de alto nivel que actúan bajo el proceso de compilación suelen ser mucho más rápidos y suelen contener una cantidad menor de instrucciones en lenguaje de máquina que sus equivalentes en lenguajes interpretados. Una forma de poder reconocer de inmediato un programa que ha sido compilado es que, por regla general, son programas que se pueden ejecutar de inmediato porque todas las instrucciones en lenguaje de máquina están contenidas en un solo archivo. Bajo un sistema operativo como Windows, estos son precisamente los programas ejecutables que tienen una extensión como .exe, .bin y .com, son programas que han sido compilados.

En un principio, escribir un programa ejecutable para computadoras personales haciéndolo de la forma más cercana posible al lenguaje de máquina del microprocesador, sin necesidad de tener que ingresar hasta el fondo en los laboriosos detalles del lenguaje ensamblador con sus instrucciones como MOV y JMP, se llevaba a cabo usando un lenguaje como el lenguaje C, descrito por los expertos como "un lenguaje ensamblador de alto nivel", el cual evolucionó posteriormente al lenguaje C++ que permitía incorporar algo novedoso en aquél entonces conocido como la programación orientada-a-objetos (object oriented programming), lo cual se llevaba a cabo escribiendo líneas de código exclusivamente a través de texto escrito. Esto evolucionó posteriormente a una programación con una interfaz visual con muchas ayudas para el programador, de lo cual los ejemplos más notorios son el compilador Borland C++ y el compilador Visual C++ de Microsoft. Una de las enormes ventajas de utilizar un lenguaje como el C++ para redactar programas ejecutables en lugar de utilizar un lenguaje ensamblador es que las instrucciones proporcionadas bajo C++ no son tan específicas para cierto microprocesador en particular, por el contrario, son lo suficientemente generales como para permitir la creación de programas ejecutables para otros microprocesadores con el simple remedio expedito de volver a compilar el mismo código fuente (con cambios mínimos) para producir programas ejecutables para computadoras construídas con otros microprocesadores. A continuación se muestra un primer ejemplo de un programa escrito en el lenguaje C:



Como puede apreciarse en este breve ejemplo, el lenguaje C permite liberalmente la inserción de comentarios en cualquier parte del programa encerrando los mismos entre los símbolos apareados "/*" y "*/". Todo lo que aparezca entre estos símbolos será ignorado por el compilador C al momento de estar compilando el programa. Al igual que el hardware que está basado en las tres funciones lógicas básicas OR, NOT y AND, el lenguaje C está basado en bloques básicos conocidos como funciones. Un programa C es una colección de una o más funciones. Para escribir un programa en lenguaje C, primero creamos las funciones, tras lo cual las agrupamos para formar el programa. Le podemos dar a las funciones creadas por nosotros cualquier nombre, excepto el nombre main, el cual está reservado para la función principal que echa a andar la ejecución del programa. En el ejemplo mostrado, el programa compilado empieza al igual que todo programa C con la ejecución de la función main, cuya acción está definida entre los corchetes "{" y "}". Este programa hace la invocación a una sola función, la función hola, dentro de la cual se invoca también dentro de sus respectivos corchetes "{" y "}" una de varias funciones reservadas por el lenguaje C, la función denominada printf que lleva a cabo la impresión de la hilera de caracteres hola\n puestos entre las dobles comillas. El símbolo "\n" puesto al final de la hilera ordena que una vez que se haya escrito la hilera indicada hola el cursor de la computadora deberá "saltar" hacia la siguiente línea (esto es el equivalente a la acción de la tecla de "Entrada" al estar escribiendo manualmente un texto en un programa como Microsoft Word). El programa mostrado simplemente imprimirá la palabra "hola" en una ventana para el manejo exclusivo de caracteres alfanuméricos (nada de gráficos), tras lo cual regresará el control de la máquina al sistema operativo. Por último, la directiva de preprocesador include puesta al inicio del programa instruye al compilador C que incluya en el proceso de compilación el archivo STDIO.H; este archivo contiene información requerida por el programa para asegurar la operación correcta de las funciones de librería estándard de Entrada/Salida, de las cuales la función printf es una de ellas.

A continuación tenemos un segundo ejemplo de otro programa escrito en lenguaje C:



En el primer ejemplo, la función definida como hola era una función que no recibe ningún tipo de argumento, simplemente imprime la palabra hola en la pantalla. En este segundo ejemplo, se ha definido la función cuadrado, la cual recibe como argumento un número entero identificado arbitrariamente por el usuario con la hilera num, el cual tiene que ser declarado previamente dentro de la función principal main como un argumento de tipo entero con la declaración "int num;" tras lo cual durante la ejecución del programa se le asigna un valor numérico entero a dicha variable con la declaración "num=100". Al ejecutarse la tercera línea del programa invocando la función cuadrado se le pasa el argumento num. Obsérvese que entre los dos paréntesis "(" y ")" que identifican a cuadrado como una función C, el contenido ya no está vacío, el contenido indica que cuadrado recibe como argumento un valor de tipo entero denotado como x (se podría haber usado cualquier otra letra o palabra, esto está a discreción del programador). Obsérvese también que la función printf es una función capaz también de poder recibir argumentos. Aquí, tras recibir como argumento de entrada el entero 100, en la hilera de impresión el símbolo reservado %d invoca el primer argumento puesto después de la hilera principal, o sea x, y el segundo símbolo reservado %d invoca el segundo argumento puesto después de la hilera principal, o sea x*x, lo cual requiere que se lleve a cabo una operación matemática de multiplicación. La acción final resultante de este programa una vez compilado como un archivo ejecutable será que la línea "100 al cuadrado es 10000" sea impresa en la pantalla.

El lenguaje C++ es un paso posterior en la evolución del lenguaje C, y la principal y más importante diferencia con respecto a su predecesor es que como ya se mencionó anteriormente permite la programación orientada-a-objetos, en la cual se diseña una "plantilla" de la cual se pueden obtener instancias que heredan de la misma las características que le programador desee que sean heredables, lo cual evita la repetición de mucho código redundante. Esto es algo muy parecido a lo que hace un usuario de un programa como Microsoft Word cuando al estar trabajando sobre un documento decide abrir un documento nuevo sin dejar el documento anterior sobre el cual está trabajando. Al abrir el segundo documento, el cual es asignado a otra ventana nueva, se abre una segunda instancia de Word con todas las capacidades que tiene la primera instancia del mismo, tras lo cual se puede abrir una tercera instancia, una cuarta instancia, etc., hasta donde lo permita la capacidad de la memoria de la máquina.

Para quienes quieran aprender a construír compiladores (por construír un compilador entendemos escribir en un lenguaje como C++ las líneas de código necesarias para producir un programa lo suficientemente potente como para que este programa pueda a su vez ser clasificado como un compilador BASIC o un compilador FORTRAN o inclusive como un compilador C, un compilador que sea capaz de traducir instrucciones en un programa fuente escritas en BASIC o en FORTRAN o en C como los dos ejemplos que vimos arriba convirtiendo dichas instrucciones en código ejecutable) se recomienda la lectura del libro clásico en la materia "Compilers: Principles, Techniques and Tools" de Alfred V Aho, Ravi Sethi y Jeffrey D. Ullman.

Para quienes quieran aprender el lenguaje de programación C/C++, Internet ofrece la posibilidad de poder descargar gratuitamente varios compiladores C/C++. Un portal que contiene una lista actualizada de varios lugares de los cuales se pueden descargar gratuitamente compiladores es el siguiente:

http://www.thefreecountry.com/compilers/cpp.shtml

Al cierre del año 2007, hay dos sitios de especial interés de los cuales se pueden descargar sin costo alguno compiladores C++ que pueden producir programas ejecutables para el sistema operativo Windows. El primero es Microsoft, del cual se puede efectuar la descarga gratuita del Visual C++ 2008 Express Edition de la siguiente dirección:

http://www.microsoft.com/express/download/

(De este sitio también se puede descargar en forma gratuita el programa-compilador Visual Basic 2008 Express Edition.)

El otro sitio es el de la empresa Borland, del cual se puede hacer una descarga gratuita de Turbo C++ del siguiente domicilio:

http://www.turboexplorer.com/

Además, de la misma empresa, se ofrece el Borland C++ Compiler en su versión 5.5 liberada el 24 de agosto de 2000, procurable del siguiente domicilio:

http://www.codegear.com/downloads/free/cppbuilder

Al momento de escribirse este artículo, el BASIC para computadoras personales trabajando bajo Windows XP y Windows Vista ha evolucionado a fines del 2007 a lo que se conoce como VisualBASIC.net, el cual seguramente seguirá evolucionando en los años que habrán de venir.

No hay comentarios: