4.9 Procedimiento y Pila
Operaciones de la Pila Si colocamos 10 panqueques, uno encima del otro en el siguiente diagrama, al resultado se le puede llamar pila. Por lo general, no sacamos un panqueque de en medio de la pila; quitamos un panqueque de la parte superior de la pila para colocarlo en nuestro plato. Pueden agregarse más panqueques a la parte superior de la pila, pero no abajo ni en medio
Los panqueques tienen algo en común con los programas de computadora. A una pila también se le conoce como estructura UEPS (Último en entrar, primero en salir), en inglés LIFO (Last-In, First-Out), ya que el último valor que se coloca en la pila siempre es el primero que se saca (UEPS es un término contable muy conocido, pero los panqueques son mucho más interesantes). Una estructura de datos tipo pila sigue el mismo principio: se agregan nuevos valores a la parte superior de la pila y los valores existentes se quitan de la parte superior. En general, las pilas son estructuras útiles para una variedad de aplicaciones de programación, y pueden implementarse con facilidad mediante el uso de métodos de programación orientada a objetos. Si usted ha tomado algún curso de programación en el que se hayan utilizado estructuras de datos, debe haber trabajado con el tipo de datos abstracto pila.
La pila en tiempo de ejecución La pila en tiempo de ejecución es un arreglo de memoria que la CPU administra directamente, mediante el uso de dos registros: SS y ESP. En modo protegido, el registro SS guarda un apuntador a un descriptor de segmento y no se modifica en los programas de usuario. El registro ESP guarda un desplazamiento de 32 bits hacia alguna ubicación en la pila. Muy raras veces es necesario manipular el registro ESP en forma directa; en vez de ello, se modifica de manera indirecta mediante las instrucciones tales como CALL, RET, PUSH y POP. El registro apuntador de pila (ESP) apunta al último entero que se va a agregar (o meter) a la pila. Para demostrar esto, vamos a empezar con una pila que contiene un solo valor. En la siguiente ilustración, el registro ESP (apuntador de pila extendido) contiene el número hexadecimal 00001000, el desplazamiento del valor más reciente que se metió a la pila (00000006):
Operación Push (meter) Una operación push de 32 bits decrementa el apuntador de la pila por 4 y copia un valor a la ubicación en la pila a la que apunta el apuntador. En la siguiente figura, metemos el valor 000000A5 en la pila. La figura muestra el orden de la pila opuesto al de la pila de panqueques que vimos antes. La pila en tiempo de ejecución siempre crece hacia abajo en la memoria, siguiendo el principio de “último en entrar, primero en salir”. Antes de la operación push, ESP = 00001000h; después de push, ESP = 00000FFCh.
Operación Pop (sacar) Una operación pop elimina un valor de la pila y lo copia a un registro o ubicación de memoria. Después de sacar el valor de la pila, el apuntador de la pila se incrementa para apuntar a la siguiente ubicación más alta en la pila. La siguiente figura muestra la pila antes y después de sacar el valor 00000002.
El área de la pila debajo de ESP está lógicamente vacía, y se sobrescribirá la próxima vez que el programa actual ejecute cualquier instrucción para meter un valor en la pila.
Instrucción PUSH La instrucción PUSH primero decrementa a ESP y después copia un operando de origen de 16 o 32 bits en la pila. Un operando de 16 bits hace que ESP se decremente por 2. Un operando de 32 bits hace que ESP se decremente por 4. Hay tres formatos para la instrucción:
PUSH r/m16 PUSH r/m32 PUSH imm32
Si su programa llama a los procedimientos de la biblioteca Irvine32, siempre debe meter valores de 32 bits; si no es así, las funciones de consola Win32 utilizadas por esta biblioteca no funcionarán correctamente. Si su programa llama a los procedimientos de la biblioteca Irvine16 (en modo de direccionamiento real), puede meter valores de 16 o de 32 bits. Instrucción POP La instrucción POP primero copia el contenido del elemento de la pila al que apunta ESP, en un operando de destino de 16 o 32 bits, y después incrementa ESP. Si el operando es de 16 bits, ESP se incrementa por 2; si el operando es de 32 bits, ESP se incrementa por 4: POP r/m16 POP r/m32
|