![]() |
Konvertierung von BigEndian-Werten
Hallo zusammen,
ich muß BigEndian-Werte aus einer Datei auslesen und dann "normal" weiter verarbeiten. Dafür nutze ich folgende Routine
Delphi-Quellcode:
Für 24 und 16Bit-Werte existieren entsprechende Routinen.
type
ta4 = array [0..3] of byte; tpa4= ^ta4; function Big2Little32(ina:tpa4):integer; begin result:=ina[3]+ ina[2] shl 8+ ina[1] shl 16+ ina[0] shl 24; end; Ist dieser Weg (nahezu) optimal oder gibt es einen besseren? ggf nur eine Routine für mehrere Größen(16,24,32...Bit)? Gruß K-H |
AW: Konvertierung von BigEndian-Werten
Was hältst du von einem Varianten Record ? Damit würdest du die schieberei sparen
|
AW: Konvertierung von BigEndian-Werten
hast Du ein Beispiel?
Meiner Meinung nach komme ich um die Schieberei auf kenen Fall herum? Gruß K-H |
AW: Konvertierung von BigEndian-Werten
Naja, also kürzer ginge es wohl schon:
Delphi-Quellcode:
Ob das schneller ist? Kann sein. Weniger Funktionen ist es leider nicht - das wäre aber auch mit zusätzlichem Aufwand verbunden...
function SwapInt32(Value: Integer): LongWord; register;
asm BSWAP EAX end; function SwapInt16(Value: SmallInt): SmallInt; register; asm XCHG EAX end; (Code ungetestet, ich kenne mich nicht besonders mit Assembler aus...) |
AW: Konvertierung von BigEndian-Werten
Delphi-Quellcode:
function Swap(Value: Cardinal): Cardinal;
asm BSWAP EAX end; // gibts auch noch: function SwapUInt64(X: UInt64): UInt64; asm mov EDX,dword ptr [X] mov EAX,dword ptr [X+4] bswap EDX bswap EAX end; |
AW: Konvertierung von BigEndian-Werten
Delphi-Quellcode:
TConvert = Record
case integer of 0 : (Bytes : Array[0..3] of Byte); 1 : (MyInt : Integer); end; function Big2Little32(ina:tpa4):integer; var lConvert : TConvert; begin lConvert.Bytes[0] := ima[3]; lConvert.Bytes[1] := ina[2]; lConvert.Bytes[2] := ina[1]; lConvert.Bytes[3] := ina[0]; Result ;) lConvert.MyInt; end; |
AW: Konvertierung von BigEndian-Werten
Ansosnten wohl eher OR, anstatt +.
Delphi-Quellcode:
Und falls man Assembler nutzt, muß man später auch noch die 64-Bit-Version basteln, denn in Win64 sind die Register anders belegt.
function Big2Little32(ina: tpa4): LongInt;
begin Result:=ina[3] or ina[2] shl 8 or ina[1] shl 16 or ina[0] shl 24; end; |
AW: Konvertierung von BigEndian-Werten
Vielen Dank!
Da hab ich ja jetzt etwas zum ausprobieren. @Himitsu Ich denke Deiner Version würde noch ein
Delphi-Quellcode:
ganz gut passen.
Result:=0;
(was man mit OR so assoziiert..) Da ich mit ASM seit Jahren nichts mehr gemacht habe, mal sehen was daraus wird. Vielen Dank nochmal K-H |
AW: Konvertierung von BigEndian-Werten
Zitat:
Delphi-Quellcode:
Result := Result or ...
Und wenn, dann hätte man das beim + auch schon mit machen müssen. :angle: Hier werden ja nur die 4 ina's ver-or-t und ich hoffe mal diese sind ordentlich initialisiert. |
AW: Konvertierung von BigEndian-Werten
Wenn du nicht für alles eine eigene Funktion willst könntest du auch einen pointer auf die Daten + die Datengröße übergeben und anhand dessen dann entsprechend viele Bytes switchen
|
AW: Konvertierung von BigEndian-Werten
Liste der Anhänge anzeigen (Anzahl: 3)
Hallo und vielen Dank nochmal auch an Mr OR!
Ich habe alle Anregungen (sofern ich sie verstanden habe) einmal verwurstet und versucht sie an Hand eines Benchmarks zu beurteilen.
Delphi-Quellcode:
Big2Little32c/function Big2Little32H sind etwa gleich schnell (im Rahmen der Messgenauigkeit)
function Big2Little32c(ina:tpa4):integer;
var dd : integer; begin dd:= ina^[3]+ (ina^[2] shl 8)+ (ina^[1] shl 16)+ (ina^[0] shl 24); result:=dd; end; function Big2Little32H(ina:tpa4):integer; begin result:=0; result:= result or ina[3] or (ina[2] shl 8) or (ina[1] shl 16) or (ina[0] shl 24); end; function Big2Little32R(ina:tpa4):integer; type tLittRec=record case integer of 1 : (wert:integer); 2 : (aa: array [0..3] of byte); end; var my : tLittRec ; begin my.wert:=0; my.aa[0]:=ina[3]; my.aa[1]:=ina[2]; my.aa[2]:=ina[1]; my.aa[3]:=ina[0]; result:=my.wert; end; function SwapInt32(Value: Integer): integer; register; asm BSWAP EAX end; SwapInt32 ist etwas schneller(-10%) Big2Little32R(ina:tpa4):integer; Braucht ca. die dreifache Zeit. Da ich nur ca 1000-3000 Werte lesen muß ist der Unterschied eigentlich irrelevant, aber in diesem Falle ist small beautiful and fast. Ich werde SirThornberrys Anregung aufgreifen und da noch ein "LängenMäntelchen" um legen, dann hab ich was ich will. Vielen Dank nochmal K-H Falls es jemanden interessiert, im Anhang das Programm und die erhaltenen Werte. |
AW: Konvertierung von BigEndian-Werten
Wobei du in Big2Little32R unnötig viel umkopierst.
Und da du sowieso alle Bytes wieder überschreibst, muß es auch nicht initialisiert werden (wert=0)
Delphi-Quellcode:
Wobei alle Vier im Prinzip auf's Selbe rauslaufen, also nach dem Kompilieren.
function Big2Little32R(ina:tpa4):integer;
type tLittRec=record case integer of 2 : (aa: array [0..3] of byte); end; var my : tLittRec absolute Result; begin my.aa[0]:=ina[3]; my.aa[1]:=ina[2]; my.aa[2]:=ina[1]; my.aa[3]:=ina[0]; end; function Big2Little32R(ina:tpa4):integer; type tLittRec= array [0..3] of byte; var my : tLittRec absolute Result; begin my[0]:=ina[3]; my[1]:=ina[2]; my[2]:=ina[1]; my[3]:=ina[0]; end; function Big2Little32R(ina: tpa4): LongInt; var res: tpa4 absolute Result; begin res[0] := ina[3]; res[1] := ina[2]; res[2] := ina[1]; res[3] := ina[0]; end; function Big2Little32R(ina: tpa4): LongInt; begin tpa4(Result)[0] := ina[3]; tpa4(Result)[1] := ina[2]; tpa4(Result)[2] := ina[1]; tpa4(Result)[3] := ina[0]; end; |
AW: Konvertierung von BigEndian-Werten
Dumme Frage
Delphi-Quellcode:
Fehlt der Integer absichtlich?
type
tLittRec=record case integer of 2 : (aa: array [0..3] of byte); end; (das absolute finde ich stark, oft eingesetzt aber nie so!) Gruß K-H |
AW: Konvertierung von BigEndian-Werten
Du hattest das 1:Integer ja nur für
Delphi-Quellcode:
benutzt.
my.wert:=0;
Und da dieses nun weg war, wurde 1:Integer auch nicht mehr benötigt. :angle: |
AW: Konvertierung von BigEndian-Werten
Nee da war noch
Delphi-Quellcode:
aber egal, auf jeden Fall ein Beispiel, das es viele Wege gibt.
result:=aa.wert;
Gruß K-H |
AW: Konvertierung von BigEndian-Werten
:oops: ganz vergessen :lol:
Nicht nur viele Wege ... auch viele Ansichten Alle meine 4 Funktionen machen ganz genau das Selbe, also wenn man es Speichertechnisch betrachtet. Nur daß der Quellcode anders aussieht, auch wenn er, wie gesagt, genau das Selbe macht. |
AW: Konvertierung von BigEndian-Werten
Oder so.
Der Compiler wird sich die richtige Funktion selber suchen.
Delphi-Quellcode:
FUNCTION ChangeEndian(value:Word):Word; overload;
asm {$IFDEF CPUX64} mov rax,rcx {$ENDIF} XCHG al,ah end; FUNCTION ChangeEndian(value:DWord):DWord; overload; asm {$IFDEF CPUX64} mov rax,rcx {$ENDIF} bswap eax end; FUNCTION ChangeEndian(const value:UInt64):UInt64; overload; asm {$IFDEF CPUX64} mov rax,rcx bswap rax {$ELSE} mov edx,[esp+8] mov eax,[esp+12] bswap eax bswap edx {$ENDIF} end; FUNCTION ChangeEndian(value:SmallInt):SmallInt; overload; asm {$IFDEF CPUX64} mov rax,rcx {$ENDIF} XCHG al,ah end; FUNCTION ChangeEndian(value:Integer):Integer; overload; asm {$IFDEF CPUX64} mov rax,rcx {$ENDIF} bswap eax end; FUNCTION ChangeEndian(const value:Int64):Int64; overload; asm {$IFDEF CPUX64} mov rax,rcx bswap rax {$ELSE} mov edx,[esp+8] mov eax,[esp+12] bswap eax bswap edx {$ENDIF} end; |
AW: Konvertierung von BigEndian-Werten
Funktioniert der Compilerswitch auch zur Laufzeit?
|
AW: Konvertierung von BigEndian-Werten
welche Anwendung wechselt zu Laufzeit zwischen 32 und 64 Bit-Anwendung?
|
AW: Konvertierung von BigEndian-Werten
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:11 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 by Thomas Breitkreuz