Inline Assembly: Difference between revisions

[unchecked revision][unchecked revision]
Line 165:
</source>
 
One example where this mightcan be useful, is the CMPXCHG instruction (see [http://en.wikipedia.org/wiki/Compare-and-swap Compare and Swap]), which the Linux kernel source code defines as follows:
<source lang="c">
#define cmpxchg( ptr, _old, _new ) { \
volatile u32 *__ptr = (volatile u32 *)(ptr); \
u32 __ret; \
asm volatile( "lock; cmpxchgl %2,%1" \
: "=a" (__ret), "+m" (*__ptr) \
: "r" (_new), "0" (_old) \
: "memory"); \
); \
__ret; \
}
</source>
 
In addition to returning the current value in EAX, CMPXCHG sets the zero flag (Z) when successful. Wihtout asm gotos, your code will have to check the returned value;
this CMP instruction can be avoided as follows:
 
<source lang="c">
#define cmpxchg( ptr, _old, _new, fail_label ) { \
volatile u32 *__ptr = (volatile u32 *)(ptr); \
u32 __ret; \
asm volatile goto( "lock; cmpxchgl %2,%1 \t\n" \
"jnz %l[fail_label] \t\n" \
: "=a" (__ret), "+m" (*__ptr) \
: "r" (_new), "0" (_old) \
: "memory" \
: fail_label ); \
); \
__ret; \
}
</source>
 
This new macro could then be used as follows:
<source lang="c">
 
volatile Item *head;
 
void addItem( Item *i ) {
again:
Item *oldHead = head;
i->next = oldHead;
cmpxchg( &tail, oldHead, i, again );
}
 
</source>
 
==Intel Syntax==
Anonymous user