Capítulo 6 - La dirección correcta

Hemos cubierto mucho terreno en los primeros cinco capítulos de este libro. Ahora tiene una idea bastante buena acerca de cómo funciona su computador, y lo que ocurre dentro del chip 6502 de su Atari cuando un programa se está ejecutando. Ahora sabe los principios de los sistemas numéricos binarios y hexadecimales, y ya sabe cómo escribir, depurar, cargar y guardar sus programas en lenguaje ensamblador. Pero en realidad solo hemos comenzado a explorar las capacidades del lenguaje ensamblador 6502.


El procesador 6502 de su computador Atari es un dispositivo increíblemente versátil. Tiene sólo siete registros, y entiende sólo 56 instrucciones. Pero aún con estas limitadas posibilidades, puede hacer cosas asombrosas. Una de las razones por las que el chip 6502 es tan versátil se debe a que puede acceder a las ubicaciones de memoria en un computador en 13 maneras diferentes. En otras palabras, el procesador 6502 cuenta con 13 diferentes modos de direccionamiento. En el mundo del lenguaje ensamblador, el modo de direccionamiento es una técnica para localizar y utilizar la información almacenada en la memoria de un computador.


En los programas presentados hasta ahora en este libro, hemos utilizado tres modos de direccionamiento: direccionamiento implícito, direccionamiento inmediato, y direccionamiento en la página cero. En este capítulo vamos a examinar estos tres modos de direccionamiento, junto con los otros diez disponibles.


Cada instrucción del 6502 debe utilizar uno de los modos de direccionamiento. Ninguna instrucción es capaz de utilizar todos los modos de direccionamiento, y no hay un modo de direccionamiento que sea utilizado por todas las instrucciones. La instrucción le indica al procesador qué hacer y el modo de direccionamiento le dice al proceso con qué hacerlo. En la página siguiente encontrará la lista completa de modos de direccionamiento y su formato de operación, para que pueda distinguir cuál modo está utilizando. Estos formatos son estándares para el microchip 6502 de modo que deben ser entendidos por la mayoría de los ensambladores del 6502.


Los Modos de Direccionamiento del 6502


Los 13 modos de direccionamiento del procesador 6502 son:


MODO DE DIRECCIONAMIENTOFORMATO
1.Implícito (Implicado)*RTS
2.AcumuladorASL A
3.Inmediato*LDA #2
4.AbsolutoLDA $5000
5.Página Cero*STA $CB
6.RelativoBCC LABEL
7.Absoluto Indexado, XLDA $5000,X
8.Absoluto Indexado, YLDA $5000,Y
9.Página Cero, XLDA $CB,X
10.Página Cero, YSTX $CB,Y
11.Indexado IndirectoLDA ($B0,X)
12.Indirecto IndexadoLDA ($B0),Y
13.IndirectoJMP ($5000)

"ADDNRS.SRC" Revisitado


Las tres instrucciones marcadas con un asterisco * son las que hemos utilizado hasta ahora en este libro. Las tres se usaron en "ADDNRS.SRC", el programa de sumas de 8-bits introducido algunos capítulos atrás, y que ahora volvemos a ver:


Código Fuente del programa ADDNRS.SRC

10 ;
20 ; Programa de sumas de 8 bits
30 ;
40    *=$0600
50 ;
60 ADDNRS CLD; Dirección implícita
70 CLC       ; Dirección implícita
80 LDA #02   ; Dirección inmediata
90 ADC #02   ; Dirección inmediata
100 STA $CB  ; Dirección de la página cero
110 RTS      ; Dirección implícita

En este ejemplo, los tres modos de direccionamiento del programa se identifican en la columna de comentarios. Ahora veamos cada uno de estos modos de direccionamiento.


Direccionamiento Implícito (o Implicado)
(Líneas 60, 70 y 110)
Formato: CLD, CLC, RTS, etc.

Cuando se utiliza el direccionamiento implícito, todo lo que tiene que escribir es una instrucción en lenguaje ensamblador de tres letras: el direccionamiento implícito no requiere el uso de un operando (de hecho no lo permite).


