Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Assembler Routine - korrekt so? (https://www.delphipraxis.net/171641-assembler-routine-korrekt-so.html)

Stevie 16. Nov 2012 13:52

Delphi-Version: XE2

Assembler Routine - korrekt so?
 
Kurze Hintergrundinfo:

Ich in gerade dabei, die DSharp Multicast Events etwas zu überarbeiten.
Momentan gibt es 3 verschiedene Methoden, ein Event aufzurufen (inline asm für Delphi 2010 und XE und jeweils pure pascal ab XE2 für 32-bit und 64-bit)

Da die pure Pascal Versionen ziemlich viel Overhead (erst die aus der ObjAuto gelieferten Parameter im auf TValue umbasteln um sie dann an die Rtti.Invoke Methode zu übergeben) und Wartungsaufwand mit sich bringen, hab ich mich mal hingesetzt und hab 2 reine asm Routinen geschrieben.

Da ich nicht gerade der Assembler Crack bin, wär es prima, wenn die, die sich damit etwas besser auskennen, mal drüber schauen könnten und mich auf Fehler und/oder Optimierungsmöglichkeiten hinweisen würden (speziell bei der 64bit Version, die ich mir nur mit Hilfe der Rtti Sourcen zusammen gefrickelt hab).

Delphi-Quellcode:
procedure InvokeMethod(const Method: TMethod; Parameters: PParameters; StackSize: Integer);
const
  PointerSize = SizeOf(Pointer);
type
  TParameters = packed record
{$IFDEF CPUX86}
    Registers: array[paEDX..paECX] of Cardinal;
    EAXRegister: Cardinal;
    ReturnAddress: Pointer;
{$ENDIF CPUX86}
    Stack: array[0..1023] of Byte;
  end;
{$IF Defined(CPUX86)}
asm
  push ebp
  mov ebp,esp
  push eax // ebp-4 = Method
  push ebx
  mov ebx, edx // ebx = Parameters

  // if StackSize > 0
  test ecx,ecx
  jz @@no_stack

  // stack address alignment
  add ecx,PointerSize-1
  and ecx,not(PointerSize-1)
  and ecx,$ffff
  sub esp,ecx

  // put stack address as second parameter
  mov edx,esp

  // put params on stack as first parameter
  lea eax,[ebx].TParameters.Stack

  call Move

@@no_stack:
  mov edx,[ebx].TParameters.Registers.dword[0]
  mov ecx,[ebx].TParameters.Registers.dword[4]
  mov ebx,[ebp-$04]
  mov eax,[ebx].TMethod.Data
  call [ebx].TMethod.Code

  pop ebx
  pop eax
  mov esp,ebp
  pop ebp
end;
{$ELSEIF Defined(CPUX64)}
asm
  .params 60
  mov [rbp+$200],Method
  mov [rbp+$208],Parameters
  test r8,r8
  jz @@no_stack

  // put params on stack as first parameter
  lea rcx,[Parameters].TParameters.Stack

  // put stack address as second parameter
  mov rdx,rsp

  call Move

  mov rdx,[rbp+$208]

@@no_stack:
  mov rcx,[rdx].TParameters.Stack.qword[0]
  mov r8,[rdx].TParameters.Stack.qword[16]
  mov r9,[rdx].TParameters.Stack.qword[24]

  movsd xmm0,[rdx].TParameters.Stack.qword[0]
  movsd xmm1,[rdx].TParameters.Stack.qword[8]
  movsd xmm2,[rdx].TParameters.Stack.qword[16]
  movsd xmm3,[rdx].TParameters.Stack.qword[24]

  mov rdx,[rdx].TParameters.Stack.qword[8]

  mov rax,[rbp+$200]
  lea rax,[rax]
  mov rcx,[rax].TMethod.Data
  call [rax].TMethod.Code
end;
{$IFEND}

himitsu 16. Nov 2012 14:05

AW: Assembler Routine - korrekt so?
 
Ich würde versuchen einfach was Fertiges zu nutzen.
RTTI hat es schon fertige Invoke-Methoden ... man müsste sich nur zur Laufzeit (beim Erstellen des MulticastEvents) eine TRTTIMethod (oder so) manuell zusammenstellen oder aus der TypeInfo einer EventMethode erstellen und könnte Dieses dann verwenden.


Beim Umstellen auf andere Zielplattformen würde Emba dann für dich den Rest mit anpassen.


[edit]
Der Nachteil wäre dann zwar, daß dieser Code dann nicht zu alten Delphis kompatibel ist, wo es die neue RTTI noch nicht gibt.


Hätte es erst richtig/komplett durchlesen sollen
Dann halt kein Pascal ._.

Stevie 16. Nov 2012 14:14

AW: Assembler Routine - korrekt so?
 
Zitat:

Zitat von himitsu (Beitrag 1191540)
Ich würde versuchen einfach was Fertiges zu nutzen.
RTTI hat es schon fertige Invoke-Methoden ... man müsste sich nur zur Laufzeit (beim Erstellen des MulticastEvents) dynamisch eine TRTTIMethod (oder so) zusammenstellen und könnte diese dann verwenden.


Beim Umstellen auf andere Zielplattformen würde Emba dann für dich den Rest mit anpassen.

Danke für den Hinweis - das ist doch in etwa das, was ich im Moment für XE2 und aufwärts mache ;)

Problem 1.: Ich darf erstmal tonnenweise Bugs in verschiedenen Delphi Versionen in der Rtti reporten und fixen
Problem 2.: Für das dynamische Zusammenbauen einer TRttiMethod nur über die TypeInfo eines Events oder einer anonymen Methode ist noch mehr Fuckelei notwendig als für das da oben
Problem 3.: Die Invoke Methoden sind inperformant


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:49 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz