Una pila es una estructura de datos con dos operaciones, PUSH (empujar, meter) y PULL (extraer, sacar). La operación PUSH almacena un dato en la pila. La operación PULL extrae un dato de la pila. La condición para que sea una pila es que el dato extraído sea el último que se introdujo. Lo mismo que ocurre en una pila de platos de un restaurante. Los platos limpios se van colocando en la parte alta de la torre de platos. Cuando se requiere un plato, se toma de la cima de la torre. Dicho plato fue el último que se metió en la torre de platos.
El procesador no tiene pilas como tales, sino punteros (o apuntadores) de pilas. El puntero S es el puntero del sistema y se verá afectado por otras operaciones del procesador como veremos en sesiones posteriores. El puntero U está a completa disposición del usuario. Trabajemos con el puntero U para ver cómo funcionan las pilas.
Lo primero que hay que hacer es darle un valor inicial al puntero de pila. Le daremos el valor 0xF000, enseguida veremos el porqué.
Imaginemos ahora que queremos introducir en la pila el valor del registro A. La instrucción en ensamblador es PSHU A. Veamos gráficamente cómo funciona:
El puntero de pila, como vemos, apunta siempre al último byte que se metió en la pila. Sigamos con el ejemplo para ver cómo podemos, mediante la pila, lograr el equivalente a la instrucción EXG A,B (intercambiar los registros A y B). Es evidente que es preferible dicha instrucción, pues es más rápida. Se pone aquí a modo de ejemplo:
Con este ejemplo habréis observado que la pila crece siempre hacia las direcciones bajas, que no es obligatorio sacar de la pila al mismo registro que se metió y que, cuando algo sale de la pila no se pierde el tiempo en borrarlo de la memoria, simplemente se incrementa el puntero.
En nuestro simulador, el valor inicial de los registros es cero. En un caso real, no tiene por qué ser así. Esto, unido al hecho de que si dejamos la pila en el 0x0000, puede empezar a crecer hacia abajo y machacarnos las direcciones peligrosas de 0xFF00, 0xFF01 y 0xFF02, hacen que un buen lugar para iniciarla en nuestro sistema sea ese 0xF000 que hemos puesto.
'\n
). En ese momento,
se imprimirán por la pantalla los caracteres tecleados en orden
inverso.
Pruébese el programa con los famosos palíndromos en español: "RECONOCER", "ACURRUCA", "DABALE ARROZ A LA ZORRA EL ABAD".
Esta operación es funcionalmente equivalente a estas tres, justo en este orden: PSHU S, PSHU Y, PSHU A.
Uno de los usos más frecuentes de las pilas en ensamblador consiste en salvaguardar en la pila los valores de los registros para poder operar con ellos y restaurar su valor con órdenes PULLs cuando se haya acabado. Imaginemos que, en el caso anterior, hemos estado operando con los registros A, S e Y y ha quedado basurilla en ellos y queremos recuperar su antiguo valor. Usamos la instrucción PULU:
Notad que la instrucción PULU A,S,Y es equivalente a estas tres: PULU A, PULU Y, PULU S, exactamente en ese orden que es, además, inverso al orden en que se metieron en la pila. De todos estos detalles se encarga la propia instrucción PULU si metéis varios registros a la vez.
Otros usos tradicionalmente dados a las pilas son el manejo de subrutinas y la creación de variables locales o temporales. De ambos asuntos trataremos sobradamente en sesiones venideras.
Ejemplo de entradas correctas:
f(7)=4
{a[0],a[1],a[2]}
{[(([{}([{}]){}]))]}
Ejemplo de entradas incorrectas:
El signo ( se usa para abrir parEntesis
1) Dos litros de cerveza negra
(2*(7+4)/5+2*f(4)))-7*325*(a+b+2*(c+d))
(2*(7+4)/5+2*f(4))-7*325*(a+b+2*(c+d]))
{[(([{)([{)}]{)}]]})
Pista: en la pila se van guardando las aperturas y, cuando llega un cierre, se saca de la la pila la última apertura guardada. Si no coinciden, hay error de sintaxis. Si coinciden, se prosigue.
PSHx
PULx
ls
cd
rm
man
cat
echo $?