Il s'agit du registre BP/EBP/RBP sur les plateformes Intel. Ce registre est par défaut dans le segment de pile (il n'a pas besoin d'un préfixe spécial pour accéder au segment de pile).
L'EBP est le meilleur choix de registre pour accéder aux structures de données, aux variables et à l'espace de travail alloué dynamiquement dans la pile. L'EBP est souvent utilisé pour accéder à des éléments de la pile par rapport à un point fixe de la pile plutôt que par rapport au TOS actuel. Il identifie généralement l'adresse de base du cadre de pile actuel établi pour la procédure en cours. Lorsque EBP est utilisé comme registre de base dans un calcul de décalage, le décalage est calculé automatiquement dans le segment de pile actuel (c'est-à-dire le segment actuellement sélectionné par SS). Comme il n'est pas nécessaire de spécifier explicitement SS, le codage des instructions est plus efficace dans ce cas. EBP peut également être utilisé pour indexer dans des segments adressables par d'autres registres de segment.
( source - http://css.csail.mit.edu/6.858/2017/readings/i386/s02_03.htm )
Comme sur la plupart des plates-formes 32 bits, le segment de données et le segment de pile sont identiques, cette association de EBP/RBP avec la pile n'est plus un problème. Il en va de même sur les plates-formes 64 bits : L'architecture x86-64, introduite par AMD en 2003, a largement abandonné le support de la segmentation en mode 64 bits : quatre des registres de segment : CS, SS, DS et ES sont forcés à 0. Ces circonstances des plateformes x86 32 bits et 64 bits signifient essentiellement que le registre EBP/RBP peut être utilisé, sans aucun préfixe, dans les instructions du processeur qui accèdent à la mémoire.
L'option du compilateur dont vous parlez permet donc d'utiliser le BP/EBP/RBP à d'autres fins, par exemple pour contenir une variable locale.
Par "Cela permet d'éviter les instructions de sauvegarde, de mise en place et de restauration des frame pointers", on entend éviter le code suivant à l'entrée de chaque fonction :
push ebp
mov ebp, esp
ou le enter
qui était très utile sur les processeurs Intel 80286 et 80386.
De même, avant le retour de la fonction, le code suivant est utilisé :
mov esp, ebp
pop ebp
ou le leave
l'instruction.
Les outils de débogage peuvent analyser les données de la pile et utiliser ces données de registre EBP poussé pour localiser call sites
c'est-à-dire d'afficher les noms de la fonction et des arguments dans l'ordre où ils ont été appelés hiérarchiquement.
Les programmeurs peuvent avoir des questions sur les cadres de pile non pas au sens large (qu'il s'agit d'une entité unique dans la pile qui sert à un seul appel de fonction et conserve l'adresse de retour, les arguments et les variables locales) mais au sens étroit - quand le terme stack frames
est mentionné dans le contexte des options du compilateur. Du point de vue du compilateur, une trame de pile est juste le code d'entrée et de sortie de la routine Les outils de débogage peuvent analyser les données de la pile et utiliser ces points d'ancrage pour le retour en arrière, tout en localisant les points d'ancrage. Les outils de débogage peuvent scanner les données de la pile et utiliser ces ancres pour le retour en arrière, tout en localisant call sites
dans la pile, c'est-à-dire pour afficher les noms des fonctions dans le même ordre qu'elles ont été appelées hiérarchiquement.
C'est pourquoi il est vital pour un programmeur de comprendre ce qu'est un stack frame en termes d'options du compilateur - car le compilateur peut contrôler s'il faut générer ce code ou non.
Dans certains cas, le cadre de pile (code d'entrée et de sortie de la routine) peut être omis par le compilateur, et les variables seront directement accessibles via le pointeur de pile (SP/ESP/RSP) plutôt que le pointeur de base pratique (BP/ESP/RSP). Les conditions pour qu'un compilateur omette les cadres de pile pour certaines fonctions peuvent être différentes, par exemple : (1) la fonction est une fonction feuille (c'est-à-dire une entité finale qui n'appelle pas d'autres fonctions) ; (2) aucune exception n'est utilisée ; (3) aucune routine n'est appelée avec des paramètres sortants sur la pile ; (4) la fonction n'a pas de paramètres.
L'omission des stack frames (code d'entrée et de sortie de la routine) peut rendre le code plus petit et plus rapide. Cependant, elles peuvent également affecter négativement la capacité des débogueurs à retracer les données de la pile et à les afficher au programmeur. Ce sont les options du compilateur qui déterminent sous quelles conditions une fonction doit satisfaire pour que le compilateur lui attribue le code d'entrée et de sortie du cadre de pile. Par exemple, un compilateur peut disposer d'options permettant d'ajouter ces codes d'entrée et de sortie aux fonctions dans les cas suivants : (a) toujours, (b) jamais, (c) lorsque cela est nécessaire (en précisant les conditions).
Revenir des généralités aux particularités : si vous utilisez l'option -fomit-frame-pointer
Option du compilateur GCC, vous pouvez gagner sur le code d'entrée et de sortie de la routine, et sur le fait d'avoir un registre supplémentaire (à moins qu'il ne soit déjà activé par défaut soit lui-même soit implicitement par d'autres options, dans ce cas, vous bénéficiez déjà du gain de l'utilisation du registre EBP/RBP et aucun gain supplémentaire ne sera obtenu en spécifiant explicitement cette option si elle est déjà activée implicitement). Notez cependant que dans les modes 16 bits et 32 bits, le registre BP n'a pas la possibilité de donner accès à ses parties 8 bits comme le fait AX (AL et AH).
Cette option, en plus de permettre au compilateur d'utiliser EBP comme un registre à usage général dans les optimisations, empêche également de générer du code de sortie et d'entrée pour le cadre de pile, ce qui complique le débogage - c'est pourquoi l'option Documentation GCC indique explicitement (en soulignant inhabituellement avec un style gras) que l'activation de cette option rend le débogage impossible sur certaines machines .
Sachez également que d'autres options du compilateur, liées au débogage ou à l'optimisation, peuvent implicitement désactiver l'option -fomit-frame-pointer
l'option ON ou OFF.
Je n'ai pas trouvé d'information officielle à gcc.gnu.org sur la façon dont les autres options affectent le système. -fomit-frame-pointer
sur les plates-formes x86 , le site https://gcc.gnu.org/onlinedocs/gcc-3.4.4/gcc/Optimize-Options.html ne stipule que ce qui suit :
-O active également -fomit-frame-pointer sur les machines où cela n'interfère pas avec le débogage.
Il n'est donc pas clair de la documentation en tant que telle si -fomit-frame-pointer
sera activé si vous compilez avec une seule option `-O' sur une plateforme x86. Cela peut être testé empiriquement, mais dans ce cas il n'y a aucun engagement de la part des développeurs de GCC de ne pas changer le comportement de cette option dans le futur sans préavis.
Cependant, Peter Cordes a fait remarquer dans les commentaires qu'il y a une différence pour les paramètres par défaut de la -fomit-frame-pointer
entre les plateformes x86-16 et les plateformes x86-32/64.
Cette option - -fomit-frame-pointer
- est également concernant le compilateur Intel C++ 15.0 et pas seulement au CCG :
Pour le compilateur Intel, cette option a un alias /Oy
.
Voici ce qu'Intel a écrit à ce sujet :
Ces options déterminent si EBP est utilisé comme un registre à usage général dans les optimisations. Les options -fomit-frame-pointer et /Oy permettent cette utilisation. Les options -fno-omit-frame-pointer et /Oy- l'interdisent.
Certains débogueurs s'attendent à ce que EBP soit utilisé comme un pointeur de cadre de pile, et ne peuvent produire un backtrace de la pile que si c'est le cas. Les options -fno-omit-frame-pointer et /Oy- demandent au compilateur de générer du code qui maintient et utilise EBP comme un pointeur de cadre de pile pour toutes les fonctions, de sorte qu'un débogueur puisse toujours produire un retour arrière de la pile sans faire ce qui suit :
Pour -fno-omit-frame-pointer : désactiver les optimisations avec -O0 Pour /Oy- : désactiver les optimisations avec /O1, /O2, ou /O3 L'option -fno-omit-frame-pointer est définie lorsque vous spécifiez l'option -O0 ou l'option -g. L'option -fomit-frame-pointer est définie lorsque vous spécifiez l'option -O1, -O2, ou -O3.
L'option /Oy est définie lorsque vous spécifiez l'option /O1, /O2 ou /O3. L'option /Oy- est définie lorsque vous spécifiez l'option /Od.
L'utilisation de l'option -fno-omit-frame-pointer ou /Oy- réduit le nombre de registres polyvalents disponibles de 1 et peut entraîner un code légèrement moins efficace.
NOTE Pour les systèmes Linux* : Il y a actuellement un problème avec la gestion des exceptions de GCC 3.2. Par conséquent, le compilateur Intel ignore cette option lorsque GCC 3.2 est installé pour C++ et que la gestion des exceptions est activée (par défaut).
Veuillez noter que la citation ci-dessus ne s'applique qu'au compilateur Intel C++ 15, et non à GCC.