web-dev-qa-db-fra.com

Quel est le but du registre de pointeur de trame EBP?

Je suis un débutant en langage assembleur et j'ai remarqué que le code x86 émis par les compilateurs conserve généralement le pointeur de trame même en mode release/optimisé quand il pourrait utiliser le registre EBP pour autre chose.

Je comprends pourquoi le pointeur de trame peut faciliter le débogage du code et peut être nécessaire si alloca() est appelé dans une fonction. Cependant, x86 a très peu de registres et l'utilisation de deux d'entre eux pour conserver l'emplacement du cadre de pile alors qu'un seul suffirait n'a pas de sens pour moi. Pourquoi l'omission du pointeur de cadre est-elle considérée comme une mauvaise idée même dans les versions optimisées/versions?

85
dsimcha

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 le même permettant d'atteindre la même variable au même décalage (tel que le premier paramètre sera toujours à EBP + 8 tandis que ESP offsets peut changer considérablement car vous allez pousser/faire sauter 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 et arguments locaux utilisent la table des symboles car ils sont garantis à un décalage constant par rapport à EBP. Sinon, il n'y a pas de moyen facile de comprendre où se trouve une variable locale à tout moment dans le code.

Comme Greg l'a mentionné, cela aide également à dérouler la pile pour un débogueur, car EBP fournit une liste inversée de cadres de pile, permettant ainsi au débogueur de déterminer la taille du cadre de pile (variables locales + arguments) de la fonction.

La plupart des compilateurs offrent une option pour omettre les pointeurs de trame bien que cela rend 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.

92
Sedat Kapanoglu

J'ajoute simplement mes deux cents à de bonnes réponses.

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 de sous-programme sont stockées. (Les sections locales sont à des décalages négatifs et les arguments sont à des décalages positifs.)

L'idée d'empêcher un registre parfaitement bon d'être utilisé dans l'optimisation soulève la question: quand et où l'optimisation vaut-elle vraiment la peine?

L'optimisation ne vaut que dans les boucles serrées qui 1) n'appellent pas de fonctions, 2) où le compteur de programme passe une fraction importante de son temps, et 3) dans le code que le compilateur verra réellement (c'est-à-dire les fonctions non liées à la bibliothèque). Il s'agit généralement d'une très petite fraction du code global, en particulier dans les grands systèmes.

D'autres codes peuvent être tordus et pressés pour se débarrasser des cycles, et cela n'aura tout simplement pas d'importance, car le compteur de programmes 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.

29
Mike Dunlavey

Cela dépend du compilateur, certainement. J'ai vu du code optimisé émis par des compilateurs x86 qui utilise librement le registre EBP comme registre à usage général. (Je ne me souviens pas avec quel compilateur j'ai remarqué cela, cependant.)

Les compilateurs peuvent également choisir de maintenir le registre EBP pour faciliter le déroulement de la pile pendant la gestion des exceptions, mais là encore, cela dépend de l'implémentation précise du compilateur.

8
Greg Hewgill

Cependant, x86 a très peu de registres

Cela n'est vrai que dans le sens où les opcodes ne peuvent traiter que 8 registres. Le processeur lui-même aura en réalité 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 dépasser la limite de registre: http://en.wikipedia.org/wiki/X86#Current_implementations .

4
MSN

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 à davantage de registres étaient un compromis technique, et les cadres de pile rapides ont gagné.

Combien économisez-vous en allant au registre pur? Est-ce que ça vaut le coup?

1
dwc