Idioma

Ensambladores para el ATARI

CONTEXTO


Cuando hablamos de Ensambladores, generalmente nos referimos a paquetes de software que nos permiten escribir programas en lenguaje Ensamblador y ejecutarlos. Estos paquetes de software suelen contener tres partes: un editor, que se utiliza para escribir el código fuente de los programas; un ensamblador, utilizado para convertir el programa en código fuente a Lenguaje de Máquina, que es el que realmente se ejecutará; y un depurador, que se utiliza para encontrar errores y corregirlos, de modo que su producto terminado funcione de la manera prevista.


Actualmente hay seis paquetes ensambladores disponibles para computadoras ATARI:


1. El cartucho Assembler/Editor, de ATARI, Inc.
2. ATARI Macro Assembler (AMAC), MEDIT (un editor) y DDT (un depurador), todos de APX, ATARI, Inc.
3. MAC/65, de Optimized Systems Software, Inc., 10379 Lansdale Avenue, Cupertino, California 95014.
4. SYNASSEMBLER, de Synapse Software, 5327 Jacuzzi, Suite 1, Richmond, California 94804.
5. The Macro Assembler/Text Editor (MAE), de Eastern House Software, 3239 Linda Drive, Winston-Salem, Carolina del Norte 27106.
6. Edit 6502, de LJK Enterprises, PO Box 10827, St. Louis, Missouri 63129.

Todos los ejemplos en este libro se escribirán utilizando el cartucho Assembler/Editor ATARI, dado que es el ensamblador disponible para la línea de computadoras ATARI más vendido, aunque ciertamente no el más poderoso. Este Capítulo describirá la sintaxis utilizada en el cartucho Assembler/Editor y lo comparará con cada uno de los otros cinco ensambladores en detalle.


No es el propósito de este libro respaldar, ni directa ni indirectamente, ninguno de estos productos. Estos ensambladores, y particularmente las diferencias entre ellos, se describen aquí para permitirle trabajar con los ejemplos de este libro y utilizar las rutinas por su cuenta, sin importar cuál de estos productos haya comprado.


EL CARTUCHO ASSEMBLER/EDITOR DE ATARI


Primero, analicemos la sintaxis. El cartucho Assembler/Editor requiere que cada línea esté precedida por un número de línea, al igual que cualquier programa BASIC que haya escrito. Al utilizar este cartucho, los números de línea deben ser números enteros entre 0 y 65535. Cada número de línea debe ir seguido de al menos un espacio en blanco. Los campos que están presentes en una línea de un programa en lenguaje Ensamblador son:


número de línea - etiqueta - mnemónico - operando - comentario


Por ejemplo, veremos una línea típica de dicho programa:


10 LOOP LDA $0342; comience obteniendo el byte alto de la variable X	

Tomemos una parte de esta línea de código en lenguaje Ensamblador a la vez. El primer campo, el campo Etiqueta, puede estar presente o no. Si está presente, puede decirle al Ensamblador que acceda a esta línea usando su etiqueta, en este caso, LOOP. Por lo tanto, podríamos escribir posteriormente otra línea de código que bifurcara a LOOP, y el Ensamblador sabría perfectamente adónde queremos ir. Generalmente, las etiquetas se utilizan sólo cuando sabemos que más adelante necesitaremos hacer referencia a esta línea desde otra parte del programa. Como se mencionó anteriormente, el campo Etiqueta, si está presente, debe tener exactamente un espacio en blanco entre el último dígito del Número de Línea y el primer carácter de la etiqueta. El primer carácter de la etiqueta debe ser una letra de la A a la Z, y los demás caracteres deben ser letras o dígitos del 0 al 9. La etiqueta puede ser tan corta como 1 carácter o tan larga como 106 menos el número de dígitos en el número de línea. Dado que algunos de los ensambladores ATARI limitan el número de caracteres que se pueden utilizar en las etiquetas, todos los nombres de etiquetas utilizados en los programas de este libro contendrán seis caracteres o menos.


