![]() |
Optimallösung gesucht: Little Endian <-> Big Endian
Hi,
kann man das noch optimieren? (Kommentiert ist der Code, den Delphi erzeugt.)
Delphi-Quellcode:
Und ich geh doch richtig davon aus, dass das, was übergeben wird, der Zeiger auf das Zeichen ist (wegen var)?
procedure SwapBytes(var X: WideChar);
asm mov dx, [X] //mov dx, [eax] xchg dl, dh mov [X], dx //mov [eax], dx end; procedure SwapBytes(var X: UCS4Char); asm mov edx, [X] //mov edx, [eax] bswap edx mov [X], edx //mov [eax], edx end; Mfg FAlter |
Re: Optimallösung gesucht: Little Endian <-> Big Endia
1. x liegt in eax und du musst es nicht erst noch weiter herumschieben.
2. gibt es für 16bit noch die Delphi-Funktion swap. Die erzeugt direkt inline-Code. |
Re: Optimallösung gesucht: Little Endian <-> Big Endia
@sirius: bei mir ist Swap 32 bit (Integer)
nja, aber es ist zumindestens noch eine Funktion ist
Delphi-Quellcode:
und als Inline ist es besser
w := Swap(w);
// erzeugt aber das selbe Ergebnis wie ByteSwap(w); aber nee, diesen Code kann man nicht mehr optimieren, (leider geht ja bei ASM kein Inline) nur ein & könnte nicht schaden.
Delphi-Quellcode:
was du optimieren könntest, wäre mehrere Zeichen umzuwandeln und nicht nur Eines.
procedure SwapBytes(var X: WideChar);
asm mov dx, [&X] xchg dl, dh mov [&X], dx end; procedure SwapBytes(var X: UCS4Char); asm mov edx, [&X] bswap edx mov [&X], edx end; // ohne BSWAP für alte CPUs procedure SwapBytes(var X: UCS4Char); asm mov edx, [&X] xchr dh, dl rol edx, 16 xchg dh, dl mov [&X], edx end; aber wie meinst du das? Zitat:
[add] @sirius:
Delphi-Quellcode:
function SwapBytes(X: WideChar): WideChar;
asm xchg al, ah end; function SwapBytes(X: UCS4Char): UCS4Char; asm bswap eax end; |
Re: Optimallösung gesucht: Little Endian <-> Big Endia
Ich denke er meint den Code aus der CPU-Ansicht vom Debugger.
|
Re: Optimallösung gesucht: Little Endian <-> Big Endia
Hi,
Swap kannte ich noch nicht, hab gleich mal nachgesehen. Aus der Delphi-Hilfe: X ist ein Ausdruck des Typs SmallInt oder Word (16 Bit). Ich hab aber WideChar. Notfalls gehts mit Typecasten. Aus der Delphi-Hilfe: Die Funktion ist nur aus Gründen der Abwärtskompatibilität vorhanden. Na Toll. Dann so:
Delphi-Quellcode:
Wenigstens wird der Aufruf jetzt so übersetzt (Result ist WideString):
procedure SwapBytes(var X: WideChar); inline;
//Hinweis siehe unter der Prozedur! begin X := WideChar(Swap(Word(X))); end; { Sollte CodeGear "swap" eines Tages endgültig abschaffen, bitte das hier nutzen: procedure SwapBytes(var X: WideChar); asm mov dx, [X] //mov dx, [eax] xchg dl, dh mov [X], dx //mov [eax], dx end; }
Code:
Schade, dass Inline und Inline-Assembler ( :lol: ) sich nicht vertragen.
[b]FAUnicode.pas.137: SwapBytes(Result[I]);[/b]
0045949D 8B06 mov eax,[esi] 0045949F 8D4458FE lea eax,[eax+ebx*2-$02] 004594A3 0FB708 movzx ecx,[eax] 004594A6 86E9 xchg cl,ch 004594A8 668908 mov [eax],cx 004594AB 43 inc ebx @roter Kasten: Es steht zwar als Integer in der OH, aber es steht auch darunter, was ich oben geschrieben habe: Smallint oder Word, also 16 Bit. Das & braucht man bloß, wenns nicht eindeutig ist. Es gibt aber kein Register X, also wird der Parameter genommen. Wenn ich ihn ch für Char genannt hätte, müsste ich &Ch schreiben. Für mehrere Zeichen müsste ich mich noch genauer mit dem Aufbau von Strings und der Übergabe von String-Parametern beschäftigen, dann kann ich auch gleich den ganzen String umwandeln (und dyn. Arrays, denn USC4String ist ein type array of USC4Char). Da es jedoch nur geschrieben wurde, weil ich es schnell brauchte und ich eigentlich was ganz anderes tun wollte, werd ich mich im Moment nicht groß in was einlesen, was ich noch nicht kann und mit dem ursprünglichen Thema nichts zu tun hat. Hab aber schon die TODO-Kommentare gesetzt. ;) Evtl. hat ja hier jemand Langeweile. Mit "wie es Delphi übersetzt" meine ich was der aus dem X macht. Erst hatte ich eax stehen aber das ging logischerweise nicht, da X als eax "übersetzt" wurde (der Parameter wurde also in eax übergeben). Aber das CPU-Fenster hat mir die Ursache gezeigt und ich bin auf (e)dx umgestiegen. Das mit den Funktionen ist schon klar, dass die dann kürzer gehen (da ich dann keine Referenzen übergeben habe), aber das ist mehr Schreibarbeit. Wird es denn optimaler, wenn ich x := SwapBytes(x) schreibe? Kann sogar sein, wenn der Wert vorm Aufruf "zufällig" in (a)ax lag und später wieder dort gebraucht wird. Nur die Variante mit der obsolete-Funktion Swap ist so schon schnell genug, aber das als inline-Funktion zu schreiben macht auch keinen Unterschied. Mfg FAlter |
Re: Optimallösung gesucht: Little Endian <-> Big Endia
[edit] ups, ausversehn gelöscht ... wollte eigentlich zitieren, statt editieren
|
Re: Optimallösung gesucht: Little Endian <-> Big Endia
Hi,
nochmal zum Thema optimieren, indem ich den ganzen String auf einmal bearbeite (vielleicht mach ich es ja doch schon jetzt):
Delphi-Quellcode:
Wird da jetzt ein Zeiger auf einen WideString (UCS4String), welcher wiederum ein Zeiger auf die Wide(UCS4)Chars ist, übergeben?
procedure SwapBytes(var X: WideString);
procedure SwapBytes(var X: UCS4String); Mfg FAlter PS: Welche alten CPUs unterstützen denn kein bswap? Ich dachte immer, das gibts ab i80386DX (und was vor dem i486DX ist, ist eh egal, da lässt sich ja kein Win32 drauf installieren). PPS: Ein WideString kat keinen Referenzzähler? :shock: [edit] Es heißt UCS4String - sorry. Dann ist der Fehler weiter unten wohl auch ursprünglich meiner. [/edit] |
Re: Optimallösung gesucht: Little Endian <-> Big Endia
Wenn die Delphi-Version Inline unterstützt, dann macht Assembler keinen Sinn mehr:
Delphi-Quellcode:
{$IFDEF BIG_ENDIAN}
type WordBE = Word; {$ELSE ~BIG_ENDIAN} function WordBE(AValue: Word): Word; inline; begin Result := Swap(AValue); end; {$ENDIF BIG_ENDIAN} procedure TForm20.FormCreate(Sender: TObject); var Value: Word; begin Value := WordBE($1234); // inlined: mov _x, $3412 !!! ShowMessage(IntToHex(Value, SizeOf(Value) * 2)); Value := WordBE(Value); // inlined: xchg _l, _h ShowMessage(IntToHex(Value, SizeOf(Value) * 2)); end; |
Re: Optimallösung gesucht: Little Endian <-> Big Endia
Hi,
darum habe ich ja, wie in #5 geschrieben, die Funktion abgewandelt als inline mit swap. Das betrifft aber erstens noch nicht die 4-Byte-Variante und zweitens kann man evtl. noch was rausholen, wenn man die ganzen Strings umwandelt. Mfg FAlter |
Re: Optimallösung gesucht: Little Endian <-> Big Endia
WideString+Ref: nein, denn Delphi leitet den Widestring an OleStr weiter und der kennt keine Refferenzzählung.
'ne "einfache" Lösung wäre:
Delphi-Quellcode:
procedure SwapString(Var S: WideString);
asm mov eax, [eax] test eax, eax jz @exit mov ecx, [eax - 4] shr ecx, 1 @loop: mov dx, [eax] xchg dl, dh mov [eax], dx add eax, 2 dec ecx jnz @loop @exit: end; procedure SwapString(Var S: UCS4String); asm mov eax, [eax] test eax, eax jz @exit mov ecx, [eax - 4] @loop: mov edx, [eax] bswap edx mov [eax], edx add eax, 4 dec ecx jnz @loop @exit: end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:10 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