Delphi内联汇编程序和类属性

Delphi内联汇编程序和类属性,delphi,assembly,properties,basm,Delphi,Assembly,Properties,Basm,我试图在汇编程序(XE3)中重写TList.IndexOf方法。这是我的密码 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 :=

我试图在汇编程序(XE3)中重写TList.IndexOf方法。这是我的密码

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;
当然,我想直接使用Count或List等属性。我理解为什么编译器拒绝访问私有字段FCount和FList,但如何访问相应的属性?Count、Self.Count和[eax].Count都给出内联汇编程序错误


JIC:我不会故意处理这里的“未找到”情况

您不能通过Delphi assembler访问对象属性

Delphi编译器很好,我相信Delphi编译的代码也很快

您的代码有错误,因为没有测试零计数值,这将导致内存访问冲突

不要使用repne scasd,因为它很慢

但是,您可以手工编写代码进行测试…:)

函数TFastList.IndexOfAsm(项:指针):整数;
//eax=自我
//edx=项目
{var
P:P点;
开始
P:=指针(FList);
对于结果:=0到FCount-1 do
开始
如果P^=项目,则
出口
公司(P),;
结束;
结果:=-1;}
常数
FItems=4//FItems的数据偏移
FCount=8//FCount的数据偏移量
asm
mov ecx[eax].FItems//ecx=@FItems
mov eax[eax].FCount//eax=FCount
dec eax//测试零计数!
js@Exit//如果计数为0,则作为-1退出
@循环://重复
cmp项目,[ecx+eax*4]
jz@Exit
dec eax
jns@Loop//直到eax<0(实际上是-1)
@出口:
结束;

您无法从asm访问属性。你放弃编译器时放弃了这个特权。我喜欢你在这里设置属性偏移量的方式。然而,Scasd的缓慢程度尚待衡量。@Anton Duzenko:有几种方法。您可以使用调试器并进入TList.add函数,将调试器窗口切换到CPU并读取FList索引,然后将其添加到行
FList[result]:=Item
。您还可以计算索引。签入系统。类如何生成TList类。FList是数据类的第一个成员,所以索引是4(0索引是ClassInfo),而FCount是8,因为整数或指针的大小是4字节。是的,我知道。现在我做了一个快速测试,在我的真实数据(每个列表大约64个元素)上,您的代码比scasd快4%。在大型列表(512+个元素)上,scasd的速度稍微快一些。delphi的IndexOf比asm慢约30%。总而言之,你是1。
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;