InterlockedCompareExchange



  • Hallo 🙂

    ich möchte besagte funktion in assembler schreiben. dazu verwende ich cmpxchg
    (x86). der code läuft im ring 0.

    _InterlockedCompareExchange:
        push ebp
        mov ebp, esp
    
        mov eax, [ebp+12]
        mov ebx, [ebp+8]
        lock cmpxchg [ebp+4], ebx
        xor eax, eax
        jnz .done
        inc eax
    .done:
        pop ebp
        ret
    

    jetzt möchte ich diese funktion in C aufrufen:

    extern unsigned int InterlockedCompareExchange(volatile unsigned *dest, unsigned newval, unsigned oldval); // __cdecl
    
    //...
    
    unsigned var1 = 5;
    unsigned res1 = InterlockedCompareExchange(&var1, 5, 1);
    unsigned var2 = var;
    unsigned res2 = InterlockedCompareExchange(&var1, 1, 5);
    unsigned var3 = var;
    

    die erste funktion sollte fehlschlagen und 0 zurück liefern. die zweite dagegen
    müsste den wert austauschen. tut sie aber nicht:

    &var1 = 2096556, var2 = 5, var3 = 5, res1 = 2031871, res2 = 2031617
    

    da müsste doch eigentlich in var3 eine 1 stehen, und in res1 0. da der wert
    auch nicht mit der addresse zusammenpasst, kann ich mir das nicht erklären.

    ich vermute, die prozedur ist irgentwie falsch. 😞


  • Mod

    _InterlockedCompareExchange:
        push ebp
        mov ebp, esp               ; das Erstellen eines Stackrahmes ist hier völlig überflüssig
    
        mov eax, [ebp+12]          ; lädt newval
        mov ebx, [ebp+8]           ; lädt dest
        lock cmpxchg [ebp+4], ebx  ; vergleicht und tauscht ggf. die Rücksprungadresse -> schlecht, wenn der Vergleich zufällig mal erfolgreich ist
        xor eax, eax               ; setzt das zero-Flag
        jnz .done                  ; Sprung wird folglich niemals ausgeführt werden
        inc eax                    ; und in eax am Ende immer 1 stehen
    .done:
        pop ebp
        ret                        ; ebx sollte besser nicht modifiziert werden
    
    _InterlockedCompareExchange:
        mov eax, [esp+12]          ; oldval
        mov edx, [esp+8]           ; newval
        mov ecx, [esp+4]           ; dest
        lock cmpxchg [ecx], edx
        setz al
        movzx eax, al
        ret
    


  • oh 🙄

    ups.

    das sieht doch schon sehr viel besser aus.
    👍


Anmelden zum Antworten