Parameterübergabe
Die ersten vier ganzzahligen Argumente werden in Registern übergeben. Ganzzahlige Werte werden (in Reihenfolge von links nach rechts) in RCX, RDX, R8 und R9 übergeben. Das vierte und alle weiteren Argumente werden an den Stapel übergeben. Alle Argumente sind in den Registern rechts ausgerichtet. Dies geschieht, damit der Aufgerufene die oberen Bits des Registers gegebenenfalls ignorieren und nur auf den erforderlichen Teil des Registers zugreifen kann.
Gleitkomma-Argumente und Argumente mit doppelter Genauigkeit werden in XMM0 bis XMM3 (bis 4) mit dem Ganzzahlslot (RCX, RDX, R8 und R9) übergeben, der normalerweise für den ignorierten Hauptslot verwendet würde (siehe Beispiel) und umgekehrt.
__m128-Typen, Arrays und Zeichenfolgen werden nie als unmittelbarer Wert übergeben, sondern es wird ein Zeiger an den vom Aufrufer belegten Speicher übergeben. Strukturen oder Unions mit 8, 16, 32 oder 64 Bits und __m64 werden wie ganze Zahlen derselben Größe übergeben. Strukturen oder Unions mit anderen als diesen Größen werden als Zeiger auf den vom Aufrufer belegten Arbeitsspeicher übergeben. Der vom Aufrufer belegte temporäre Speicher für diese als Zeiger übergebenen Aggregattypen (einschließlich __m128) ist auf 16 Byte ausgerichtet.
Systeminterne Funktionen, die keinen Stapelspeicher zuweisen und keine anderen Funktionen aufrufen, können andere flüchtige Register für die Übergabe zusätzlicher Registerargumente verwenden, da eine enge Bindung zwischen dem Compiler und der Implementierung der systeminternen Funktion besteht. Hier bietet sich eine weitere Gelegenheit zur Verbesserung der Leistung.
Der Aufgerufene hat die Aufgabe, die Registerparameter bei Bedarf in ihrem Shadow-Speicher zu sichern.
In der folgenden Tabelle ist zusammengefasst, wie Parameter übergeben werden:
Parametertyp |
Übergabe |
---|---|
Gleitkomma |
Erste 4 Parameter: XMM0 bis XMM3. Weitere Parameter werden an den Stapel übergeben. |
Integer |
Erste 4 Parameter: RCX, RDX, R8, R9. Weitere Parameter werden an den Stapel übergeben. |
Aggregate (8, 16, 32 oder 64 Bits) und __m64 |
Erste 4 Parameter: RCX, RDX, R8, R9. Weitere Parameter werden an den Stapel übergeben. |
Aggregate (sonstige) |
Durch Zeiger. Die ersten 4 Parameter werden als Zeiger in RCX, RDX, R8 und R9 übergeben. |
__m128 |
Durch Zeiger. Die ersten 4 Parameter werden als Zeiger in RCX, RDX, R8 und R9 übergeben. |
Beispiel 1 für die Argumentübergabe: nur ganze Zahlen
func1(int a, int b, int c, int d, int e);
// a in RCX, b in RDX, c in R8, d in R9, e pushed on stack
Beispiel 2 für die Argumentübergabe: nur Gleitkommazahlen
func2(float a, double b, float c, double d, float e);
// a in XMM0, b in XMM1, c in XMM2, d in XMM3, e pushed on stack
Beispiel 3 für die Argumentübergabe: Gemischte Ganz- und Gleitkommazahlen
func3(int a, double b, int c, float d);
// a in RCX, b in XMM1, c in R8, d in XMM3
Beispiel 4 für die Argumentübergabe: __m64, __m128 und Aggregate
func4(__m64 a, _m128 b, struct c, float d);
// a in RCX, ptr to b in RDX, ptr to c in R8, d in XMM3