__fastcall
-
__fastcall
Was bedeutet das genau?
-
Steht doch in der Hilfe! Registerdingsbums für anderes Dingsda!
-
Hm, ist vielleicht ein wenig mager erklärt.
Ich versuchs mal.
Siehe Bild:
http://www.directupload.net/show_image.php?d=138&n=579FcDz7.jpgFangen wir ein wenig mit Theorie an. Es gibt ein paar verschiedene Art und Weisen, in denen Funktionen aufgerufen werden können. Diese möchte ich nun kurz anschneiden:
1. C-Call (cdecl-Call)
Das ist die gängigste Methode eine Funktion aufzurufen. Die Methode f() wird mit dieser Aufrufsmethode aufgerufen. Dabei werden die Parameter in umgekehrter reihenfolge auf dem Stack gepackt:
push ox03 push ox02 push ox01
nun erfolgt der Methodenaufruf mit
call f(int, int, int)
In der Methdoe F() müssen nun die Parameter ausgelesen werden.
Dafür wird meist erst einmal eine Variable geschaffen (den Basepointer), den wir auf den ersten Eintrag auf dem Stack zeigt. Dafür nimmt man esppush EBP mov ebp,esp
Da die Parameter nun auf dem Stack liegen, kann man anhand des Basepointers, die relative Adresse absehen und den Parameter verwenden. Dieser fängt in der Regel bei 0X08 an.
Hier werden also die Parameter ausgelesen. In der Funktion werden die Parameter wiederum auf dem Stack gelegt, weil wir ja die Methode hier wieder aufrufen (rekursiv):
Push dword ptr [ebp+0x10] Push dword ptr [ebp+0x0c] Push dword ptr [ebp+0x08]
Wie man sieht wieder in umgekehrter Reihenfolge.
Nach dem Aufruf wird unser Basiszeiger noch eben vom Stack geholt und zur Main() zurückgesprungen. Dort muss noch der Stackpointer für den vorherigen Aufruf wieder zurückgesetzt werden.Das geschiet mit
add esp, 0x0c
Das ist ein vollständiger C-Call- Funktionsablauf.
2. Standard-Call-Aufruf
Dieses kennen wir von stdcall aus der WINAPI. Der unterschied zum cdecl-Call ist, dass die Funktion selbst den Stackpointer zurücksetzen muss.
Das kann man in der funktion W() sehen:ret 0x000c
hier wird beim Rücksprung der Stackpointer zurückgesetzt.
Wie man an der Main-Methode sieht, wird kein add, „esp,0x0c“ aufgerufen.
Hat den Vorteil, dass die aufrufende Methode aufgeräumter ist.3. Fastcall-Aufruf
Hierbei werden die Parameter der Methode nicht auf dem Stack geschoben, sondern direkt in Register geschrieben, die lesend von der Methode verwendet werden können.
Hier werden die Register ecx, edx, eax geschrieben:
Mov ecx,0x000000003 Mov edx,0x000000003 Mov eax,0x000000003
Nun erfolgt der Methodenaufruf und in der Methode kann die Methode die Parameter einfach über die Register lesen.
Mov[ebp-0xoc],ecx Mov[ebp-0x08],edx Mov[ebp-0x04],eax
Nun ist aber das Problem, das der Compiler von Borland da irgendwie Mist baut.
Um die Methode m() (rekursiv) in der Methode m() aufzurufen schiebt er die Parameter wieder in die Register. Das ist normalerweise Quatsch. Aber egal, kann ja daran liegen, dass die Methode selbst auch Schwachsinn ist. Aber es zeigt die Unterschiede. Und nur das zählt.__fastcall ist also (theoretisch) schneller, weil direkt auf die Register geschrieben wird und nicht die Parameter auf dem Stak gepush werden müssen.