title: Illegal instruction in ASM: lock cmpxchg dest, src
body: <p>I've been messing around with some x86 assembly as its come up in a number of my classes. In particular, I've wanted to expose compare-and-swap (CAS) as a user function. This is with the intent that I can implement my own locks.</p>
  
  <p>I'm using Linux 2.6.31 with GCC 4.1.1 on an Intel CPU.</p>
  
  <p>I have the following:</p>
  
  <pre><code>// int cmpxchg(int *dest, int expected, int update)
  .globl cmpxchg
  cmpxchg:
    pushl %ebp
    movl  %esp, %ebp
  
    // edx holds dest
    movl 8(%ebp), %edx
    // eax holds expected value
    movl 12(%ebp), %eax
    // ecx holds the new value
    movl 16(%ebp), %ecx
  
    // cmpxchg dest_addr, exp_value
    // compare to %eax is implicit
    lock cmpxchgl %edx, %ecx
  
    leave
    ret
  </code></pre>
  
  <p>This is within a *.s file, which I compile with my driver program. When I include the line</p>
  
  <pre><code>  lock cmpxchgl %edx, %ecx
  </code></pre>
  
  <p>and execute, I receive an "Illegal instruction" error.
  When I replace the line with</p>
  
  <pre><code>  cmpxchgl %edx, %ecx
  </code></pre>
  
  <p>my code seems to run fine.</p>
  
  <p>First off, is <code>lock</code> necessary? I'm not sure whether <code>cmpxchgl</code> is naturally atomic, so I used <code>lock</code> to be sure. As a userland program, am I even allowed to use <code>lock</code>? </p>
  
  <p>Thanks</p>
  
  <p>================================================================</p>
  
  <p>My final code (for those who may wander here in the future):</p>
  
  <pre><code>// int cmpxchg(int *dest, int expected, int update)
  .globl cmpxchg
  cmpxchg:
    pushl %ebp
    movl  %esp, %ebp
  
    // edx holds dest, use eDx for Destination ;-)
    movl 8(%ebp), %edx
    // eax holds expected value implicitly
    movl 12(%ebp), %eax
  
    // cmpxchg dest_add, src_value
    lock cmpxchgl %edx, 16(%ebp)
  
    leave
    ret
  </code></pre>