Einzelnen Beitrag anzeigen

Benutzerbild von Stevie
Stevie

Registriert seit: 12. Aug 2003
Ort: Soest
4.016 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#1

Assembler Routine - korrekt so?

  Alt 16. Nov 2012, 14:52
Delphi-Version: XE2
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}
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight
  Mit Zitat antworten Zitat