[gelöst] UInt32 aus Filestream lesen

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
kirchfritz
Beiträge: 227
Registriert: Mo 3. Jan 2011, 13:34
OS, Lazarus, FPC: Win11 (L 3.0 FPC 3.2.2)
CPU-Target: 64Bit
Wohnort: Nürnberg

[gelöst] UInt32 aus Filestream lesen

Beitrag von kirchfritz »

Kann mir das jemand nach PASCAL übersetzen:
UInt32.png
UInt32.png (226.58 KiB) 2307 mal betrachtet
soweit habe ich das verstanden:

1)reader ist ein TFilestream
2)gelesen wird ein UINt32 Wert und in die Variable value gesteckt;
3)dann wird die Variable value irgendwie verarbeitet und das Verarbeitungsergebnis zurückgeliefert.

Was genau macht diese "Verarbeitung" und wie schreibt man das in PASCAL?
Zuletzt geändert von kirchfritz am Do 11. Jul 2024, 19:22, insgesamt 1-mal geändert.

wp_xyz
Beiträge: 5188
Registriert: Fr 8. Apr 2011, 09:01

Re: UInt32 aus Filestream lesen

Beitrag von wp_xyz »

UInt32 = DWord --> Result := Stream.ReadDWord.

Die Routine macht aber noch eine Umwandlung in die Big-Endian-Byteabfolge ("ABCD" wird zu "DCBA"), u. Dafür gibt es in FPC die mehrfach überladenen Funktionen SwapEndian. Bleibt noch das Problem, wann das zu machen ist. Dein Screenshot hat dafür BitConverter.IsLittleEndian. Angenommen, du kannst diese Information irgendwo in einer Variablen IsLittleEndian speichern, dass wäre der komplette Code so:

Code: Alles auswählen

var
  Value: DWord;
...
Value := Reader.ReadDWord;
if IsLittleEndian then SwapEndian(Value);

Benutzeravatar
theo
Beiträge: 10920
Registriert: Mo 11. Sep 2006, 19:01

Re: UInt32 aus Filestream lesen

Beitrag von theo »

Ist das im original C?
Am Ende ist ja BSWAP ein x86 ASM Befehl.
Warum wird der im obigen Code nicht genutzt?

Socke
Lazarusforum e. V.
Beiträge: 3178
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: UInt32 aus Filestream lesen

Beitrag von Socke »

Ich tipper eher auf C++ - public ergibt in C wenig Sinn. Wenn der Autor den ASM-Befehl nicht kennt, gibt es keinen Grund ihn zu nutzen :lol:.

Zur Thematik:
Da ein DWord (bzw. alle größeren Zahl-Datentypen) aus mehren Bytes bestehen (DWord = 4 Byte), muss im Prozessor entschieden werden, welches Byte/Bit welche Wertigkeit hat. Steht der höchste Zahlwert im ersten oder im letzten Byte? Das nennt man Endianess und wird durch den Prozessorhersteller festgelegt. Bei x86 oder x86_64 ist das "Little Endian" - hier hat das erste Byte den niedrigsten Zahlwert und das vierte Byte die höchsten Zahlwerte.

Beim Schreiben von Dateien hast du ein ähnliches Problem: Wenn du eine Datei auf einem Big-Endian Computer schreibst, musst du die Zahlen umwandeln, damit auf einem Little-Endian-Computer die richtigen Werte entstehen. Im Gegensatz zum Prozessor kann der Softwareentwickler festlegen, was in der Datei steht.

Wenn die Endianess der Datei (Big Endian) feststeht, dann kann durch den Compiler entschieden werden, ob ein Swap notwendig ist:

Code: Alles auswählen

var
  Value: DWord;
...
Value := Reader.ReadDWord;
{$IFDEF ENDIAN_LITTLE}
SwapEndian(Value);
{$ENDIF}
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Benutzeravatar
Zvoni
Beiträge: 396
Registriert: Fr 5. Jul 2024, 08:26
OS, Lazarus, FPC: Windoof 10 Pro (Laz 2.2.2 FPC 3.2.2)
CPU-Target: 32Bit
Wohnort: BW

Re: UInt32 aus Filestream lesen

Beitrag von Zvoni »

Socke hat geschrieben: Mi 10. Jul 2024, 13:05 Ich tipper eher auf C++ - public ergibt in C wenig Sinn. Wenn der Autor den ASM-Befehl nicht kennt, gibt es keinen Grund ihn zu nutzen :lol:.

Zur Thematik: Wenn die Endianess der Datei (Big Endian) feststeht, dann kann durch den Compiler entschieden werden, ob ein Swap notwendig ist:

Code: Alles auswählen

var
  Value: DWord;