El Mnemónico, a menudo llamado Código de Operación u "op code", es la instrucción 6502 que deseamos que la computadora ejecute en ese punto del programa. En el ejemplo anterior, queremos que la computadora cargue el Acumulador, y el mnemónico para esto es LDA, como aprendimos en el Capítulo 5. Esta instrucción debe aparecer con un espacio en blanco entre ella y la etiqueta (si es que hay una etiqueta), o con dos espacios en blanco entre el último dígito del número de línea y la primera letra del mnemónico (si es que no hay etiqueta). Por ejemplo:


10 LABEL LDA $0342	

o

10  LDA $0342	

La razón de esto debería ser evidente: Si solo se dejara uno de esos espacios en blanco después del número de línea, el Ensamblador intentaría aplicar el mnemónico como una etiqueta y terminaría con una etiqueta llamada LDA. Luego, el ensamblador intentaría interpretar el operando, $0342, como una instrucción 6502, sin ningún éxito.


El Operando es la conclusión de la instrucción 6502 y especifica la dirección o número con el que queremos operar. Por ejemplo, en este caso el operando define el modo de direccionamiento Absoluto, en el que el Acumulador debe cargarse con el número almacenado en la ubicación de memoria $0342. El operando podría haber sido #$24, en cuyo caso el modo de direccionamiento habría sido Inmediato y el Acumulador se habría cargado con el número hexadecimal $24, en lugar de un número de algún lugar de la memoria de la computadora. El operando comienza con al menos un espacio en blanco entre su primer carácter y el último carácter del mnemónico, aunque se permiten más espacios en blanco. De hecho, puede tabular al campo del operando si así lo desea. En este libro, usaremos un espacio en blanco.


Con cualquier mnemónico que utilice el modo de direccionamiento del Acumulador, el operando debe ser la letra A mayúscula para que el cartucho Assembler/Editor lo interprete correctamente. Por lo tanto, una instrucción para rotar el contenido del Acumulador hacia la derecha debe escribirse así:


130 ROR A; ojo con la A mayúscula	

El campo Comentario es el último campo de una línea de código en lenguaje Ensamblador y debe describir la operación que se realiza en términos de función del programa. Es decir, el comentario no debe describir la operación (que LDA $0342 significa cargar el Acumulador desde $0342); más bien, el comentario debería recordarle qué está haciendo esa línea de código en particular, para que pueda volver a ella 6 meses después y no pasar 10 horas preguntándose para qué sirve esa línea. En nuestro primer ejemplo arriba, el comentario nos dice que estamos obteniendo el byte alto de una variable que llamamos X, desde la ubicación de memoria $0342.


Los comentarios se pueden eliminar del código de dos maneras. Primero, si al menos un espacio en blanco sigue al campo del operando, el Ensamblador interpretará cualquier otra cosa que siga a esa línea como un comentario. Una segunda forma es indicar una línea completa como comentario. Como veremos, esto a menudo hace que su código sea mucho más legible y será de gran ayuda para mantener la cordura. Para comentar una línea, A continuación, del número de línea con un espacio, coloque un punto y coma. Cualquier otra cosa en esa línea se interpretará como un comentario en el momento del ensamble. Ejemplos de cada uno de estos métodos son:


100 ; Esta línea completa es una línea de comentario
100 LDA $0343; esto también es un comentario	

Para propósitos de este libro, todos los comentarios, ya sean de línea completa o no, estarán precedidos por un punto y coma, de modo que, si ve un punto y coma antes de algún texto, sabrá que está leyendo un comentario.


Ahora conocemos la estructura de una línea de código en lenguaje Ensamblador y hay algunas otras convenciones que también necesitaremos conocer.


Directivas


La mayoría de los ensambladores proveen al programador de una serie de instrucciones que pueden ser interpretadas por el Ensamblador, extendiendo esencialmente el conjunto de instrucciones del 6502. Estas se llaman Directivas o, a veces, Pseudo-ops, ya que se usan como los opcodes, pero no son parte del conjunto de instrucciones del 6502. Las más importantes para el cartucho Assembler/Editor se describen a continuación, con una breve descripción de cada una.


