delphiassemblypropertiesbasm

Delphi inline assembler and class properties


I am trying to rewrite the TList.IndexOf method in assembler (XE3). Here is my code

function TFastList.IndexOfAsm(Item: Pointer): Integer;
{var
  P: PPointer;
begin
  P := Pointer(FList);
  for Result := 0 to FCount - 1 do
  begin
    if P^ = Item then
      Exit;
    Inc(P);
  end;
  Result := -1;}
var
  FCnt, rslt: Integer;
  FData: Pointer;
begin
  FCnt := Count;
  FData := List;
asm
  push edi

  mov ecx, FCnt
  mov edi, FData
  mov eax, Item
  repne scasd

  mov eax, FCnt
  sub eax, ecx
  dec eax
  mov rslt, eax

  pop edi
end;
  Result := rslt;
end;

Naturally I would like to use the properties like Count or List directly. I understand why the compiler refuses to give access to private fields FCount and FList, but how do I access the corresponding properties? Count, Self.Count, and [eax].Count all give the inline assembler error.

JIC: I don't handle the not found situation here by intent


Solution

  • You can't access the object property via Delphi assembler!

    Delphi compiler is good and Delphi compiled code I belive is also very fast.

    Your code has mistake because doesn't test zero count velue what should cause memory access violation!

    Do not use repne scasd because it is slow.

    However you can hack code manualy to make test... :)

    function TFastList.IndexOfAsm(Item: Pointer): Integer;
    //eax = self
    //edx = Item
    {var
      P: PPointer;
    begin
      P := Pointer(FList);
      for Result := 0 to FCount - 1 do
      begin
        if P^ = Item then
          Exit;
        Inc(P);
      end;
      Result := -1;}
    const
      FItems = 4; //data offset of FItems
      FCount = 8; //data offset of FCount
    asm
      mov   ecx, [eax].FItems  //ecx = @FItems
      mov   eax, [eax].FCount  //eax = FCount
      dec   eax                //test zero count!
      js    @Exit              //if count was 0 then exit as -1
    @Loop:                     //repeat
      cmp   Item, [ecx + eax * 4]
      jz    @Exit
      dec   eax
      jns   @Loop              //until eax < 0 (actually -1)
    @Exit:
    end;