Entwickler-Ecke
Algorithmen, Optimierung und Assembler - 4-Bytes in 1-Integer umwandeln
DevilFish - Mo 15.09.08 23:17
Titel: 4-Bytes in 1-Integer umwandeln
Hallo Leute,
ich bin dabei ein Program zu schreiben welches Dateien im BlowFish verfahren verschlüsselt. Das funktioniert soweit auch ganz gut, allerdings bin ich gerade dabei den Algorithmus etwas zu optimieren und habe dazu ein Fragen. VLt. kann ja jemand helfen.
Gibt es eine Möglichkeit 4 Byte-Variabeln, Bit für Bit, in eine Integer-Variable zu schreiben/kopieren. Und das Ganze auch wieder zurück(Integer -> 4 Byte). Ich suche ein möglichst schnelles Verfahren, da das ganze in einer Schleife immer wieder abläuft.
zB. 11001100 + 10101010 + 00110011 + 00001111 = 11001100/10101010/00110011/00001111
Byte1 + Byte2 + Byte3 + Byte4 = Integer
Meine Lösung:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| var L : LongWord; Buffer : array[1..4] of Byte; . . . For a := 1 to 4 do begin inc(L, Buffer[a]); If b < 4 then L := L shl 8; end;
For a := 4 downto 1 do begin Buffer[a] := L mod 256; If a > 1 then L := L shr 8; end; |
Hat jemand vlt. eine bessere Idee. Würd mich freuen.
mfg DevilFish
Moderiert von
AXMD: Delphi-Tags hinzugefügt
Tilman - Di 16.09.08 00:20
Bin mir jetzt nich ganz sicher wie die Bytes da so im speicher rumliegen, aber soweit ich weis wenn du die als array deklarierst liegen die hintereinander, und folglich müsstest du das direkt als Integer ansprechen können, in dem du den Zeiger auf das erste Byte in einen Integer-Zeiger castest.
Evtl. wäre es auch denkbar es mit einem varianten record zu machen. (--> case-anweisung in records).
Narses - Di 16.09.08 07:05
Moin!
Tilman hat folgendes geschrieben: |
| Evtl. wäre es auch denkbar es mit einem varianten record zu machen. (--> case-anweisung in records). |
Ja, das geht. Z.B. so: ;)
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| type T4Bytes = packed record case Integer of 0: (Bytes: array[0..3] of Byte); 1: (Total: Cardinal); end;
implementation
procedure TForm1.Button1Click(Sender: TObject); var Test: T4Bytes; begin Test.Total := $DEADBEEF; ShowMessageFmt('%p%s%x.%x.%x.%x', [Pointer(Test.Total),#13, Test.Bytes[0],Test.Bytes[1], Test.Bytes[2],Test.Bytes[3]]); end; |
Aber Vorsicht! Intels sind big-endian CPUs! Die Werte sind also genau andersrum in Speicher, als beim binären Zahlensystem, Motorola-CPUs, Network-Byte-Order und wie von dir erwartet. :nixweiss:
cu
Narses
baka0815 - Di 16.09.08 08:24
Ansonsten sollte auch sowas funktionieren:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26:
| var IntVal: Integer; B1, B2, B3: Byte;
begin B1 := 1; B2 := 2; B3 := 3; IntVal := 0; Inc(IntVal, B1); IntVal := IntVal shl 8; Inc(IntVal, B2) IntVal := IntVal shl 8; Inc(IntVal, B3)
B3 := 0; B2 := 0; B1 := 0;
B3 := IntVal and $FF; IntVal := IntVal shr 8; B2 := IntVal and $FF; IntVal := IntVal shr 8; B1 := IntVal and $FF; end; |
Narses - Di 16.09.08 08:39
Moin!
baka0815 hat folgendes geschrieben: |
| Ansonsten sollte auch sowas funktionieren: |
Wo ist denn da jetzt der Unterschied zur Lösung von
DevilFish? :gruebel:
cu
Narses
baka0815 - Di 16.09.08 08:41
Öhm... hust... das hab' ich irgendwie überlesen :roll:
Um hier dann nicht ganz unnütz drin gewesen zu sein:
DevilFish hat folgendes geschrieben: |
Meine Lösung:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| var L : LongWord; Buffer : array[1..4] of Byte; . . . For a := 1 to 4 do begin inc(L, Buffer[a]); If b < 4 then L := L shl 8; end;
For a := 4 downto 1 do begin Buffer[a] := L mod 256; If a > 1 then L := L shr 8; end; | |
Hast du das falsch kopiert? Sollte mich wundern, wenn das mit "b" dort funktioniert. :)
hjm - Di 16.09.08 09:57
Hallo DevilFish,
warum machst Du es nicht einfach mit Schiebeoperationen
Delphi-Quelltext
1: 2: 3: 4: 5: 6:
| var b0,b1,b2,b3 : Byte; GetParamVal : Long; ...
GetParamVal := (b3 SHL 24) + (b2 SHL 16) + (b1 SHL 8) + b0; |
sollte eingentlich recht zügig gehen, da nur Grundop's.
Grüße
baka0815 - Di 16.09.08 10:06
hjm hat folgendes geschrieben: |
Hallo DevilFish,
warum machst Du es nicht einfach mit Schiebeoperationen |
Entweder willst du mich veräppeln oder ich bin tatsächlich nicht der Einzige, der's überlesen hat. ;)
Lossy eX - Di 16.09.08 10:42
Auch wenn das Problem bereits gelöst wurde. Eine Schleife mit einer konstanten Anzahl an durchlaufen ist der Overkill. Die sollte man durch das Wiederholen des Codes ausrollen. Die Schiebeopratoren sind gut. Allerdings sollte man dann auch die Addition bzw das Inc (was auch zur addition wird) sein lassen. Dazu kann man auch den Operator OR benutzen. Denn der fügt nur unterschiedliche Inhalte zusammen und das ist im Endeffekt das Gleiche, nur ohne mathematische Operationen. Allerdings kann man dort auch mit Assembler arbeiten, dann würde man durch die Benutzung der Register AL und AH lediglich noch ein einziges Schieben benötigen und hätte sonst nur simple Zuweisungen ganz ohne irgendwelche Operationen.
Allerdings ist selbst die Variante in Assembler mit Aufwand verbunden. Und sei es nur der Aufwand eine Methode aufzurufen (der häufig einfach ignoriert wird). Aufwand der eigentlich dadurch umgangen werden kann in dem man dafür sorgt, dass die einzelnen Variablen sich einen Speicherbereich teilen. Denn dann muss man nur entscheiden wie man drauf zugreifen möchte. Und diese Möglichkeit hatte
Narses bereits gezeigt. Ich denke etwas schnelleres wird es nicht geben. Das case in dem Record ist im übrigen nicht nur auf 2 Einträge beschränkt. Man kann auch auch ein case für 2 Words einfügen etc. Oder was man halt sonst noch benötigt.
Eine andere Alternative zu Speicherteilen ist der Operator absolute. Damit teilt man dem Kompiler mit, dass die Speicherstelle an der Adresse der Anderen liegt. Allerdings wenn man sich mit der Zielvariable vertut, dann kann man sich ziemlich schnell irgendwas kaput machen. Also lieber die Recordvariante auch wenn die mehr Schreibarbeit bedeutet.
Narses - Di 16.09.08 11:05
Moin!
Lossy eX hat folgendes geschrieben: |
| Allerdings ist selbst die Variante in Assembler mit Aufwand verbunden. |
Ich hätte da nochmal eine Frage zum byte-sex der CPUs, ist ja die richtige Sparte hier und leidlich ins Thema passen tut´s auch. ;)
Ich habe mir von Leuten, die es wissen sollten, sagen lassen, dass man bei "modernen" CPUs (also damals... :lol: es ging um Intel x86 und PowerPC) den byte-sex im Steuerregister umschalten kann! :idea: Man könnte also theoretisch vor einer Lese-Operation von big- auf little-endian switchen und dann wieder zurück, analog beim Schreiben. :D
Geht das? Wenn ja, wie? :nixweiss:
cu
Narses
Lossy eX - Di 16.09.08 11:53
Ich muss gestehen da haste mich jetzt ein bisschen eiskalt erwischt. :P Ohne mein schlaues Buch weiß ich kaum etwas. Und das liegt zu Hause.
Ob es ein Flag gibt, was das automatisiert steuert, weiß ich nicht. Allerdings gibt es den Befehl BSWAP. Der tauscht in einem Rutsch in einem 32 Bit Register die Bytes 1 mit 4 und 2 mit 3. Also dreht genau die Reihenfolge der Bytes um.
BenBE - Di 16.09.08 12:46
Narses hat folgendes geschrieben: |
Aber Vorsicht! Intels sind big-endian CPUs! Die Werte sind also genau andersrum in Speicher, als beim binären Zahlensystem, Motorola-CPUs, Network-Byte-Order und wie von dir erwartet. :nixweiss:
cu
Narses |
Also Narses!!! Intel's sind die TYPISCHEN Vertreter für
Little Endian! :mahn:
Big-Endian sind z.B. die ganzen Sun-Kisten, die Java-VM, die ganzen Motorola-Prozessoren (der 68k z.B.) und die gesamte Übertragung im Netzwerk (Network Order), was auch von den ganzen Sun-Mainframes herrührt, die dominant waren, als die ganzen RFCs entwickelt wurden.
Und ein Zahlensystem an sich kann nicht Little-Endian oder Big-Endian per se sein. Ich kann auch
11111110bLE schreiben und habe damitim Binärzahlensystem Little-Endian genutzt. Was du sicherlich meintest war, dass man auf dem Papier typischerweise Big Endian verwendet, da dieses einfach gewohnt für uns ist.
@Narses: k, fühlt sich gut an, das auch mal bei Dir zu machen, wenn Du das sonst immer in meinem TuDorial machst ;-)
Narses - Di 16.09.08 13:17
Moin!
BenBE hat folgendes geschrieben: |
| Also Narses!!! Intel's sind die TYPISCHEN Vertreter für Little Endian! :mahn: |
Jaja, hast ja recht :roll: hab´s mal wieder verwechselt... :nut: Hätte mal direkt
hier reinsehen [
http://de.wikipedia.org/wiki/Big-endian] sollen... *seufz*
cu
Narses
DevilFish - Di 16.09.08 20:25
Danke für die vielen Antworten.
Ich werd mal Narses Ansatz probieren. Leider zieht diese Methode noch gravierende Änderungen der Proceduren zum lesen/schreiben und ver- und entschlüsseln nach sich, da ich 2048 Byte auf einmal einlese und unnötige weitere herumschieberei der Daten verhindern möchte.
Hab mir das so gedacht: Buffer : array[1..512] of T4Byte;
Und damit dann 2048 Blöcke auslesen.
@baka0815: Ja das b steht da falsch, ist im Original aber alles am rechten Fleck. :)
Ist wohl bei copy/paste und schnell was ändern und dazuschreiben was falsch
gelaufen.
mfg DevilFish
---
Moderiert von
Narses: Beiträge zusammengefasst---
Und verdammte Axt, es geht alles auf anhieb.
vielen Dank Narses. :zustimm:
Narses - Di 16.09.08 21:34
Moin!
Bitte, gern geschehen. :)
Markierst du den Thread noch entsprechend, wenn dein Problem gelöst ist? Danke. ;)
cu
Narses
Greenberet - Mi 17.09.08 06:55
Narses hat folgendes geschrieben: |
Ich habe mir von Leuten, die es wissen sollten, sagen lassen, dass man bei "modernen" CPUs (also damals... :lol: es ging um Intel x86 und PowerPC) den byte-sex im Steuerregister umschalten kann! :idea: Man könnte also theoretisch vor einer Lese-Operation von big- auf little-endian switchen und dann wieder zurück, analog beim Schreiben. :D
Geht das? Wenn ja, wie? :nixweiss: |
Es existieren Prozessoren, z. B. bestimmte MIPS-Varianten und PowerPC unter Windows NT, die zwischen Little Endian und Big Endian umschaltbar sind. Auch ARM-Prozessoren (inkl. des Intel XScales) können sowohl Little als auch Big Endian betrieben werden.
Quelle = WIKI^^ [
http://de.wikipedia.org/wiki/Big-endian#Mischvarianten_.28Bi-Endian.29]
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!