Uno de los más importantes es la sentencia "origin". Dado que el Ensamblador crea código en Lenguaje de Máquina que residirá en un lugar específico de la memoria, debemos decirle al Ensamblador dónde está ese lugar. Para hacer esto, usamos la sentencia "origin". Con el cartucho Assembler/Editor, el formato de esta declaración es el siguiente:


10  *= $0600 ;el origen	

Tenga en cuenta que hay dos espacios entre el último dígito del número de línea y el asterisco, ningún espacio entre el asterisco y el signo igual, y un espacio entre el signo igual y el primer carácter de la dirección. Esta línea le dice al Ensamblador que queremos que nuestro código comience a ensamblarse en la dirección hexadecimal $0600, o Página 6. Esta declaración de origen generalmente será la primera, o una de las primeras, declaraciones en nuestros programas. Cuando el ensamblador ve la directiva *=, asigna al Contador de Programa el valor de la expresión que sigue a esta directiva. Es perfectamente factible tener más de una directiva *= en cualquier programa si se van a ensamblar diferentes regiones de código en diferentes áreas de memoria.


Otros pseudo-ops incluyen:


.BYTE reserva al menos una ubicación en la memoria para uso futuro. El operando puede colocar información en este espacio. Por ejemplo, la instrucción


110 .BYTE 34	

toma una ubicación en la memoria en la posición actual del Contador de Programa y almacena el número #$22 (34 decimal) en esa ubicación. También es posible almacenar una serie de bytes usando una instrucción .BYTE, tal como se muestra a continuación:


125 .BYTE "HELLO",$9B	

Esto almacena los números hexadecimales $48, $45, $4C, $4C, $4F y $9B en ubicaciones consecutivas. Estos números son los códigos ATASCII (ATari ASCII) para las letras de la palabra HELLO.


.DBYTE reserva dos ubicaciones para cada valor del operando. Esta instrucción se utiliza para datos en los que los números son mayores que 256 y, por lo tanto, requieren 2 bytes para almacenarse. El número se almacena primero con el byte de orden superior, seguido del byte de orden inferior. Por ejemplo,


115 .DBYTE 300	

almacena 2 números hexadecimales en ubicaciones de memoria consecutivas. El primero es $01 y el segundo es $2C, ya que 300 decimal equivale a $012C hexadecimal.


.WORD es idéntico a la directiva .DBYTE, excepto que el byte de orden inferior se almacena primero, seguido del byte de orden superior.


LABEL = se utiliza para asignar un valor a una etiqueta. Por ejemplo, si escribimos un programa que requiere el uso frecuente de la dirección $9F, podemos asignar esta dirección a una variable con nombre, de la siguiente manera:


112 FREQ = $9F	

Dado que la etiqueta en la directiva LABEL = es una etiqueta real, debe comenzar exactamente con un espacio en blanco entre el último dígito del número de línea y el primer carácter de la etiqueta. Ahora, siempre que necesitemos la dirección, podemos llamar a la etiqueta. Por ejemplo:


245 LDA FREQ	

El ensamblador ahora sabe cómo cargar el Acumulador desde la dirección $9F.


.END le dice al ensamblador que ha completado el ensamblaje y que debe detenerse allí mismo. Obviamente, debería ser la última línea de su programa. El cartucho Assembler/Editor supone que si no hay más líneas de código y no se incluye ninguna directiva .END, el programa finaliza. Esto hace que la directiva .END sea opcional, al igual que la declaración END en un programa ATARI BASIC es opcional.


Hay muchas otras directivas disponibles para el cartucho Assembler/Editor, pero hemos discutido las más importantes y por el momento son las únicas que veremos. Consulte el manual del cartucho para obtener más información sobre todos los pseudo-ops disponibles.


MATEMÁTICAS DEL CAMPO OPERANDO


Una nota adicional sobre el cartucho Assembler/Editor es que admite sumas, restas, multiplicaciones y divisiones en el campo Operando. Por ejemplo, si queremos descomponer la dirección de la etiqueta LOOP en un byte alto y uno bajo, podemos escribir la siguiente sección de código:


