Ahora vamos a divertirnos un poco con el lenguaje ensamblador de Atari. En este capítulo, aprenderá a imprimir mensajes en la pantalla, codificar y decodificar caracteres ATASCII (El código ASCII de Atari), y cómo realizar otros trucos en lenguaje ensamblador. Vamos a realizar estas hazañas usando técnicas avanzadas de programación en lenguaje ensamblador que no hemos tratado hasta ahora, junto con nuevas variantes de las técnicas que hemos visto en capítulos anteriores. Estas son algunas de las técnicas de programación que vamos a cubrir en este capítulo.
* Uso de la directiva .BYTE del lenguaje ensamblador.
* Incremento y decremento de los registros X e Y.
* Uso en conjunto de las instrucciones de comparación y salto ("branch").
* Uso avanzado de ciclos y saltos.
* Escritura de instrucciones reubicables en lenguaje ensamblador.
Sin embargo, antes de empezar, haré un truco muy astuto. Voy a pedirle que escriba y guarde en un disco un programa que no le he presentado anteriormente. Es probable que no lo entienda, a menos que tenga experiencia previa en programación en lenguaje ensamblador. Le pido que escriba este programa porque contiene un par de rutinas que son necesarias para ejecutar otros dos programas que le presentaré y explicaré más adelante en este capítulo. El programa, que puede que no entienda, será explicado en detalle en el capítulo 12, "E/S y Usted".
**Dos buenas razones**
En este programa encontrará dos sofisticadas pero muy útiles subrutinas. Una de ellas es una rutina que abre la pantalla como dispositivo de salida y pone su Atari en modo de edición. Ya tendrá ese trabajo hecho la próxima vez que lo encuentre, en el capítulo "E/S y Usted". Así que espero que mire hacia el futuro y vea pastos más verdes en el último capítulo de este libro, y no se enoje demasiado conmigo por pedirle que escriba ahora este programa.
**PROGRAMA PARA IMPRIMIR EN LA PANTALLA**
%%(code)
10 ;
20 .TITLE "RUTINA PRNTSC"
30 .PAGE "RUTINAS PARA IMPRIMIR EN LA PANTALLA"
40 ;
50 *=$5000
60 ;
70 BUFLEN=23
80 ;
0100 EOL=$9B
0105 ;
0110 OPEN=$03
0120 OWRIT=$0B
0130 PUTCHR=$0B
0135 ;
0140 IOCB2=$20
0170 ICCOM=$342
0180 ICBAL=$344
0190 ICBAH=$345
0200 ICBLL=$348
0210 ICBLH=$349
0220 ICAX1=$34A
0230 ICAX2=$34B
0235 ;
0240 CIOV=$E456
0250 ;
0260 SCRNAM .BYTE "E:",EOL
0270 ;
0280 OSCR LDX #IOCB2 ; RUTINA PARA ABRIR LA
0300 LDA #OPEN ; PANTALLA
0310 STA ICCOM,X
0320 ;
0330 LDA #SCRNAM&255
0340 STA ICBAL,X
0350 LDA #SCRNAM/256
0360 STA ICBAH,X
0370 LDA #OWRIT
0380 ;
0390 STA ICAX1,X
0400 LDA #0
0410 STA ICAX2,X
0420 JSR CIOV
0430 ;
0440 LDA #PUTCHR
0450 STA ICCOM,X
0460 ;
0470 LDA #TXTBUF&255
0480 STA ICBAL,X
0490 LDA #TXTBUF/256
0500 STA ICBAH,X
0510 RTS 0520 ;
0530 PRNT
0540 LDX #IOCB2
0550 LDA #BUFLEN&255
0560 STA ICBLL,X
0570 LDA #BUFLEN/256
0580 STA ICBLH,X
0590 JSR CIOV
0600 RTS
0610 ;
0620 TXTBUF=*
0630 ;
0640 *=*+BUFLEN
0650 ;
0660 .END
%%
¡Ahora guárdelo!
Cuando haya escrito este programa, puede ensamblar su código objeto y guardarlo en un disco usando el nombre PRNTSC.OBJ. A continuación encontrará otro programa que me gustaría que escriba y ensamble. Es el único con el que vamos a trabajar el resto de este capítulo.
**THE VISITOR**
%%(code)
10 ;
20 ; EL VISITANTE
30 ;
35 TXTBUF=$5041
40 OPNSCR=$5003
50 PRNTLN=$5031
70 ;
80 *=$600
90 ;
0100 TEXT .BYTE $4C,$4C,$45,$56,$41,$4D,$45,$20
0110 .BYTE $43,$4F,$4E,$50,$20,$54,$55,$20
0120 .BYTE $4C,$49,$44,$45,$52,$21
0130 ;
0140 VIZTOR
0150 ;
0160 LDX #0
0170 LOOP LDA TEXT,X
0180 STA TXTBUF,X
0190 INX
0200 CPX #23
0210 BNE LOOP
0220 JSR OPNSCR
0230 JSR PRNTLN
0240 INFIN JMP INFIN
%%
Este programa se llama (por razones que pronto descubrirá) The Visitor (El Visitante). Es un programa que está diseñado para imprimir un mensaje críptico en nuestra pantalla.
**Ejecutando "The Visitor"**
Cuando haya terminado de escribir The Visitor, puede ejecutarlo de inmediato. Sólo ensámblelo, y luego cargue el código objeto del programa PRNTSC en su computador. Entonces, puede ejecutar The Visitor, ya sea poniendo el computador en modo DEBUG y escribiendo G617, o entrando al modo DOS y ejecutándolo con un comando de DOS.
Cuando haya terminado de escribir el programa, no sería una mala idea guardarlo también en un disco. El nombre de archivo sugerido para el programa es VISITOR.SRC. Luego de que haya ejecutado y guardado su programa, sabrá exactamente lo que éste hace. Así que ahora podremos explicar cómo es que hizo lo que acaba de hacer. Empezaremos con una explicación de la Directiva .BYTE del lenguaje ensamblador, que verá desde la línea 100 a la 120.
%%(wacko wrapper=text wrapper_align=center)((https://www.atariware.cl/archivos/atariroots/ar19.jpg))%%
**La Directiva. BYTE**
A la directiva .BYTE a veces se le llama pseudo código de operación, o pseudo-op, porque aparece en la columna de op-codes del listado de código fuente en lenguaje ensamblador. Pero en realidad no forma parte del conjunto de instrucciones del lenguaje ensamblador del 6502. En cambio, es una directiva especializada diseñada para ser usada en algunos ensambladores, pero no con todos. Por ejemplo, .BYTE funciona con en el ensamblador MAC/65 y con el Atari Assembler Editor, pero no funciona con el Atari Macro Assembler y Atari Program-Text Editor. Al escribir un programa con el Atari Macro Assembler y Atari Program-Text Editor, tiene que usar las letras DB en lugar de la directiva .BYTE. Otros pseudo códigos de operación también son distintos entre ensambladores. No hay estándares generales para la escritura de directivas, por lo que los pseudo códigos de operación diseñados para un ensamblador a menudo no funcionan en otro.
**Lo que hace la directiva .BYTE**
Cuando se utiliza la directiva .BYTE en un programa creado con el ensamblador MAC/65 o el Atari Assembler Editor, los bytes que vienen a continuación de la directiva son ensamblados en posiciones consecutivas de la memoria RAM. En el programa llamado "The Visitor", los bytes que vienen a continuación de la etiqueta TEXT corresponden al código ATASCII (código ASCII de Atari) de una serie de caracteres de texto.
**Dando vueltas en el ciclo**
Como explicamos en el capítulo 6, los registros X e Y del chip 6502 pueden ser progresivamente incrementados o disminuídos dentro de los ciclos de un programa. En el programa The Visitor, el registro X es incrementado desde 0 hasta 23 dentro del ciclo en que se leen los caracteres de una cadena de texto. Los caracteres a ser leídos están escritos en código ATASCII en las líneas 100 y 120 del programa. En la línea 160, la orden LDX# 0 se utiliza para cargar un cero en el registro X. A continuación, en la línea 170, comienza el ciclo.
**Incrementando el registro X**
La primera instrucción dentro del ciclo es LDA TEXT, X. Cada vez que comienza el ciclo, esta instrucción usa el direccionamiento indexado para cargar el acumulador con el código ATASCII de un carácter. Luego, en la línea 180, se usa de nuevo el modo de direccionamiento indexado, esta vez para almacenar el carácter en un buffer de texto. Cuando termina el ciclo, todos los caracteres en el buffer de texto se imprimen en la pantalla. La primera vez que el programa The Visitor llegue a la línea 170, habrá un 0 en el registro X (Ya que se acaba de cargar en la línea anterior un 0 en el registro X). Así que la primera vez que el programa se encuentra con la orden LDA TEXT, X, carga el acumulador con el número hexadecimal $54 - lo que los programadores a veces llaman "el 0-avo byte" a continuación de la etiqueta TEXT. (Por cierto, no hay necesidad de poner un símbolo "#" delante del número $54, ya que los números que vienen a continuación de la directiva .BYTE siempre son interpretados como números literales por el ensamblador MAC/65 y por el Atari Assembler Editor).
**Incrementando y decrementando los registros X e Y**
Ahora vamos a pasar a la línea 190. El mnemónico que ve ahí - INX - significa "incrementar el registro X". Dado que el registro X contiene actualmente un 0, esta instrucción incrementará ahora ese 0 a 1. A continuación, en la línea 200, vemos la instrucción CPX #23. Esto significa "comparar el valor en el registro X con el número literal 23". La razón por la que queremos hacer esta comparación es para poder determinar si ya se han impreso 23 caracteres en la pantalla. Hay 23 caracteres en la cadena de texto que se está imprimiendo, y cuando se hayan impreso todos, necesitaremos imprimir un retorno de carro y terminar nuestro programa.
**Comparación de valores en Lenguaje Ensamblador**
Hay tres instrucciones de comparación en el lenguaje ensamblador del 6502: CMP, CPX, y CPY. CMP significa "Comparar con el valor que tiene el acumulador". Cuando se usa la instrucción CMP, seguido de un operando, el valor expresado por el operando se resta al valor que tiene el acumulador. Esta operación de resta no se realiza para determinar la diferencia exacta entre estos dos valores, sino simplemente para comprobar si son o no iguales, y si no son iguales, para determinar cuál es más grande que el otro. Si el valor del acumulador es igual al valor que se desea comprobar, se activa la bandera cero (Z) del registro de estado del procesador (P). Si el valor en el acumulador no es igual al valor que se desea comprobar, la bandera Z quedará desactivada.
Si el valor en el acumulador es menor que el valor a comprobar, entonces la bandera de acarreo (C) del registro P será desactivada. Y si el valor en el acumulador es mayor o igual al valor a comprobar, entonces la bandera Z se activará y la bandera de acarreo también. CPX y CPY trabajan de la misma manera que CMP, solo que se utilizan para comparar valores con el contenido de los registros X e Y. Producen los mismos efectos que CMP sobre las banderas del registro de estado P.
**Uso en conjunto de las instrucciones de comparación y de salto**
Las tres instrucciones de comparación del lenguaje ensamblador de Atari se suelen utilizar en conjunto con otras ocho instrucciones - las ocho instrucciones de salto condicional que se mencionaron en el capítulo 6. El programa de ejemplo que hemos denominado The Visitor contiene una instrucción de salto condicional en la línea 210. Esa instrucción es BNE LOOP, que significa "salte a la instrucción cuya etiqueta es LOOP sólo si la bandera cero (del registro de estado del procesador) está activa". Esta instrucción usa una convención un poco confusa del chip 6502. En el registro de estado del procesador 6502, la bandera cero se activa (es igual a 1) si el resultado de la operación que se acaba de realizar es 0, y se desactiva (es igual a 0) si el resultado de la operación que se acaba de realizar es distinto de cero.
**En realidad no importa**
Todo esto es muy académico, sin embargo, en lo que al resultado de la orden BNE LOOP se refiere. Cuando el computador se encuentre con la línea 210, seguirá saltando de vuelta a la línea 170 (la línea con la etiqueta LOOP), siempre y cuando el valor del registro X no haya disminuído hasta llegar a cero. Una vez que el valor del registro X haya disminuído hasta llegar a cero, la instrucción BNE LOOP en la línea 210 será ignorada, y el programa pasará a la línea 220, que es la línea siguiente. En la línea 220, el programa salta a la subrutina OPNSCR - que actualmente reside en RAM a partir de la dirección de memoria $5041, siempre y cuando el código objeto, tanto de PRNTSC como el de VISITOR, hayan sido cargados en su computador y estén listos para ser ejecutados.
**Instrucciones de salto condicional**
Como señalamos en el capítulo anterior, en el lenguaje ensamblador del 6502 tenemos ocho instrucciones de salto condicional. Todas comienzan con la letra B, y se les conoce también como instrucciones de direccionamiento relativo o de bifurcación. A continuación se presentan estas 8 instrucciones y su significado:
**BCC** – “Branch if Carry flag is Clear": Salte sólo si la bandera de acarreo (C) del registro de estado del procesador (P) está desactivada. (Si la bandera de acarreo está activada, la operación no tendrá ningún efecto).
**BCS** – “Branch if Carry flag is Set": Salte sólo si la bandera de acarreo (C) del registro de estado del procesador (P) está activada. (Si la bandera de acarreo está desactivada, la operación no tendrá ningún efecto).
**BEQ** – “Branch if EQual to zero": Salte sólo si el resultado de una operación es igual a cero (Si la bandera cero (Z) fue activada como resultado de una operación).
**BMI** – “Branch on MInus": Salte sólo si el resultado de una operación es menor que cero (Si la bandera de negativo (N) fue activada como resultado de una operación).
**BNE** – “Branch if Not Equal to zero": Salte sólo si el resultado de una operación es distinto de cero (Si la bandera de cero (Z) fue desactivada como resultado de una operación).
**BPL** – “Branch on PLus": Salte sólo si el resultado de una operación es mayor que cero (Si la bandera de negativo (N) fue desactivada como resultado de una operación).
**BVC** – “Branch if oVerflow flag is Clear": Salte sólo si la bandera de desbordamiento (V) fue desactivada como resultado de una operación.
**BVS** – “Branch if oVerflow flag is Set": Salte sólo si la bandera de desbordamiento (V) fue activada como resultado de una operación.
**Cómo se utilizan las Instrucciones de salto condicional**
El método habitual para utilizar una instrucción de salto condicional en el lenguaje ensamblador del 6502 consiste en cargar el registro X o Y con un cero o algún otro valor, y luego cargar en el registro A (o algún otro registro de la memoria) un valor a ser comparado. Una vez comparado, se usa una instrucción de salto condicional para decirle al computador cuál bandera del registro P se debe consultar, y qué hacer si dicha comprobación resulta exitosa o no. Todo esto suena muy complicado, y lo es. Pero una vez que entienda el concepto general de salto condicional, podrá utilizar una tabla simple para escribir instrucciones de salto condicional. Aquí le presento una tabla de este tipo.
#|
*|PARA COMPROBAR SI :|HAGA ESTO :|Y LUEGO ESTO OTRO :|*
||A = VALOR|CMP #VALOR|BEQ||
||A <> VALOR|CMP #VALOR|BNE||
||A >= VALOR|CMP #VALOR|BCS||
||A > VALOR|CMP #VALOR|BEQ y luego BCS||
||A < VALOR|CMP #VALOR|BCC||
||A = [DIRECC]|CMP $DIRECC|BEQ||
||A <> [DIRECC]|CMP $DIRECC|BNE||
||A >= [DIRECC]|CMP $DIRECC|BCS||
||A > [DIRECC]|CMP $DIRECC|BEQ y luego BCS||
||A < [DIRECC]|CMP $DIRECC|BCC||
||X = VALOR|CPX #VALOR|BEQ||
||X <> VALOR|CPX #VALOR|BNE||
||X >= VALOR|CPX #VALOR|BCS||
||X > VALOR|CPX #VALOR|BEQ y luego BCS||
||X < VALOR|CPX #VALOR|BCC||
||X = [DIRECC]|CPX $DIRECC|BEQ||
||X <> [DIRECC]|CPX $DIRECC|BNE||
||X >= [DIRECC]|CPX $DIRECC|BCS||
||X > [DIRECC]|CPX $DIRECC|BEQ y luego BCS||
||X < [DIRECC]|CPX $DIRECC|BCC||
||Y = VALOR|CPY #VALOR|BEQ||
||Y <> VALOR|CPY #VALOR|BNE||
||Y >= VALOR|CPY #VALOR|BCS||
||Y > VALOR|CPY #VALOR|BEQ y luego BCS||
||Y < VALOR|CPY #VALOR|BCC||
||Y = [DIRECC]|CPY $DIRECC|BEQ||
||Y <> [DIRECC]|CPY $DIRECC|BNE||
||Y >= [DIRECC]|CPY $DIRECC|BCS||
||Y > [DIRECC]|CPY $DIRECC|BEQ y luego BCS||
||Y < [DIRECC]|CPY $DIRECC|BCC||
|#
**Ciclos en el Lenguaje Ensamblador**
En el lenguaje ensamblador del 6502, las instrucciones de comparación y de salto condicional generalmente se utilizan juntas. En el programa de ejemplo llamado The Visitor, la instrucción de comparación CPX y la instrucción de salto BNE se usan juntas en un ciclo controlado por el incremento de un valor en el registro X. Cada vez que el programa pasa por este ciclo, el valor en el registro X es incrementado o disminuido progresivamente. Y cada vez que el programa llega a la línea 200, el valor en el registro X es comparado con el número literal 23. Cuando se llega a ese número, el ciclo termina. El programa por lo tanto seguirá volviendo a la línea 170 hasta que se hayan impreso 23 caracteres en la pantalla. Luego, en las líneas 220 y 230, se abre la pantalla de su computador - limpiándola en el proceso - y se imprime la cadena que se ha transferido en el buffer de texto. Por último, en la línea 240, el programa entrará en lo que se conoce como un bucle de ciclo infinito - saltando una y otra vez a la misma instrucción JMP, sin hacer nada más hasta que se pulsa la tecla BREAK o de alguna otra manera se detiene el programa.
**¿Por qué utilizar un buffer?**
Antes de pasar a nuestro siguiente tema - mejorar el programa The Visitor – vale la pena responder a una pregunta que se le puede o no haber ocurrido. La pregunta es: ¿Por qué se debe utilizar un buffer de texto? ¿Por qué no imprimir el texto en las líneas de la 100 a 120 directamente en la pantalla, sin tener que primero moverlo a un buffer y luego sacarlo del mismo?
He aquí la respuesta a esa pregunta: El texto de un buffer puede ser cargado de muchas maneras: por medio de un teclado o un módem telefónico, por ejemplo, o con datos entregados directamente por un programa. Y una vez que una cadena de texto está en el buffer, puede ser eliminado de la memoria de diferentes maneras. Otra de las ventajas de un buffer de texto es que puede ser cargado en la memoria RAM, tomar nota de su dirección, y usarlo a partir de entonces cuando lo necesite. Un buffer puede servir como un repositorio central para cadenas texto, al que luego se podrá acceder con gran facilidad y de muchas maneras.
%%(wacko wrapper=text wrapper_align=center)((https://www.atariware.cl/archivos/atariroots/ar20.jpg))%%
**Mejorando el Programa The Visitor**
Ahora estamos listos para hacer algunas mejoras al programa llamado "The Visitor". No es que el programa no funcione, de hecho lo hace, pero tiene ciertas limitaciones. Y algunas de esas limitaciones podrían ser mejoradas fácilmente - como se ha hecho en este nuevo programa, al que he llamado Response.
Response es similar a The Visitor – pero es, como pronto veremos, significativamente mejor en varios aspectos:
RESPONSE
%%(code)
10 ;
20 ; RESPUESTA
30 ;
40 TXTBUF=$5041
50 OPNSCR=$5031
60 PRNTLN=$5031
70 ;
80 EOL=$9b
90 ;
100 *=$650
110 ;
120 TEXT .BYTE "YO SOY vuestro líder, tonto!",EOL
130 ;
140 RSPONS
150 ;
160 LDX #0
170 LOOP
180 LDA TEXT, X
190 STA TXTBUF, X
200 CMP #$9B
210 BEQ FINI
220 INX
230 JMP LOOP
240 FINI
250 JSR OPNSCR
260 JSR PRNTLN
270 INFIN
280 JMP INFIN
%%
Si desea ejecutar el programa Response - y espero que lo quiera hacer - puede digitarlo en la memoria de su computador en este momento. Puesto que llama a las mismas subrutinas que su predecesor, puede ensamblarlo y ejecutarlo tan pronto como lo haya digitado, siempre y cuando todavía tenga el programa PRNTSC cargado en la memoria RAM.
Para ejecutar el programa Response, puede llamar a su programa de depuración y usar el comando G, o ir al modo DOS y utilizar el comando de DOS apropiado. Sea cual sea el modo que decida utilizar, será capaz de ejecutar el programa usando la dirección de ejecución $066B, siempre y cuando lo haya digitado y ensamblado de acuerdo con las sugerencias que he proporcionado. Sin embargo, incluso si usted ha seguido las instrucciones, aun así encontraremos un pequeño problema. Sólo los primeros 23 caracteres de la cadena "YO SOY vuestro líder, tonto!" se mostrarán en la pantalla del computador. Esto porque el buffer de texto que hemos creado en el programa PRNTSC tiene sólo 23 caracteres de longitud.
Este error es fácil de remediar. Pero antes de solucionarlo, tal vez sea una buena idea guardar Response en un disco, tanto en sus versiones código fuente y código objeto. Los nombres de archivo sugeridos para el programa son RESPONSE.SRC y RESPONSE.OBJ.
**Arreglando el programa PRNTSC**
Ahora estamos listos para alargar el buffer de texto utilizado en el programa PRNTSC, por lo que se imprimirá su mensaje completo en la pantalla del computador. Para alargar el buffer de impresión, ponga su ensamblador en modo de edición y cargue el código fuente del programa en la memoria de su computador. Luego cambie la línea 70 de BUFLEN = 23 a BUFLEN = 40. Cuando haya hecho este cambio, puede guardar el código fuente modificado bajo el nombre de archivo PRNTSC.SR2, ensamblarlo, y guardar el código objeto con el nombre de PRNTSC.OB2 (para distinguirlo de PRNTSC.SRC y PRNTSC.OBJ, los programas originales de PRNTSC).
Cuando haya guardado sus programas PRNTSC.SR2 y PRNTSC.OB2, puede volver a cargar el programa Response y ejecutarlo con PRNTSC.OB2 en lugar de PRNTSC.OBJ. Esta vez debería ver la cadena completa que el programa Response presenta en la pantalla de video, pero lamentablemente, ahora se dará cuenta de que otra cosa anda mal. A continuación de la línea "YO SOY vuestro líder, tonto!" verá una línea de pequeños corazones. ¿Cómo llegaron allí? Responderé a esa pregunta en un momento. Pero primero, echemos un vistazo a algunas de las diferencias entre el programa que se llama The Visitor y el que se llama Response.
**Una rutina mejor**
Desde un punto de vista técnico, el programa Response es mejor que The Visitor - por varias razones. La diferencia más obvia entre ambos programas es la forma en que manejan las cadenas de texto. En el programa llamado The Visitor, se utilizó una cadena de texto compuesta de código ATASCII. En Response, usamos un string compuesto de caracteres literales. Eso hizo que el programa sea mucho más fácil de escribir, y también mucho más fácil de leer.
Otra diferencia importante entre nuestro último programa y su predecesor es la forma en que se escribió el bucle. En el programa llamado The Visitor, el ciclo cuenta el número de caracteres que se han impreso en la pantalla, y termina cuando el conteo llega a 23. Ahora bien, este es un sistema perfectamente correcto - para imprimir cadenas de texto que tienen 23 caracteres de longitud. Desafortunadamente, no es tan apropiado para imprimir cadenas de otras longitudes. Por lo que no es una rutina muy versátil para imprimir caracteres en la pantalla.
**Comprobando un Retorno de Carro**
El programa Response es mucho más versátil que The Visitor, ya que puede imprimir cadenas de casi cualquier longitud en una pantalla. Esto porque no hace un seguimiento del número de caracteres que se han impreso en la pantalla. En vez de eso, cada vez que el programa encuentra un carácter, comprueba para ver si su valor es $9B - el código ATASCII del retorno de carro, o el carácter de final de línea (EOL). Si el carácter es no es un EOL, el computador lo imprime en la pantalla y pasa al siguiente carácter en la cadena. Si el carácter es un EOL, se imprime en la pantalla y la rutina termina. Y eso es todo - excepto por esos corazones un poco molestos que nos encontramos cuando ejecutamos el programa Response. Ahora vamos a echar otro vistazo a los corazones, y veremos qué podemos hacer al respecto.
%%(wacko wrapper=text wrapper_align=center)((https://www.atariware.cl/archivos/atariroots/ar21.jpg))%%
**Una Cadena de Corazones**
Los corazones están allí porque el buffer de texto que hemos creado para nuestro mensaje de los programas Visitor y Response tiene ahora 40 caracteres de largo - más largo que cualquiera de nuestros mensajes. Y la parte sobrante del buffer está rellena con ceros, tal como generalmente están las posiciones de memoria vacías de un computador. ¿Entonces por qué los corazones? Bueno, en el código de caracteres ATASCII que utiliza su Atari, un cero no equivale a un espacio; en cambio, equivale a un carácter gráfico con forma de corazón. El código ASCII para el espacio es $20, o 32 en la notación decimal. Basta con mirar la cadena de caracteres ASCII en los programas Visitor y Response, y verá que los espacios en el mensaje "LLEVAME CON TU LIDER!" son de hecho representados por el valor $20.
Es posible, por supuesto, imprimir los mensajes en la pantalla de su Atari sin cadenas de corazones a continuación. Lo que tiene que hacer para evitar que aparezcan estos corazones es limpiar su buffer de texto - o, más exactamente, rellenarlo con espacios - antes de que se ejecute el programa.
**Limpieza del Buffer de Texto**
He aquí una rutina corta que limpiará un buffer de texto - o cualquier otro bloque de memoria - y lo rellenará con espacios, ceros, o cualquier otro valor que usted elija. Mediante la incorporación de esta rutina en nuestros programas The Visitor y Response, puede reemplazar los ceros de sus mensaje que aparecerá en pantalla por espacios ASCII, y hacer que los espacios aparezcan como tales en la pantalla de su computador, en vez de corazones. A medida que siga trabajando con el lenguaje ensamblador, encontrará que las rutinas de borrado de memoria como ésta pueden ser muy útiles en muchos tipos de programas. Procesadores de texto, programas de telecomunicaciones, y muchos tipos de paquetes de software hacen uso extensivo de rutinas que limpian los valores en los bloques de memoria y los reemplazan por otros valores.
**PROGRAMA PARA LIMPIAR UN BLOQUE DE MEMORIA**
%%(code)
1300 FILL
1310 LDA #FILLCH
1320 LDA #BUFLEN
1330 START
1340 DEX
1350 STA TXTBUF,X
1360 BNE START
1370 RTS
%%
Este programa es muy sencillo. Usa el direccionamiento indirecto y una cuenta atrás sobre el registro X, para llenar cada dirección de memoria en un buffer de texto (TXTBUF) con un carácter de relleno (FILLCH) determinado. Luego, el programa termina. Esta rutina funciona con cualquier carácter de relleno de 8 bits, y con cualquier longitud de buffer (BUFLEN) de hasta 255 caracteres. Más adelante en este libro encontrará algunas rutinas de 16 bits que pueden rellenar con valores bloques más extensos de memoria RAM. Puede utilizar esta rutina, integrándola en sus programas The Visitor y Response. Agreguémosla a estos dos programas ahora, comenzando con The Visitor. Con su ensamblador en modo de edición, cárguelo desde el disco y agréguele las siguientes líneas:
%%(code)
55 BUFLEN=40
60 FILLCH=$20
150 JSR FILL
1300 FILL
1310 LDA #FILLCH
1320 LDA #BUFLEN
1330 START
1340 DEX
1350 STA TXTBUF,X
1360 BNE START
1370 RTS
%%
Cuando estos cambios se hayan hecho, su programa VISITOR.SRC debería tener el siguiente aspecto:
**THE VISITOR**
%%(code)
10 ;
20 ; EL VISITANTE
30 ;
35 TXTBUF=$5041
40 OPNSCR=$5003
50 PRNTLN=$5031
55 BUFLEN=40
60 FILLCH=$20
70 ;
80 *=$600
90 ;
0100 TEXT .BYTE $4C,$4C,$45,$56,$41,$4D,$45,$20
0110 .BYTE $43,$4F,$4E,$50,$20,$54,$55,$20
0120 .BYTE $4C,$49,$44,$45,$52,$21
0130 ;
0140 VIZTOR
0150 JSR FILL
0160 LDX #0
0170 LOOP LDA TEXT,X
0180 STA TXTBUF,X
0190 INX
0200 CPX #23
0210 BNE LOOP
0220 JSR OPNSCR
0230 JSR PRNTLN
0240 INFIN JMP INFIN
1300 FILL
1310 LDA #FILLCH
1320 LDX #BUFLEN
1330 START
1340 DEX
1350 STA TXTBUF,X
1360 BNE START
1370 RTS
%%
Cuando su programa se vea así, puede guardar en un disco su versión mejorada. Entonces puede hacer exactamente los mismos cambios en su programa Response, y guardarlo también. Cuando haya terminado con el programa Response, debería verse así:
**RESPONSE**
%%(code)
10 ;
20 ; RESPUESTA
30 ;
40 TXTBUF=$5041
50 OPNSCR=$5031
60 PRNTLN=$5031
65 BUFLEN=40
70 FILLCH=$20
75 ;
80 EOL=$9b
90 ;
100 *=$650
110 ;
120 TEXT .BYTE "YO SOY vuestro líder, tonto!",EOL
130 ;
140 RSPONS
150 ;
160 LDX #0
170 LOOP
180 LDA TEXT, X
190 STA TXTBUF, X
200 CMP #$9B
210 BEQ FINI
220 INX
230 JMP LOOP
240 FINI
250 JSR OPNSCR
260 JSR PRNTLN
270 INFIN
280 JMP INFIN
1300 FILL
1310 LDA #FILLCH
1320 LDX #BUFLEN
1330 START
1340 DEX
1350 STA TXTBUF,X
1360 BNE START
1370 RTS
%%
**Haciéndolo**
Cuando haya guardado de manera segura en un disco ambos programas mejorados - tanto en sus versiones código fuente como código objeto - podrá ejecutarlos y verá que todos nuestros problemas con nuestro buffer de texto se habrán resuelto. Y eso nos lleva a nuestro próximo capítulo, en el que aprenderá a llamar a rutinas de lenguaje ensamblador desde programas en BASIC.