Freigeben über


Verwenden und Beibehalten von Registern in der Inlineassembly

Microsoft-spezifisch

Im Allgemeinen sollten Sie nicht davon ausgehen, dass ein Register über einen angegebenen Wert verfügt, wenn ein __asm-Block beginnt. Registerwerte werden möglicherweise nicht über separate __asm Blöcke beibehalten. Wenn Sie einen Block Inlinecode beenden und einen anderen beginnen, können Sie nicht auf die Register im zweiten Block verlassen, um ihre Werte aus dem ersten Block zu behalten. Ein __asm-Block erbt jegliche Registerwerte, die aus dem normalen Programmablauf resultieren.

Wenn Sie die __fastcall-Aufrufkonvention verwenden, übergibt der Compiler Funktionsargumente an Register statt an Stapel. Dies kann Probleme mit Funktionen mit __asm-Blöcken ergeben, da für eine Funktion keine Möglichkeit da ist, zu übermitteln, welcher Parameter ist in welchem Register. Wenn die Funktion in EAX einen Parameter empfängt und sofort etwas anderes in EAX speichert, ist der erste Parameter verloren. Außerdem müssen Sie das ECX-Register in jeder Funktion beibehalten, die mit __fastcall deklariert ist.

Um solche Registerkonflikte zu vermeiden, sollten Sie nicht die __fastcall-Konvention für Funktionen mit einem __asm-Block verwenden. Wenn Sie die Konvention __fastcall global mit der Compileroption /Gr- angeben, deklarieren Sie alle Funktionen, die einen __asm-Block mit __cdecl oder __stdcall enthält. (Das __cdecl-Attribut weist den Compiler an, die C-Aufrufkonvention für diese Funktion zu verwenden.) Wenn Sie nicht mit /Gr kompilieren, dürfen Sie die Funktion nicht mit dem __fastcall-Attribut deklarieren.

Beim Schreiben von Assemblersprache in C/C++-Funktionen mit __asm müssen die Register EAX, EBX, ECX, EDX, ESI und EDI nicht beibehalten werden. Beispielsweise behält im POWER2.C-Beispiel in Schreiben-Funktionen mit Inlineassembly, die power2-Funktion den Wert nicht im EAX-Register bei. Die Verwendung dieser Register wird sich jedoch auf die Qualität des Codes auswirken, weil der Registerzuordner sie nicht verwenden kann, um Werte über __asm-Blöcke zu speichern. Darüber hinaus zwingen Sie den Compiler, diese Register im Funktionsprolog und -epilog zu speichern und wiederherstellen, indem Sie EBX, oder ESI EDI im Inlineassemblycode verwenden.

Sie sollten andere verwendete Register (z.B. DS, SS, SP, BP und Flag-Register) für den Bereich des __asm-Blocks beibehalten. Sie sollten die ESP- und EBP-Register beibehalten, es sei denn, Sie haben einigen Grund, sie zu ändern (Stapel wechseln, z. B). Siehe auch Optimieren der Inlineassembly.

Einige SSE-Typen erfordern die 8-Byte-Stapelausrichtung, die den Compiler zwingt, dynamischen Stapelausrichtungscode auszugeben. Um nach der Ausrichtung sowohl auf die lokalen Variablen als auch auf die Funktionsparameter zugreifen zu können, verwaltet der Compiler zwei Framezeiger. Wenn der Compiler Framezeigerauslassung (FPO) ausführt, verwendet er EBP und ESP. Wenn der Compiler nicht FPO ausführt, verwendet er EBX und EBP. Um die ordnungsgemäße Ausführung des Codes zu gewährleisten, ändern Sie EBX nicht in ASM-Code wenn die Funktion dynamische Stapelausrichtung benötigt, da dies Änderungen am Framezeiger zur Folge haben könnte. Entweder verschieben Sie die auf Acht Byte ausgerichteten Typen aus der Funktion oder vermeiden die Verwendung von EBX.

Hinweis

Wenn Ihr Inlineassemblycode das Richtungsflag mithilfe der STD- oder CLD-Anweisungen ändert, müssen Sie das Flag auf den ursprünglichen Wert zurücksetzen.

END Microsoft-spezifisch

Siehe auch

Referenz

Inlineassembler