3

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

PhiS
  • 4,540
  • 25
  • 35
Anton Duzenko
  • 2,366
  • 1
  • 21
  • 26

1 Answers1

5

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;
GJ.
  • 10,810
  • 2
  • 45
  • 62
  • I like how you const'ed property offsets here. Scasd slowness, however, is yet to be measured. – Anton Duzenko Aug 21 '14 at 12:12
  • @Anton Duzenko: there are several ways. You can use debugger and step in to the TList.add function down to the line `FList[result] := Item` than switch debuger window to CPU and read the FList index. You can also calcolate the index. Check in System.Classes how is made TList class. FList is first member of data class so the index is 4 (0 index is ClassInfo) than is FCount wich is 8 because the size of integer or pointer is 4 bytes. – GJ. Aug 21 '14 at 13:29
  • Yes, I know that. Now I did a quick test and on my real data (around 64 elements per list) your code is about 4% faster than scasd. On large lists (512+ elements) scasd is marginally faster. The delphi's IndexOf is about 30% slower than asm. All in all, you're #1. – Anton Duzenko Aug 21 '14 at 20:50