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

PROGRAMACIÓN DEL MICROPROCESADOR ( III )

Un buen ejemplo de un programa emulador al momento de escribirse este artículo es el programa 8086 Microprocessor Emulator, el cual en su versión de demostración gratuita se puede descargar de Internet del siguiente domicilio:

http://www.emu8086.com/

Este emulador es un programa que puede correr en cualquier computadora que tenga el sistema operativo Windows instalado en ella. Como su nombre lo indica, este emulador emula el comportamiento del microprocesador Intel 8086, el pionero de los microprocesadores. A continuación se muestra una de las "ventanas" propias del emulador:





Del lado izquierdo de la ventana, podemos ver, en un momento dado de la ejecución de un programa en lenguaje de máquina que está siendo emulado, los contenidos de los registros del microprocesador Intel 8086. Podemos ver que este microprocesador 8086 contiene cuatro registros de propósito general: el registro AX, el registro BX, el registro CX y el registro DX. El registro AX que vemos en la "ventana" contiene el número hexadecimal (en sistema numérico base 16) 0003, y lo contiene en dos bytes separados, un byte alto (identificado como H, del inglés "High") y un byte bajo (identificado como L, del inglés "Low"). Juntos, el byte alto H y el byte bajo L de cada registro permiten almacenar un número binario de 16 bits en lo que parece ser un solo registro "virtual" como el registro A o el registro D. Además de este registro, podemos ver la presencia del registro IP, acrónimo del inglés Instruction Pointer. En realidad, este registro es el mismo que anteriormente hemos denominado como el Contador de Programa, el cual es complementado con el registro CS para aumentar su capacidad.

En la "ventana" en el extremo derecho del emulador, tenemos las instrucciones escritas en lenguaje ensamblador con notación mnemónica que nos es más humana, más familiar, que el críptico lenguaje de máquina de unos y ceros, el cual nos permite utilizar instrucciones como JMP (acrónimo del inglés JUMP, el salto incondicional que ya se vió anteriormente) o como INC (acrónimo del inglés INCREMENT) utilizado para incrementar el operando en una unidad. Así, la instrucción en assembler:

JMP 011Eh

significa "saltar al domicilio 011E hexadecimal" (la letra h puesta al final del número deja en claro que se trata de un número hexadecimal), mientras que la instrucción:

INC DH

se lee como "incrementar los contenidos del registro DH en una unidad".

Sin lugar a dudas, escribir un programa así sea elemental en lenguaje ensamblador resulta mucho más ameno que escribirlo en lenguaje de máquina. Pero aunque al principio escribir programas computacionales en lenguaje ensamblador pueda resultar divertido, llega un momento en el que la extensión de dichos programas puede convertirse en algo exasperante. Escribir un programa muy grande siempre tiene la enorme desventaja de que cualquier omisión o equivocación cometida por el programador en una sola línea entre cientos de miles de líneas de código puede hacer que la ejecución del programa se estrelle, produciendo lo que en el argot técnico se conoce como un computer crash. Casi todos los usuarios han experimentado algún problema de este tipo en el cual debido a una situación o combinación de instrucciones no anticipada por los programadores la computadora se "cuelga" y es necesario apagarla para volver a inicializar de nuevo todo el sistema. En este respecto, los programas computacionales son muy poco tolerantes, no admiten ni un solo error humano. El menor error humano en la elaboración de un programa complicado puede salir a flote desagradablemente en lo que comúnmente se denomina como una "falla insecto" o computer bug. Esta es la razón por la cual sistemas operativos complejos como Windows XP, Linux o Windows Vista elaborados sobre millones de líneas de código constantemente tienen que ser actualizados con parches o (patches), debido a situaciones no anticipadas por los programadores que son descubiertas por los usuarios en el campo.

Aunque la creación de los lenguajes ensambladores representa un gran paso evolutivo hacia la reducción de errores de programación, elaborar un programa largo en lenguaje ensamblador puede ser un proceso tardado y costoso. A modo de ejemplo, el procedimiento de sumar dos números enteros "largos" y almacenar el resultado en un tercer entero largo requiere únicamente de una sola intrucción en el lenguaje de alto nivel C:

i = j + k;

pero en un microprocesador como el 8086 esto mismo requiere de seis instrucciones en lenguaje de máquina a través de un programa ensamblador:
...
mov ax,[j]
mov dx,[j+2]
add ax,[k]
adc dx,[k+2]
mov [i],ax
mov [i+2],dx
...
Obviamente, resulta más fácil escribir una sola línea de código en lenguaje C que seis líneas de código en lenguaje ensamblador. Y cuando se trata de elaborar un programa que requiere cientos de líneas de código en lenguaje C, elaborar en lenguaje ensamblador un programa que haga lo mismo posiblemente requerirá miles de líneas de código. Entonces, ¿para qué programar en lenguaje ensamblador, si es más difícil que cualquier otro lenguaje de mayor nivel? Una razón para ello es que la programación en lenguaje ensamblador nos permite tener acceso directo a cualquier parte de la memoria RAM y controlar directamente hasta sus más íntimos detalles la entrada y salida de cualquier unidad periférica conectada al microprocesador. Además, el lenguaje ensamblador es el lenguaje nativo de la máquina, un programa bien escrito en lenguaje ensamblador será el programa más veloz de todos los programas posibles. Sin embargo, la necesidad de mantener bajo control los costos involucrados en un proyecto para la elaboración de un programa complicado prácticamente exige que se recurre directamente a la programación en lenguaje de máquina sólo en aquellos casos en los que sea absolutamente necesario interactuar con el "hardware" de la máquina (los programas drivers proporcionados en un disco CD que requieren ser instalados para que la máquina y el sistema operativo que está corriendo en ella puedan reconocer y utilizar cierta impresora láser ó alguna novedosa cámara digital son ejemplo de ello).

