AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

pack-Funktion optimieren

Ein Thema von luke2 · begonnen am 4. Feb 2012 · letzter Beitrag vom 5. Feb 2012
 
jbg

Registriert seit: 12. Jun 2002
3.485 Beiträge
 
Delphi 10.1 Berlin Professional
 
#3

AW: pack-Funktion optimieren

  Alt 4. Feb 2012, 19:28
Viel lässt sich da nicht optimieren.
Oh, doch. Die 64bit Div- und Mod-Operationen sind sehr teuer und zudem auch nicht für Divisoren kleiner 2^32 optimiert. Und wenn man dann noch das Div und Mod in einem Schwung ermittelt, kann man da noch einiges rausholen.
Aber auch entfernen der String-Konkatenation tut sein übriges dazu.

Delphi-Quellcode:
function UDivMod6432(const Dividend: Int64; Divisor: LongWord; var Rest: LongWord): Int64;
// DivMod64 für "Divisor < 2^32"
{$IFDEF CPUX64}
asm
  // in: RCX = Dividend
  // EDX = Divisor
  // R8 = @Rest
  // out: RAX = Quotient
  mov rax, rcx // Register für die Division (RDX:RAX / RCX) vorbereiten
  mov ecx, edx // Divisor in ECX für die Division schieben
  xor rdx, rdx

  //div ecx // "Divisor < 2^32" ausnutzen
  db $F7, $F1 // XE2 compiler bug, es wird immer "div rcx" generiert

  mov dword ptr [r8], edx // Rest in "Rest" schreiben
end;
{$ELSE}
asm
  // in: [ebp+$0c]:[ebp+$08] = Dividend
  // EAX = Divisor
  // EDX = @Rest
  // out: EDX:EAX = Quotient
  push ebx
  push edx // Zeiger auf Rest sichern
  mov ecx, eax

  mov eax, dword ptr [ebp+$0c] // HIGH DWORD des Dividenden als LOW DWORD für die Division laden
  xor edx, edx // kein HIGH DWORD bei der Division
  div ecx // und dividieren (EDX enthält Rest, der als Übertrag genutzt wird)

  mov ebx, eax // HIGH DWORD des Quotienten sichern
  mov eax, dword ptr [ebp+$08] // LOW DWORD des Dividenden laden
  div ecx // und dividieren (EDX enthält Rest)

  pop ecx // Zeiger auf Rest wiederherstellen
  mov dword ptr [ecx], edx // Rest in "Rest" schreiben
  mov edx, ebx // HIGH DWORD des Quotienten wiederherstellen
  pop ebx
end;
{$ENDIF CPUX64}

function cvbase_ANSI(n: Int64): AnsiString;
var
  Buf: array[0..7] of AnsiChar;
  Index: Integer;
  r: LongWord;
begin
  Index := Length(Buf);
  while n > 0 do
  begin
    Dec(Index);
    n := UDivMod6432(n, 255, r);
    Buf[Index] := chtab[r];
  end;
  SetString(Result, PAnsiChar(@Buf[Index]), Length(Buf) - Index);
end;

function cvbase(n: Int64): string;
var
  Buf: array[0..7] of Char;
  Index: Integer;
  r: LongWord;
begin
  Index := Length(Buf);
  while n > 0 do
  begin
    Dec(Index);
    n := UDivMod6432(n, 255, r);
    Buf[Index] := chtab[r];
  end;
  SetString(Result, PChar(@Buf[Index]), Length(Buf) - Index);
end;
UPDATE: Die 32bit assembler Version nahm eine falsche Parameterreihenfolge an.

Geändert von jbg ( 5. Feb 2012 um 17:35 Uhr)
  Mit Zitat antworten Zitat
 


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:54 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz