Je suis un débutant en langage d'assemblage et j'ai remarqué que le code x86 émis par les compilateurs garde généralement le pointeur de cadre, même en mode version / optimisé, lorsqu'il pourrait utiliser le EBP
registre pour autre chose.
Je comprends pourquoi le pointeur de trame peut faciliter le débogage du code et peut être nécessaire s'il alloca()
est appelé dans une fonction. Cependant, x86 a très peu de registres et l'utilisation de deux d'entre eux pour contenir l'emplacement du cadre de la pile alors qu'il en suffirait un n'a tout simplement pas de sens pour moi. Pourquoi l'omission du pointeur d'image est-elle considérée comme une mauvaise idée, même dans les versions optimisées / de version?
performance
assembly
x86
dsimcha
la source
la source
alloca
) 3. facilité de mise en œuvre à l'exécution: gestion des exceptions, bac à sable, GCRéponses:
Le pointeur de trame est un pointeur de référence permettant à un débogueur de savoir où se trouve une variable locale ou un argument avec un seul décalage constant. Bien que la valeur d'ESP change au cours de l'exécution, EBP reste la même, ce qui permet d'atteindre la même variable au même décalage (par exemple, le premier paramètre sera toujours à EBP + 8 tandis que les décalages ESP peuvent changer de manière significative puisque vous pousserez / faire éclater des choses)
Pourquoi les compilateurs ne jettent-ils pas le pointeur de cadre? Parce qu'avec le pointeur de trame, le débogueur peut déterminer où les variables locales et les arguments utilisent la table de symboles car ils sont garantis à un décalage constant par rapport à EBP. Sinon, il n'y a pas de moyen facile de déterminer où se trouve une variable locale à un moment quelconque du code.
Comme Greg l'a mentionné, cela facilite également le déroulement de la pile pour un débogueur car EBP fournit une liste liée inversée de cadres de pile permettant ainsi au débogueur de déterminer la taille de la trame de pile (variables locales + arguments) de la fonction.
La plupart des compilateurs offrent une option pour omettre les pointeurs de trame bien que cela rende le débogage vraiment difficile. Cette option ne doit jamais être utilisée globalement, même dans le code de version. Vous ne savez pas quand vous devrez déboguer le plantage d'un utilisateur.
la source
-fomit-frame-pointer
. Ce paramètre est le paramètre par défaut dans gcc récent..eh_frame_hdr
section est également utilisée pour les exceptions d'exécution. Vous le trouverez (avecobjdump -h
) dans la plupart des binaires sur un système Linux, c'est environ 16k pour/bin/bash
, contre 572B pour GNU/bin/true
, 108k pourffmpeg
. Il existe une option gcc pour désactiver sa génération, mais c'est une section de données "normale", pas une section de débogage quistrip
supprime par défaut. Sinon, vous ne pouvez pas revenir en arrière via une fonction de bibliothèque qui n'a pas de symboles de débogage. Cette section peut être plus grande que lespush/mov/pop
instructions qu'elle remplace, mais son coût d'exécution est presque nul (par exemple, le cache uop).Juste ajouter mes deux cents à des réponses déjà bonnes.
Cela fait partie d'une bonne architecture de langage d'avoir une chaîne de cadres de pile. Le BP pointe vers la trame actuelle, où les variables locales du sous-programme sont stockées. (Les sections locales sont à des décalages négatifs et les arguments à des décalages positifs.)
L'idée que cela empêche l'utilisation d'un registre parfaitement bon dans l'optimisation pose la question: quand et où l'optimisation vaut-elle réellement la peine?
L'optimisation n'est valable que dans les boucles serrées qui 1) n'appellent pas de fonctions, 2) où le compteur de programme passe une fraction significative de son temps, et 3) dans le code que le compilateur verra réellement (c'est-à-dire les fonctions non-bibliothèque). Il s'agit généralement d'une très petite fraction du code global, en particulier dans les grands systèmes.
Un autre code peut être tordu et pressé pour se débarrasser des cycles, et cela n'a tout simplement pas d'importance, car le compteur de programme n'est pratiquement jamais là.
Je sais que vous ne l'avez pas demandé, mais d'après mon expérience, 99% des problèmes de performances n'ont rien à voir avec l'optimisation du compilateur. Ils ont tout à voir avec la sur-conception.
la source
Cela dépend du compilateur, certainement. J'ai vu du code optimisé émis par des compilateurs x86 qui utilisent librement le registre EBP comme registre à usage général. (Je ne me souviens pas avec quel compilateur j'ai remarqué cela.)
Les compilateurs peuvent également choisir de maintenir le registre EBP pour aider au déroulement de la pile pendant la gestion des exceptions, mais là encore, cela dépend de l'implémentation précise du compilateur.
la source
-fomit-frame-pointer
lorsque l'optimisation est activée. (lorsque l'ABI le permet). GCC, clang, ICC et MSVC le font tous, IIRC, même en ciblant Windows 32 bits. Oui, ma réponse sur Pourquoi est-il préférable d'utiliser ebp que le registre esp pour localiser les paramètres sur la pile? montre que même Windows 32 bits peut omettre le pointeur de cadre. Linux x86 32 bits le peut et le fait. Et bien sûr, les ABI 64 bits ont permis l'omission du pointeur de trame dès le début.Ceci n'est vrai que dans le sens où les opcodes ne peuvent adresser que 8 registres. Le processeur lui-même aura en fait beaucoup plus de registres que cela et utilisera le renommage de registre, le pipelining, l'exécution spéculative et d'autres mots à la mode du processeur pour contourner cette limite. Wikipedia a un bon paragraphe d'introduction sur ce qu'un processeur x86 peut faire pour surmonter la limite de registre: http://en.wikipedia.org/wiki/X86#Current_implementations .
la source
L'utilisation de cadres de pile est devenue incroyablement bon marché dans n'importe quel matériel, même à distance moderne. Si vous avez des cadres de pile bon marché, la sauvegarde de quelques registres n'est pas aussi importante. Je suis sûr que les cadres de pile rapides par rapport à plus de registres étaient un compromis d'ingénierie, et les cadres de pile rapides ont gagné.
Combien économisez-vous sur le registre pur? Est-ce que ça vaut le coup?
la source