flat assembler
Message board for the users of flat assembler.

Index > Main > Question about CMPXCHG

Author
Thread Post new topic Reply to topic
Zoltanmatey31



Joined: 10 Jan 2023
Posts: 20
Zoltanmatey31 15 Jan 2023, 19:06
I have found this in the flat assembler documentation:

"cmpxchg compares the value in the al, ax, or eax register with the destination
operand. If the two values are equal, the source operand is loaded into the destination
operand. Otherwise, the destination operand is loaded into the al, ax, or eax register.
The destination operand may be a general register or memory, the source operand must
be a general register.
cmpxchg dl,bl
cmpxchg [bx],dx
; compare and exchange with register
; compare and exchange with memory"

therefore if the two values are equal what is the use of loading the other value into the destination with which this value is equal?
Post 15 Jan 2023, 19:06
View user's profile Send private message Reply with quote
edfed



Joined: 20 Feb 2006
Posts: 4354
Location: Now
edfed 15 Jan 2023, 20:28
read better:

if the value in xAx reg is equal the DESTINATION, the SOURCE is copied to DESTINATION. otherwise, DESTINATION is copied to the xAx reg.

A, S, D.
if A == D, D = S
else A = D
Post 15 Jan 2023, 20:28
View user's profile Send private message Visit poster's website Reply with quote
DimonSoft



Joined: 03 Mar 2010
Posts: 1228
Location: Belarus
DimonSoft 15 Jan 2023, 20:30
Rewrite with particular value if current value equals what is expected (xAx). Otherwise find out what value really is there. Quite common pattern for some multi-threaded code.
Post 15 Jan 2023, 20:30
View user's profile Send private message Visit poster's website Reply with quote
Furs



Joined: 04 Mar 2016
Posts: 2607
Furs 15 Jan 2023, 21:48
Scenario: You want to atomically update some status variable. So you load the value, modify it to how you want it changed, and then use cmpxchg.

You ask, why not just write it directly? Some other thread or CPU could change it (multi-threaded code). Then you change it wrong, because it was already changed, so you have to inspect it again! Any time you use multiple instructions to do it, you're at risk of race condition.

So if the comparison succeeds, it's the same as writing it directly. But what happens if it fails? You want to know why it failed, so that's why it gives you the value that is there now (into *ax).

After it failed, you can retry by changing it again, but this time using the new value you got (in *ax) and trying cmpxchg again...
Post 15 Jan 2023, 21:48
View user's profile Send private message Reply with quote
Zoltanmatey31



Joined: 10 Jan 2023
Posts: 20
Zoltanmatey31 16 Jan 2023, 08:55
oh ok, i was tired at night read it wrong. Sorry for the hustle.
Post 16 Jan 2023, 08:55
View user's profile Send private message Reply with quote
edfed



Joined: 20 Feb 2006
Posts: 4354
Location: Now
edfed 16 Jan 2023, 11:53
you don't have to be sorry. it is interresting to enlight the purpose of this instruction.

i wonder in what practical case i should use it.

anyone have an example code? does it have an other function than thread management?
Post 16 Jan 2023, 11:53
View user's profile Send private message Visit poster's website Reply with quote
Furs



Joined: 04 Mar 2016
Posts: 2607
Furs 16 Jan 2023, 13:22
edfed wrote:
anyone have an example code? does it have an other function than thread management?
I guess you can use it with a register destination operand if its purpose fits your algorithm logic, especially if you want to code for size. I expect such situation to be rare, though.
Post 16 Jan 2023, 13:22
View user's profile Send private message Reply with quote
Hrstka



Joined: 05 May 2008
Posts: 63
Location: Czech republic
Hrstka 17 Jan 2023, 09:57
I have seen it many years ago in a code to synchronize execution between multiple threads and thus avoid race conditions. I remember it looked like this:
Code:
try_get_lock:
  xor eax, eax          ; set eax to 0
  mov ecx, 1
  lock cmpxchg [lock_variable], ecx
  jz  lock_acquired

  ; wait, some other thread has the lock
  mov ecx, 0x4000
@@:
  dec ecx
  jnz @b

  jmp try_get_lock

lock_acquired:
  ; only one thread at a time can execute this code
  ; ...

lock_release:
  mov [lock_variable], 0    
If lock_variable is 0, then the thread will acquire the lock and the lock_variable will be set to 1. If the thread doesn't acquire the lock, it shall wait or perform some other task. In Windows, you would normally use EnterCriticalSection function instead.
Post 17 Jan 2023, 09:57
View user's profile Send private message Reply with quote
Furs



Joined: 04 Mar 2016
Posts: 2607
Furs 17 Jan 2023, 14:09
He did say "other than thread management" Wink
Post 17 Jan 2023, 14:09
View user's profile Send private message Reply with quote
Hrstka



Joined: 05 May 2008
Posts: 63
Location: Czech republic
Hrstka 18 Jan 2023, 08:23
Okay, so just ignore my previous post.
Post 18 Jan 2023, 08:23
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.