Delphi-PRAXiS
Seite 2 von 2     12   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Neuen Beitrag zur Code-Library hinzufügen (https://www.delphipraxis.net/33-neuen-beitrag-zur-code-library-hinzufuegen/)
-   -   Delphi ReverseString für ältere Delphi-Versionen (https://www.delphipraxis.net/144590-reversestring-fuer-aeltere-delphi-versionen.html)

Amateurprofi 12. Dez 2009 00:03

Re: ReverseString für ältere Delphi-Versionen
 
@Himitsu:
So ähnlich wollte ich auch antworten.
Ich hab mal getestet wie schnell/langsam die Routinen sind und habe auch noch eine eigene Routine dazu gestellt.

Delphi-Quellcode:
PROCEDURE ReverseStr(var s:string);
var p1,p2:PChar; c:Char;
begin
   if s='' then exit;
   p1:=@s[1];
   p2:=p1+Length(s)-1;
   while p1<p2 do begin
      c:=p1^;
      p1^:=p2^;
      p2^:=c;
      inc(p1);
      dec(p2);
   end;
end;
Die Angaben sind CPU-Ticks.
Gemessen wurde auf Basis eines Strings mit 10 Zeichen.


Code:
#1 von Wolfgang Mix : 12650
#2  von jfheins     :  450
#4  von himitsu     :  280
#7  von turboPASCAL : 11660 
#11 von amateurprofi :   45
zu letzterer sei angemerkt, dass diese Routine eine Prozedur ist, der Vergleich mit den Funktionen ist also nicht ganz fair.

Amateurprofi 12. Dez 2009 18:25

Re: ReverseString für ältere Delphi-Versionen
 
Und nochmal @himitsu:

Die Systemroutinen kannst du mit z.B.
CALL System.@LStrSetLength
aufrufen.
Zu deiner Assembler Routine:
Hast du die mal getestet ?
Bei Längen im Bereich 1 bis 3 gibts Probleme.
Warum?:
ECX enthält Length(Text).
Wenn ECX<4 ist dann wird ECX durch SHR ECX,2 auf 0 gestellt.
Das Loop senkt dann ECX um 1 und springt zu @@Loop4, bis ECX=0 ist.
Die Schleife wird also 2^32 mal durchlaufen, bzw. bis es 'ne Exception gibt.
Delphi-Quellcode:
    SHR  ECX, 2
    XOR  EAX, EAX
    @@Loop4:
    MOV  EDX, [ESI + EAX * 4]
    BSWAP EDX
    MOV  [EDI + ECX * 4], EDX
    INC  EAX
    LOOP @@Loop4
Bei Längen > 3 funktioniert die Routine zwar, aber dafür funktioniert danach irgend etwas anderes nicht mehr.
Warum ?: Weil du EDI und ESI veränderst.

Ich hab die Idee mit dem bswap aufgegriffen.
Delphi-Quellcode:
FUNCTION ReverseStr_A(s:string):string;
asm
         test    eax,eax
         jne     @Start
         mov     eax,edx
         jmp     system.@LStrClr
@Start: push    edi
         mov     edi,edx
         push    eax
         mov     edx,[eax-4]
         mov     eax,edi
         call    System.@LStrSetLength
         pop     edx            // @s[1]
         mov     ecx,[edx-4]      // Length(s)
         mov     edi,[edi]        // @result[1]
         jmp     @NextDW
@DWLoop: mov     eax,[edx+ecx]
         bswap   eax
         stosd
@NextDW: sub     ecx,4
         jnc     @DWLoop
         add     ecx,3
         js      @End
@BLoop: mov     al,[edx+ecx]
         stosb        
         sub     ecx,1
         jnc     @BLoop
@End:   pop     edi
end;

himitsu 12. Dez 2009 19:00

Re: ReverseString für ältere Delphi-Versionen
 
Ups, das mit EDI und ESI hatte ich ganz vergessen :oops: (dachte die waren so wie EAX, EDX und ECX)
joar, und das mit dem <4 stimmt :?

hab es oben mal geändert



für "sub ecx,1" würde wohl auch "dec ecx" gehn
und

"loop @BLoop" entspricht einem "dec ecx; jnz @BLoop", aber ich weiß hier nicht, welches optimaler arbeitet

"call @LStrSetLength" hatte ich aber probiert und ich wäre nicht drauf gekommen, daß man den System-Namespace unbedingt verwenden muß :shock:

Joat und das stord/storb macht sich auch besser, wenn man eh schon esi/edi verwendet :thumb:

Amateurprofi 12. Dez 2009 19:32

Re: ReverseString für ältere Delphi-Versionen
 
Intel empfiehlt statt INC xxx / DEC xxx besser ADD xxx,1 / SUB xxx,1 zu verwenden (weil schneller).
Und LOOP ist deutlich langsamer als SUB ECX,1; JNZ .
Deshalb ist die von mir gezeigte Version auch erheblich schneller....

himitsu 12. Dez 2009 19:47

Re: ReverseString für ältere Delphi-Versionen
 
:shock:

Also bei INC/DEC hätte ich es genau andersrum gedacht, da dese doch eigentlikch weniger machen, im Gegensatz zum ADD/SUB :gruebel:
(nja, ich hab 'nen AMD und keinen Intel :mrgreen: )

und beim LOOP hätte ich mindestens fast gleich schnell erwartet.


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:42 Uhr.
Seite 2 von 2     12   

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