Is it possible that this code in Delphi XE is defect? I keep getting AVs in the last line:

Is it possible that this code in Delphi XE is defect? I keep getting AVs in the last line:

class function TInterlocked.CompareExchange(var Target: Integer; Value: Integer; Comparand: Integer; out Succeeded: Boolean): Integer;
asm
XCHG EAX,EDX
XCHG EAX,ECX
LOCK CMPXCHG [EDX],ECX
MOV ECX,[ESP+4]
SETZ [ECX].Boolean
end;

Comments

  1. The `Succeded` parameter is not in [ESP+4] because the compiler creates stack frame for the function.
    Debugging shows that the parameter is passed in [EBP+8], but you need not calculate offsets manually and simply write
    MOV ECX,Succeeded.

    ReplyDelete
  2. Sergey Kasandrov Thanks, that code is from the Delphi XE RTL (SyncObjs.pas) and not written by me though. Later versions are using the AtomicCmpExchange intrinsic which obviously works.

    ReplyDelete
  3. Same thing in XE2 - but there is an interesting .NOFRAME pragma...
     
    class function TInterlocked.CompareExchange(var Target: Integer; Value: Integer; Comparand: Integer; out Succeeded: Boolean): Integer;
    {$IFDEF X64ASM}
    asm
      .NOFRAME
      MOV  EAX,R8d
      LOCK CMPXCHG [RCX].Integer,EDX
      SETZ [R9].Boolean
    end;
    {$ELSE !X64ASM}
    {$IFDEF X86ASM}
    asm
      XCHG EAX,EDX
      XCHG EAX,ECX
      LOCK CMPXCHG [EDX],ECX
      MOV  ECX,[ESP+4]
      SETZ [ECX].Boolean
    end;
    {$ENDIF X86ASM}
    {$ENDIF !X64ASM}

    and none of those functions uses source\rtl\sys\InterlockedAPIs.inc - Delphi RTL team seems chaotic or disconnected, reinventing the wheel time and again...

    ReplyDelete
  4. That's because [ESP+4] does not reference to Succeeded param. It's better to enable stackframes that allows you to access stack without making many changes to your asm code.
    This will do the trick:
    ----------------------------
    MOV ECX,[EBP+8] // Skip stackframe + return address.

    ReplyDelete

Post a Comment