...
Value := Reader.ReadDWord;
{$IFDEF ENDIAN_LITTLE}
SwapEndian(Value);
{$ENDIF}
Ist Dot Crap C#
Und ich muss zu deinem IFDEF widersprechen: Bitte korrigiert mich, falls ich falsch liege, aber $IFDEF ist doch eine Compile-Time-Conditional?
Bedeutet: Wenn ich Kompiliere wird festgelegt: Du wirst auf einer LittleEndian-Maschine kompiliert, als füge den Code für Swap hinzu.
Und die kompilierte EXE nehm ich dann und schieb sie "as is" auf eine BE-Maschine (würde die überhaupt laufen? Gebe zu, da kenn ich mich jetzt gar nicht aus)
Ein System sie alle zu knechten, ein Code sie alle zu finden,
Eine IDE sie ins Dunkel zu treiben, und an das Framework ewig zu binden,
Im Lande Redmond, wo die Windows drohn.

wp_xyz
Beiträge: 5188
Registriert: Fr 8. Apr 2011, 09:01

Re: UInt32 aus Filestream lesen

Beitrag von wp_xyz »

Auch ich habe Bedenken wegen des {$IFDEF}. Denn es gibt Dateien (z.B. PNG, EXIF-Metadaten), in denen sich Big-Endian und Little-Endian-Inhalt je nach Belieben des Erstellers abwechselt. Daher kommt es auf den Zusammenhang an, in dem der Code verwendet wird.

Benutzeravatar
theo
Beiträge: 10920
Registriert: Mo 11. Sep 2006, 19:01

Re: UInt32 aus Filestream lesen

Beitrag von theo »

Socke hat geschrieben: Mi 10. Jul 2024, 13:05 Ich tipper eher auf C++ - public ergibt in C wenig Sinn. Wenn der Autor den ASM-Befehl nicht kennt, gibt es keinen Grund ihn zu nutzen :lol:.
Ja klar, aber der innere "Arbeitscode" ist ja doch C-mässig.
Eigentlich müsste C++ oder C# SwapEndian doch auch zur Verfügung stellen, ohne dass man das "zu Fuss" machen muss.
Deshalb die Frage.

schoschy
Beiträge: 56
Registriert: Di 18. Okt 2022, 15:46

Re: UInt32 aus Filestream lesen

Beitrag von schoschy »

theo hat geschrieben: Mi 10. Jul 2024, 14:15
Socke hat geschrieben: Mi 10. Jul 2024, 13:05 Ich tipper eher auf C++ - public ergibt in C wenig Sinn. Wenn der Autor den ASM-Befehl nicht kennt, gibt es keinen Grund ihn zu nutzen :lol:.
Ja klar, aber der innere "Arbeitscode" ist ja doch C-mässig.
Eigentlich müsste C++ oder C# SwapEndian doch auch zur Verfügung stellen, ohne dass man das "zu Fuss" machen muss.
Jo, gibt es
https://learn.microsoft.com/en-us/dotne ... definition

Benutzeravatar
theo
Beiträge: 10920
Registriert: Mo 11. Sep 2006, 19:01

Re: UInt32 aus Filestream lesen

Beitrag von theo »

schoschy hat geschrieben: Mi 10. Jul 2024, 14:38
theo hat geschrieben: Mi 10. Jul 2024, 14:15
Socke hat geschrieben: Mi 10. Jul 2024, 13:05 Ich tipper eher auf C++ - public ergibt in C wenig Sinn. Wenn der Autor den ASM-Befehl nicht kennt, gibt es keinen Grund ihn zu nutzen :lol:.
Ja klar, aber der innere "Arbeitscode" ist ja doch C-mässig.
Eigentlich müsste C++ oder C# SwapEndian doch auch zur Verfügung stellen, ohne dass man das "zu Fuss" machen muss.
Jo, gibt es
https://learn.microsoft.com/en-us/dotne ... definition
Das nahm ich an. Deshalb ist es umso merkwürdiger, dass es in dem C# Code zu Fuss gemacht wird.

Mathias
Beiträge: 6955
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: UInt32 aus Filestream lesen

Beitrag von Mathias »

Beim Schreiben von Dateien hast du ein ähnliches Problem: Wenn du eine Datei auf einem Big-Endian Computer schreibst, musst du die Zahlen umwandeln, damit auf einem Little-Endian-Computer die richtigen Werte entstehen. Im Gegensatz zum Prozessor kann der Softwareentwickler festlegen, was in der Datei steht.
Da habe ich auch mal geübt.
Bei Java ist auch alles verdreht.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

kirchfritz
Beiträge: 227
Registriert: Mo 3. Jan 2011, 13:34
OS, Lazarus, FPC: Win11 (L 3.0 FPC 3.2.2)
CPU-Target: 64Bit
Wohnort: Nürnberg

Re: UInt32 aus Filestream lesen

Beitrag von kirchfritz »