135  LDA #LOOP&255  ;obtener el byte bajo de LOOP
140  STA DEST       ;almacenarlo en DEST
145  LDA #LOOP/256  ;obtener el byte alto
150  STA DEST+1     ;y listo.	

La línea 135 toma la dirección de LOOP y le aplica un AND con #$FF, lo que nos da el byte de orden inferior. La línea 145 divide esta dirección por 256, lo que nos da el byte de orden superior de la dirección. Tenga en cuenta que la línea 150 almacenará este byte en la dirección DEST más 1.


EL MACRO ASSEMBLER DE ATARI


Ahora discutiremos las diferencias entre los otros ensambladores disponibles y el cartucho Assembler/Editor.


Un ensamblador de macros le permite escribir, de manera bastante inteligente, macros, que generalmente son segmentos cortos de código en lenguaje Ensamblador que planea usar con frecuencia dentro de un programa. Un ejemplo de macro podría ser JMI, que contendría el código para implementar una instrucción Jump on Minus, la que, como ahora sabemos, no está presente en el conjunto de instrucciones 6502. Usando un ensamblador de macro, podríamos codificar esta instrucción y luego, cuando queramos bifurcar en valor negativo, podríamos usar JMI de manera muy similar a una instrucción normal del conjunto del 6502. En el momento del ensamblaje, el Ensamblador encontrará la macro correcta y la insertará en todos los lugares donde se utilice la instrucción JMI.


¡El ATARI Macro Assembler es único entre los ensambladores disponibles capaz de ensamblar un solo archivo cuyo tamaño puede ser muchas veces más grande que todo el espacio de memoria del ATARI! Lo hace leyendo el código de su unidad de disco, ensamblándolo y escribiendo el código objeto ensamblado en otro archivo de disco. Tiene otra característica poderosa: el uso de archivos separados, llamados archivos SYSTEXT. Estos pueden incluir todas las referencias de etiquetas, de modo que dicho archivo SYSTEXT se pueda construir una vez, con todas las equivalencias del ATARI contenidos en él. Este archivo se puede utilizar para todos los programas que escriba, sin la necesidad de volver a construir laboriosamente esta tabla.


Este ensamblador también es diferente en otro aspecto: no utiliza números de línea. Las líneas simplemente se insertan o eliminan en el orden apropiado y su programa se desplaza por la memoria. Para ver el comienzo de su programa, desplace el texto hacia abajo hasta que aparezca el comienzo, y viceversa para el final de su código. Cuando utilice este ensamblador, debe tener cuidado de colocar las líneas en el orden correcto o, de lo contrario, tendrá problemas en tiempo de ejecución.


La etiqueta comienza en la columna 1 y el mnemónico generalmente está tabulado en unos ocho espacios. Los campos de operando y comentario siguen al mnemónico. Las etiquetas pueden tener cualquier longitud, pero sólo los primeros seis caracteres son significativos; Las etiquetas más largas se utilizan bajo su propia responsabilidad. Se admiten números octales, además de binarios, decimales y hexadecimales, y cuando se utilizan, van precedidos del signo @. Las cadenas, como HELLO usada en el ejemplo anterior, están entre comillas simples, en lugar de dobles. El ensamblador AMAC también admite sumas, restas, multiplicaciones y divisiones, así como una serie de operaciones lógicas. Una dirección se puede dividir en bytes de orden alto y bajo simplemente usando las palabras HIGH y LOW, sin necesidad de división como en el ejemplo anterior. Por supuesto, las macros están permitidas. Para cualquier instrucción que utilice el modo Acumulador, la letra A debe seguir al mnemónico. Los pseudo-ops son prácticamente todos diferentes a los del cartucho. A continuación, se describen las versiones de los pseudo-ops del ATARI Macro Assembler (AMAC) y del cartucho Assembler/Editor (A/E):


