Hallo,
ich hab mal drei Fragen zu Calling-Conventions. Jene möchte ich gerade für meine Plattform spezifizieren und bin da auf ein paar Problemchen gestoßen.
1. Wenn eine Funktion sehr viele Parameter, oder eine variable Anzahl an Parametern, hat dann können die ja nicht mehr alle per Register übertragen werden. Dafür gibt es 2 Möglichkeiten, entweder alle überzähligen bzw. variablen Parameter der Reihe nach auf den Stack legen (an Top-of-Stack ähnlich cdecl), wobei dann wieder geklärt werden muss wer den Stack frei gibt (am besten der Aufrufer dann funktionieren auch variable Parameter), oder alle überzähligen Parameter in einen passenden Speicherbereich legen (was normalerweise auch der Stack ist aber eben nicht Top-of-Stack sondern irgendwo im Stack-Frame des Callers) und die Adresse dieses Bereichs als unsichtbares Parameter im Register übergeben (also wie FastCall). Die zweite Variante hat den Nachteil das ein zusätzliches Parameter ein Register belegt und man zum Zugriff auf die zusätzlichen Parameter immer auch eine zusätzliche Info (eben diesen Pointer) benötigt was sicher oft zu einem zusätzlichen Befehl führt und manchmal, falls dieser Pointer mal aus den Registern verdrängt werden muss, sogar ein zusätzlicher Speicherzugriff ist. Ich möchte mich lieber für die erste Variante entscheiden bin mir aber nicht sicher ob ich was übersehen hab. Die FastCall-Variante wird z.B. vom Linux-Kernel (intern und beim SYSCALL) verwendet und ich gehe mal davon aus das die sich dabei was gedacht haben. Gerade auf x86 mit den wenigen Registern muss man sich schon ordentlich Mühe geben damit die Parameterübergabe nicht zum kostspieligen Fiasko wird. Auf meiner Plattform hab ich zwar deutlich mehr Register, so das dieser Schuh nicht so sehr drückt. Welche von beiden Varianten haltet Ihr für besser? Gibt es noch andere Möglichkeiten? Ich möchte dieses Problem schon ordentlich lösen und auch nur eine Calling-Convention haben die alle Anwendungsfälle mit möglichst maximaler Performance abdeckt.
2. Wie sieht das mit dem this-Pointer bei Klassen-Methoden aus? Dazu hab ich kaum Infos gefunden (außer den thiscall von MS und den will ich nicht kopieren). Ich würde diesen unsichtbaren Parameter gerne als erstes im Registerbereich ablegen und den auch bei der Rückkehr dort lassen so das dieses Register gar nicht verändert werden muss wenn Methoden einer Klasse sich gegenseitig aufrufen (was ja nicht unbedingt selten ist), also ein Register exklusiv für diese Verwendung reserviert wird (bei insgesamt 64 Registern tut das nicht weh).
3. Was haltet ihr eigentlich davon kleine Strukturen (bis 32 oder 64 Byte) direkt in den Registern zu übergeben oder würdet ihr einen Pointer bevorzugen?
Ich hoffe ihr habt ein paar Anregungen für mich. Danke schon mal im Voraus.
Grüße
Erik