Introducción
Bienvenido al mundo de la programación en lenguaje Ensamblador para las computadoras ATARI. A estas alturas, sin duda ya habrá probado suerte programando su ATARI en BASIC y habrá descubierto que es un lenguaje potente y muy fácil de usar. Pero probablemente también haya encontrado algunas cosas que simplemente no se pueden hacer en BASIC, y sabe que todos los excelentes juegos de acción en tiempo real y las búsquedas y clasificaciones rápidas están programadas en un lenguaje misterioso llamado Lenguaje de Máquina. El propósito de este libro es enseñarle cómo programar su ATARI en el lenguaje más rápido, potente y versátil disponible: el lenguaje Ensamblador. Al leer este libro, aprenderá a utilizar todos los recursos sofisticados y potentes de una de las computadoras domésticas más impresionantes, el ATARI.
La mayoría de los ejemplos de este libro están relacionados con BASIC, por lo que el dominar este lenguaje será importante para comprender este libro. Sin embargo, muchos programas en lenguaje Ensamblador no tienen una contraparte en BASIC, por lo que para estos ejemplos no nos será de utilidad. Los problemas se presentarán a lo largo del libro y se recomienda encarecidamente que intente resolverlos usted mismo. En cada caso, las respuestas se presentan y se discuten, para ayudarle si es que tiene problemas.
UNA VARIEDAD DE LENGUAJES DE PROGRAMACIÓN
A un nivel muy fundamental, su ATARI sólo entiende un lenguaje de programación: el Lenguaje de Máquina. Un programa típico en Lenguaje de Máquina se ve así:
Ahora, antes de dejar este libro y volver al BASIC, comprendamos una cosa de inmediato: prácticamente nadie programa directamente en Lenguaje de Máquina. Incluso muchos programas que se anuncian como escritos en "Lenguaje 100% de Máquina" no lo son. En realidad, estos son escritos en lenguaje Ensamblador y luego son traducidos a Lenguaje de Máquina. Todos los lenguajes informáticos deben traducirse en algún momento a Lenguaje de Máquina para poder ser ejecutados, incluso el BASIC. Así es, el "cerebro" central de su computadora ATARI en realidad ni siquiera entiende BASIC.
EL BASIC:
UN LENGUAJE INTERPRETADO
Dediquemos un momento a discutir cómo se ejecuta un programa BASIC, en un esfuerzo por comprender mejor qué son realmente el lenguaje Ensamblador y el Lenguaje de Máquina, y en qué se diferencian.
Primero escribamos un programa BASIC muy simple:
10 PRINT "HELLO" 20 FOR I= 1 TO 200 30 NEXT I 40 PRINT "GOODBYE" 50 END
Si ahora escribimos RUN y pulsamos la tecla RETURN, sabemos que en la pantalla de nuestro televisor o monitor aparecerá la palabra HELLO y, tras una breve pausa, aparecerá justo debajo la palabra GOODBYE, seguido varias líneas más tarde por la palabra READY. Pero, ¿Cómo sucede esto exactamente?
El cartucho que contiene el ATARI BASIC en realidad se llama, más apropiadamente, el Intérprete del ATARI BASIC. Un intérprete, al igual que el uso no informático de la palabra, es alguien o algo que traduce información de una forma a otra, ya sea del inglés al ruso o del BASIC a algún otro idioma. En nuestro caso, el cartucho BASIC contiene un programa que puede traducir palabras clave del BASIC a una forma comprensible para el "cerebro" de nuestra computadora. Veamos cómo lo hace.
A medida que escribimos la línea 10, la palabra PRINT se traduce a un código para la palabra PRINT, llamado componente léxico o "token". Este proceso se llama "tokenización" de su programa BASIC y se realiza a medida que escribe cada línea en su ATARI y presiona la tecla RETURN. Es este proceso el que verifica simultáneamente la sintaxis o las reglas gramaticales para asegurarse de que haya escrito correctamente una línea de código. De lo contrario, verá el conocido mensaje ERROR inmediatamente después de escribir la línea y luego podrá corregir sus errores antes de continuar. Esto asegura que cuando el cartucho BASIC comience a interpretar su programa, puede tener errores lógicos con los que lidiar, pero al menos cada línea es internamente correcta.
Después de haber escrito completamente el programa anterior, la interpretación del programa comienza al escribir RUN y presionar RETURN. Lo primero que sabe este intérprete es que el comienzo del programa, el lugar donde debe comenzar cuando se escribe la palabra RUN, es la línea con el número más bajo del programa BASIC. En realidad, antes de llegar a este punto, realiza algunas tareas de limpieza, como establecer todas las variables utilizadas en su programa en cero, limpiar cualquier cadena (string) o matriz utilizada anteriormente y muchas otras funciones. Luego dirige su atención a la línea 10, que se convierte a Lenguaje de Máquina mediante algo llamado "Tabla de Salto", sobre la cual aprenderemos mucho en el Capítulo 9. En cualquier caso, primero se traduce la línea 10, se ejecuta, y luego el código en Lenguaje de Máquina se descarta para dejar espacio para la siguiente línea, la línea 20. El proceso de traducción, ejecución y descarte se repite para la línea 20, luego para la línea 30, y así sucesivamente.
Luego de haber ejecutado el programa completamente y visto el mensaje READY que nos dice que BASIC está listo para nuevas instrucciones, ¿Qué supone que sucederá si escribimos RUN nuevamente? ¡Exacto! Todo el proceso de traducir, ejecutar y descartar cada línea se repetirá nuevamente. Luego veremos el mensaje READY otra vez. De hecho, todo este proceso ocurrirá tantas veces como decidamos escribir la palabra RUN. Como sin duda puede ver, este es un proceso muy derrochador. BASIC continúa repitiendo una y otra vez dos de los tres pasos que en realidad no son necesarios para ejecutar el programa, la traducción y el descarte de información. Si pudiéramos evitar la necesidad de estos dos pasos, imagine qué tan rápido se ejecutaría nuestro programa. Al fin y al cabo, si nos deshacemos de estos dos pasos, lo único que queda es la ejecución.
LENGUAJE ENSAMBLADOR:
UN LENGUAJE ENSAMBLADO
¡Ahora ya conoce el propósito de la programación en lenguaje Ensamblador! Cuando programamos en este lenguaje, utilizando un traductor conocido como Ensamblador, podemos producir el código ejecutable en Lenguaje de Máquina que podemos almacenar y que la computadora puede ejecutar directamente. Lo traducimos una sola vez y no lo descartamos en absoluto, con lo que conseguimos la máxima eficacia y, por tanto, la máxima velocidad. Y ese es el verdadero beneficio de la programación en lenguaje Ensamblador: la velocidad. De hecho, es posible escribir un programa en lenguaje Ensamblador que se ejecute 1.000 veces más rápido que su equivalente BASIC. Para los juegos de arcade y procesos que consumen mucho tiempo, como mover bloques de memoria, buscar, clasificar y otros procedimientos similares, la programación en lenguaje Ensamblador puede ser absolutamente indispensable.
La otra gran ventaja del lenguaje Ensamblador es el control absoluto que le da al programador sobre la computadora. En BASIC, el programador a menudo está separado del hardware de la computadora y no tiene un control detallado sobre muchas de sus funciones. Este control está disponible sólo a través de programación en lenguaje Ensamblador.
LENGUAJES INTERPRETADOS VERSUS ENSAMBLADOS
Estas son las ventajas de la programación en lenguaje Ensamblador: velocidad y control. ¿Qué hay de las desventajas? En primer lugar, por supuesto, está la necesidad de aprender un nuevo lenguaje informático. Este libro le permitirá hacer eso. En segundo lugar, ATARI BASIC es un lenguaje interpretado, mientras que el lenguaje Ensamblador no lo es. Esto se vuelve importante cuando necesita realizar cambios en un programa. En BASIC, simplemente realiza el cambio y vuelve a ejecutar el programa. Por ejemplo, para cambiar el programa anterior, simplemente podríamos escribir:
40 PRINT "GOODBYE"; 50 PRINT " Y'ALL" 60 END
Ahora, cuando ejecutemos el programa, dirá GOODBYE Y'ALL en lugar de simplemente GOODBYE, como se indicó anteriormente. El cambio completo en el programa puede tardar 15 segundos para un mecanógrafo muy lento. Esta flexibilidad es una gran ventaja de los lenguajes interpretados. Para realizar un cambio similar en un programa en lenguaje Ensamblador sería necesario escribir mucho más y luego habría que volver a ensamblar el programa. Este proceso de ensamblaje, que convierte el programa en lenguaje Ensamblador a Lenguaje de Máquina, a veces toma 15 minutos o más, dependiendo del tamaño del programa y del ensamblador utilizado. Por supuesto, nuestro ejemplo es muy corto y no tomaría tanto tiempo, pero el punto es que hacer incluso un cambio muy simple en un programa en lenguaje Ensamblador puede tomar bastante tiempo, y si comete un error, ¡Necesitará repetir el proceso nuevamente!
Una tercera desventaja del lenguaje Ensamblador es la cantidad de programación necesaria para realizar incluso la tarea más simple. Por ejemplo, la instrucción PRINT en BASIC, que requiere que escriba solo una palabra, puede requerir 20 o 30 líneas de programación en lenguaje Ensamblador. Por este motivo, estor programas suelen ser muy largos.
La cuarta y última desventaja del lenguaje Ensamblador es la dificultad de comprender un listado impreso del programa. Ciertamente la declaración PRINT en BASIC es mucho más comprensible que una serie de instrucciones como:
LDA #$01 STA CRSINH
o algo igualmente obtuso. Este problema puede y debe ser superado por todos los buenos programadores en lenguaje Ensamblador mediante la inclusión de comentarios en prácticamente cada línea. Los comentarios son el equivalente en lenguaje Ensamblador de las declaraciones REM en BASIC: ayudan al programador a recordar qué estaba tratando de lograr en una línea determinada. Ciertamente, el ejemplo anterior tiene algo más de sentido cuando se presenta A continuación, con comentarios, incluso para alguien que no entiende el lenguaje Ensamblador en absoluto.
LDA #$01 ;para inhibir el cursor STA CRSINH ;ponga un 1 aqui
Ahora tal vez sea más comprensible que cuando vemos un programa anunciado como escrito en "100% Lenguaje de Máquina", lo que realmente quiere decir es que fue escrito en lenguaje Ensamblador, y luego se traduce desde su forma final al Lenguaje de Máquina, que es la forma en la que se vende. Estos programas generalmente son mucho más rápidos de ejecutar que los programas en BASIC, y el control adicional que el programador tiene sobre la computadora permite lograr efectos especiales que no se pueden obtener desde BASIC.
Existe una distinción adicional entre BASIC y lenguaje Ensamblador. BASIC pertenece a una familia de lenguajes de programación denominados lenguajes de alto nivel. Esta nomenclatura se refiere a la capacidad de una declaración simple para realizar una tarea bastante complicada, como el ejemplo de PRINT usado anteriormente. En cierto sentido, esta facilidad de programación también aísla al programador del hardware, colocándolo a distancia, por así decirlo. Es a partir de esta visión de lenguajes como el BASIC que surgió el término lenguaje de alto nivel. Entre miles de otros lenguajes de alto nivel se encuentran Pascal, FORTRAN, PILOT y Ada. A diferencia de estos, los lenguajes como el Lenguaje de Máquina o el lenguaje Ensamblador se denominan lenguajes de bajo nivel, porque para programar con ellos se requiere una comprensión del hardware y la capacidad de llegar a las entrañas reales de la máquina para la que se está programando.
TRABAJAR CON LENGUAJE ENSAMBLADOR
Para poder convertir un programa en lenguaje Ensamblador a Lenguaje de Máquina, debemos utilizar otro programa, llamado Ensamblador. Disponemos de varios ensambladores excelentes para las computadoras ATARI y las técnicas utilizadas en este libro funcionarán con cualquiera de ellos. El Capítulo 6 está dedicado a la sintaxis y funciones especiales de cada ensamblador, pero los programas en lenguaje Ensamblador enumerados en este libro fueron programados utilizando el cartucho Assembler/Editor de ATARI. El Capítulo 6 especifica todos los cambios necesarios para utilizar estos programas con cada uno de los demás ensambladores.
COMPILADORES
Existe otra forma de convertir programas a Lenguaje de Máquina. Un Compilador es un programa que convierte un programa escrito en un lenguaje de alto nivel como BASIC a Lenguaje de Máquina. Estos compiladores generalmente convierten todo el programa de una sola vez, a diferencia de un intérprete, que traduce una línea a la vez. El programa convertido creado por el compilador se puede ejecutar sin un cartucho BASIC instalado y, por lo general, será de cinco a diez veces más rápido que el programa BASIC original. ¿Por qué sólo cinco o diez veces? Estos compiladores son programas muy complejos, que deben tener en cuenta todas las combinaciones posibles de comandos BASIC que cualquiera pueda escribir. Por lo tanto, crean código en Lenguaje de Máquina que realiza todos los pasos correctos en el programa original, pero no pueden optimizar el código producido. Por lo tanto, en general, los programas escritos en lenguaje Ensamblador y ensamblados en Lenguaje de Máquina se ejecutarán mucho más rápido que el mismo programa escrito y compilado en BASIC.
La otra gran desventaja del código compilado es su tamaño. Por ejemplo, algunas de las subrutinas del Capítulo 7 tienen aproximadamente 100 bytes de longitud. ¡Las mismas rutinas escritas en BASIC y compiladas podrían tener hasta 8000 bytes! Sería muy difícil utilizarlas como subrutinas en un programa BASIC, como lo hacemos en el Capítulo 7.
TERMINOLOGÍA
Antes de continuar, hablemos de una serie de términos que los programadores utilizan con frecuencia. Es la jerga de su oficio. Para que todos hablemos el mismo idioma, repasemos brevemente algunos de ellos. Cuando hablamos de Memoria de computadora, frecuentemente escuchamos mencionar los términos ROM y RAM. ROM (Read Only Memory) significa Memoria de sólo lectura y la memoria de este tipo se puede leer, pero no escribir. Por ejemplo, en las computadoras ATARI, todas las ubicaciones de memoria superiores a 49152 son ROM, y aunque en BASIC podemos hacer PEEK para ver qué está almacenado allí, no podemos hacer POKE para poder almacenar nuevos valores en ellas. Pero puede preguntarse "¿Qué pasa con los gráficos Player/Missile?...¡Hacemos POKE a ubicaciones de memoria más altas que esta todo el tiempo!".
Es cierto, pero si luego echa un vistazo a ese lugar, descubrirá que en realidad no ha cambiado nada en absoluto. El valor almacenado en esa ubicación no se modifica mediante dichos POKE. Es el acto de escribir en esa dirección lo que provoca los cambios que se ven en los gráficos Player/Missile u otras aplicaciones que requieren escritura en ubicaciones de memoria superiores a 49152.
Esto contrasta directamente con la RAM, que significa memoria de acceso aleatorio (Random-Access Memory). En realidad, tanto la ROM como la RAM son de acceso aleatorio, y la RAM debería llamarse más propiamente memoria de lectura-escritura (read-write memory); pero como RWM es impronunciable, RAM se ha convertido en el término aceptado. El término Acceso Aleatorio se refiere al método mediante el cual se accede a la información y debe contrastarse con el Acceso Secuencial, el otro método importante de almacenamiento. La mejor manera de visualizar el acceso secuencial es imaginar una cinta de audio. Para reproducir una canción en el medio de la cinta, de alguna manera debes inspeccionar toda la primera parte de la cinta, ya sea reproduciéndola o usando la tecla de avance rápido. Por el contrario, pensemos en un disco fonográfico. Para tocar la canción del medio en un lado, simplemente levantamos el brazo y lo bajamos sobre la canción que queremos, que inmediatamente comienza a reproducirse. No hemos tenido que repasar ninguna otra canción para llegar a esa. La cinta de audio es un dispositivo de acceso secuencial, como lo es una cinta de computadora, como la grabadora de programas ATARI 410, y el disco fonográfico es un dispositivo de acceso aleatorio, como lo es un disco de computadora, como el usado en la unidad de discos ATARI 810.
Los siguientes términos, con los que puede que esté familiarizado o no, son OS y DOS. OS significa Operating System (Sistema Operativo) y su ATARI tiene uno de los mejores sistemas operativos de cualquier microcomputadora. El Sistema Operativo está contenido en la ROM de su computadora (¿Recuerda? ¡Memoria de sólo lectura!) y es responsable de controlar casi todo lo que sucede dentro de su ATARI. Sin el Sistema Operativo, no pasaría nada al encender su computadora. El Sistema Operativo tiene el control total sobre cada faceta de la informática. Aprenderemos cómo interactuar con este excelente Sistema Operativo con considerable detalle a medida que avancemos en este libro.
Quizás cabe decir que el ATARI tiene varios de los mejores sistemas operativos de las microcomputadoras populares, ya que el Sistema Operativo de los 400 y 800 es ligeramente diferente al del 1200XL, el que a su vez es ligeramente diferente al del 600XL, el 800XL y el 1450XLD. De hecho, incluso las computadoras 400 y 800 tenían dos versiones diferentes de sus sistemas operativos: ¡Las llamadas ROM A y B! ¿Cómo vamos a empezar a programar para tantos sistemas operativos diferentes?
Esta es la mejor parte del Sistema Operativo para las computadoras ATARI. El fabricante ha garantizado que ciertos vectores del Sistema Operativo nunca cambiarán. Un Vector es una flecha, un indicador direccional. Nos dice cómo encontrar rutinas particulares o dónde encontrar una determinada parte del Sistema Operativo. Con esta información, es posible escribir un programa que funcione no sólo en nuestro 400, 800 o 800XL, sino incluso en generaciones de computadoras ATARI que los propios ATARI aún no han soñado con producir.
Hay varios atajos alrededor de estos vectores disponibles en las computadoras ATARI, pero no hay garantía de que los programas que usan estos atajos funcionen en todos los modelos. Por esta razón, no se recomiendan para uso general. Por supuesto, si simplemente está escribiendo una subrutina rápida e informal para su propio programa, para usarla sólo en su computadora, estos atajos son útiles, pero muchos programas escritos en lenguaje Ensamblador dejaron de funcionar tan pronto como los nuevos sistemas operativos estuvieron disponibles por ATARI. En un caso, tal falta de previsión incluso provocó la desaparición prematura de una empresa de software de terceros, por lo que si está pensando en vender lo que escribe, asegúrese de obedecer las reglas.
El término relacionado DOS significa Disk Operating System (Sistema Operativo del Disco). Este es el programa que controla cualquier unidad de disco que pueda estar conectada a su ATARI. En realidad, consta de dos partes: DOS.SYS y DUP.SYS. La porción DOS.SYS de DOS se carga en su computadora cuando la enciende por primera vez y siempre está presente. La parte DUP.SYS de DOS sólo se carga cuando escribe DOS desde el teclado. Contiene el conocido menú de DOS que permite muchos de los comandos habituales de manipulación de archivos, como copiar discos, guardar áreas de memoria, formatear discos y muchos otros. Debe tener en cuenta que no hay vectores garantizados en DOS, aunque hay tanto software dependiendo de ciertas ubicaciones que los cambios en estas deberían considerarse improbables. Pero nunca se sabe.
Ahora que conoce la diferencia entre lenguajes e intérpretes, y entre ensambladores y compiladores, a continuación, exploraremos los diversos sistemas numéricos utilizados por nuestras computadoras.