Funktionsaufrufe, enter, leave & Co.
-
Hallo,
neulich habe ich mir Assembler-Ausgabe eines kleinen C-Programms angeschaut, erzeugt mit:gcc -S prog.c -O3
und folgendes ist mir dabei aufgefallen: Bei einigen Funktionen wird der Stack vorbereitet nach dem bekannten Schema
func_a: pushl %ebp movl %esp, %ebp
und aufgeräumt mit
movl %ebp, %esp popl %ebp ret
Bei einigen anderen Funktionen wird allerding aufgeräumt mit:
leave ret
Am Anfang der Funktion wurde aber enter-Befehl nicht aufgerufen, sondern der Stack nach dem bekannten Schema wie oben vorbereitet.
Gibt es einen bestimmten Grund dafür? Oder soll ich mir an dieser Stelle keine Gedanken machen, da die Ausgabe vom gcc-Compiler stammt? Ist vielleicht der leave-Befehl schneller als "movl %ebp, %esp - popl %ebp"-Kombination? Warum wird kein enter-Befehl verwendet?
-
leave macht praktisch nur "mov sp, bp; pop bp;" - macht also keinen Unterscheid.
Eine moeglicher Grund, warum im selben Programm mal leave und mal das Gebroesel verwendet wird, koennten anders compilierte eingebundene Libs sein...
enter braucht praktisch eigentlich kein Schwein - findet auch nur selten Verwendung. Schneller als die Einzelbefehle ist es jedenfalls nicht, und dieses "nesting" scheint's ja auch nicht so zu bringen.
-
und was ist so die gängige Praxis?
Benutzt man ehe "push-mov"- oder "enter-leave"-Kombination oder beides irgendwie gemischt? Oder ist das ehe vom Anwendungsfall abhängig? Ich kann mir vorstellen, man kann sich bei kurzen Funktionen, wenn es geht, auf die Stackvorbereitung verzichten...
-
Die Entwicklung tendiert dahin, dass diese Spezialbefehle eher langsamer sind, als aus eher grundlegenden Befehlen nachgebaute Konstrukte.
Was zu verwenden ist, haengt also hauptsaechlich davon ab, fuer welche CPU du optimieren willst.
Sonst reine Geschmackssache.
Wie gesagt, gibt es zwischen enter/leave oder dem anderen Gebastel praktisch sonst keinen Unterschied - laesst sich also auch problemlos mischen.