Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   einzelne bytes in ein 4-byte int umwandeln (https://www.delphipraxis.net/192101-einzelne-bytes-ein-4-byte-int-umwandeln.html)

JayZ 20. Mär 2017 15:08

einzelne bytes in ein 4-byte int umwandeln
 
hallo

es gibt doch in c++ den operator >> mit dem man irgendwie bytes rumschrieben kann. kann man in delphi irgendwie 4 bytes definieren und dann diese vier bytes zussamenfügen das es das ergiebt:

Delphi-Quellcode:
var
 b1, b2, b3, b4 : byte;
 int : integer;
begin
 b1 := $AB;
 b2 := $CD;
 b3 := $EF;
 b4 := $42;
// int := $ABCDEF42;
end;
am liebsten math operationen, ich krieg nur ein string gewrustel hin :(

dankeschon mal! :stupid:

Geda 20. Mär 2017 15:16

AW: einzelne bytes in ein 4-byte int umwandeln
 
var
b1, b2, b3, b4 : byte;
int : integer;
begin
b1 := $AB;
b2 := $CD;
b3 := $EF;
b4 := $42;

int := b1;
int := (int shl 8) + b2;
int := (int shl 8) + b3;
int := (int shl 8) + b4;

ShowMessage(IntToHex(int, 8));


Gruß,

Geert

DeddyH 20. Mär 2017 15:23

AW: einzelne bytes in ein 4-byte int umwandeln
 
Es ginge auch mit einem varianten Record:
Delphi-Quellcode:
type
  TZahl = record
    case integer of
      1: (Zahl: integer);
      2: (b4, b3, b2, b1: Byte)
  end;


procedure TFormTest.FormCreate(Sender: TObject);
var
  Zahl: TZahl;
begin
  Zahl.b1 := $AB;
  Zahl.b2 := $CD;
  Zahl.b3 := $EF;
  Zahl.b4 := $42;
  ShowMessage(IntToHex(Zahl.Zahl, 8));
end;

Neutral General 20. Mär 2017 15:44

AW: einzelne bytes in ein 4-byte int umwandeln
 
Oder in einer Zeile ohne Records:

Delphi-Quellcode:
Int := (B1 shl 24) or (B2 shl 16) or (B3 shl 8) or B4;

JayZ 20. Mär 2017 15:51

AW: einzelne bytes in ein 4-byte int umwandeln
 
wow das sind aber viele möglichkeiten hehe
vielen vielen dank euch allen =)

p80286 20. Mär 2017 15:55

AW: einzelne bytes in ein 4-byte int umwandeln
 
oder so:

Delphi-Quellcode:
var
  i : integer;
  b : Array [0..3] of Byte absolute i;

begin
  b[0]:=$AB;
  b[1]:=$CD;
  b[2]:=$EF;
  b[3]:=$42;
end;
(:hi: Mavarik)

Gruß
K-H

Uwe Raabe 20. Mär 2017 15:58

AW: einzelne bytes in ein 4-byte int umwandeln
 
Ähnlich dem, was DeddyH gezeigt hat, nur mit Bordmitteln:
Delphi-Quellcode:
var
  Zahl: LongRec; { in Sysutils }
begin
  Zahl.Bytes[0] := $AB;
  Zahl.Bytes[1] := $CD;
  Zahl.Bytes[2] := $EF;
  Zahl.Bytes[3] := $42;
  ShowMessage(Integer(Zahl).ToHexString(8));
end;
Oder unter Verwendung von Winapi.Windows:

Delphi-Quellcode:
  ShowMessage(MakeLong(MakeWord($42, $EF), MakeWord($CD, $AB)).ToHexString(8));

Rollo62 20. Mär 2017 16:04

AW: einzelne bytes in ein 4-byte int umwandeln
 
Die Frage die ich mir immer stelle ist: Was ist denn jetzt das Schnellste ?

DeddyHs und Mavariks Lösungen habe ich ja im Verdacht ganz gut zu sein.

Aber es könnte am Ende doch NeutralGeneral der Gewinner sein,
weil da der Compiler die Chance hat bis auf die Knochen zu optimieren.

Hat das schonmal mal einer vermessen ?

Rollo

Neutral General 20. Mär 2017 16:17

AW: einzelne bytes in ein 4-byte int umwandeln
 
Die Record-Varianten (und das absolute) sind wahrscheinlich am schnellsten weil da quasi gar nichts gerechnet wird.

p80286 20. Mär 2017 16:40

AW: einzelne bytes in ein 4-byte int umwandeln
 
Frage:
muß das nicht
Delphi-Quellcode:
packed record
sein?
oder ist das bei varianten Records automatisch dabei?

Gruß
K-H

Zacherl 20. Mär 2017 16:50

AW: einzelne bytes in ein 4-byte int umwandeln
 
Zitat:

Zitat von p80286 (Beitrag 1364856)
muß das nicht
Delphi-Quellcode:
packed record
sein?
oder ist das bei varianten Records automatisch dabei?

Ja, sollte der Sicherheit halber
Delphi-Quellcode:
packed
sein, wobei in diesem Falle kein Padding und Aligning stattfinden sollte.

t.roller 20. Mär 2017 17:08

AW: einzelne bytes in ein 4-byte int umwandeln
 
Alles schon mal dagewesen...

p80286 20. Mär 2017 17:50

AW: einzelne bytes in ein 4-byte int umwandeln
 
das nennt man "Weitergabe des Wissens" und ist unsere Daseinsberechtigung.

Gruß
K-H

t.roller 20. Mär 2017 20:49

AW: einzelne bytes in ein 4-byte int umwandeln
 
Noch eine Lösung:
Delphi-Quellcode:
procedure TForm1.ButtonClick(Sender: TObject);
var
aByte  : Packed array[0..3] of Byte;
dwErgebnis : DWord absolute aByte;
begin
  //Einzelbyte eintragen
  aByte[0] :=$10;
  aByte[1] :=$20;
  aByte[2] :=$30;
  aByte[3] :=$40;
  //Ergebnis verwenden
  Label1.Caption:= IntToStr(dwErgebnis);
end;

Mavarik 20. Mär 2017 21:31

AW: einzelne bytes in ein 4-byte int umwandeln
 
Zitat:

Zitat von p80286 (Beitrag 1364842)
(:hi: Mavarik)

Thanx...

JayZ 21. Mär 2017 21:35

AW: einzelne bytes in ein 4-byte int umwandeln
 
Zitat:

Zitat von Neutral General (Beitrag 1364840)
Oder in einer Zeile ohne Records:

Delphi-Quellcode:
Int := (B1 shl 24) or (B2 shl 16) or (B3 shl 8) or B4;

Sorry das ich nochmal nachfrage aber gäbe es auch so einen einzeiler (pro byte) um das umgekehrte zu machen?

Also zb:
Delphi-Quellcode:
Int := $ABCDEF42;
byte1 := $AB; // get first byte from int
byte2 := $CD; // get 2nd byte from int
byte3 := $EF; // get 3rd byte from int
byte4 := $42; // get 4th byte from int
danke :)