La instrucción en un direccionamiento implícito es similar a un verbo intransitivo en inglés: no tiene objeto. No se especifica la dirección a la que se refiere (si es que se refiere a una dirección), sino que ésta se da a entender por el mnemotécnico propiamente tal. Así que no se requiere ni se permite un operando en el direccionamiento implícito. Los mnemotécnicos de códigos de operación ("op codes") que se puede utilizar en el modo de direccionamiento implícito son BRK, CLC, CLD, CLI, CLV, DEX, DEY, INX, INY, NOP, PHA, PHP, PLA, PLP, RTI, RTS, SEC, SED, SEI, TAX, TAY, TSX, TXA, TXS, y TYA.


Direccionamiento Inmediato
(Líneas 80 y 90)
Formato: LDA #02, ADC #02, etc.

Cuando se utiliza el direccionamiento inmediato en una instrucción de lenguaje ensamblador, el operando que viene a continuación del código de operación ("op code") es un número literal, y no la dirección de una posición de memoria. Así, en una orden que utiliza direccionamiento inmediato, el símbolo "#" de un número literal siempre aparece delante del operando. Cuando se utiliza una dirección inmediata en una instrucción en lenguaje ensamblador, el ensamblador no tiene que ir y mirar en la posición de memoria para encontrar el valor. En cambio, el valor es asignado directamente en el acumulador. Así, cualquier operación que sea llamada por la orden podrá ser ejecutada de inmediato. Las instrucciones que pueden ser usadas en modo de direccionamiento inmediato son ADC, AND, CMP, CPX, CPY, EOR, LDA, LDX, LDY, ORA, y SBC.


Direccionamiento de Página Cero
(Línea 100)
Formato: STA $CB, etc.

No es difícil distinguir entre una orden que utiliza direccionamiento inmediato y una que utiliza el direccionamiento de página cero. En una orden que utiliza el direccionamiento de página cero, el operando siempre consta de un solo byte, el que puede ir desde $00 hasta $FF. Y este número equivale a una dirección que está dentro de un bloque de la memoria RAM llamado "página cero".


El símbolo "#" no se utiliza en el direccionamiento de página cero, porque el operando en este tipo de direccionamiento es siempre una posición de memoria, y nunca un número literal. Así que la operación que es invocada en la orden se ejecuta sobre el contenido de la posición de memoria especificada, y no sobre el operando en sí. Las direcciones de la página cero usan operandos de un solo byte porque eso es todo lo que necesitan. Como acabamos de decir, las posiciones de memoria a las que hacen referencia se encuentran en un bloque de memoria de su computador que se llama, lógicamente, página cero. Y para direccionar una posición de memoria en la página cero, un operando de un solo byte es todo lo que se necesita.


En concreto, el bloque de memoria de su computador al que se le conoce como página cero se extiende desde las dirección de memoria $00 hasta la dirección de memoria $FF. También se puede decir (correctamente) que la página cero se extiende desde la dirección $0000 hasta la dirección $00FF. Pero en realidad no es necesario usar los pares de ceros extra cuando se quiere hacer referencia a una dirección de la página cero. Cuando usted pone una dirección de un solo byte a continuación de una instrucción en lenguaje ensamblador, el computador sabe que la dirección está en la página cero. Dado que las direcciones de la página cero usan operandos de un solo byte, la página cero es un área preciada en la memoria RAM de su Atari. De hecho es tan preciada, que la gente que diseñó su computador se adueñó de la mayor parte de ella. Casi toda la página cero es utilizada por el sistema operativo de su computador y otras rutinas esenciales, y no dejan mucho espacio para los programas escritos por los usuarios.


Más adelante en este libro, en un capítulo dedicado a la gestión de memoria, vamos a discutir en detalle el espacio de memoria que se encuentra disponible en la página cero. Por ahora, lo importante es recordar que la página cero es un modo de direccionamiento que utiliza una dirección de memoria en la página cero como un operando de un solo byte. Las instrucciones que se pueden utilizar con el direccionamiento de página cero son ADC, AND, ASL, BIT, CMP, CPX, CPY, DEC, EOR, INC, LDA, LDX, LDY, LSR, ORA, ROL, ROR, SBC, STA, STX, y STY.


Nuevos modos de direccionamiento