Scheinbar besteht grosses Interesse daran, in welcher Programmiersprache mein Codebeispiel geschrieben ist.
Guckt doch mal hier:
https://www.youtube.com/watch?v=SO83KQuuZvg

Socke
Lazarusforum e. V.
Beiträge: 3178
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: UInt32 aus Filestream lesen

Beitrag von Socke »

Zvoni hat geschrieben: Mi 10. Jul 2024, 13:15 Ist Dot Crap C#
Und ich muss zu deinem IFDEF widersprechen: Bitte korrigiert mich, falls ich falsch liege, aber $IFDEF ist doch eine Compile-Time-Conditional?
Bedeutet: Wenn ich Kompiliere wird festgelegt: Du wirst auf einer LittleEndian-Maschine kompiliert, als füge den Code für Swap hinzu.
Und die kompilierte EXE nehm ich dann und schieb sie "as is" auf eine BE-Maschine (würde die überhaupt laufen? Gebe zu, da kenn ich mich jetzt gar nicht aus)
Ein Big Endian Prozessor kann keine Little Endian Programme ausführen (und umgekehrt). Es gibt einige Prozessoren, die zwischen beiden Verarbeitungsmethoden umschalten können, das wird aber durch das Betriebssystem festgelegt/gesteuert und ändert sich nicht während deiner Programmausführung.
wp_xyz hat geschrieben: Mi 10. Jul 2024, 13:55 Auch ich habe Bedenken wegen des {$IFDEF}. Denn es gibt Dateien (z.B. PNG, EXIF-Metadaten), in denen sich Big-Endian und Little-Endian-Inhalt je nach Belieben des Erstellers abwechselt. Daher kommt es auf den Zusammenhang an, in dem der Code verwendet wird.
Dann musst aber den Kontext befragen, z.B. ein Flag in deiner Datei. Der C# BitConverter gibt dir Infos zu deiner Laufzeitumgebung (https://learn.microsoft.com/de-de/dotne ... ew=net-8.0) - die kenn deine Datei gar nicht. Da der .NET Common Intermediate Language Code theoretisch auf unterschiedlichen Architekturen laufen kann (muss der dann nur neu gelinkt werden oder kann man die selbe .exe auch wo anders direkt ausführen?), muss es dort im normalen Code umgesetzt werden.

Native Programme können wie oben geschrieben immer nur in ein Binärformat übersetzt werden; daher kann man dort mit Compiler Bedingungen arbeiten - für eine andere Architektur musst es ohnehin neu übersetzen.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2822
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: UInt32 aus Filestream lesen

Beitrag von m.fuchs »

Socke hat geschrieben: Mi 10. Jul 2024, 22:55 Da der .NET Common Intermediate Language Code theoretisch auf unterschiedlichen Architekturen laufen kann (muss der dann nur neu gelinkt werden oder kann man die selbe .exe auch wo anders direkt ausführen?
Da wird nix gelinkt, die .exe enthält CLI-Bytecode und dazu einen kleinen PE-Header der Bescheid sagt dass man .NET braucht bzw. es automatisch startet.
Beim Start wird dann der Bytecode vom JIT-Compiler in den Maschinencode des Systems übersetzt und gestartet.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

Socke
Lazarusforum e. V.
Beiträge: 3178
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: UInt32 aus Filestream lesen

Beitrag von Socke »

m.fuchs hat geschrieben: Mi 10. Jul 2024, 23:54 Da wird nix gelinkt, die .exe enthält CLI-Bytecode und dazu einen kleinen PE-Header der Bescheid sagt dass man .NET braucht bzw. es automatisch startet.
Beim Start wird dann der Bytecode vom JIT-Compiler in den Maschinencode des Systems übersetzt und gestartet.
Den CLI-Bytecode in eine .exe verpacken kann ich im weitesten Sinne als "Linken" verstehen - zumindest werden alle relevanten Bytecode-Dateien eingesammelt und zusammengepackt. Die .exe ist auf anderen Plattformen vermutlich nicht verständlich, oder gibt es unter Linux auch dort einen PE-Loader? Bisher war mir der nur von WINE bekannt.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

kirchfritz
Beiträge: 227
Registriert: Mo 3. Jan 2011, 13:34
OS, Lazarus, FPC: Win11 (L 3.0 FPC 3.2.2)
CPU-Target: 64Bit
Wohnort: Nürnberg

Re: UInt32 aus Filestream lesen

Beitrag von kirchfritz »

Ich wollte eigentlich nur die Bedeutung von

Code: Alles auswählen

const byte ByteMask = 0b11111111;
UINt32 a = (value >> 24) & ByteMask;
UINt32 b = (value >> 16) & ByteMask;
UINt32 c = (value >> 8) & ByteMask;
UINt32 d = (value >> 0) & ByteMask;
value = a << 0 | b << 8 | c << 16 | d <<24
verstehen, und wie man das in PASCAL - Syntax übersetzt.

Antworten