AMACCartucho A/EComentario
DB.BYTE(.BYTE también es aceptable para AMAC)
DW.WORD(.WORD también es aceptable para AMAC)
END.END(.END también es aceptable para AMAC)
EQU=
LOC Establece el contador de ubicación para el ensamblaje
ORG*=

MAC/65


MAC/65 también es un ensamblador de macros con características similares a las ya descritas. Este ensamblador es el único que "tokeniza" su código fuente, tal como lo hace BASIC. Además, verifica la sintaxis de su línea tan pronto como presiona RETURN después de escribirla. Esta característica no es tan importante en la programación en lenguaje Ensamblador como lo es en BASIC, ya que la mayoría de los errores en lenguaje Ensamblador no son resultado de errores de sintaxis, sino de errores lógicos. Sin embargo, para el programador principiante en lenguaje Ensamblador, esta es una característica interesante que puede eliminar algunos errores simples y comunes. Se requieren números de línea en el rango de 0 a 65535 para cada línea. Tal como se describe para el cartucho Assembler/Editor, el número de línea debe ir seguido de un solo espacio antes de una etiqueta y de 2 espacios antes del mnemónico en líneas sin etiquetas. Las cadenas dentro de un programa deben estar entre comillas dobles, como cuando se utiliza el cartucho Assembler/Editor. Los comentarios comienzan al menos 1 espacio A continuación, del campo operando y no necesitan ir precedidos de un punto y coma. Los comentarios que ocupan una línea completa deben ir precedidos de un punto y coma o un asterisco. Cualquier instrucción que utilice el modo de direccionamiento del Acumulador requiere que el mnemónico vaya seguido de la letra A mayúscula, tal como ocurre con el cartucho Assembler/Editor. Las etiquetas pueden tener hasta 127 caracteres, siendo todos significativos.


MAC/65 admite suma, resta, multiplicación y división. Sin embargo, mientras que el cartucho Assembler/Editor no tiene precedencia de operadores y simplemente evalúa una expresión aritmética compleja de izquierda a derecha, este ensamblador tiene la precedencia habitual de los operadores de multiplicación > división > suma > resta. También utiliza los símbolos > y < para designar los bytes alto y bajo de una dirección, respectivamente.


Este ensamblador se puede utilizar con archivos creados por otro ensamblador: el comando ENTER permite leer dichos archivos en el editor. De hecho, líneas no numeradas como las producidas por AMAC pueden incluso numerarse automáticamente usando el comando ENTER. Luego, cambios menores en la sintaxis permitirán modificar y ensamblar el programa usando MAC/65.


Los pseudo-ops discutidos anteriormente para el cartucho Assembler/Editor se usan exactamente de la misma manera para MAC/65, y el símbolo *= para la declaración de origen también se usa en ambos ensambladores. Se admiten macros y el depurador que viene con MAC/65 es un programa que debe cargarse por separado, al igual que AMAC.


EL SYNASSEMBLER


SYNASSEMBLER también requiere números de línea, que deben ir seguidos de un espacio en blanco antes de ingresar una etiqueta. El rango de números de línea aceptable es de 0 a 63999. Las tabulaciones están integradas en el editor para permitir un formato fácil de las líneas de código y, de hecho, el modo de numeración automática de líneas requiere el uso de la tabulación para imprimir el nuevo número de línea en la pantalla. Las etiquetas pueden tener hasta 32 caracteres de largo y todos los caracteres son significativos. El modo de direccionamiento del Acumulador no utiliza la letra A después del mnemónico. Los comentarios requieren punto y coma sólo cuando se utilizan líneas completas para los comentarios.


El SYNASSEMBLER sólo admite sumas y restas. Por lo tanto, deberá escribir código para admitir otras operaciones o utilizar números calculados en lugar de expresiones aritméticas complejas. Sin embargo, se incluyen operadores los símbolos # y /, utilizados para separar un número en bytes altos y bajos, respectivamente. Por ejemplo:


124 LDA #STOR1 ;indica byte bajo de STOR1
128 STA STOR3
132 LDA /STOR1 ;indica byte alto	

