Ver el código de CAPÍTULO 8 EL PROCESAMIENTO DE LA PILA

===8.0 INTRODUCCIÓN A LA PILA Y AL CONCEPTO DE EMPUJE (PUSH) HACIA ABAJO===

En todas las discusiones sobre direccionamiento, se ha asumido que se conoce la ubicación exacta o al menos una relación con la ubicación exacta de una dirección de memoria. 
Aunque esto es correcto en la mayor parte de la programación para aplicaciones de control, hay ciertos tipos de programación y aplicaciones que requieren que el programa básico no trabaje con posiciones conocidas, sino sólo con un orden conocido para acceder a ella. Este tipo de programación se llama codificación de reentrada (re-entrant coding) y se usa a menudo en el servicio de interrupciones. 
Para implementar este tipo de direccionamiento, el microprocesador mantiene un generador de direcciones separado que el programa utiliza para acceder a la memoria. Este generador de direcciones utiliza el concepto de empuje hacia abajo de la Pila ("push down stack"). 
Las discusiones sobre el este concepto generalmente se expresan mejor considerando que si a uno le dan 3 cartas, un as, un rey y un diez y le dicen que el orden de las cartas es importante y le piden que las dejen sobre la mesa en el orden en que fueron dadas, el as primero, el rey encima y finalmente el diez, y luego, si se retira una carta a la vez, el diez se recupera primero a pesar de que se puso en último lugar, el rey se recupera en segundo lugar, el as se recuperó en último lugar, a pesar de que se puso primero. 
Los únicos comandos necesarios para implementar esta operación son "poner la siguiente carta en la Pila" y "sacar la siguiente carta de la Pila". La Pila podría procesar tréboles y luego ir a diamantes y volver a los tréboles. Sin embargo, sabemos que mientras procesamos tréboles, siempre encontraremos el diez primero, luego el rey, etc. La implementación hardware de la Pila de cartas ordenada que se acaba de describir corresponde a un contador de 16 bits, en el que está almacenada la dirección de una posición de memoria. Este contador se denomina "Puntero de la Pila". Cada vez que los datos van a ser empujados a la Pila, se coloca el Puntero de la Pila en el bus de Direcciones, los datos se escriben en la memoria direccionada por el puntero de Pila, y este puntero se decrementa en 1, tal como se puede ver en el ejemplo 8.1. Cada vez que se extraen datos de la Pila, su puntero se incrementa en 1. El Puntero de la Pila se coloca en el bus de Direcciones y los datos se leen desde la posición de memoria direccionada por el puntero de la Pila. Esta implementación del uso del puntero de la Pila da el efecto de una Pila de empuje hacia abajo, lo que corresponde a un direccionamiento independiente del programa.

__Ejemplo 8.1:  Mapa Básico de la Pila para Secuencia de Salto a Subrutina de Profundidad 3__

#|
*|Dirección de la Pila|Datos|*
||01FF|PCH 1||
||01FE|PCL 1||
||01FD|PCH 2||
||01FC|PCL 2||
||01FB|PCH 3||
||01FA|PCL 3||
||01F9| ||
|#

En el ejemplo anterior, el Puntero de la Pila comienza en 0lFF. El Puntero de la Pila se utiliza para almacenar el primer estado del Contador de Programa, almacenando el contenido de su byte superior en 0lFF y el del byte inferior en 0lFE. El Puntero de la Pila ahora apunta a 0lFD. La segunda vez que se realiza el almacenamiento del Contador de Programa, su byte superior se almacena en la Pila en la dirección 01FD y su byte inferior en la dirección 01FC. El Puntero de la Pila ahora apunta a 01FB. El mismo procedimiento se utiliza para almacenar por tercera vez el Contador de Programa.
Cuando se toman datos de la Pila, PCL 3 vendrá primero y PCH 3 a continuación, siempre y cuando sumemos 1 al puntero de Pila antes de cada lectura de memoria. El ejemplo anterior guarda el Contador de Programa por 3 operaciones sucesivas de salto y almacenamiento, donde el salto transfiere el control a una subrutina y almacena el valor del Contador de Programa en la Pila para recordar a qué dirección debe regresar el programa después de completar la subrutina. 

El siguiente es un programa que recrea la operación de Pila del Ejemplo 8.1.

((https://www.atariware.cl/archivos/mcs6500/ch08_02.webp align=center))

Esto se conoce como anidamiento de subrutinas y se encuentra a menudo al resolver ecuaciones de control complejas.
Para usar correctamente la Pila en este tipo de operaciones, se requiere una instrucción de salto a la subrutina y otra de retorno desde la subrutina.

{{anchor href="JSR"}}
===8.1 JSR-SALTAR A LA SUBRUTINA===

Esta instrucción transfiere el control del Contador de Programa a la ubicación de una subrutina, pero deja un puntero de retorno en la Pila para permitir que el usuario retorne y ejecute la siguiente instrucción en el programa principal después de que la subrutina se haya completado. Para lograr esto, la instrucción JSR almacena en la Pila la dirección del Contador de Programa, la cual apunta al último byte de la instrucción de salto, usando el Puntero de la Pila. El byte de la Pila contiene primero el byte superior del Contador de Programa, seguido por el byte inferior del mismo. 

JSR entonces transfiere las direcciones que vienen a continuación, de la instrucción de salto al byte inferior y superior del Contador de Programa, instruyéndole así al programa para que comience en esa nueva dirección. 

La notación simbólica para esto es PC + 2↓, (PC + 1) → PCL, (PC + 2) → PCH. 

La instrucción JSR no afecta a las banderas, sólo hace que el Puntero de la Pila se decremente en 2 y sustituye los nuevos valores del byte inferior y superior del Contador de Programa. El modo de direccionamiento para JSR siempre es Absoluto. 

El ejemplo 8.3 da los detalles de una instrucción JSR.

__Ejemplo 8.3:  Ilustración de la Instrucción JSR__

**Memoria del Programa**
#|
*|CP|Datos|*
||0100|JSR||
||0101|ADL||
||0102|ADH Subrutina||
|#

**Memoria de la Pila**
#|
*|Puntero de la Pila|Pila|*
||01FD| ||
||01FE|02||
||01FF|01||
|#

#|
*|Ciclo|Bus de Dirección|Bus de Datos|Operación Externa|Operación Interna|*
||1|0100|OP CODE|Obtener Instrucción|Finalizar Operación Anterior; Incrementar PC a 0101||
||2|0101|Nuevo ADL|Obtener Nuevo ADL|Decodificar JSR; Incrementar PC a 0102||
||3|01FF| | |Guardar ADL||
||4|01FF|PCH|Almacenar PCH|Guardar ADL, Decrementar S a 01FE||
||5|01FE|PCL|Almacenar PCL|Guardar ADL, Decrementar S a 01FD||
||6|0102|ADH|Obtener ADH|Guardar Puntero de la Pila||
||7|ADH, ADL|Nuevo OP CODE|Buscar nuevo OP CODE|ADL → PCL, ADH → PCH||
|#

  * S denota "Puntero de Pila".

En este ejemplo, se puede ver que el microprocesador obtiene la instrucción JSR durante el primer ciclo. El byte inferior de la dirección del Contador de Programa nuevo se obtiene durante el segundo ciclo. Al final del ciclo 2, el microprocesador ha decodificado la instrucción JSR y mantiene el byte inferior de la dirección en el microprocesador hasta que se completen las operaciones de la Pila.
NOTA: La Pila siempre se almacena en la página 1 (dirección hexadecimal 0100-01FF).
El funcionamiento de la Pila en la familia de microprocesador MCS650X es tal que el Puntero de la Pila siempre se deja apuntando a la siguiente posición de memoria donde se pueda almacenar datos. En el ejemplo 8.3, se supone que al comienzo el Puntero de la Pila está en 01FF y el PC (Program Counter - Contador de Programa) en la dirección 0100. Durante el tercer ciclo, el microprocesador coloca el Puntero de la Pila en las líneas de dirección y en el cuarto escribe el contenido del valor actual del byte superior del Contador de Programa, 01, en la posición de memoria indicada por la dirección del Puntero de la Pila. Durante el tiempo que se lleva a cabo la escritura, el Puntero de la Pila se decrementa automáticamente en 1, por lo que queda apuntando a 01FE. Durante el quinto ciclo, el byte inferior del Contador de Programa (PCL) se almacena en la siguiente posición de memoria con el puntero de Pila decrementado de manera automática.
Cabe señalar que el byte inferior del Contador de Programa, que ahora se almacena en la Pila, apunta a la última dirección en la secuencia de JSR. Esto no es lo que se espera como resultado de una instrucción JSR. La Pila debe apuntar a la siguiente instrucción. Esta aparente anomalía en la máquina se corrige durante la instrucción RTS ("Return from Subroutine" - Regresar desde de subrutina). 

Nota: Al final de la instrucción JSR, los valores en la Pila contienen el byte inferior y el byte superior del Contador de Programa, que hace referencia a la última dirección de la instrucción JSR. Cualquier llamada a subrutina que desee utilizar el Contador de Programa como puntero intermedio debe tener en cuenta esto. Cabe señalar también que la instrucción RTS ("Return from Subroutine") realiza un incremento automático al finalizar, lo que significa que cualquier Contador de Programa que se sustituya en la Pila deben ser de 1 byte o 1 contador de puntero menos que el Contador de Programa que RTS le devuelve al programador.
La ventaja de retrasar el acceso al byte superior de la dirección hasta después de que el Contador de Programa actual se pueda escribir en la Pila es que sólo el byte inferior de la dirección tiene que ser almacenado en el microprocesador. Esto acorta la instrucción JSR en 1 byte y también minimiza los requisitos de almacenamiento.
Después de que tanto el byte inferior como superior del Contador de Programa han sido transferidos a la Pila, éste se usa para acceder al siguiente byte, que corresponde al byte superior de la dirección para la instrucción JSR. Durante esta operación, en el sexto ciclo, el microprocesador internamente almacena el puntero de la Pila, que ahora apunta a 01FD, o a la siguiente posición en la que se puede cargar la memoria.
Durante el séptimo ciclo, el byte superior de la dirección del bus de Datos y el byte inferior de la dirección almacenada en el microprocesador se transfieren al nuevo Contador de Programa, y se utilizan para acceder al siguiente OP CODE, lo que convierte a JSR en una instrucción de 6 ciclos.
Al finalizar la subrutina, el programador quiere volver a la instrucción que va a continuación, de la instrucción JSR ("Jump-to-Subroutine" - Saltar a la subrutina). Esto es se logra transfiriendo los últimos 2 bytes de la Pila al Contador de Programa, permitiendo que el microprocesador reanude las operaciones en la instrucción que viene a continuación, de JSR, lo que se hace mediante la instrucción RTS.

{{anchor href="RTS"}}
===8.2 RTS-REGRESAR DESDE LA SUBRUTINA===

Esta instrucción carga el Contador de Programa con el byte inferior y superior del Contador de Programa almacenado en la Pila, y luego lo incrementa de manera que apunte a la instrucción que viene a continuación, de JSR. El Puntero de la Pila se ajusta incrementándolo dos veces.
La notación simbólica para RTS es PC↑, INC PC.
La instrucción RTS no afecta a ninguna bandera y sólo afecta a PCL y a PCH. RTS es una instrucción de un sólo byte y su modo de direccionamiento es Implícito.
El ejemplo 8.4 proporciona los detalles de la instrucción RTS. Es el reverso completo del JSR que se muestra en el Ejemplo 8.3. 

__Ejemplo 8.4:  Ilustración de la Instrucción RTS__

**Memoria del Programa**
#|
*|PC|Datos|*
||0300|RTS||
||0301|?||
|#

**Memoria de la Pila**
#|
*|Puntero de la Pila|Pila|*
||01FD|?||
||01FE|02||
||01FF|01||
|#

**Regresar desde Subrutina (Ejemplo)**
#|
*|Ciclo|Bus de Dirección|Bus de Datos|Operación Externa|Operación Interna|*
||1|0300|OP CODE|Obtener OP CODE|Finalizar Operación Anterior, 0301 → PC||
||2|0301|Dato Descartado|Obtener Dato Descartado|Decodificar RTS||
||3|01FD|Dato Descartado|Obtener Dato Descartado|Incrementar el Puntero de la Pila a 01FE||
||4|01FE|02|Obtener PCL|Incrementar el Puntero de la Pila a 01FF||
||5|01FF|01|Obtener PCH| ||
||6|0102|Dato Descartado|Apagar PC|Incrementar PC en 1 a 0103||
||7|0103|Siguiente OP CODE|Obtener Siguiente OP CODE| ||
|#

Como se puede ver, la instrucción RTS efectivamente deshace lo que la instrucción JSR le hizo a la Pila. Debido a que RTS es una instrucción de un sólo byte, desperdicia el segundo acceso a la memoria al hacer una operación anticipada. Durante el segundo ciclo, se lee el valor ubicado en la dirección del programa inmediatamente después de la instrucción RTS, pero no se utiliza en esta operación. Se debe tomar en consideración que la Pila siempre se deja apuntando a la siguiente posición vacía, lo que significa que, para sacar datos de la Pila, el microprocesador tiene que esperar un ciclo mientras suma 1 a la dirección de la Pila. Esto se hace para acortar la secuencia de interrupción que se discutirá a continuación; por lo tanto, el ciclo 3 es un ciclo muerto en el que el microprocesador obtiene, pero no utiliza el valor actual de la Pila y, tal como la recuperación del byte inferior de la dirección en operaciones Indexadas y de Página Cero Indexada, no hace más que poner el microprocesador en el estado adecuado. Se puede ver que el Puntero de la Pila decrece a medida que los datos se envían a la Pila y se incrementa a medida que los datos son sacados de ella. En el cuarto ciclo de la instrucción RTS, el microprocesador saca la dirección 01FE, lee los datos almacenados allí, que corresponde al byte inferior del Contador de Programa que se escribió en el segundo ciclo de escritura de JSR. Durante el quinto ciclo, el microprocesador saca la Pila incrementada recogiendo el byte superior del Contador de Programa que se escribió en el primer ciclo de escritura de la JSR.
Como se indicó durante la discusión de la instrucción JSR, el Contador de Programa almacenado en la Pila realmente apunta a la última dirección de la instrucción JSR; por lo tanto, durante el sexto ciclo, RTS hace que el Contador de Programa de la Pila sea incrementado. Ese es el único propósito del sexto ciclo. Finalmente, en el séptimo ciclo, el Contador de Programa incrementado se utiliza para buscar la siguiente instrucción; por lo tanto, la instrucción RTS toma en total 6 ciclos.
Debido a que cada subrutina requiere una instrucción JSR seguido de una instrucción RTS, el tiempo para saltar y regresar de una subrutina es de 12 ciclos. En los 2 ejemplos anteriores, hemos mostrado las instrucciones JSR, ubicada en la posición 100, y RTS, ubicada en la posición 300. El siguiente diagrama pictórico, ejemplo 8.5, ilustra cómo podría verse el mapa de memoria para esta operación: 

((https://www.atariware.cl/archivos/mcs6500/ch08_05.webp align=center))

Con esta capacidad de creación de subrutinas, el microprocesador permite que el programador pueda ir desde el programa principal a la primera subrutina, luego a la segunda subrutina, y luego a la tercera, para finalmente regresar al programa principal. El ejemplo 8.6 es una expansión del ejemplo 8.2 con los retornos incluidos.

((https://www.atariware.cl/archivos/mcs6500/ch08_06.webp align=center))

Este concepto se conoce como anidamiento de subrutinas, y el número de subrutinas que pueden ser llamadas y devueltas de tal manera es
limitado únicamente por la longitud de la Pila.

===8.3 IMPLEMENTACIÓN DE LA PILA EN LOS MICROPROCESADORES DEL MCS6501 AL MCS6505===

Como hemos visto, el requisito principal para la Pila es que, independientemente de dónde o cuándo se llama a una operación de Pila, el microprocesador debe tener un contador o registro independiente que contenga la dirección de la Pila. Este registro se denomina Puntero de la Pila (S). La Pila se convierte en un campo auxiliar de la Memoria, que es básicamente independiente del control del programador. Más adelante hablaremos de cómo el Puntero de la Pila se inicializa, pero una vez que esto sucede, el principal requisito es que sea autoajustable; en otras palabras, las operaciones que colocan datos en la Pila hacen que su puntero disminuya automáticamente; las operaciones que quitan datos de la Pila hacen que el puntero se incremente automáticamente. Sólo en raras circunstancias el programador debería considerar necesario mover su Pila de un lugar a otro si es que está usando la Pila tal como se diseñó.
En base a esto, no es necesario que la Pila tenga más de 256 bytes. Para realizar una sola llamada a una subrutina se necesitan tan sólo 2 bytes de memoria de la Pila. Para realizar una interrupción sólo se necesitan 3 bytes de Memoria de la Pila. Por lo tanto, con 256 bytes, uno puede tener acceso a una profundidad de hasta 128 subrutinas o realizar 85 interrupciones. Por lo tanto, es muy poco probable que la longitud de la Pila sea una limitante. Los modelos MCS6501 al MCS6505 tienen una longitud de Pila de 256 bytes.
La figura 8.1, que ahora es el diagrama de bloques completo, muestra todos los registros del microprocesador. El registro de 8 bits puntero de la Pila, S, ha sido agregado. Este es inicializado por el programador y luego automáticamente incrementado o decrementado, dependiendo de si los datos son puestos o sacados de la Pila por el microprocesador ya sea bajo el control del programa o de las líneas de interrupción. 

((https://www.atariware.cl/archivos/mcs6500/ch08_07.webp align=center))

El propósito principal de la Pila es proporcionar un bloque de posiciones de memoria en el que el microprocesador pueda escribir datos, como el Contador de Programa, para su uso en el procesamiento posterior. En muchos sistemas de control, las peticiones de memoria de lectura/escritura son mínimos y la Pila representa sólo una más de estas solicitudes. Por lo tanto, a estas aplicaciones les gustaría que la Pila se ubicara en la Página Cero para que se puedan ejecutar tanto la asignación de memoria para la Pila, como las operaciones de Página Cero y el direccionamiento Indirecto. Por lo tanto, uno de los requisitos de una Pila es que sea fácilmente localizable en la Página Cero.
Por otro lado, si se necesita más de una página de RAM debido a la cantidad de datos que deben manejar los programas del usuario, el tener la Pila en la Página Cero es un desperdicio innecesario de esta memoria en el sentido de que la Pila no puede sacar ninguna ventaja real al estar ubicada en la Página Cero, mientras que otras operaciones sí pueden hacerlo.
En cada uno de los ejemplos, la Pila se ubica en una dirección de memoria con orden superior 01 seguida del orden inferior. De la misma manera en que el microprocesador asigna un 00 a los 8 bits de orden superior de las posiciones de memoria de las operaciones de Página Cero, el microprocesador automáticamente asigna 01 hexadecimal a los bits de orden superior de la dirección durante cada operación de la Pila. Esto tiene la ventaja para el usuario de ubicar la Pila en la Página Uno de la memoria, que sería la siguiente ubicación de memoria a sumar si los requisitos de funcionamiento de la Página Cero superan la capacidad de su memoria. Esto tiene la ventaja de que la Pila no requiere que se le agregue memoria específicamente, sólo requiere la asignación de ubicaciones de memoria existentes. Cabe señalar que los conceptos de direccionamiento seleccionados por los dispositivos que soportan el microprocesador MCS650X implican conectar las memorias de tal manera que el bit 8, que es el bit de selección de Página Uno versus Página Cero, sea un valor que "no importa" para las operaciones en las que el usuario no necesita más de una página de memoria de lectura/escritura. Esto es lo que le da al usuario el efecto de ubicar la Pila en la Página Cero para esas aplicaciones.
La segunda característica que debe notar de los ejemplos es que la Pila estaba ubicada al final de la Página Uno y disminuyó a partir de ahí hasta llegar el principio de la página. Esta es la manera natural en que opera la Pila. La Memoria RAM viene en incrementos discretos de 64, 128 y 256 bytes, por lo que el método normal de asignación del direccionamiento de la Pila es que el usuario calcule el número de bytes probablemente necesarios para el acceso a la Pila. Esto se puede hacer analizando ya sea el número de subrutinas que son llamadas y la cantidad de datos que se colocan en la Pila para comunicarse entre ellas, o el número de interrupciones y de subrutinas que podrían ocurrir con sus datos respectivos almacenados en la Pila para cada uno de ellas. Contando 3 bytes por cada interrupción, 2 bytes por cada salto a una subrutina, más 1 byte por cada operación de Pila controlada por el programador, el diseñador del microprocesador puede estimar la cantidad de memoria que debe ser asignada para la Pila. Esto es parte de su proceso de toma de decisiones para decidir cuánta memoria es necesaria para su programa.
Una vez realizada la asignación, se recomienda al usuario distribuir su almacenamiento de trabajo partiendo desde el principio de la memoria y siempre cargando su Pila al final de la Página Cero, o de la Página Uno, o al final de la memoria física que se encuentra ubicada en uno de esos lugares. Esto dará el efecto de tener los bytes de memoria más altos asignados a la Pila y los bytes de memoria más bajos asignados al almacenamiento de trabajo del usuario, los que con suerte nunca se superpondrán.
Cabe señalar que el funcionamiento natural de la Pila, que a menudo es llamado por hardware que no está totalmente bajo el control del programa, es tal que continuará disminuyendo a lo largo de la página a la que se asigna, independientemente del deseo del usuario de que así lo haga. Un error normal en la asignación en la memoria puede resultar en que el usuario escriba datos en una ubicación de memoria y luego la acceda con otra subrutina u otra parte de su programa, sólo para descubrir que la Pila ha escrito sobre esa área como resultado de la realización de operaciones de control de hardware. Este es uno de los problemas más difíciles de diagnosticar. Si el programador sospecha este problema, debe analizar las posiciones mayores a las que contienen los datos alterados.
Hay un patrón distintivo para las operaciones de Pila que son únicas al programa del usuario pero que son bastante predecibles. Un análisis del valor que ha sido destruido a menudo indicará que éste forma parte de una dirección que normalmente se esperaría durante la ejecución del programa entre el momento en que se almacenaron los datos y en que se recuperaron. Esto es una indicación de que la Pila de alguna manera alcanzó el área del programa del usuario. Esto casi siempre es causado por un control inadecuado de las líneas de interrupción u operaciones inesperadas de interrupción o llamadas a subrutinas y tiene sólo 2 soluciones: (1) Si la operación es normal y predecible, el usuario debe asignar más memoria a su programa y particularmente reasignarla de manera que la Pila tenga más espacio para operar; o (2) si el funcionamiento de las líneas de interrupción no es predecible, se debe resolver el problema de hardware que causa este tipo de operación impredecible. 

__**8.3.1 Resumen de la Implementación de la Pila**__

Los microprocesadores del MCS6501 al MCS6505 tienen un único registro Pila de 8 bits. Este registro se incrementa y decrementa automáticamente bajo el control del microprocesador para realizar operaciones de manipulación de la Pila, bajo la dirección del programa del usuario o de las líneas de Interrupción. Una vez que se ha inicializado el Puntero de la Pila al final de cualquier memoria en la que quiera que opere, el programador puede ignorar el direccionamiento de la Pila excepto en aquellos casos en los que hay una interferencia entre las operaciones de la Pila y el espacio de trabajo normal de su programa.
En los microprocesadores del MCS6501 a MCS6505, la Pila se ubica automáticamente en la Página Uno. Para cada operación de Pila, el microprocesador siempre suma la dirección 0100 al registro de la Pila. Por medio de ciertas técnicas de memoria, el usuario puede ubicar la Pila en la Página Cero o en la Página Uno, dependiendo de si la Página Cero está disponible o no para su hardware. 

===8.4 USO DE LA PILA POR PARTE DEL PROGRAMADOR===

En la Sección 8.1 se discutió el uso de la instrucción JSR para llamar a una subrutina. Sin embargo, no se indicó la técnica por la cual la subrutina sabe sobre qué datos operar. Hay 3 técnicas clásicas para comunicar datos entre subrutinas. La primera técnica, que es la más sencilla, es que cada subrutina tenga un conjunto definido de registros de trabajo ubicados en la Página Cero en las que el usuario ha dejado valores para ser utilizados por la subrutina. Los registros pueden contener los valores directamente o pueden contener punteros indirectos a las direcciones de los valores que se utilizarán. El siguiente ejemplo muestra una combinación de estos: 

__Ejemplo 8.7: Subrutina "Call-a-move" Usando Posiciones de Memoria Preasignadas__

  * Ubicación 10     = Conteo
  * Ubicación 11, 12 = Dirección base "FROM" (Origen)
  * Ubicación 13, 14 = Dirección base "TO" (Destino)

 **Rutina Principal**
#|
*|Nº de Bytes|Instrucción|Comentario|*
||2|LDA #Conteo -1|Cargar valor fijo para el movimiento||
||2|STA 10| ||
||2|LDA #FRADH| ||
||2|STA 12|Configurar el puntero de origen||
||2|LDA #FRADL| ||
||2|STA 11| ||
||2|LDA #TOADL| ||
||2|STA 13| ||
||2|LDA #TOADH| ||
||2|STA 14|Configuración del puntero de destino||
||3|JSR SUB1| ||
||23 bytes||
|#

**Codificación de la Subrutina**
#|
*|Nº de Bytes|Etiqueta|Instrucción|*
||2|SUB1|LDY 10||
||2|BUCLE|LDA (11), Y||
||2| |STA (13), Y||
||1| |DEY||
||2| |BNE BUCLE||
||1| |RTS||
||33 bytes en tota||
|#

Como se ha desarrollado previamente, el tiempo del bucle es la consideración primordial en lugar del tiempo de preparación para un gran número de ejecuciones. Puede verse que hemos utilizado las técnicas desarrolladas en secciones anteriores relativas a la referenciación indirecta, al salto a la subrutina y el retorno de la subrutina para realizar este tipo de comunicación de valores. En este caso, no hubo uso de la Pila excepto para almacenar el valor del Contador de Programa.
Una segunda forma de comunicación es el uso de la propia Pila como almacenamiento intermedio de los datos que se van a comunicar a la subrutina. Para que el programador use la Pila como almacenamiento intermedio, necesita instrucciones que le permitan poner y leer datos de la Pila. Estas instrucciones se conocen como instrucciones de introducir (push) y extraer (pull). 

{{anchor href="PHA"}}
===8.5 PHA-INTRODUCIR (PUSH) EL CONTENIDO DEL ACUMULADOR EN LA PILA===

Esta instrucción transfiere el valor actual del Acumulador a la siguiente ubicación en la Pila, decrementándola automáticamente para que apunte a la siguiente posición vacía.
La notación simbólica para esta operación es A↓. Cabe señalar que la notación ↓ significa introducir a la Pila, mientras que ↑ significa extraer de la Pila.
La instrucción Push A sólo afecta al registro del puntero de Pila, el que se decrementa en 1 como resultado de la operación. No afecta a las banderas.
PHA es una instrucción de un sólo byte y su modo de direccionamiento es Implícito.
El siguiente ejemplo muestra las operaciones que ocurren durante la instrucción Push A. 

__Ejemplo 8.8:  Operación de PHA, Asumiendo que la Pila Se Encuentra en 01FF__

#|
*|Ciclos|Bus de Direcciones|Bus de Datos|Operaciones Externas|Operaciones Internas|*
||1|0100|OP CODE|Obtener Instrucción|Finalizar Operación Anterior, Incrementar PC a 0101||
||2|0101|Siguiente OP CODE|Obtener Siguiente OP CODE y descartar|Interpretar Instrucción PHA, retener contador P||
||3|01FF|(A)|Escribir A en la Pila|Decrementar el Puntero de la Pila a 01FE||
||4|0101|Siguiente OP CODE|Obtener Siguiente OP CODE| ||	
|#

Como se puede observar, cuando PHA lleva 3 ciclos, aprovecha el hecho de que el Puntero de la Pila apunta a la ubicación correcta para escribir el valor de A. Como resultado de esta operación, el Puntero de la Pila se ajusta a 01FF. La notación (A) hace referencia al contenido del Acumulador. Ahora que los datos están en la Pila, más adelante el programador solicitará los datos que se recuperarán de la Pila usando la instrucción PLA en su programa. 

{{anchor href="PLA"}}
===8.6 PLA-EXTRAER (PULL) EL CONTENIDO DEL ACUMULADOR DESDE LA PILA===

Esta instrucción suma 1 al valor actual del Puntero de la Pila, y lo usa para dirigirse a la Pila y cargar su contenido en un registro. 
Su notación simbólica es A↑.
La instrucción PLA no afecta las banderas de Acarreo o Desbordamiento. Esta instrucción establece en 1 la bandera Negativo si, como resultado de las instrucciones, el bit 7 del Acumulador fue activado. De lo contrario, se borra. Si el Acumulador es cero como resultado de la instrucción PLA, entonces la bandera Z se establece en 1. De lo contrario, se borra.
La instrucción PLA cambia el contenido del Acumulador al contenido de la posición de memoria ubicada en el registro de Pila más 1, y también incrementa este registro.
La instrucción PLA es una instrucción de un sólo byte y su modo de direccionamiento es Implícito.
En el siguiente ejemplo, los datos almacenados en la Pila del Ejemplo 8.8 se transfieren al Acumulador. 

__Ejemplo 8.9: Operación PLA de la Pila del Ejemplo 8.8__

#|
*|Ciclos|Bus de Direcciones|Bus de Datos|Operaciones Externas|Operaciones Internas|*
||1|0200|PLA|Obtener Instrucción|Finalizar Operación Anterior, Incrementar PC a 0101||
||2|0201|Siguiente OP CODE|Obtener Siguiente OP CODE  y descartar|Interpretar Instrucción, retener contador P||
||3|01FE| |Leer la Pila|Incrementar el Puntero de la Pila a 01FF||
||4|01FF|(A)|Obtener A|Guardar la Pila||
||5|0201|Siguiente OP CODE|Obtener Siguiente OP CODE|M → A||
|#

Al sacar datos de la Pila, hay un ciclo adicional durante el cual se accede, pero no se usa el contenido actual del registro de la Pila y el Puntero de la Pila se incrementa en 1 para permitir el acceso al valor que se almacenó previamente en ella. El Puntero de la Pila se deja apuntando a esta posición porque ahora se le considera una ubicación vacía que puede ser utilizada por la Pila durante una operación posterior. 

===8.7 USO DE LAS INSTRUCCIONES PUSH (INTRODUCIR) Y PULL (EXTRAER) PARA COMUNICAR VARIABLES ENTRE OPERACIONES DE SUBRUTINA===

En el Ejemplo 8.10, realizamos la misma operación que hicimos en el Ejemplo 8.7; solo que aquí, en lugar de usar ubicaciones fijas para recoger los punteros, vamos a utilizar la Pila como vehículo de comunicaciones:

__Ejemplo 8.10:  Subrutina "Call-a-move" Usando la Pila Para Comunicarse__

  * Ubicación 11, 12 = Dirección base de "FROM" (Desde)
  * Ubicación 13, 14 = Dirección base de "TO" (Hasta)

**Rutina Principal**
#|
*|Bytes|Instrucción|*
||2|LDA #Count -1||
||1|PHA||
||2|LDA #FRADL||
||1|PHA||
||2|LDA #FRADH||
||1|PHA||
||2|LDA #TOADL||
||1|PHA||
||2|LDA #TOADH||
||1|PHA||
||3|JSR SUB1||
||18||
|#

**Subrutina**
#|
*|Bytes|Etiqueta|Instrucción|Comentarios|*
||2|SUB1|LDX 6| ||
||1|BUCLE1|PLA| ||
||2| |STA 10,X| ||
||1| |DEX|Mover Pila a la Memoria||
||2| |BNE BUCLE1| ||
||1| |PLA|Preparar contador||
||1| |TAY| ||
||2|BUCLE2|LDA (11), Y| ||
||2| |STA (13),Y|Mover ubicación de Memoria||
||2| |DEY| ||
||2| |BNE BUCLE2| ||
||2| |LDA 15| ||
||2| |PHA| ||
||2| |LDA 16|Restaurar CP a la Pila||
||2| |PHA| || 
||1| |RTS| ||
||42 bytes en tota||
|#

En este ejemplo podemos ver que usar la Pila como medio de comunicación en realidad aumenta el número de bytes en la subrutina y el total de bytes en general. Sin embargo, la única vez que uno debería usar subrutinas de este tipo es cuando ésta es bastante larga y es utilizada de manera bastante frecuente. Esta técnica reduce el número de bytes en la secuencia de llamada. La secuencia de llamada se repite normalmente una vez por cada llamada a la instrucción; por lo tanto, el uso de la Pila para comunicarse debería resultar en una reducción neta en el número de bytes utilizados por el programa.
Hasta este momento, hemos considerando que la Pila está en una ubicación fija y que todas las referencias a la Pila usan el Puntero de la Pila. No se ha explicado cómo el puntero de Pila en el microprocesador es cargado o accedido. Esto se hace a través de la comunicación entre el Puntero de la Pila y el registro Índice X. 

{{anchor href="TXS"}}
===8.8 TXS-TRANSFERIR EL REGISTRO ÍNDICE X AL PUNTERO DE LA PILA===

Esta instrucción transfiere el valor en el registro Índice X al puntero de la Pila.
La notación simbólica es X → S. 
TXS cambia sólo el Puntero de la Pila, haciéndolo igual al contenido del registro Índice X. No afecta a ninguna de las banderas. 
TXS es ​​una instrucción de un sólo byte y su modo de direccionamiento es Implícito. 
Otra aplicación para TXS es el concepto de pasar parámetros a la subrutina almacenándolos inmediatamente después de la instrucción de salto a la subrutina. 
En el ejemplo 8.11, la dirección "desde" y "hasta", más el contador con el número de valores, se escriben a continuación, de la instrucción JSR y su dirección. 
Al ubicar la Pila en la Página Cero, la dirección del último byte de la instrucción JSR se puede incrementar para que apunte a los bytes del parámetro y luego se puede usar como un puntero indirecto para mover el parámetro a su ubicación en la memoria. La clave de este enfoque es transferir el Puntero de la Pila a X, que permite que el programa opere directamente en la dirección mientras está en el Pila. Cabe señalar que este enfoque deja automáticamente la dirección en la Pila, posicionado de manera tal que RTS recoja la dirección del siguiente OP CODE. 

__Ejemplo 8.11: Salto a Subrutina (JSR) Seguido de Parámetros__

#|
*|Bus de Direcciones|Datos|*
||0100|JSR||
||0101|ADL||
||0102|ADH||
||0103|Byte superior de "desde"||
||0104|Byte inferior de "desde"||
||0105|Byte superior de "hasta"||
||0106|Byte inferior de "hasta"||
||0107|Contador||
||0108|Siguiente OP CODE||
|#

Antes de concluir esta discusión sobre subrutinas y el paso de parámetros, uno debe notar nuevamente que el uso de subrutinas debe limitarse a aquellos casos en los que el usuario espera duplicar código de longitud significativa varias veces dentro del programa. En estos casos, y sólo en estos casos, se garantiza el uso de la llamada de subrutina en lugar del modo normal en el que se conocen las direcciones y se especifican en una instrucción. En todos los casos en que el tiempo es de gran interés, también deben evitarse las subrutinas. Las subrutinas aumentan significativamente el tiempo de configuración y ejecución de la solución del problema. Sin embargo, definitivamente tienen su lugar en el código de microcomputadoras y se han presentado 3 alternativas para su uso en programas de aplicación. El usuario encontrará útil la combinación de las técnicas anteriores para resolver su problema particular. 

{{anchor href="TSX"}}
===8.9 TSX-TRANSFERIR EL PUNTERO DE LA PILA AL REGISTRO ÍNDICE X===

Esta instrucción transfiere el valor del puntero de Pila al registro Índice X.
La notación simbólica es S → X.
TSX no afecta las banderas de acarreo o desbordamiento. Establece en 1 la bandera N si el bit 7 está activado en el índice X como resultado de la instrucción; de lo contrario, se borra. Si el índice X es cero como resultado de la instrucción TSX, se establece en 1 la bandera Z; de lo contrario, se borra. TSX cambia el valor del índice X, haciéndolo igual al contenido del Puntero de la Pila.
TSX es una instrucción de un sólo byte y su modo de direccionamiento es Implícito. 

===8.10 ALMACENAMIENTO DEL REGISTRO DE ESTADO DEL PROCESADOR===

Durante las secuencias de interrupción, el contenido actual del registro de Estado del Procesador (P) se guarda en la Pila automáticamente. Sin embargo, hay ocasiones en que el contenido actual del registro P debe guardarse para realizar algún tipo de operación. Un ejemplo particular de esto sería el caso de una subrutina que se llama de forma independiente y que implica aritmética decimal. Es importante que el programador realice un seguimiento del modo aritmético en el que se encuentra el programa en todo momento. Una manera de hacer esto es convenir que la máquina siempre estará en modo binario o decimal, con cada subrutina cambiando su modo y siendo responsable de restaurarlo al estado conocido. Esta es una convención superior a la que se describe a continuación.
Una convención más general sería aquella en la que la subrutina que quiere cambiar los modos de operación empuja P a la Pila, luego establece el modo Decimal para realizar la subrutina y luego extrae P de la Pila antes de regresar de la subrutina.
Las instrucciones que le permiten al usuario lograr esto son las siguientes: 

{{anchor href="PHP"}}
===8.11 PHP-INTRODUCIR EL REGISTRO DE ESTADO DEL PROCESADOR EN LA PILA===

Esta instrucción transfiere el contenido del registro de Estado del Procesador a la Pila sin cambios, tal como lo dicta el Puntero de la Pila. 
La notación simbólica es P↓. 
La instrucción PHP no afecta a registros ni banderas en el microprocesador. 
PHP es una instrucción de un sólo byte y su modo de direccionamiento es Implícito

{{anchor href="PLP"}}
===8.12 PLP-EXTRAER EL REGISTRO DE ESTADO DEL PROCESADOR DESDE LA PILA===

Esta instrucción transfiere el siguiente valor en la Pila al registro de estado del procesador, cambiando así todas las banderas y configurando el modo en base a los valores que se han obtenido de la Pila.
La notación simbólica es P↑.
La instrucción PLP no afecta a ningún registro en el procesador, excepto al registro de Estado.
Esta instrucción podría afectar todas las banderas en el registro de Estado. 
PLP es una instrucción de un sólo byte y su modo de direccionamiento es Implícito. 

===8.13 RESUMEN DE LA PILA===

La Pila de la familia MCS650X es una Pila de empuje hacia abajo ("push-down") implementada por un registro del procesador llamado Puntero de la Pila, el cual el programador inicializa por medio de una instrucción LDX seguida inmediatamente de una instrucción TXS. A partir de ese momento es controlado por el microprocesador, el que carga los datos en la memoria basado en una dirección construida en base a la suma del contenido del Puntero de la Pila y una dirección fija, la dirección hexadecimal 0100. Cada vez que el microprocesador carga datos en la memoria usando el puntero de Pila, automáticamente disminuye el puntero, dejándolo así apuntando al siguiente byte de memoria disponible. Cada vez que el microprocesador accede a los datos de la Pila, suma 1 al valor actual del Puntero de la Pila y lee la posición de memoria obteniendo la dirección 0100 más el Puntero de la Pila. El registro de estado apunta automáticamente a la siguiente ubicación de Memoria en la que ahora se pueden escribir datos. La Pila es un lugar interesante para almacenar datos temporales sin que el programador tenga que preocuparse por la ubicación real donde serán almacenados.
Hay 8 instrucciones que afectan a la Pila. Estas son: BRK, JSR, PHA, PHP, PLA, PLP, RTI y RTS.
BRK y RTI involucran el manejo de las Interrupciones.