Ahora vamos a describir los cinco modos de direccionamiento del 6502 que no hemos visto hasta ahora:


Direccionamiento del Acumulador
Formato: ASL A

El modo de direccionamiento del acumulador se utiliza para realizar una operación sobre un valor almacenado en el acumulador del procesador 6502. El comando ASL A, por ejemplo, se utiliza para desplazar ("shift") una posición en cada bit en el acumulador, provocando que el bit de más a la izquierda (el bit 7) sea asignado al bit de acarreo del registro de estados del procesador §. Otras instrucciones que pueden ser utilizadas con el modo de direccionamiento del acumulador son LSR, ROL, y ROR.


Direccionamiento Absoluto
Formato: STA $5000

El direccionamiento absoluto es similar al direccionamiento de página cero. En una orden que utiliza el direccionamiento absoluto, el operando es una dirección de memoria, no un número literal. La operación invocada en una orden con direccionamiento absoluto se realiza siempre sobre el valor almacenado en la posición de memoria especificada, y no sobre el operando. La diferencia entre una dirección absoluta y una dirección de página cero es que una orden de direccionamiento absoluto no tiene que estar en la página cero, sino que puede estar en cualquier lugar de la memoria RAM libre. Por lo tanto, una orden de direccionamiento absoluto requiere un operando de dos bytes, y no un operando de un byte, que es todo lo que necesita una dirección de la página cero.


Así se ve nuestro programa ADDNRS.SRC si se usa direccionamiento absoluto en lugar de direccionamiento de página cero:


Código fuente del programa "ADDNRS"
(Con direccionamiento absoluto en la línea 100)

10 ;
20 ; Programa de sumas de 8 bits
30 ;
40        *=$0600
50 ;
60 ADDNRS CLD      ; Dirección implícita
70        CLC      ; Dirección implícita
80        LDA #02  ; Dirección inmediata
90        ADC #02  ; Dirección inmediata
100       STA $5000; Dirección absoluta
110       RTS      ; Dirección implícita

El único cambio que se ha hecho a este programa está en la línea 100. El operando en esa línea ahora es un operando de dos bytes, y el cambio hace que el programa sea un byte más largo. Pero ahora la dirección en la línea 100 ya no tiene que estar en la página cero. Ahora puede ser la dirección de cualquier byte en la RAM libre.


Mnemotécnicos que pueden utilizar el modo de direccionamiento absoluto son ADC, AND, ASL, BIT, CMP, CPX, CPY, DEC, EOR, INC, JMP, JSR, LDA, LDX, LDY, LSR, ORA, ROL, ROR, SBC, STA, STX, y STY.


Direccionamiento Relativo
Formato: BCC NEXT

El direccionamiento relativo es un modo de direccionamiento utilizado por una técnica llamada ramificación ("branching") o salto condicional, un método para ordenarle a un programa que salte a una rutina determinada bajo ciertas condiciones en el lenguaje ensamblador del 6502. Hay ocho instrucciones de salto condicional, o mnemotécnicos de dirección relativa. Los ocho comienzan con la letra "B", que significa "branch to – saltar a". A continuación se presentan algunos ejemplos de instrucciones de salto condicional que utilizan el direccionamiento relativo:


BCC (Salta a la dirección especificada, si la bandera de acarreo está desactivada.)
BCS (Salta a la dirección especificada, si la bandera de acarreo está activada).
BEQ (Salta a la dirección especificada, si la bandera Cero está activada).
BNE (Salta a la dirección especificada, si la bandera Cero está desactivada.)


Las ocho instrucciones de salto condicional serán descritas más adelante en un capítulo dedicado a los bucles y saltos.


Lo que hacen las instrucciones de comparación


Los ocho mnemotécnicos de salto condicional a menudo se usan junto con otras tres instrucciones llamadas instrucciones de comparación. Normalmente, una instrucción de comparación se usa para comparar dos valores entre sí, y luego se usa una instrucción de salto condicional para determinar qué debe hacerse si la comparación resulta de una u otra manera. Las tres instrucciones de comparación son:


CMP ("comparar el número en el acumulador con...")


CPX ("comparar el valor en el registro X con...")


CPY ("comparar el valor en el registro Y con...")


Las instrucciones de salto condicional también pueden venir a continuación de operaciones aritméticas o lógicas, o de pruebas de bits y bytes. Por lo general, una instrucción de ramificación causa que un programa salte a una dirección determinada, si ciertas condiciones se cumplen o no. Un salto podría ejecutarse si, por ejemplo, un número es mayor que otro, si dos números son iguales, o si el resultado de una operación devuelve un número positivo, negativo o cero.


Un ejemplo de salto condicional


Acá tenemos un ejemplo de una rutina en lenguaje ensamblador que utiliza el salto condicional:


Programa de sumas de 8 Bits con verificación de error

10 ;
20 ; SUMA DE 8-BIT CON VERIFICACION DE ERROR
30 ;
40         *=$0600
50 ;
60 ADD8BTS CLD
70         CLC
80         LDA $5000
90         ADC $5001
100        BCS ERROR
110        STA $5002
120        RTS
130 ERROR  RTS

Este es un programa de sumas de números de 8 bits que incluye una sencilla comprobación de errores. Se suman dos números de 8 bits usando direccionamiento absoluto. Si este cálculo da como resultado un valor de 16 bits (un número mayor que 255), habrá un error de desbordamiento, y además, el bit de acarreo del registro de estado del procesador se activará. Si no se activa el bit de acarreo, entonces la suma de los valores almacenados en las direcciones $5000 y $5001 se guardará en la dirección $5002. Sin embargo, si se activa el bit de acarreo, esta condición será detectada en la línea 100, y el programa saltará hacia la línea con la etiqueta ERROR (es decir, la línea 130). En la línea 100, usted puede comenzar cualquier tipo de rutina que necesite: por ejemplo, puede escribir una rutina que imprima un mensaje de error en la pantalla. Sin embargo, en este programa de ejemplo, un error sólo deriva en la ejecución de la instrucción RTS.


Direccionamiento Absoluto Indexado
Formato: LDA $0500,X o LDA $0500,Y

Una dirección indexada, tal como una dirección relativa, se calcula usando un desplazamiento ("offset"). Pero en una dirección indexada, el desplazamiento está determinado por el contenido actual del registro X o del registro Y del 6502. Una orden que contiene una dirección indexada puede ser escrita utilizando cualquiera de los siguientes formatos:

##LDA $5000,X

o

LDA $5000,Y

Cómo funciona el Direccionamiento Indexado Absoluto


Cuando se utiliza el direccionamiento indexado en una instrucción en lenguaje ensamblador, el contenido ya sea del registro X o del registro Y (dependiendo del registro índice que se esté utilizando) es sumado a la dirección indicada en la instrucción para determinar la dirección final. He aquí un ejemplo de una rutina que usa direccionamiento indexado. La rutina está diseñado para recorrer cada uno de los bytes de una cadena (“String”) de caracteres ATASCII (El código ASCII de Atari), guardando la cadena en un buffer de texto. Cuando la cadena se haya almacenado en el buffer, la rutina termina. El texto que se va a mover tiene la etiqueta TEXT y el buffer que va a ser llenado con el texto tiene la etiqueta TXTBUF. La dirección inicial de TXTBUF, y el código ATASCII para el retorno de carro ("RETURN") se definen en una tabla de símbolos que precede al programa.


RUTINA PARA MOVER UN BLOQUE DE TEXTO
(Un Ejemplo de Direccionamiento Indexado)
MOVEBLOC.SRC

10 ;
20 ; Rutina para mover un bloque de texto
30 ;
40 TXTBUF = $5000
50 EOL = $9B
60 ;
70          *=$600
80 ;
90  TEXT   .BYTE $54,$41,$4B,$45,$20,$4D,$45,$20
100        .BYTE $54,$4F,$20,$59,$4F,$55,$52,$20
110        .BYTE $4C,$45,$41,$44,$45,$52,$21,$9B
120 ;
130 DATMOV
140 ;
150        LDX #0
160 LOOP   LDA TEXT,X
170        STA TXTBUF,X
180        CMP #EOL
190        BEQ FINI
200        INX
210        JMP LOOP
220 FINI   RTS
230        .END

Verificando el retorno de carro


Al comenzar el programa, sabemos que la cadena termina con un retorno de carro (Código ATASCII $9B), como habitualmente terminan las cadenas en los programas Atari. A medida que avanza el programa a través de la cadena, comprueba cada carácter para ver si se trata o no de un retorno de carro. Si el carácter no es un retorno de carro, el programa pasa al siguiente carácter. Si el carácter es un retorno de carro, significa que no hay más caracteres en la cadena, y la rutina termina.


Direccionamiento Página Cero, X
Formato: LDA $CB, X

El direccionamiento "Página Cero, X" se utiliza tal como el "Direccionamiento Indexado, X". Sin embargo, la dirección utilizada en el modo de direccionamiento "Página Cero, X" se encuentra (lógicamente) en la página cero. Las instrucciones que se pueden utilizar en el modo de direccionamiento "Página Cero, X" son ADC, AND, ASL, CMP, DEC, EOR, INC, LDA LDY, LSR, ORA, ROL, ROR, SBC, STA, y STY.


Direccionamiento Página Cero, Y
Formato: STX $CB, Y

El direccionamiento "Página Cero, Y" funciona tal como el direccionamiento "Página Cero, X", pero se puede utilizar sólo con dos mnemotécnicos: LDX y STX. Si no fuera por el direccionamiento "Página Cero, Y", no sería posible utilizar el direccionamiento absoluto indexado con las instrucciones LDX y STX – esta es la única razón por la que existe este modo de direccionamiento.


Direccionamiento Indirecto


Hay dos subcategorías de direccionamiento indexado: direccionamiento indirecto indexado, y direccionamiento indexado indirecto. Ambos direccionamientos se utilizan principalmente para buscar datos almacenados en tablas. Si piensa que los nombres de estos modos de direccionamiento son confusos, no es el primero en quejarse. Nunca pude entenderlos hasta que ideé un truco para ayudarme a terminar con la confusión.


Este es el truco: El Direccionamiento Indirecto Indexado, que tiene una "x" en la última palabra de su nombre, es un modo de direccionamiento que hace uso del registro X del chip 6502. El Direccionamiento Indexado Indirecto, que no tiene una "x" en la última palabra de su nombre, utiliza el registro Y del 6502.


Ahora vamos a revisar los dos modos de direccionamiento indirecto de su Atari, partiendo por el Direccionamiento Indirecto Indexado.


Direccionamiento Indirecto Indexado
Formato: ADC($C0,X)

El Direccionamiento Indirecto Indexado trabaja en varios pasos. En primer lugar, el contenido del registro X se suma a una dirección de la página cero – no el contenido de la dirección, sino a la dirección en sí misma. El resultado de este cálculo debe ser siempre otra dirección de la página cero. Cuando esta segunda dirección se ha calculado, se toma el valor que contiene esta dirección, junto con el contenido de la siguiente dirección, y ambos constituyen una tercera dirección. Esta tercera dirección es (por fin) la dirección que finalmente será interpretada como el operando de la instrucción en cuestión.


Un ejemplo de direccionamiento indirecto indexado


Un ejemplo puede ayudar a clarificar este proceso.


Supongamos que la dirección de memoria $B0 en su computador contiene el número $00, y que la dirección de memoria $B1 contiene el número $06, y el registro X contiene el número 0. Éstas son las equivalencias correspondientes en una forma más fácil de leer:


$B0 = #$00
$B1 = #$06


X = #$00


Ahora vamos a suponer que está ejecutando un programa que contiene la instrucción indirecta indexada LDA ($B0, X). Si todas estas condiciones existen cuando el equipo encuentre la instrucción LDA ($B0, X), el equipo sumará el contenido del registro X (un cero) al número $B0. La suma de $B0 y 0, por supuesto, es $B0. Así que el equipo irá a las direcciones de memoria $B0 y $B1, encontrará el número $00 en la dirección de memoria $B0, y el número $06 en la dirección $B1.


Ya que los computadores basados en el 6502 almacenan los números de 16 bits en orden inverso o sea, el byte bajo primero, el computador interpretará el número que se encuentra en $B0 y $B1 como $0600. Por lo que cargará el acumulador con el número $0600, el valor de 16 bits que estaba almacenado en $B0 y $B1. Ahora imaginemos qué pasa cuando el equipo encuentra la instrucción LDA ($ B0, X), y el registro X del 6502 contiene el número 04, en lugar del número 00. Aquí tiene un gráfico que ilustra los valores, además de otras equivalencias que usaremos en breve:


$B0 = #$00
$B1 = #$06
$B2 = #$9B
$B3 = #$FF
$B4 = #$FC
$B5 = #$1C


X = #$04


Si estas son las condiciones cuando el equipo encuentre la instrucción LDA ($B0, X), entonces el computador sumará el número $04 (el valor en el registro X) al número $B0, y después irá a las direcciones de memoria $B4 y $B5. En estas dos direcciones encontrará finalmente la dirección (primero el byte menor, por supuesto) del dato que estaba buscando, en este caso, $1CFC.


Un modo rara vez usado


El Direccionamiento Indirecto Indexado no se utiliza mucho en programas de lenguaje ensamblador. Se usa cuando se desea localizar una dirección de 16-bits que se encuentra en una tabla de direcciones almacenada en la página cero. Dado que encontrar espacio disponible en la página cero es difícil, es poco probable que pueda almacenar muchas tablas de datos en ella. Así que es muy probable que casi nunca use el direccionamiento indirecto indexado.


Direccionamiento Indexado Indirecto
Formato: ADC ($C0), Y

El Direccionamiento Indexado Indirecto no es tan escaso como el Direccionamiento Indirecto Indexado. De hecho, es utilizado en programas en lenguaje ensamblador en muchas ocasiones. El direccionamiento Indexado Indirecto utiliza el registro Y (nunca el registro X) como desplazamiento ("offset") para el cálculo de la dirección base del comienzo de una tabla. La dirección de inicio de la tabla tiene que estar almacenada en la página cero, pero la tabla no tiene que estar ahí. Cuando un ensamblador encuentra una dirección indexada indirecta en un programa, lo primero que hace es mirar en la página cero el contenido de la dirección que viene entre paréntesis y que precede a la "Y". El valor de 16 bits almacenado en esa dirección y en la dirección que viene a continuación se suma al contenido del registro Y. El valor resultante es una dirección de 16 bits: y corresponde a la dirección que la instrucción está buscando.


Un ejemplo de direccionamiento indexado indirecto


He aquí un ejemplo de direccionamiento indexado indirecto:


Su computador está ejecutando un programa y llega a la instrucción “ADC ($ B0), Y”. A continuación, examina las direcciones de memoria $B0 y $B1. En $B0 se encuentra el número $00. En $B1, se encuentra el número $50. Y el registro Y contiene el número 4. Aquí tiene un gráfico que ilustra las condiciones:


$B0 = #$00
$B1 = #$50


Y = #$04


Si estas son las condiciones cuando el computador encuentre la instrucción “ADC ($B0), Y”, entonces combinará los números $00 y $50, obteniendo (bajo la forma peculiar del 6502 o sea, el byte más bajo primero) la dirección $5000. A continuación sumará el contenido del registro Y (4 en este caso) al número $5000, y terminará obteniendo un total de $5004. Esta cifra, $5004, será el valor final del operando ($B0, Y). Por lo tanto el contenido del acumulador será sumado al número que se almacena en la dirección de memoria $5004.


Una vez que entienda el direccionamiento indexado indirecto, verá que puede convertirse en una herramienta muy valiosa en la programación en lenguaje ensamblador. Una sola dirección, la dirección de comienzo de la tabla, tiene que estar almacenada en la página cero, donde el espacio disponible siempre es escaso. Sin embargo, esa dirección, sumada al contenido del registro de Y, puede ser utilizada como un punto de partida para localizar cualquier otra dirección en la memoria de su computador. A medida que se familiarice con el lenguaje ensamblador, tendrá muchas oportunidades para ver cómo funciona el direccionamiento indirecto. Encontrará ejemplos de esta técnica en algunos programas de este libro, y encontrará muchos más ejemplos en otros programas en lenguaje ensamblador.


Direccionamiento Indirecto
Formato: JMP ($5000)

