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.
-
_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.