Precisamente por lo arriba señalado, se vuelve deseable tener lenguajes más "compactos" y más parecidos a nuestro lenguaje humano, en los cuales el programa fuente elaborado por el programador contenga la menor cantidad posible de líneas de código. Esta es la razón por la cual de los programas ensambladores se vió la necesidad de tener que evolucionar a lenguajes de alto nivel, lenguajes como BASIC. Con un lenguaje como BASIC, en vez de tener que escribir algo como lo que arriba fue señalado para la suma de los números 17 y 35, escribiríamos algo como lo siguiente:
10_A=17
20_B=35
30_LET C=A+B
40_PRINT C
50_END
Esto es indudablemente mucho más "humano" y mucho más ameno para la búsqueda de posibles errores dentro del mismo programa que lo anterior que teníamos escrito en lenguaje de máquina o lenguaje ensamblador. Traducido a lenguaje cotidiano, lo anterior nos está diciendo, línea por línea, lo siguiente:

Línea 10 → "Asígnese a una localidad A de la memoria RAM el número entero 17"
Línea 20 → "Asígnese a una localidad B de la memoria RAM el número entero 35"
Línea 30 → "Súmense los números en las localidades de memoria A y B, y asígnese el resultado a la localidad C de la memoria RAM" (la palabra reservada LET en la instrucción es optativa, muchas versiones de BASIC la proporcionan con la intención de que el programador le pueda dar una mayor claridad a sus programas)
Línea 40 → "Imprímase (en el monitor o en una impresora) el número contenido en la localidad C de la memoria RAM"
Línea 50 → "El programa ha terminado. Deténgase la ejecución"

El lenguaje BASIC original fue desarrollado en Dartmouth College en 1963 por John George Kemeny y Thomas Eugene Kurtz con el fin de proporcionar a los estudiantes no-especialistas en ciencias computacionales un medio para poder tener acceso a las computadoras. El lenguaje BASIC fue precisamente el primer lenguaje con capacidades de programación que fue distribuído en las primeras computadoras personales caseras, fue el primer lenguaje en ser incorporado dentro del sistema operativo MS-DOS (escrito en varias versiones tales como GW-BASIC y BASICA y QuickBASIC) por una entonces desconocida empresa fundada por dos empresarios igualmente desconocidos, Bill Gates y Paul Allen.

Posiblemente mis lectores se estén preguntando ya cómo se puede llevar a cabo la conversión de algo que está escrito en lenguaje "alfabético" que asemeja al lenguaje de los humanos en las instrucciones de "unos" y "ceros" que la microcomputadora está acostumbrada a manejar en su lenguaje de máquina. Hay varias formas de hacerlo. En la actualidad, en una computadora de escritorio, la conversión inicial a "unos" y "ceros" del texto alfanumérico se comienza a llevar a cabo precisamente cuando se van "tecleando" cada uno de los caracteres en el teclado de la computadora. Al oprimir una tecla, esencialmente se "cierra" un contacto eléctrico que permite que le llegue al microprocesador un código binario correspondiente a cada tecla que fue oprimida. El código binario a ser enviado al microprocesador es enteramente arbitrario, aunque podemos usar como punto de partida alguna convención que haya sido utilizada ampliamente en el pasado reciente. Una convención tal es el código ASCII (American Standard Code for Information Interchange). Este código asigna una secuencia binaria específica a dígito numérico del cero al nueve:



y a cada letra del alfabeto:



Hay también secuencias binarias reservadas para símbolos tales como el que se usa en la adición aritmética (+), así como otras secuencias binarias reservadas para lo que llamamos caracteres de control, cuyo propósito no es representar en forma binaria una letra o un dígito numérico o un símbolo aritmético sino el proporcionarle información adicional a la computadora sobre cosas tan importantes como el punto de inicio de un programa que va a ser ejecutado y el punto de terminación en el cual la ejecución del programa llega a su conclusión:




Bajo este esquema, un programa elemental BASIC para la suma de los números decimales 5 y 8 asignados primero a localidades en la memoria identificadas como A y B iría entrando a la computadora como un torrente continuo de "unos" y "ceros" en el siguiente orden:



Todavía hasta en tiempos recientes, esta información en formato de "unos" y "ceros" era almacenada no en los discos duros magnéticos sellados que hoy conocemos y mucho menos en los drives portátiles "flash" USB, sino en simples rollos de cinta magnética e inclusive en cintas de papel perforado, en las cuales la presencia de un "uno" era tomada como una perforación en la cinta y la ausencia de una perforación podía ser tomada como un "cero". Estos rollos de cinta permitían almacenar programas completos, los cuales afortunadamente eran extremadamente pequeños en comparación con los que hoy conocemos, programas que en muchas ocasiones en tamaño no excedían ni siquiera los 64K (hoy en día, nadie en su sano juicio pensaría almacenar un programa tan grande como el sistema operativo Windows XP o Windows Vista en tal medio, ya que se requerirían varios miles de rollos abarcando una extensión de varios kilómetros al ser extendidos). Una de las máquinas perforadoras de cinta más populares (de las cuales todavía hay algunas en uso) es el teletipo ASR-33:





en el cual podemos ver a la izquierda del teclado una cinta que está siendo perforada.

No hay comentarios: