![]() |
Re: Optimallösung gesucht: Little Endian <-> Big Endia
Hi,
danke. Ein kleiner Fehler: Es heißt UCS4String statt USC4String (war plötzlich ne rote Wellenlinie da). Wie ich an deinem Code erkennen kann, werden wirklich Zeiger auf die Zeiger übergeben. Aber jetzt ist die Frage ja nicht mehr nötig. Zumindest, wenn es läuft - werds gleich mal testen. Mfg FAlter [edit] Scheint zu funktionieren - und ich versteh sogar was, ist also nicht zu kompliziert geworden! :D [/edit] |
Re: Optimallösung gesucht: Little Endian <-> Big Endia
ups: nja, hatte die UCS4String-Version ohne zu testen (um)geschrieben :angel2:
PS: das "SHR 1" ist ein schnelles "div 2" und es ist nötig, da die OleStr (ole32.dll) die Länge in Byte angibt. und bei USC4 nicht, da Delphi bei seinen dynamischen Arrays (String, WideString, dynArray und Co.) die Anzahl der Elemente/Chars PS: in FTypes.pas schau dir mal den Abschnitt "Compiler Intern Data-Types" (ab Zeile 1213) an ![]() bei "SwapString(Var S: WideString);" könnte man jetzt noch jeweils 2 Chars via BSWAP zusammen verarbeiten |
Re: Optimallösung gesucht: Little Endian <-> Big Endia
Hi,
Zitat:
Zitat:
Zitat:
Zitat:
Mfg FAlter |
Re: Optimallösung gesucht: Little Endian <-> Big Endia
besser kommt man in dem Sinne, daß nun integerweise gearbeitet wird, also mit 2*16 Bit ... wobei die 32 Bit-CPU da doch optimaler arbeitet :angel:
Delphi-Quellcode:
ach, da ich eh grad etwas zuviel Zeit hatte (blöd, wenn man auf was warten muß :? )
procedure SwapString(Var S: WideString);
asm mov eax, [eax] test eax, eax jz @exit mov ecx, [eax - 4] shr ecx, 1 push ecx shr ecx, 1 jz @onechar @loop: mov edx, [eax] bswap edx rol edx, 16 mov [eax], edx add eax, 4 dec ecx jnz @loop @onechar: pop ecx and ecx, $01 jz @exit mov dx, [eax] xchg dl, dh mov [eax], dx @exit: end; ist aber noch ungetestet |
Re: Optimallösung gesucht: Little Endian <-> Big Endia
Hi,
stimmt, wenn man es rotieren lässt, hat man die beiden Teile des DWords ja auch wider getauscht, insofern ist ein effizientes Tauschen dann möglich. Evtl. könnte man das Label @onechar noch drei Anweisungen nach unten verschieben, denn wenn es nur ein Zeichen ist muss nicht nochmal geprüft werden, ob die Anzahl ungerade ist (ein Byte übrig bleibt), das ist dann nämlich eben der Fall. Mfg FAlter [edit] Getestet mit verschobenem @onechar läuft nicht. Was hab ich da nur schon wieder übersehen? :gruebel: [/edit] |
Re: Optimallösung gesucht: Little Endian <-> Big Endia
Mögliche Assembler-Version für UCS2-Swap:
Delphi-Quellcode:
procedure SwapWords(var AWords; ACount: LongWord); register;
asm mov ecx, edx jecxz @@exit @@loop: ror word ptr [eax + ecx * 2 - 2], 8 loop @@loop @@exit: end; procedure TestSwapWords(); var Value: WideString; begin Value := #$4800#$6500#$6C00#$6C00#$6F00#$2C00#$2000 + #$5700#$6F00#$7200#$6C00#$6400#$2100; SwapWords(Value[1], Length(Value)); ShowMessage(Value); end; |
Re: Optimallösung gesucht: Little Endian <-> Big Endia
Hi,
sieht zwar kurz aus, aber himitsus Version ist schöner, da sie (1.) die Parameter verwendet, wie ich sie mir vorstelle (mit viel weniger Tipparbeit) und (2.) die loop-Anweisung unschön ist. Keine Ahnung, wer die überhaupt eingeführt hat :? jedenfalls ist sie nur dann empfehlenswert, wenn man Speicherplatz sparen will, ansonsten kommt man mit dec und jz besser (zumindest wars früher so, evtl. ist sie heute etwas optimiert worden). Mfg FAlter |
Re: Optimallösung gesucht: Little Endian <-> Big Endia
Dann halt mit WideString und dec/jnz :)
Delphi-Quellcode:
procedure SwapUCS2(var AValue: WideString); register;
asm mov eax, [AValue] or eax, eax jz @@exit // Empty (nil) mov ecx, [eax - 4] // Relies on internal BSTR knowlegde! shr ecx, 1 // jz @@exit // Should not happen (Empty <> nil) @@loop: dec ecx ror word ptr [eax + ecx * 2], 8 jnz @@loop @@exit: end; |
Re: Optimallösung gesucht: Little Endian <-> Big Endia
also ohne deine Signatur wär mir langsam was komisch vorgekommen (wo kommt denn das x-Anhänsel her?)
nja, gegen die Assemblerprofies hat man einfach keine Chance :| dafür bin ich einfach zu sehr gedanklich in der Delphi-/Pascalschiene drin ... übersetze es sozusagen und versuch's dann zu optimieren...
Delphi-Quellcode:
nja, zumindestens lerntman da auch immer was dazu.
procedure SwapString(Var S: WideString);
asm mov eax, [eax] // eax := PWideChar(S); test eax, eax // if eax = nil then goto @exit; jz @exit mov ecx, [eax - 4] // ecx = length(eax) {div 2}; shr ecx, 1 push ecx // temp := ecx; shr ecx, 1 // ecx := ecx div 2; jz @onechar // if ecx = 0 then goto @onechar; @loop: // @loop: mov edx, [eax] // PLongWord(eax)^ := bswap(PLongWord(eax)^) rol 16; bswap edx rol edx, 16 mov [eax], edx add eax, 4 // inc(eac, 4); //dec ecx // //dec(ecx); //jnz @loo // //if ecx <> 0 then goto @loop; loop @loop // dec(ecx); if ecx <> 0 then goto @loop; @onechar: // @onechar: pop ecx // ecx := temp; and ecx, $01 // ecx := ecx and $01; jz @exit // if ecx = 0 then goto @exit; mov dx, [eax] // PWord(eax)^ := xchg(PWord(eax)^); xchg dl, dh mov [eax], dx @exit: // @exit: end; wußte noch garnicht, daß man ROR/ROL nicht nur mit Register verwenden kann ... schade, daß dieses nicht auch mit BSWAP geht, sonst würde ich brstimmt auch fast so weit runter(klein) kommen ^_^ |
Re: Optimallösung gesucht: Little Endian <-> Big Endia
Wenn man davon ausgeht, dass UCS4String ein array of UCS4Char (dynamisches Array) ist, dann könnte man folgendes 'verbrechen':
Delphi-Quellcode:
Statt read/BSWAP/write hätte man an auch drei ROR (8/16/8) nehmen können:
procedure SwapUCS4(var AValue: UCS4String); register;
asm mov eax, [AValue] or eax, eax jz @@exit // Empty (nil) mov ecx, [eax - 4] // Relies on internal DynArray knowlegde! // jecxz @@exit // Should not happen (Empty <> nil) // dec ecx // Skip the terminating $00000000 // jz @@exit @@loop: dec ecx mov edx, [eax + ecx * 4] bswap edx mov [eax + ecx * 4], edx jnz @@loop @@exit: end; procedure TestSwapUCS4; const Hello: array [0..13] of UCS4Char = ( $48000000, $65000000, $6C000000, $6C000000, $6F000000, $2C000000, $20000000, $57000000, $6F000000, $72000000, $6C000000, $64000000, $21000000, $00000000 ); var Value: UCS4String; begin SetLength(Value, Length(Hello)); Move(Hello[0], Value[0], SizeOf(Hello)); SwapUCS4(Value); ShowMessage(UCS4StringToWideString(Value)); end;
Delphi-Quellcode:
ps: das x kommt von nicodex (Vorname) / nicodex (Thema) / nicodex (Land) / nicodex (Neigung) / nicodex (Spiel) :]
procedure SwapUCS4(var AValue: UCS4String); register;
asm mov eax, [AValue] or eax, eax jz @@exit sub eax, 4 mov ecx, [eax] // dec ecx // Skip terminating $00000000 // jz @@exit @@loop: add eax, 4 dec ecx ror word ptr [eax], 8 ror dword ptr [eax], 16 ror word ptr [eax], 8 jnz @@loop @@exit: end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:25 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