Ich versuche, GCC Inline-Asm für CMPXCHG8B für ia32 zu schreiben. Nein, ich kann __sync_bool_compare_and_swap
nicht verwenden. Es muss mit und ohne -fPIC funktionieren.
Bisher ist das Beste, was ich habe ( BEARBEITEN : funktioniert nicht, siehe meine eigene Antwort unten für Details)
%Vor%Ich bin mir jedoch nicht sicher, ob das tatsächlich stimmt.
Ich kann nicht "b" ((int32)(set & 0xFFFFFFFF))
für ebx_val wegen PIC tun, aber anscheinend register asm("ebx")
Variable wird vom Compiler akzeptiert.
BONUS : Die ret-Variable wird für die Verzweigung verwendet, daher sieht der Code wie folgt aus:
%Vor%Irgendeine Idee, wie man Ausgangsoperanden beschreibt, so dass es wird:
%Vor%?
Danke.
Wie wäre es mit dem Folgenden, das in einem kleinen Test für mich zu funktionieren scheint:
%Vor%Wenn dies auch falsch kompiliert wird, können Sie bitte ein kleines Snippet einfügen, das dieses Verhalten auslöst?
In Bezug auf die Bonusfrage glaube ich nicht, dass es möglich ist, nach dem Assembler-Block mit dem Bedingungscode aus der Anweisung cmpxchg8b
zu verzweigen (es sei denn, Sie verwenden die asm goto
oder ähnliche Funktionalität). Von GNU C-Spracherweiterungen :
Es ist eine natürliche Idee, nach einer Möglichkeit zu suchen, um auf den von der Assembler-Anweisung hinterlassenen Zustandscode zuzugreifen. Als wir jedoch versuchten, dies zu implementieren, fanden wir keine Möglichkeit, es zuverlässig funktionieren zu lassen. Das Problem besteht darin, dass Ausgabeoperanden möglicherweise neu geladen werden müssen, was zu zusätzlichen "Store" -Instruktionen führen würde. Bei den meisten Maschinen würden diese Anweisungen den Zustandscode ändern, bevor Zeit zum Testen war. Dieses Problem tritt für gewöhnliche "Test" - und "Vergleichs" -Befehle nicht auf, weil sie keine Ausgangsoperanden haben.
BEARBEITEN: Ich kann keine Quelle finden, die auf die eine oder andere Weise angibt, ob es in Ordnung ist, den Stapel zu ändern, während auch die Eingabewerte %N
( Dieser uralte Link sagt:" Du kannst deine Register sogar auf den Stapel schieben, sie benutzen und zurückstellen. ", aber das Beispiel hat keine Eingabe.) .
Aber es sollte möglich sein, darauf zu verzichten, indem man die Werte in anderen Registern festlegt:
%Vor%Das habe ich:
%Vor% Es verwendet das Feature asm goto
, neu mit gcc 4.5, das Sprünge von der Inline-Assemblierung in C-Beschriftungen ermöglicht. (Oh, ich sehe Ihren Kommentar über die Unterstützung von alten Versionen von gcc. Na ja. Ich habe versucht. :-P)
Erstaunlicherweise wird das Codefragment in der Frage unter bestimmten Umständen immer noch falsch kompiliert: Wenn der nullte asm-Operand indirekt über EBX (PIC) adressierbar ist, bevor das EBX-Register mit register asm
eingerichtet wird, dann geht gcc weiter zu Laden Sie den Operanden über EBX, nachdem er set & 0xFFFFFFFF
! zugewiesen wurde!
Dies ist der Code, den ich versuche, jetzt zu arbeiten: (BEARBEITEN: Vermeiden Sie Push / Pop)
%Vor%Die Idee hier ist, die Operanden zu laden, bevor Sie die EBX überlisten, vermeiden Sie auch jede indirekte Adressierung, während Sie den EBX-Wert für CMPXCHG8B setzen. Ich repariere das harte Register ESI für die untere Hälfte des Operanden, denn wenn ich es nicht tun würde, würde es GCC freistehen, jedes andere bereits vergebene Register wiederzuverwenden, wenn es beweisen könnte, dass der Wert gleich war. Das EDI-Register wird manuell gespeichert, da es einfach durch Hinzufügen zu der geblockten Registerliste GCC mit "unmöglichen Neuladungen" erstickt, wahrscheinlich aufgrund eines hohen Registerdrucks. Der PUSH / POP wird beim Speichern von EDI vermieden, da andere Operanden möglicherweise ESP-adressiert sind.
Tags und Links gcc assembly x86 inline-assembly ia-32