webentwicklung-frage-antwort-db.com.de

Was ist der Zweck des EBP-Rahmenzeigerregisters?

Ich bin ein Anfänger in der Assemblersprache und habe bemerkt, dass der von Compilern ausgegebene x86-Code den Frame-Zeiger normalerweise auch im freigegebenen/optimierten Modus herumhält, wenn er das EBP -Register für etwas anderes verwenden könnte.

Ich verstehe, warum der Frame-Zeiger das Debuggen von Code erleichtern und erforderlich sein kann, wenn alloca() innerhalb einer Funktion aufgerufen wird. X86 hat jedoch nur sehr wenige Register, und zwei davon zu verwenden, um die Position des Stapelrahmens zu halten, wenn eine ausreichen würde, ergibt für mich einfach keinen Sinn. Warum wird das Weglassen des Frame-Zeigers selbst in optimierten/Release-Builds als schlechte Idee angesehen?

85
dsimcha

Der Frame-Zeiger ist ein Referenzzeiger, mit dem ein Debugger mit einem einzigen konstanten Offset erkennen kann, wo sich die lokale Variable oder ein Argument befindet. Obwohl sich der Wert von ESP im Laufe der Ausführung ändert, bleibt EBP derselbe, wodurch es möglich ist, die gleiche Variable mit dem gleichen Versatz zu erreichen (der erste Parameter liegt immer bei EBP + 8, während ESP Versätze) kann sich erheblich ändern, da du Dinge drückst/knallst)

Warum werfen Compiler den Frame-Zeiger nicht weg? Denn mit dem Frame-Zeiger kann der Debugger herausfinden, wo lokale Variablen und Argumente die Symboltabelle verwenden, da sie garantiert einen konstanten Versatz zu EBP aufweisen. Ansonsten gibt es keine einfache Möglichkeit, herauszufinden, wo sich eine lokale Variable an einer beliebigen Stelle im Code befindet.

Wie Greg erwähnte, hilft es auch beim Abwickeln des Stacks für einen Debugger, da EBP eine umgekehrt verknüpfte Liste von Stack-Frames bereitstellt, sodass der Debugger die Größe des Stack-Frames (lokale Variablen + Argumente) der Funktion ermitteln kann.

Die meisten Compiler bieten die Option, Frame-Zeiger wegzulassen, obwohl das Debuggen dadurch sehr schwierig wird. Diese Option sollte niemals global verwendet werden, auch nicht im Release-Code. Sie wissen nicht, wann Sie den Absturz eines Benutzers beheben müssen.

92
Sedat Kapanoglu

Fügen Sie einfach meine zwei Cent zu den bereits guten Antworten hinzu.

Es ist Teil einer guten Spracharchitektur, eine Kette von Stapelrahmen zu haben. Der BP zeigt auf den aktuellen Frame, in dem unterprogrammlokale Variablen gespeichert sind. (Einheimische sind in negativen Offsets und Argumente in positiven Offsets.)

Die Idee, dass es verhindert, dass ein perfektes Register für die Optimierung verwendet wird, wirft die Frage auf: Wann und wo lohnt sich die Optimierung tatsächlich?

Die Optimierung lohnt sich nur in engen Schleifen, in denen 1) keine Funktionen aufgerufen werden, 2) der Programmzähler einen erheblichen Teil seiner Zeit in Anspruch nimmt und 3) der Compiler tatsächlich jemals Code sieht (d. H. Funktionen, die keine Bibliotheken sind). Dies ist normalerweise ein sehr kleiner Teil des Gesamtcodes, insbesondere in großen Systemen.

Anderer Code kann verdreht und gequetscht werden, um Zyklen loszuwerden, und es spielt einfach keine Rolle, da der Programmzähler praktisch nie da ist.

Ich weiß, dass Sie dies nicht gefragt haben, aber meiner Erfahrung nach haben 99% der Leistungsprobleme überhaupt nichts mit der Compileroptimierung zu tun. Sie haben alles mit Überdesign zu tun.

29
Mike Dunlavey

Das hängt natürlich vom Compiler ab. Ich habe optimierten Code von x86-Compilern gesehen, der das EBP-Register frei als Universalregister verwendet. (Ich erinnere mich aber nicht, bei welchem ​​Compiler ich das bemerkt habe.)

Compiler können sich auch dafür entscheiden, das EBP-Register beizubehalten, um das Abwickeln des Stacks während der Ausnahmebehandlung zu unterstützen. Dies hängt jedoch wiederum von der genauen Implementierung des Compilers ab.

8
Greg Hewgill

X86 hat jedoch nur sehr wenige Register

Dies gilt nur in dem Sinne, dass Opcodes nur 8 Register adressieren können. Der Prozessor selbst wird tatsächlich viel mehr Register als das haben und Registerumbenennung, Pipelining, spekulative Ausführung und andere Modewörter des Prozessors verwenden, um diese Grenze zu umgehen. Wikipedia hat einen guten einleitenden Absatz, was ein x86-Prozessor tun kann, um das Registerlimit zu überwinden: http://en.wikipedia.org/wiki/X86#Current_implementations .

4
MSN

Die Verwendung von Stack-Frames ist in jeder Hardware unglaublich billig geworden, auch wenn diese aus der Ferne modern ist. Wenn Sie billige Stapelrahmen haben, ist das Speichern einiger Register nicht so wichtig. Ich bin sicher, dass schnelle Stapelrahmen gegen mehr Register ein technischer Kompromiss waren und schnelle Stapelrahmen gewonnen haben.

Wie viel sparen Sie, wenn Sie sich registrieren? Lohnt es sich?

1
dwc