Se trata del registro BP / EBP / RBP en plataformas Intel. Este registro tiene como valor predeterminado el segmento de pila (no necesita un prefijo especial para acceder al segmento de pila).
El EBP es la mejor opción de registro para acceder a estructuras de datos, variables y espacio de trabajo asignado dinámicamente dentro de la pila. EBP se usa a menudo para acceder a elementos en la pila en relación con un punto fijo en la pila en lugar de en relación con el TOS actual. Por lo general, identifica la dirección base del marco de pila actual establecido para el procedimiento actual. Cuando se utiliza EBP como registro base en un cálculo de compensación, la compensación se calcula automáticamente en el segmento de pila actual (es decir, el segmento seleccionado actualmente por SS). Debido a que SS no tiene que especificarse explícitamente, la codificación de instrucciones en tales casos es más eficiente. EBP también se puede utilizar para indexar en segmentos direccionables a través de otros registros de segmento.
(fuente: http://css.csail.mit.edu/6.858/2017/readings/i386/s02_03.htm )
Dado que en la mayoría de las plataformas de 32 bits, el segmento de datos y el segmento de la pila son iguales, esta asociación de EBP / RBP con la pila ya no es un problema. Lo mismo ocurre con las plataformas de 64 bits: la arquitectura x86-64, introducida por AMD en 2003, ha eliminado en gran medida el soporte para la segmentación en el modo de 64 bits: cuatro de los registros de segmento: CS, SS, DS y ES están forzados a 0 Estas circunstancias de las plataformas x86 de 32 y 64 bits significan esencialmente que el registro EBP / RBP se puede utilizar, sin ningún prefijo, en las instrucciones del procesador que acceden a la memoria.
Entonces, la opción del compilador sobre la que escribiste permite que BP / EBP / RBP se use para otros medios, por ejemplo, para mantener una variable local.
Por "Esto evita las instrucciones para guardar, configurar y restaurar punteros de cuadro" se entiende evitar el siguiente código en la entrada de cada función:
push ebp
mov ebp, esp
o la enter
instrucción, que fue muy útil en los procesadores Intel 80286 y 80386.
Además, antes del retorno de la función, se usa el siguiente código:
mov esp, ebp
pop ebp
o la leave
instrucción.
Las herramientas de depuración pueden escanear los datos de la pila y utilizar estos datos de registro EBP insertados mientras se localizan call sites
, es decir, para mostrar los nombres de la función y los argumentos en el orden en que se han llamado jerárquicamente.
Los programadores pueden tener preguntas sobre los marcos de pila no en un término amplio (que es una entidad única en la pila que sirve solo una llamada de función y mantiene la dirección de retorno, argumentos y variables locales) pero en un sentido estricto - cuando el término stack frames
se menciona en el contexto de las opciones del compilador. Desde la perspectiva del compilador, un marco de pila es solo el código de entrada y salida de la rutina , que empuja un ancla a la pila, que también se puede usar para depurar y manejar excepciones. Las herramientas de depuración pueden escanear los datos de la pila y utilizar estos anclajes para realizar un seguimiento, mientras se ubican call sites
en la pila, es decir, para mostrar los nombres de la función en el orden en que se han llamado jerárquicamente.
Por eso es muy importante que un programador comprenda qué es un marco de pila en términos de opciones del compilador, porque el compilador puede controlar si generar este código o no.
En algunos casos, el compilador puede omitir el marco de la pila (código de entrada y salida para la rutina) y se accederá directamente a las variables a través del puntero de la pila (SP / ESP / RSP) en lugar del puntero base conveniente (BP / ESP / RSP). Las condiciones para que un compilador omita los marcos de pila para algunas funciones pueden ser diferentes, por ejemplo: (1) la función es una función hoja (es decir, una entidad final que no llama a otras funciones); (2) no se utilizan excepciones; (3) no se llaman rutinas con parámetros salientes en la pila; (4) la función no tiene parámetros.
Omitir marcos de pila (código de entrada y salida para la rutina) puede hacer que el código sea más pequeño y más rápido, pero también puede afectar negativamente la capacidad de los depuradores para rastrear los datos en la pila y mostrarlos al programador. Estas son las opciones del compilador que determinan bajo qué condiciones debe satisfacer una función para que el compilador le otorgue el código de entrada y salida del marco de pila. Por ejemplo, un compilador puede tener opciones para agregar dicho código de entrada y salida a las funciones en los siguientes casos: (a) siempre, (b) nunca, (c) cuando sea necesario (especificando las condiciones).
Volviendo de las generalidades a las particularidades: si usa la -fomit-frame-pointer
opción del compilador GCC, puede ganar tanto en el código de entrada como en el de salida de la rutina, y en tener un registro adicional (a menos que ya esté activado de forma predeterminada, ya sea por sí mismo o implícitamente por otros opciones, en este caso, ya se está beneficiando de la ganancia de usar el registro EBP / RBP y no se obtendrá ninguna ganancia adicional especificando explícitamente esta opción si ya está activada implícitamente). Sin embargo, tenga en cuenta que en los modos de 16 y 32 bits, el registro BP no tiene la capacidad de acceder a partes de 8 bits como lo ha hecho AX (AL y AH).
Dado que esta opción, además de permitir que el compilador use EBP como un registro de propósito general en las optimizaciones, también evita la generación de códigos de entrada y salida para el marco de la pila, lo que complica la depuración, es por eso que la documentación de GCC establece explícitamente (inusualmente enfatizado con negrita estilo) que habilitar esta opción hace que la depuración sea imposible en algunas máquinas
También tenga en cuenta que otras opciones del compilador, relacionadas con la depuración u optimización, pueden activar -fomit-frame-pointer
o desactivar implícitamente la opción.
No encontré ninguna información oficial en gcc.gnu.org sobre cómo afectan otras opciones -fomit-frame-pointer
en las plataformas x86 , https://gcc.gnu.org/onlinedocs/gcc-3.4.4/gcc/Optimize-Options.html solo establece lo siguiente:
-O también activa -fomit-frame-pointer en máquinas donde hacerlo no interfiere con la depuración.
Por lo tanto, no está claro de la documentación en sí si -fomit-frame-pointer
se activará si solo compila con una sola -O
opción en la plataforma x86. Puede probarse empíricamente, pero en este caso, los desarrolladores de GCC no se comprometen a no cambiar el comportamiento de esta opción en el futuro sin previo aviso.
Sin embargo, Peter Cordes ha señalado en los comentarios que existe una diferencia en la configuración predeterminada -fomit-frame-pointer
entre las plataformas x86-16 y las plataformas x86-32 / 64.
Esta opción - -fomit-frame-pointer
- también es relevante para Intel C ++ Compiler 15.0 , no solo para GCC:
Para el compilador Intel, esta opción tiene un alias /Oy
.
Esto es lo que Intel escribió al respecto:
Estas opciones determinan si EBP se utiliza como un registro de propósito general en las optimizaciones. Las opciones -fomit-frame-pointer y / Oy permiten este uso. Las opciones -fno-omit-frame-pointer y / Oy- no lo permiten.
Algunos depuradores esperan que EBP se use como un puntero de marco de pila y no pueden producir un seguimiento de pila a menos que sea así. Las opciones -fno-omit-frame-pointer y / Oy- dirigen al compilador a generar código que mantiene y usa EBP como un puntero de marco de pila para todas las funciones, de modo que un depurador aún pueda producir un seguimiento de pila sin hacer lo siguiente:
Para -fno-omit-frame-pointer: desactivación de optimizaciones con -O0 For / Oy-: desactivación de optimizaciones / O1, / O2 u / O3 La opción -fno-omit-frame-pointer se establece cuando especifica la opción - O0 o la opción -g. La opción -fomit-frame-pointer se establece cuando especifica la opción -O1, -O2 u -O3.
La opción / Oy se establece cuando especifica la opción / O1, / O2 o / O3. Option / Oy- se establece cuando especifica la opción / Od.
El uso de la opción -fno-omit-frame-pointer o / Oy- reduce el número de registros de propósito general disponibles en 1 y puede resultar en un código ligeramente menos eficiente.
NOTA Para sistemas Linux *: actualmente existe un problema con el manejo de excepciones de GCC 3.2. Por lo tanto, el compilador Intel ignora esta opción cuando se instala GCC 3.2 para C ++ y el manejo de excepciones está activado (el valor predeterminado).
Tenga en cuenta que la cita anterior solo es relevante para el compilador Intel C ++ 15, no para GCC.