Los pseudo-ops del SYNASSEMBLER son considerablemente diferentes a los del cartucho Assembler/Editor, como puede ver en el siguiente cuadro:


SYNASSEMBLERCartucho A/EComentario
.AS.BYTEsolo para literales ASCII
.BS.BYTE
.DA.WORD
.EN.END
.EQ=
.OR*=

SYNASSEMBLER también tiene un comando ENTER, que le permite ensamblar código producido por uno de los otros paquetes discutidos en este Capítulo. Un uso que puede hacer de esta característica es tener el código ensamblador de SYNASSEMBLER escrito originalmente usando el Assembler/Editor, ya que SYNASSEMBLER es de 50 a 100 veces más rápido en ensamblar código que el cartucho Assembler/Editor. Para programas cortos esta diferencia es relativamente insignificante, pero para programas largos, el tiempo necesario para ensamblar el código es una parte sustancial del proceso de depuración. Reducir sustancialmente este tiempo producirá una sesión de edición mucho más productiva.


Finalmente, las cadenas pueden estar rodeadas por cualquier delimitador, por lo que se pueden usar comillas simples o dobles.


EL MACRO ASSEMBLER/TEXT EDITOR (MAE)


MAE es otro ensamblador de macros disponible para las computadoras ATARI. Requiere números de línea en el rango de 0 a 9999. Cualquier etiqueta en una línea debe seguir inmediatamente al número de línea sin espacios intermedios. A partir de la etiqueta, los campos están separados por espacios. Se requieren puntos y coma al principio de los comentarios de línea completa únicamente; los comentarios al final de una línea sólo necesitan estar separados del operando por un espacio. El modo Acumulador requiere que la letra A siga al mnemónico.


MAE solo admite sumas y restas, pero se incluyen dos símbolos para calcular los bytes alto y bajo respectivamente de un número: #H y #L. Las etiquetas pueden tener hasta 31 caracteres y cada carácter es significativo.


Los pseudo-ops admitidos por MAE, con sus equivalentes en el cartucho Assembler/Editor, se detallan a continuación:


MAECartucho A/E
.BA*=
.BY.BYTE
.EN.END

Se requieren comillas simples alrededor de las cadenas. Una diferencia importante entre MAE y todos los demás ensambladores es que, con MAE, cualquier referencia al direccionamiento de Página Cero debe comenzar con un asterisco. Por ejemplo, si STOR1 y STOR2 están definidos para residir en la Página Cero, entonces el código para cargar el Acumulador desde STOR1 y luego almacenar este valor en STOR2 debería escribirse así:


105 LDA *STOR1
110 STA *STOR2	

EDIT 6502


Este ensamblador no requiere números de línea para el código en lenguaje Ensamblador. Admite sumas, restas, multiplicación y división, sin precedencia; Las expresiones aritméticas complejas se evalúan de izquierda a derecha. Se puede hacer referencia al Contador de Programa mediante el uso del asterisco. Las cadenas pueden estar entre comillas simples o dobles. Si se utilizan comillas simples, el bit superior de cada byte se borra (se iguala a cero) y si se utilizan comillas dobles, se establece el bit superior de cada byte (se iguala a 1). El modo de direccionamiento del Acumulador no utiliza la letra A, sólo el mnemónico, como en este ejemplo:


LDA $4235
ASL	

Se puede utilizar el símbolo > para generar el byte alto de un número y el símbolo < generará el byte bajo.


Edit 6502 utiliza una serie de pseudo-ops que son diferentes a los del Cartucho Assembler/Editor de ATARI, tal como se describe a continuación:


Edit 6502Cartucho A/E
EQU=
ORG*=
DFB.BYTE
DFW.WORD
END.END

Ahora que hemos explorado algunas de las diferencias que necesitará conocer para usar cualquiera de estos ensambladores para las computadoras ATARI, podemos comenzar a escribir algunos programas útiles en lenguaje Ensamblador. El próximo Capítulo explora algunas subrutinas que pueden usarse desde BASIC para acelerar sustancialmente un programa.



Índice de Contenido | Capítulo anterior | Siguiente capítulo