Uwe Raabe 21. Mär 2017 21:54

AW: einzelne bytes in ein 4-byte int umwandeln
 
Zitat:

Zitat von JayZ (Beitrag 1364988)
Sorry das ich nochmal nachfrage aber gäbe es auch so einen einzeiler (pro byte) um das umgekehrte zu machen?

Delphi-Quellcode:
byte1 := LongRec(Value).Bytes[0];
byte2 := LongRec(Value).Bytes[1];
byte3 := LongRec(Value).Bytes[2];
byte4 := LongRec(Value).Bytes[3];

JayZ 21. Mär 2017 22:10

AW: einzelne bytes in ein 4-byte int umwandeln
 
geil danke! da werden mir ja ganz neue seiten von delphi gezeit :D nur so aus interesse... gibts da auch ne möglichkeit mit shl und shr die nicht allzu komplex ist? :stupid:

Uwe Raabe 21. Mär 2017 22:30

AW: einzelne bytes in ein 4-byte int umwandeln
 
Zitat:

Zitat von JayZ (Beitrag 1364991)
geil danke! da werden mir ja ganz neue seiten von delphi gezeit :D nur so aus interesse... gibts da auch ne möglichkeit mit shl und shr die nicht allzu komplex ist? :stupid:

Nee, nicht wirklich:

Delphi-Quellcode:
function GetByte(Index, Value: Integer): Byte;
var
  BitsToShift: Integer;
begin
  BitsToShift := (Index xor 3) shl 3;
  result := (Value and ($FF shl BitsToShift)) shr BitsToShift;
