En la programación en lenguaje ensamblador , el prólogo de la función son unas pocas líneas de código al comienzo de una función, que preparan la pila y los registros para su uso dentro de la función. De manera similar, el epílogo de la función aparece al final de la función y restaura la pila y los registros al estado en el que estaban antes de que se llamara a la función.
El prólogo y el epílogo no son parte del lenguaje ensamblador en sí; representan una convención utilizada por programadores de lenguaje ensamblador y compiladores de muchos lenguajes de nivel superior . Son bastante rígidos, teniendo la misma forma en cada función.
El prólogo y el epílogo de la función también contienen a veces código para la protección de desbordamiento del búfer .
Prólogo
Un prólogo de función normalmente realiza las siguientes acciones si la arquitectura tiene un puntero base (también conocido como puntero de marco) y un puntero de pila:
- Inserta el puntero de la base actual en la pila, para que se pueda restaurar más tarde.
- Asigna el valor del puntero base a la dirección del puntero de la pila (que apunta a la parte superior de la pila) de modo que el puntero base apunte a la parte superior de la pila.
- Mueve el puntero de la pila aún más disminuyendo o aumentando su valor, dependiendo de si la pila crece hacia abajo o hacia arriba. En x86, el puntero de la pila se reduce para dejar espacio para las variables locales de la función.
Se pueden escribir varios prólogos posibles, lo que da como resultado una configuración de pila ligeramente diferente. Estas diferencias son aceptables, siempre que el programador o compilador use la pila de la manera correcta dentro de la función.
Como ejemplo, aquí hay un prólogo típico de función en lenguaje ensamblador x86 producido por el GCC
empujar ebp mov ebp , esp sub esp , N
El valor inmediato de N es el número de bytes reservados en la pila para uso local.
El mismo resultado se puede lograr usando la enter
instrucción:
ingrese N , 0
Se pueden obtener prólogos más complejos utilizando valores diferentes (distintos de 0) para el segundo operando de la enter
instrucción. Estos prólogos empujan varios punteros base / marco para permitir funciones anidadas , como lo requieren lenguajes como Pascal . Sin embargo, las versiones modernas de estos lenguajes no usan estas instrucciones porque limitan la profundidad de anidación en algunos casos. [ cita requerida ]
Epílogo
El epílogo de la función invierte las acciones del prólogo de la función y devuelve el control a la función que llama. Por lo general, realiza las siguientes acciones (este procedimiento puede diferir de una arquitectura a otra):
- Coloque el puntero de la pila en el puntero base actual, de modo que se libere el espacio reservado en el prólogo para las variables locales.
- Saca el puntero de la base de la pila, por lo que se restaura a su valor antes del prólogo.
- Vuelve a la función de llamada, sacando el contador de programa del marco anterior de la pila y saltando a él.
El epílogo dado revertirá los efectos de cualquiera de los prólogos anteriores (ya sea el completo o el que usa enter
). Bajo ciertas convenciones de llamada , es responsabilidad del destinatario limpiar los argumentos de la pila, por lo que el epílogo también puede incluir el paso de mover el puntero de la pila hacia abajo o hacia arriba.
Por ejemplo, estos tres pasos se pueden realizar en lenguaje ensamblador x86 de 32 bits mediante las siguientes instrucciones:
mov esp , ebp pop ebp ret
Al igual que el prólogo, el procesador x86 contiene una instrucción incorporada que realiza parte del epílogo. El siguiente código es equivalente al código anterior:
dejar ret
La leave
instrucción realiza las instrucciones mov
y pop
, como se describe anteriormente.
Una función puede contener varios epílogos. Cada punto de salida de función debe saltar a un epílogo común al final o contener su propio epílogo. Por lo tanto, los programadores o compiladores suelen utilizar la combinación de leave
y ret
para salir de la función en cualquier momento. (Por ejemplo, un compilador de C sustituirá una return
instrucción con una secuencia leave
/ ret
).
Otras lecturas
- de Boyne Pollard, Jonathan (2010). "Los perílogos gen en función" . Respuestas dadas con frecuencia .