En el lenguaje ensamblador del 6502, el direccionamiento indirecto no indexado puede ser utilizado con un solo mnemotécnico: JMP. Un ejemplo de direccionamiento indirecto no indexado es la instrucción JMP ($ 5000), que significa "Saltar a la posición de memoria que se encuentra almacenada en las direcciones de memoria $ 5000 y $ 5001."


El concepto 'LIFO'


La pila es lo que los programadores a veces llaman bloque de memoria "LIFO" (Last In First Out – El primero en entrar es el primero en salir). Funciona como una pila de platos en un restaurante. Cuando usted pone un número en la posición de memoria que está en la parte superior de la pila, cubre el número que antes estaba en la cima de la pila. Así que se debe quitar el número que está en la parte superior de la pila antes de poder acceder al número que está debajo de este, el mismo que anteriormente estaba en la parte superior de la pila.


Cómo el 6502 usa la pila


El procesador 6502 a menudo usa la pila para el almacenamiento temporal de datos durante la operación de un programa. Por ejemplo, cuando un programa salta a una subrutina, el 6502 toma la dirección de memoria a la que el programa más adelante tendrá que volver, y deja ("push") esa dirección en la cima de la pila. Luego, cuando la subrutina termina con una instrucción RTS, la dirección de retorno se extrae ("pull") de la parte superior de la pila y se carga en el contador de programa del 6502. Luego, el programa puede volver a la dirección apropiada, y el procesamiento normal puede reanudarse. La pila también se utiliza a menudo en programas escritos por el usuario. He aquí un ejemplo de una rutina que hace uso de la pila. Puede reconocer que es una variación del programa de sumas de 8 bits que hemos estado utilizando.


No trate de ejecutar este programa hasta que entienda cómo funciona la pila y cómo impedir que el programa falle.


RUTINA DE SUMAS QUE USA EL STACK
STACKADD.SRC

10 ;
20 ; STACKADD.SRC
30 ;
40        *=$0600
50 ;
60 ; CUANDO COMIENZA ESTE PROGRAMA, DOS
70 ; NUMEROS DE 8 BITS ESTAN EN LA PILA
80 ;
90 STKADD
100       CLD
105       CLC
110       PLA
120       STA $B0
130       PLA
140       ADC $B0
150       STA $C0
160       RTS
170       .END

Este programa es una rutina directa y simple de sumas que muestra lo fácil y cómodo que es utilizar la pila en programas en lenguaje ensamblador. En la línea 110, se toma un valor de la pila y se almacena en el acumulador. Luego, en la línea 120, el valor se almacena en la dirección de memoria $B0. En las líneas 130 y 140, se toma otro valor de la pila, y se agrega ahora al valor almacenado en $B0. El resultado de este cálculo se almacena en $C0, y con esto finaliza la rutina. Este es sólo un pequeño ejemplo de las muchas formas en que se puede usar la pila.


Encontrará otras maneras de utilizar la pila en los últimos capítulos de este libro. Si se preocupa de manejar la pila adecuadamente, o sea, si limpia la pila después de cada uso, puede llegar a ser una herramienta de programación muy potente. ¡Pero, si enreda la pila mientras la está usando, seguro que tendrá problemas!


Los mnemotécnicos que hacen uso de la pila son:


PHA ("empujar el contenido del acumulador en la pila")


PLA ("sacar el valor superior de la pila y depositarlo en el acumulador")


PHP ("empujar el contenido del registro P en la pila")


PLP ("sacar el valor superior de la pila y depositarlo en el registro P")


JSR ("poner el PC actual en la pila y saltar a la dirección")


RTS ("sacar la dirección de retorno de la pila y ponerla en el PC e incrementarlo en uno." Esto provoca que la ejecución continúe
donde quedó anteriormente.)


Las operaciones PHP y PLP a menudo se incluyen en subrutinas en lenguaje ensamblador para que el contenido del registro P no sea eliminado mientras se ejecutan las subrutinas. Al saltar a una subrutina que puede cambiar el estado del registro P, siempre es una buena idea comenzar la subrutina empujando el contenido del registro P a la pila. Luego, justo antes de terminar la subrutina, puede restaurar el estado anterior del registro de P con una instrucción PHP. De esta forma, el contenido del registro P no será destruido mientras se ejecuta la subrutina.