end;

Zacherl 21. Mär 2017 22:43

AW: einzelne bytes in ein 4-byte int umwandeln
 
Zitat:

Zitat von JayZ (Beitrag 1364991)
gibts da auch ne möglichkeit mit shl und shr die nicht allzu komplex ist? :stupid:

Die nicht-generische Variante ist etwas verständlicher:
Delphi-Quellcode:
B1 := DW and $FF;
B2 := (DW shr 8) and $FF;
B3 := (DW shr 16) and $FF;
B4 := (DW shr 24) and $FF;

OlafSt 22. Mär 2017 07:51

AW: einzelne bytes in ein 4-byte int umwandeln
 
Wenn es nicht 64-Bit sein muß, dann ginge auch noch sowas:

Delphi-Quellcode:
var
   b1,b2,b3,b4: byte;
begin
   Int:=$ABCDEF42;
   asm
      mov eax,Int
      mov b4,al
      mov b3,ah
      shl eax,2
      mov b2,al
      mov b1,ah
   end;
end;

p80286 22. Mär 2017 15:01

AW: einzelne bytes in ein 4-byte int umwandeln
 
Zitat:

Zitat von OlafSt (Beitrag 1365011)
Wenn es nicht 64-Bit sein muß, dann ginge auch noch sowas:

Delphi-Quellcode:
var
   b1,b2,b3,b4: byte;
begin
   Int:=$ABCDEF42;
   asm
      mov eax,Int
      mov b4,al
      mov b3,ah
      shl eax,2
      mov b2,al
      mov b1,ah
   end;
end;

Müßte es nicht
Delphi-Quellcode:
shl eax,16
Heißen?

Gruß
K-H

JayZ 23. Mär 2017 18:40

AW: einzelne bytes in ein 4-byte int umwandeln
 
Wow an eine inline assembly lösung dachte ich gar nicht. (Zum glück habe ich mir das vor ein paar wochen angefangen anzueignen :D)

So gehts: (shr eax, 16 ; wars ;))
Delphi-Quellcode:
procedure TForm1.btn1Click(Sender: TObject);
var
  LInt : integer;

  LB1, LB2, LB3, LB4 : Byte;
begin
  LInt := $DEADBEEF;

  asm
    mov eax, LInt
    mov LB4, al
    mov LB3, ah
    shr eax, 16
    mov LB2, al
    mov LB1, ah
  end;

  ShowMessage(
    IntToHex(LB1, 2) +
    IntToHex(LB2, 2) +
    IntToHex(LB3, 2) +
    IntToHex(LB4, 2)
  );
end;
danke :)

Zacherl 23. Mär 2017 19:10

AW: einzelne bytes in ein 4-byte int umwandeln
 
Von inline Assembly würde ich abraten. Ist zwar tatsächlich schneller, als die vom Delphi Compiler ziemlich hirnlos generierte Übersetzung des Pascal Äquivalents, aber:
  1. es lässt sich deutlich schlechter lesen
  2. es ist verdammt Fehler-anfällig und schlecht zu warten
  3. 64-Bit unterstützt kein inline Assembly

Wenn du es doch umbedingt verwenden willst, dann solltest du dran denken volatile Register zu preserven:
Delphi-Quellcode:
asm
  push eax
  ..
  pop eax
end;
In der Standard Calling-Convention von Delphi wird EAX zwar final als Return-Value verwendet, aber theoretisch steht es dem Compiler frei auch mitten in der Funktion irgendwelche Werte in EAX abzulegen, die vielleicht nach deinem Assembler Block nochmal gebraucht werden.

JayZ 23. Mär 2017 19:23

AW: einzelne bytes in ein 4-byte int umwandeln
 
stimmt, danke für den hinweis! =)

OlafSt 23. Mär 2017 22:04

AW: einzelne bytes in ein 4-byte int umwandeln
 
Die ersten zwei Punkte kann man in diesem speziellen Fall nun wirklich ignorieren. Ein Kommentar hin und gut ist.

Weiterhin lassen sich manche Dinge in inline-ASM wirklich elegant lösen (wie dieses hier z.B. oder auch Little-Endian nach Big-Endian z.B.) - aber auch das sind nur maximal 4-Zeiler und mehr als das würde auch ich nicht empfehlen in Inline-ASM.

Genug OT ;)


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:40 Uhr.

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