Reverse CRC16

  • C#
  • .NET (FX) 1.0–2.0

Es gibt 13 Antworten in diesem Thema. Der letzte Beitrag () ist von Niko Ortner.

    Reverse CRC16

    Hallo Community,

    Ich nutze folgende CRC16 Implementierung (Es gibt ja sehr viele versch.) :

    C#-Quellcode

    1. public class CRC16
    2. {
    3. private static readonly ushort[] CrcTable = {
    4. 0X0000, 0XC0C1, 0XC181, 0X0140, 0XC301, 0X03C0, 0X0280, 0XC241,
    5. 0XC601, 0X06C0, 0X0780, 0XC741, 0X0500, 0XC5C1, 0XC481, 0X0440,
    6. 0XCC01, 0X0CC0, 0X0D80, 0XCD41, 0X0F00, 0XCFC1, 0XCE81, 0X0E40,
    7. 0X0A00, 0XCAC1, 0XCB81, 0X0B40, 0XC901, 0X09C0, 0X0880, 0XC841,
    8. 0XD801, 0X18C0, 0X1980, 0XD941, 0X1B00, 0XDBC1, 0XDA81, 0X1A40,
    9. 0X1E00, 0XDEC1, 0XDF81, 0X1F40, 0XDD01, 0X1DC0, 0X1C80, 0XDC41,
    10. 0X1400, 0XD4C1, 0XD581, 0X1540, 0XD701, 0X17C0, 0X1680, 0XD641,
    11. 0XD201, 0X12C0, 0X1380, 0XD341, 0X1100, 0XD1C1, 0XD081, 0X1040,
    12. 0XF001, 0X30C0, 0X3180, 0XF141, 0X3300, 0XF3C1, 0XF281, 0X3240,
    13. 0X3600, 0XF6C1, 0XF781, 0X3740, 0XF501, 0X35C0, 0X3480, 0XF441,
    14. 0X3C00, 0XFCC1, 0XFD81, 0X3D40, 0XFF01, 0X3FC0, 0X3E80, 0XFE41,
    15. 0XFA01, 0X3AC0, 0X3B80, 0XFB41, 0X3900, 0XF9C1, 0XF881, 0X3840,
    16. 0X2800, 0XE8C1, 0XE981, 0X2940, 0XEB01, 0X2BC0, 0X2A80, 0XEA41,
    17. 0XEE01, 0X2EC0, 0X2F80, 0XEF41, 0X2D00, 0XEDC1, 0XEC81, 0X2C40,
    18. 0XE401, 0X24C0, 0X2580, 0XE541, 0X2700, 0XE7C1, 0XE681, 0X2640,
    19. 0X2200, 0XE2C1, 0XE381, 0X2340, 0XE101, 0X21C0, 0X2080, 0XE041,
    20. 0XA001, 0X60C0, 0X6180, 0XA141, 0X6300, 0XA3C1, 0XA281, 0X6240,
    21. 0X6600, 0XA6C1, 0XA781, 0X6740, 0XA501, 0X65C0, 0X6480, 0XA441,
    22. 0X6C00, 0XACC1, 0XAD81, 0X6D40, 0XAF01, 0X6FC0, 0X6E80, 0XAE41,
    23. 0XAA01, 0X6AC0, 0X6B80, 0XAB41, 0X6900, 0XA9C1, 0XA881, 0X6840,
    24. 0X7800, 0XB8C1, 0XB981, 0X7940, 0XBB01, 0X7BC0, 0X7A80, 0XBA41,
    25. 0XBE01, 0X7EC0, 0X7F80, 0XBF41, 0X7D00, 0XBDC1, 0XBC81, 0X7C40,
    26. 0XB401, 0X74C0, 0X7580, 0XB541, 0X7700, 0XB7C1, 0XB681, 0X7640,
    27. 0X7200, 0XB2C1, 0XB381, 0X7340, 0XB101, 0X71C0, 0X7080, 0XB041,
    28. 0X5000, 0X90C1, 0X9181, 0X5140, 0X9301, 0X53C0, 0X5280, 0X9241,
    29. 0X9601, 0X56C0, 0X5780, 0X9741, 0X5500, 0X95C1, 0X9481, 0X5440,
    30. 0X9C01, 0X5CC0, 0X5D80, 0X9D41, 0X5F00, 0X9FC1, 0X9E81, 0X5E40,
    31. 0X5A00, 0X9AC1, 0X9B81, 0X5B40, 0X9901, 0X59C0, 0X5880, 0X9841,
    32. 0X8801, 0X48C0, 0X4980, 0X8941, 0X4B00, 0X8BC1, 0X8A81, 0X4A40,
    33. 0X4E00, 0X8EC1, 0X8F81, 0X4F40, 0X8D01, 0X4DC0, 0X4C80, 0X8C41,
    34. 0X4400, 0X84C1, 0X8581, 0X4540, 0X8701, 0X47C0, 0X4680, 0X8641,
    35. 0X8201, 0X42C0, 0X4380, 0X8341, 0X4100, 0X81C1, 0X8081, 0X4040 };
    36. public static ushort ComputeCrc(byte[] data)
    37. {
    38. ushort crc = 0;
    39. for (int i = 0; i < data.Length; ++i)
    40. {
    41. byte index = (byte)(crc ^ data[i]);
    42. crc = (ushort)((crc >> 8) ^ CrcTable[index]);
    43. }
    44. return crc;
    45. }
    46. }


    Ich habe gehört CRC16 kann zurückgerechnet werden, der normale Hash-Vorgang wäre :

    C#-Quellcode

    1. result = CRC16(value);


    Nun gilt es das inverse zu finden, d.h. ein byte array arr, welches, wenn davon der CRC16 wert berechnet wird in dem parameter num resultiert.

    C#-Quellcode

    1. arr = ReverseCRC16(num);


    CRC16 scheint nicht mehr als eine Polynomberechnung zu sein, dementsprechend gehe ich davon aus das diese eindeutig zurückgerechnet werde kann?
    Kann mir jemand helfen wie ich das anstellen kann?
    C# Developer
    Learning C++

    Rikudo schrieb:

    Ich habe gehört CRC16 kann zurückgerechnet werden
    Ich denke mal nicht, denn da wird aus einem byte[]-Array ein ushort.
    Da ist bereits die Bestimmung der Länge des Arrays, was Du ausrechnen willst, vergebliche Lebensmüh. ;(
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @Rikudo Ein CRC-Wert ist so was wie eine Prüfsumme, und die wird üblicherweise auf große Darenfelder angewendet.
    Da macht Deine Annahme wenig Sinn.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    schau mal hier rein:
    danielvik.com/2010/10/calculating-reverse-crc.html
    Mit "zurückrechnen" hat das weniger zu tun als mit "reverse engineering" um eine Nachricht so zu modifizieren, dass sie nach wie vor den selben CRC ausspuckt.

    Wäre doch auch besorgniserregend, wenn ich aus ner 300MB Datei nen 2/4 Byte Hash machen kann, den verschicke, und diesen an der Gegenstelle wieder zurückrechnen kann.
    Das wäre der heilige Gral der komprimierung.
    Das ist mir bewusst.
    Allerdings (sollte?) meine Annahme schon sinn machen.
    Da der oben gepostete CRC16-Algorithmus einen ushort returned gibt es nur eine begrenzte Anzahl an "Ergebnissen".
    Da ein ushort eine Range von 0 to 65,535 bietet, und man 65,535 mit 2 bytes darstellen kann und ich davon ausgehe das es
    für den Bereich 0-65535 (als bytearray) keine Kollisionen gibt denke ich das man für jeden möglichen Hashwert ein 2-byte grosses array erzeugen kann.
    (Naturlich gibt es fur großere Arrays Kollisionen!)

    Nur eine Vermutung.
    C# Developer
    Learning C++
    Aber es ist nicht garantiert (das heißt, falls das nicht tatsächlich schon bewiesen wurde), dass es in den 2^16 Möglichkeiten keine Duplikate gibt. Also es kann vielleicht passieren, dass CRC16(a) == CRC16(b) && a != b. Und wenn das der Fall ist, dann gibt es mindestens ein Ergebnis, das Du nicht mit einem der 2^16 verschiedenen Parameterwerten erreichen kannst.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    @Niko Ortner : Ich habe testweise alle Zahlen von 0 bis 65535 in ein Bytearray konvertiert und davon die CRC16 generiert.
    Es gab bei allen 65535 Ergebnissen keine Duplikate.
    Ziel ist es ja nicht den ursprünglichen Output zu finden sondern eine Kollision, d.h. ein (zufälliges) bytearray welches in einem bestimmten CRC16 wert resultiert.
    C# Developer
    Learning C++
    wenn du fest davon ausgehst, dass du 2 Byte input hast, dann berechne doch einfach alle 65536 crcs und mach nen lookup. Ist aufjedenfall einfach und schnell. Das erzeugen vorher passiert einmalig, danach ists einfach nen array lookup mit Index, somit O(1) und die 64kb Speicher die das Array verbraucht interessiert aufm PC auch niemand.
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Seh ich aktuell nicht. Die einzige Möglichkeit die ich seh ist wenn du bei jedem Divisionsschritt weißt, wie viele Stellen dabei "aufgingen" und das ist nicht aus dem Endwert auslesbar. Evtl. gibt es einen anderen mathematischen Zusammenhang, aber den erkenn ich auf jedenfall nicht.

    Wie gesagt 64kb sind nichts außerdem ist performance wichtiger als Memory, denn davon hat man idR genug, vorallem wenn man den RAM Zuwachs und Geschwindigkeitsincrease der letzten Jahre vergleicht.
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    @jvbsl
    Bzw. 128kib, weil wegen 2 Bytes pro Eintrag.
    @Rikudo
    Ich finde zwar auch, dass das eine akzeptable Lösung wäre, aber ich hab mich mal spaßeshalber drangesetzt und es ausprobiert.
    Lösungsweg

    Ich habe es in VB geschrieben, da einige unschöne Konvertierungen wegfallen, die in C# nötig sind. (Der XOR-Operator gibt in C# immer int zurück, in VB praktischerweise den Typ des größten Operanden. Ähnliches Problem beim Shiften.)
    Die originale Funktion sieht, geringfügig vereinfacht, so aus:

    VB.NET-Quellcode

    1. Public Shared Function OriginalComputeCrc(data As Byte()) As UInt16
    2. Dim crc As UInt16 = 0
    3. For i = 0 To data.Length - 1
    4. Dim TableValue As UInt16 = CrcTable(CByte(crc And &HFF) Xor data(i))
    5. crc = (crc >> 8) Xor TableValue
    6. Next
    7. Return crc
    8. End Function

    Wir wissen aber, dass data immer genau 2 Elemente groß ist. Deshalb können wir den Loop ausrollen:

    VB.NET-Quellcode

    1. Public Shared Function Expanded1ComputeCrc(data As Byte()) As UInt16
    2. Dim crc As UInt16 = 0
    3. Dim TableValue As UInt16 = CrcTable(CByte(crc And &HFF) Xor data(0))
    4. crc = (crc >> 8) Xor TableValue
    5. TableValue = CrcTable(CByte(crc And &HFF) Xor data(1))
    6. crc = (crc >> 8) Xor TableValue
    7. Return crc
    8. End Function

    Um zu vermeiden, dass in irgendwelche Variablen (nach der Deklaration und Initialisierung nochmal) geschrieben werden (was später nur unnötige Komplikationen ergeben würde) noch etwas umgeformt. Da, wo die crc-Variable zum ersten Mal verwendet wurde, habe ich direkt den Startwert (0) eingefügt.

    VB.NET-Quellcode

    1. Public Shared Function Expanded2ComputeCrc(data As Byte()) As UInt16
    2. Dim TableValueA As UInt16 = CrcTable(CByte(0US And &HFF) Xor data(0))
    3. Dim crcA As UInt16 = (0US >> 8) Xor TableValueA
    4. Dim TableValueB As UInt16 = CrcTable(CByte(crcA And &HFF) Xor data(1))
    5. Dim crcB As UInt16 = (crcA >> 8) Xor TableValueB
    6. Return crcB
    7. End Function

    Dadurch kann extrem vereinfacht werden. Der Shift fällt beim ersten Mal weg und der Index in die Tabelle ist beim ersten Mal garantiert immer nur data(0). Und TableValueA fällt weg.

    VB.NET-Quellcode

    1. Public Shared Function Expanded3ComputeCrc(data As Byte()) As UInt16
    2. Dim crcA As UInt16 = CrcTable(data(0))
    3. Dim TableValueB As UInt16 = CrcTable(CByte(crcA And &HFF) Xor data(1))
    4. Dim crcB As UInt16 = (crcA >> 8) Xor TableValueB
    5. Return crcB
    6. End Function

    Um besser darzustellen, wie die einzelnen Bytes der crcA- und crcB-Variablen verwendet werden ersetze ich den Shift und das And &HFF durch extensions, die es verständlicher machen:

    VB.NET-Quellcode

    1. Public Module Extensions
    2. <Extension()>
    3. Public Function Byte0(Target As UInt16) As Byte
    4. Return CByte(Target And &HFF)
    5. End Function
    6. <Extension()>
    7. Public Function Byte1(Target As UInt16) As Byte
    8. Return CByte(Target >> 8)
    9. End Function
    10. End Module

    Außerdem gibt die Funktion nun die Bytes separat zurück und nimmt sie separat entgegen.

    VB.NET-Quellcode

    1. Public Shared Function Expanded4ComputeCrc(data0 As Byte, data1 As Byte) As Tuple(Of Byte, Byte)
    2. Dim crcA As UInt16 = CrcTable(data0)
    3. Dim TableValueB As UInt16 = CrcTable(crcA.Byte0 Xor data1)
    4. Dim crcB As UInt16 = crcA.Byte1 Xor TableValueB
    5. Return Tuple.Create(crcB.Byte1, crcB.Byte0)
    6. End Function

    Das hat den Sinn, dass man das zweite Xor jetzt besser auf die einzelnen Bytes aufteilen kann. Denn der linke Operand ist nur 1 Byte groß. Also wird das Byte1 von TableValueB garantiert mit 0 ge-Xor-t, also nicht verändert:

    VB.NET-Quellcode

    1. Public Shared Function Expanded4ComputeCrc(data0 As Byte, data1 As Byte) As Tuple(Of Byte, Byte)
    2. Dim crcA As UInt16 = CrcTable(data0)
    3. Dim TableValueB As UInt16 = CrcTable(crcA.Byte0 Xor data1)
    4. Dim crcB1 As Byte = TableValueB.Byte1
    5. Dim crcB0 As Byte = crcA.Byte1 Xor TableValueB.Byte0
    6. Return Tuple.Create(crcB1, crcB0)
    7. End Function

    Dadurch fällt auch crcB1 weg. Jetzt habe ich noch das erste Xor herausgenommen und was übrig bleibt ist eine ganz simple Liste von einzelnen Operationen, die man Zeile für Zeile behandeln kann.

    VB.NET-Quellcode

    1. Public Shared Function Expanded5ComputeCrc(data0 As Byte, data1 As Byte) As Tuple(Of Byte, Byte)
    2. Dim crcA As UInt16 = CrcTable(data0)
    3. Dim XorResultA As UInt16 = crcA.Byte0 Xor data1
    4. Dim TableValueB As UInt16 = CrcTable(XorResultA)
    5. Dim crcB0 As Byte = crcA.Byte1 Xor TableValueB.Byte0
    6. Return Tuple.Create(TableValueB.Byte1, crcB0)
    7. End Function

    Die Umkehr-Funktion nimmt ebenfalls zwei Bytes entgegen und gibt zwei zurück, aber die Parameter sollten natürlich nicht data0 und data1 heißen, sondern so, wie die Dinge, die in der normalen Funktion zurückgegeben wurden:

    VB.NET-Quellcode

    1. Public Shared Function Reverse1Crc(TableValueB_Byte1 As Byte, crcB0 As Byte) As Tuple(Of Byte, Byte)
    2. '-------------------------------------------------------
    3. Dim crcA As UInt16 = CrcTable(data0)
    4. Dim XorResultA = crcA.Byte0 Xor data1
    5. Dim TableValueB As UInt16 = CrcTable(XorResultA)
    6. Dim crcB0 As Byte = crcA.Byte1 Xor TableValueB.Byte0
    7. Return Tuple.Create(TableValueB.Byte1, crcB0)
    8. End Function

    Um die Funktion umzudrehen wird einfach immer die letzte Zeile genommen, umgekehrt und über die eingezeichnete Linie geschrieben. Das Return ergibt sich bereits durch die Parameter, also kann man das weglassen.
    Beim Xor gibt es aber ein Problem. crcB0 ist ja bekannt. Aber es gibt unterschiedliche Kombinationen von crcA.Byte1 und TableValueB.Byte0, die auf dieses Ergebnis kommen könnten. Also kann man das Xor nicht einfach umdrehen. Das ignoriere ich jetzt einfach mal. Stattdessen deklariere ich die Operanden manuell und schreibe danach das hin, dass sie zusammen XorResultA ergeben sollen. Und Punkte in den Namen sind durch Unterstriche ersetzt.

    VB.NET-Quellcode

    1. Public Shared Function Reverse2Crc(TableValueB_Byte1 As Byte, crcB0 As Byte) As Tuple(Of Byte, Byte)
    2. Dim crcA_Byte1 As Byte, TableValueB_Byte0 As Byte
    3. 'crcA_Byte1 Xor TableValueB_Byte0 = crcB0
    4. '-------------------------------------------------------
    5. Dim crcA As UInt16 = CrcTable(data0)
    6. Dim XorResultA = crcA.Byte0 Xor data1
    7. Dim TableValueB As UInt16 = CrcTable(XorResultA)
    8. End Function

    Das Rausholen eines Wertes aus der Tabelle lässt sich umkehren. Allerdings wird TableValueB als UInt16 benötigt. Deshalb noch eine kleine Hilfsunktion, die zwei Bytes zu einem UInt16 zusammenstellt. Und Array.IndexOf gibt natürlich einen Integer zurück. Wir wissen, dass es nur Indices bis 255 gibt, deshalb konvertieren wir manuell:

    VB.NET-Quellcode

    1. Private Shared Function UInt16FromBytes(Byte1 As Byte, Byte0 As Byte) As UInt16
    2. Return CUShort(Byte1) << 8 Or Byte0
    3. End Function
    4. Public Shared Function Reverse3Crc(TableValueB_Byte1 As Byte, crcB0 As Byte) As Tuple(Of Byte, Byte)
    5. Dim crcA_Byte1 As Byte, TableValueB_Byte0 As Byte
    6. 'crcA_Byte1 Xor TableValueB_Byte0 = crcB0
    7. Dim XorResultA As Byte = CByte(Array.IndexOf(CrcTable, UInt16FromBytes(TableValueB_Byte1, TableValueB_Byte0)))
    8. '-------------------------------------------------------
    9. Dim crcA As UInt16 = CrcTable(data0)
    10. Dim XorResultA = crcA.Byte0 Xor data1
    11. End Function

    Der Rest wiederholt sich einfach, und dann kann das passende Return auch gleich eingefügt werden:

    VB.NET-Quellcode

    1. Public Shared Function Reverse3Crc(TableValueB_Byte1 As Byte, crcB0 As Byte) As Tuple(Of Byte, Byte)
    2. Dim crcA_Byte1 As Byte, TableValueB_Byte0 As Byte
    3. 'crcA_Byte1 Xor TableValueB_Byte0 = crcB0
    4. Dim XorResultA As Byte = CByte(Array.IndexOf(CrcTable, UInt16FromBytes(TableValueB_Byte1, TableValueB_Byte0)))
    5. Dim crcA_Byte0 As Byte, data1 As Byte
    6. 'crcA_Byte0 Xor data1 = XorResultA
    7. Dim data0 As Byte = CByte(Array.IndexOf(CrcTable, UInt16FromBytes(crcA_Byte1, crcA_Byte0)))
    8. Return Tuple.Create(data0, data1)
    9. End Function

    Jetzt wird's interessant.
    TableValueB_Byte1 ist durch einen Parameter vorgegeben. Das heißt, wir können alle Indices (sprich: XorResultA) suchen, bei denen beim entsprechenden Tabelleneintrag das obere Byte gleich TableValueB_Byte1 ist. Das sollten nicht allzuviele sein. Um ganz genau zu sein: Das ist genau einer. Jeder Tabelleneintrag hat ein anderes Byte1. Es gibt keine Duplikate. (Es gibt dagegen aber nur 8 verschiedene Byte0s.)
    Jetzt wissen wir nicht nur den Index, sondern auch gleich noch das Byte0 vom Eintrag (also XorResultA).

    VB.NET-Quellcode

    1. Public Shared Function Reverse4Crc(TableValueB_Byte1 As Byte, crcB0 As Byte) As Tuple(Of Byte, Byte)
    2. Dim crcA_Byte1 As Byte, TableValueB_Byte0 As Byte
    3. 'crcA_Byte1 Xor TableValueB_Byte0 = crcB0
    4. 'Dim XorResultA As Byte = CByte(Array.IndexOf(CrcTable, UInt16FromBytes(TableValueB_Byte1, TableValueB_Byte0)))
    5. Dim XorResultA As Byte = CByte(CrcTable.IndexOfFirst(Function(i) i.Byte1 = TableValueB_Byte1))
    6. TableValueB_Byte0 = CrcTable(XorResultA).Byte0
    7. Dim crcA_Byte0 As Byte, data1 As Byte
    8. 'crcA_Byte0 Xor data1 = XorResultA
    9. Dim data0 As Byte = CByte(Array.IndexOf(CrcTable, UInt16FromBytes(crcA_Byte1, crcA_Byte0)))
    10. Return Tuple.Create(data0, data1)
    11. End Function

    TableValueB_Byte0, das jetzt bekannt ist, ist einer der Operanden des Xor. Das Ergebnis davon ist ebenfalls bekannt (durch den Parameter). Dadurch können wir den anderen Parameter bestimmen:

    VB.NET-Quellcode

    1. crcA_Byte1 Xor TableValueB_Byte0 = crcB0 | Beide Seiten Xor TableValueB_Byte0
    2. crcA_Byte1 Xor TableValueB_Byte0 Xor TableValueB_Byte0 = crcB0 Xor TableValueB_Byte0 | A Xor A = 0
    3. crcA_Byte1 Xor 0 = crcB0 Xor TableValueB_Byte0 | A Xor 0 = A
    4. crcA_Byte1 = crcB0 Xor TableValueB_Byte0

    Deshalb (nach ein bisschen Aufräumen):

    VB.NET-Quellcode

    1. Public Shared Function Reverse5Crc(TableValueB_Byte1 As Byte, crcB0 As Byte) As Tuple(Of Byte, Byte)
    2. 'Dim XorResultA As Byte = CByte(Array.IndexOf(CrcTable, UInt16FromBytes(TableValueB_Byte1, TableValueB_Byte0)))
    3. Dim XorResultA As Byte = CByte(CrcTable.IndexOfFirst(Function(i) i.Byte1 = TableValueB_Byte1))
    4. Dim TableValueB_Byte0 = CrcTable(XorResultA).Byte0
    5. 'crcA_Byte1 Xor TableValueB_Byte0 = crcB0
    6. Dim crcA_Byte1 = crcB0 Xor TableValueB_Byte0
    7. Dim crcA_Byte0 As Byte, data1 As Byte
    8. 'crcA_Byte0 Xor data1 = XorResultA
    9. Dim data0 As Byte = CByte(Array.IndexOf(CrcTable, UInt16FromBytes(crcA_Byte1, crcA_Byte0)))
    10. Return Tuple.Create(data0, data1)
    11. End Function

    Uuund, wiederholt sich schon wieder:

    VB.NET-Quellcode

    1. Public Shared Function Reverse6Crc(TableValueB_Byte1 As Byte, crcB0 As Byte) As Tuple(Of Byte, Byte)
    2. 'Dim XorResultA As Byte = CByte(Array.IndexOf(CrcTable, UInt16FromBytes(TableValueB_Byte1, TableValueB_Byte0)))
    3. Dim XorResultA As Byte = CByte(CrcTable.IndexOfFirst(Function(i) i.Byte1 = TableValueB_Byte1))
    4. Dim TableValueB_Byte0 = CrcTable(XorResultA).Byte0
    5. 'crcA_Byte1 Xor TableValueB_Byte0 = crcB0
    6. Dim crcA_Byte1 = crcB0 Xor TableValueB_Byte0
    7. 'Dim data0 As Byte = CByte(Array.IndexOf(CrcTable, UInt16FromBytes(crcA_Byte1, crcA_Byte0)))
    8. Dim data0 As Byte = CByte(CrcTable.IndexOfFirst(Function(i) i.Byte1 = crcA_Byte1))
    9. Dim crcA_Byte0 = CrcTable(data0).Byte0
    10. 'crcA_Byte0 Xor data1 = XorResultA
    11. Dim data1 = XorResultA Xor crcA_Byte0
    12. Return Tuple.Create(data0, data1)
    13. End Function

    Das wars. Habs getestet und funktioniert.
    Bzw. lässt sich das noch weiter vereinfachen und optimieren.
    Die Umkehrung des Zugriffs auf die Tabelle kann vorausberechnet werden, um Zeit zu sparen:

    VB.NET-Quellcode

    1. Public Shared Function Reverse7Crc(CrcByte1 As Byte, CrcByte0 As Byte) As Tuple(Of Byte, Byte)
    2. Dim PairB = CrcReverseTable(CrcByte1)
    3. Dim PairA = CrcReverseTable(CrcByte0 Xor PairB.Byte0)
    4. Dim data0 As Byte = PairA.Index
    5. Dim data1 As Byte = PairB.Index Xor PairA.Byte0
    6. Return Tuple.Create(data0, data1)
    7. End Function

    Die Tabelle

    Lässt sich auch zu lauter UInt16 Werten zusammenfassen, aber das ist dann natürlich bei der Verwendung nicht mehr so schön zu lesen.

    VB.NET-Quellcode

    1. Private Structure Byte0IndexPair
    2. Public Byte0 As Byte
    3. Public Index As Byte
    4. Public Sub New(NewByte0 As Byte, NewIndex As Byte)
    5. Byte0 = NewByte0
    6. Index = NewIndex
    7. End Sub
    8. End Structure
    9. Private Shared ReadOnly CrcReverseTable As Byte0IndexPair() = _
    10. {
    11. New Byte0IndexPair(&H0, &H0), New Byte0IndexPair(&H40, &H3), New Byte0IndexPair(&H80, &H6), New Byte0IndexPair(&HC0, &H5),
    12. New Byte0IndexPair(&H40, &HF), New Byte0IndexPair(&H0, &HC), New Byte0IndexPair(&HC0, &H9), New Byte0IndexPair(&H80, &HA),
    13. New Byte0IndexPair(&H80, &H1E), New Byte0IndexPair(&HC0, &H1D), New Byte0IndexPair(&H0, &H18), New Byte0IndexPair(&H40, &H1B),
    14. New Byte0IndexPair(&HC0, &H11), New Byte0IndexPair(&H80, &H12), New Byte0IndexPair(&H40, &H17), New Byte0IndexPair(&H0, &H14),
    15. New Byte0IndexPair(&H40, &H3F), New Byte0IndexPair(&H0, &H3C), New Byte0IndexPair(&HC0, &H39), New Byte0IndexPair(&H80, &H3A),
    16. New Byte0IndexPair(&H0, &H30), New Byte0IndexPair(&H40, &H33), New Byte0IndexPair(&H80, &H36), New Byte0IndexPair(&HC0, &H35),
    17. New Byte0IndexPair(&HC0, &H21), New Byte0IndexPair(&H80, &H22), New Byte0IndexPair(&H40, &H27), New Byte0IndexPair(&H0, &H24),
    18. New Byte0IndexPair(&H80, &H2E), New Byte0IndexPair(&HC0, &H2D), New Byte0IndexPair(&H0, &H28), New Byte0IndexPair(&H40, &H2B),
    19. New Byte0IndexPair(&H80, &H7E), New Byte0IndexPair(&HC0, &H7D), New Byte0IndexPair(&H0, &H78), New Byte0IndexPair(&H40, &H7B),
    20. New Byte0IndexPair(&HC0, &H71), New Byte0IndexPair(&H80, &H72), New Byte0IndexPair(&H40, &H77), New Byte0IndexPair(&H0, &H74),
    21. New Byte0IndexPair(&H0, &H60), New Byte0IndexPair(&H40, &H63), New Byte0IndexPair(&H80, &H66), New Byte0IndexPair(&HC0, &H65),
    22. New Byte0IndexPair(&H40, &H6F), New Byte0IndexPair(&H0, &H6C), New Byte0IndexPair(&HC0, &H69), New Byte0IndexPair(&H80, &H6A),
    23. New Byte0IndexPair(&HC0, &H41), New Byte0IndexPair(&H80, &H42), New Byte0IndexPair(&H40, &H47), New Byte0IndexPair(&H0, &H44),
    24. New Byte0IndexPair(&H80, &H4E), New Byte0IndexPair(&HC0, &H4D), New Byte0IndexPair(&H0, &H48), New Byte0IndexPair(&H40, &H4B),
    25. New Byte0IndexPair(&H40, &H5F), New Byte0IndexPair(&H0, &H5C), New Byte0IndexPair(&HC0, &H59), New Byte0IndexPair(&H80, &H5A),
    26. New Byte0IndexPair(&H0, &H50), New Byte0IndexPair(&H40, &H53), New Byte0IndexPair(&H80, &H56), New Byte0IndexPair(&HC0, &H55),
    27. New Byte0IndexPair(&H40, &HFF), New Byte0IndexPair(&H0, &HFC), New Byte0IndexPair(&HC0, &HF9), New Byte0IndexPair(&H80, &HFA),
    28. New Byte0IndexPair(&H0, &HF0), New Byte0IndexPair(&H40, &HF3), New Byte0IndexPair(&H80, &HF6), New Byte0IndexPair(&HC0, &HF5),
    29. New Byte0IndexPair(&HC0, &HE1), New Byte0IndexPair(&H80, &HE2), New Byte0IndexPair(&H40, &HE7), New Byte0IndexPair(&H0, &HE4),
    30. New Byte0IndexPair(&H80, &HEE), New Byte0IndexPair(&HC0, &HED), New Byte0IndexPair(&H0, &HE8), New Byte0IndexPair(&H40, &HEB),
    31. New Byte0IndexPair(&H0, &HC0), New Byte0IndexPair(&H40, &HC3), New Byte0IndexPair(&H80, &HC6), New Byte0IndexPair(&HC0, &HC5),
    32. New Byte0IndexPair(&H40, &HCF), New Byte0IndexPair(&H0, &HCC), New Byte0IndexPair(&HC0, &HC9), New Byte0IndexPair(&H80, &HCA),
    33. New Byte0IndexPair(&H80, &HDE), New Byte0IndexPair(&HC0, &HDD), New Byte0IndexPair(&H0, &HD8), New Byte0IndexPair(&H40, &HDB),
    34. New Byte0IndexPair(&HC0, &HD1), New Byte0IndexPair(&H80, &HD2), New Byte0IndexPair(&H40, &HD7), New Byte0IndexPair(&H0, &HD4),
    35. New Byte0IndexPair(&HC0, &H81), New Byte0IndexPair(&H80, &H82), New Byte0IndexPair(&H40, &H87), New Byte0IndexPair(&H0, &H84),
    36. New Byte0IndexPair(&H80, &H8E), New Byte0IndexPair(&HC0, &H8D), New Byte0IndexPair(&H0, &H88), New Byte0IndexPair(&H40, &H8B),
    37. New Byte0IndexPair(&H40, &H9F), New Byte0IndexPair(&H0, &H9C), New Byte0IndexPair(&HC0, &H99), New Byte0IndexPair(&H80, &H9A),
    38. New Byte0IndexPair(&H0, &H90), New Byte0IndexPair(&H40, &H93), New Byte0IndexPair(&H80, &H96), New Byte0IndexPair(&HC0, &H95),
    39. New Byte0IndexPair(&H80, &HBE), New Byte0IndexPair(&HC0, &HBD), New Byte0IndexPair(&H0, &HB8), New Byte0IndexPair(&H40, &HBB),
    40. New Byte0IndexPair(&HC0, &HB1), New Byte0IndexPair(&H80, &HB2), New Byte0IndexPair(&H40, &HB7), New Byte0IndexPair(&H0, &HB4),
    41. New Byte0IndexPair(&H0, &HA0), New Byte0IndexPair(&H40, &HA3), New Byte0IndexPair(&H80, &HA6), New Byte0IndexPair(&HC0, &HA5),
    42. New Byte0IndexPair(&H40, &HAF), New Byte0IndexPair(&H0, &HAC), New Byte0IndexPair(&HC0, &HA9), New Byte0IndexPair(&H80, &HAA),
    43. New Byte0IndexPair(&H81, &HFE), New Byte0IndexPair(&HC1, &HFD), New Byte0IndexPair(&H1, &HF8), New Byte0IndexPair(&H41, &HFB),
    44. New Byte0IndexPair(&HC1, &HF1), New Byte0IndexPair(&H81, &HF2), New Byte0IndexPair(&H41, &HF7), New Byte0IndexPair(&H1, &HF4),
    45. New Byte0IndexPair(&H1, &HE0), New Byte0IndexPair(&H41, &HE3), New Byte0IndexPair(&H81, &HE6), New Byte0IndexPair(&HC1, &HE5),
    46. New Byte0IndexPair(&H41, &HEF), New Byte0IndexPair(&H1, &HEC), New Byte0IndexPair(&HC1, &HE9), New Byte0IndexPair(&H81, &HEA),
    47. New Byte0IndexPair(&HC1, &HC1), New Byte0IndexPair(&H81, &HC2), New Byte0IndexPair(&H41, &HC7), New Byte0IndexPair(&H1, &HC4),
    48. New Byte0IndexPair(&H81, &HCE), New Byte0IndexPair(&HC1, &HCD), New Byte0IndexPair(&H1, &HC8), New Byte0IndexPair(&H41, &HCB),
    49. New Byte0IndexPair(&H41, &HDF), New Byte0IndexPair(&H1, &HDC), New Byte0IndexPair(&HC1, &HD9), New Byte0IndexPair(&H81, &HDA),
    50. New Byte0IndexPair(&H1, &HD0), New Byte0IndexPair(&H41, &HD3), New Byte0IndexPair(&H81, &HD6), New Byte0IndexPair(&HC1, &HD5),
    51. New Byte0IndexPair(&H1, &H80), New Byte0IndexPair(&H41, &H83), New Byte0IndexPair(&H81, &H86), New Byte0IndexPair(&HC1, &H85),
    52. New Byte0IndexPair(&H41, &H8F), New Byte0IndexPair(&H1, &H8C), New Byte0IndexPair(&HC1, &H89), New Byte0IndexPair(&H81, &H8A),
    53. New Byte0IndexPair(&H81, &H9E), New Byte0IndexPair(&HC1, &H9D), New Byte0IndexPair(&H1, &H98), New Byte0IndexPair(&H41, &H9B),
    54. New Byte0IndexPair(&HC1, &H91), New Byte0IndexPair(&H81, &H92), New Byte0IndexPair(&H41, &H97), New Byte0IndexPair(&H1, &H94),
    55. New Byte0IndexPair(&H41, &HBF), New Byte0IndexPair(&H1, &HBC), New Byte0IndexPair(&HC1, &HB9), New Byte0IndexPair(&H81, &HBA),
    56. New Byte0IndexPair(&H1, &HB0), New Byte0IndexPair(&H41, &HB3), New Byte0IndexPair(&H81, &HB6), New Byte0IndexPair(&HC1, &HB5),
    57. New Byte0IndexPair(&HC1, &HA1), New Byte0IndexPair(&H81, &HA2), New Byte0IndexPair(&H41, &HA7), New Byte0IndexPair(&H1, &HA4),
    58. New Byte0IndexPair(&H81, &HAE), New Byte0IndexPair(&HC1, &HAD), New Byte0IndexPair(&H1, &HA8), New Byte0IndexPair(&H41, &HAB),
    59. New Byte0IndexPair(&HC1, &H1), New Byte0IndexPair(&H81, &H2), New Byte0IndexPair(&H41, &H7), New Byte0IndexPair(&H1, &H4),
    60. New Byte0IndexPair(&H81, &HE), New Byte0IndexPair(&HC1, &HD), New Byte0IndexPair(&H1, &H8), New Byte0IndexPair(&H41, &HB),
    61. New Byte0IndexPair(&H41, &H1F), New Byte0IndexPair(&H1, &H1C), New Byte0IndexPair(&HC1, &H19), New Byte0IndexPair(&H81, &H1A),
    62. New Byte0IndexPair(&H1, &H10), New Byte0IndexPair(&H41, &H13), New Byte0IndexPair(&H81, &H16), New Byte0IndexPair(&HC1, &H15),
    63. New Byte0IndexPair(&H81, &H3E), New Byte0IndexPair(&HC1, &H3D), New Byte0IndexPair(&H1, &H38), New Byte0IndexPair(&H41, &H3B),
    64. New Byte0IndexPair(&HC1, &H31), New Byte0IndexPair(&H81, &H32), New Byte0IndexPair(&H41, &H37), New Byte0IndexPair(&H1, &H34),
    65. New Byte0IndexPair(&H1, &H20), New Byte0IndexPair(&H41, &H23), New Byte0IndexPair(&H81, &H26), New Byte0IndexPair(&HC1, &H25),
    66. New Byte0IndexPair(&H41, &H2F), New Byte0IndexPair(&H1, &H2C), New Byte0IndexPair(&HC1, &H29), New Byte0IndexPair(&H81, &H2A),
    67. New Byte0IndexPair(&H41, &H7F), New Byte0IndexPair(&H1, &H7C), New Byte0IndexPair(&HC1, &H79), New Byte0IndexPair(&H81, &H7A),
    68. New Byte0IndexPair(&H1, &H70), New Byte0IndexPair(&H41, &H73), New Byte0IndexPair(&H81, &H76), New Byte0IndexPair(&HC1, &H75),
    69. New Byte0IndexPair(&HC1, &H61), New Byte0IndexPair(&H81, &H62), New Byte0IndexPair(&H41, &H67), New Byte0IndexPair(&H1, &H64),
    70. New Byte0IndexPair(&H81, &H6E), New Byte0IndexPair(&HC1, &H6D), New Byte0IndexPair(&H1, &H68), New Byte0IndexPair(&H41, &H6B),
    71. New Byte0IndexPair(&H1, &H40), New Byte0IndexPair(&H41, &H43), New Byte0IndexPair(&H81, &H46), New Byte0IndexPair(&HC1, &H45),
    72. New Byte0IndexPair(&H41, &H4F), New Byte0IndexPair(&H1, &H4C), New Byte0IndexPair(&HC1, &H49), New Byte0IndexPair(&H81, &H4A),
    73. New Byte0IndexPair(&H81, &H5E), New Byte0IndexPair(&HC1, &H5D), New Byte0IndexPair(&H1, &H58), New Byte0IndexPair(&H41, &H5B),
    74. New Byte0IndexPair(&HC1, &H51), New Byte0IndexPair(&H81, &H52), New Byte0IndexPair(&H41, &H57), New Byte0IndexPair(&H1, &H54)
    75. }

    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    @Niko Ortner :

    Wow, vielen Dank für deine Mühe !
    Ich hab das ganze mal etwas umgeschrieben, die Tuples sind unnötig und können durch ein Array ersetzt werden.
    Desweiteren kann man als Input-Value direkt ein ushort spezifizieren :

    C#-Quellcode

    1. public static byte[] Reverse7Crc(ushort value)
    2. {
    3. byte[] bytes = BitConverter.GetBytes(value);
    4. var pairB = CrcReverseTable[bytes[1]];
    5. var pairA = CrcReverseTable[bytes[0] ^ pairB.Byte0];
    6. byte data0 = pairA.Index;
    7. byte data1 = (byte)(pairB.Index ^ pairA.Byte0);
    8. return new byte[] { data0, data1 };
    9. }
    10. private struct ByteIndexPair
    11. {
    12. public readonly byte Byte0;
    13. public readonly byte Index;
    14. public ByteIndexPair(byte newByte0, byte newIndex)
    15. {
    16. Byte0 = newByte0;
    17. Index = newIndex;
    18. }
    19. }
    20. private static readonly ByteIndexPair[] CrcReverseTable = {
    21. new ByteIndexPair(0x0, 0x0),
    22. new ByteIndexPair(0x40, 0x3),
    23. new ByteIndexPair(0x80, 0x6),
    24. new ByteIndexPair(0xc0, 0x5),
    25. new ByteIndexPair(0x40, 0xf),
    26. new ByteIndexPair(0x0, 0xc),
    27. new ByteIndexPair(0xc0, 0x9),
    28. new ByteIndexPair(0x80, 0xa),
    29. new ByteIndexPair(0x80, 0x1e),
    30. new ByteIndexPair(0xc0, 0x1d),
    31. new ByteIndexPair(0x0, 0x18),
    32. new ByteIndexPair(0x40, 0x1b),
    33. new ByteIndexPair(0xc0, 0x11),
    34. new ByteIndexPair(0x80, 0x12),
    35. new ByteIndexPair(0x40, 0x17),
    36. new ByteIndexPair(0x0, 0x14),
    37. new ByteIndexPair(0x40, 0x3f),
    38. new ByteIndexPair(0x0, 0x3c),
    39. new ByteIndexPair(0xc0, 0x39),
    40. new ByteIndexPair(0x80, 0x3a),
    41. new ByteIndexPair(0x0, 0x30),
    42. new ByteIndexPair(0x40, 0x33),
    43. new ByteIndexPair(0x80, 0x36),
    44. new ByteIndexPair(0xc0, 0x35),
    45. new ByteIndexPair(0xc0, 0x21),
    46. new ByteIndexPair(0x80, 0x22),
    47. new ByteIndexPair(0x40, 0x27),
    48. new ByteIndexPair(0x0, 0x24),
    49. new ByteIndexPair(0x80, 0x2e),
    50. new ByteIndexPair(0xc0, 0x2d),
    51. new ByteIndexPair(0x0, 0x28),
    52. new ByteIndexPair(0x40, 0x2b),
    53. new ByteIndexPair(0x80, 0x7e),
    54. new ByteIndexPair(0xc0, 0x7d),
    55. new ByteIndexPair(0x0, 0x78),
    56. new ByteIndexPair(0x40, 0x7b),
    57. new ByteIndexPair(0xc0, 0x71),
    58. new ByteIndexPair(0x80, 0x72),
    59. new ByteIndexPair(0x40, 0x77),
    60. new ByteIndexPair(0x0, 0x74),
    61. new ByteIndexPair(0x0, 0x60),
    62. new ByteIndexPair(0x40, 0x63),
    63. new ByteIndexPair(0x80, 0x66),
    64. new ByteIndexPair(0xc0, 0x65),
    65. new ByteIndexPair(0x40, 0x6f),
    66. new ByteIndexPair(0x0, 0x6c),
    67. new ByteIndexPair(0xc0, 0x69),
    68. new ByteIndexPair(0x80, 0x6a),
    69. new ByteIndexPair(0xc0, 0x41),
    70. new ByteIndexPair(0x80, 0x42),
    71. new ByteIndexPair(0x40, 0x47),
    72. new ByteIndexPair(0x0, 0x44),
    73. new ByteIndexPair(0x80, 0x4e),
    74. new ByteIndexPair(0xc0, 0x4d),
    75. new ByteIndexPair(0x0, 0x48),
    76. new ByteIndexPair(0x40, 0x4b),
    77. new ByteIndexPair(0x40, 0x5f),
    78. new ByteIndexPair(0x0, 0x5c),
    79. new ByteIndexPair(0xc0, 0x59),
    80. new ByteIndexPair(0x80, 0x5a),
    81. new ByteIndexPair(0x0, 0x50),
    82. new ByteIndexPair(0x40, 0x53),
    83. new ByteIndexPair(0x80, 0x56),
    84. new ByteIndexPair(0xc0, 0x55),
    85. new ByteIndexPair(0x40, 0xff),
    86. new ByteIndexPair(0x0, 0xfc),
    87. new ByteIndexPair(0xc0, 0xf9),
    88. new ByteIndexPair(0x80, 0xfa),
    89. new ByteIndexPair(0x0, 0xf0),
    90. new ByteIndexPair(0x40, 0xf3),
    91. new ByteIndexPair(0x80, 0xf6),
    92. new ByteIndexPair(0xc0, 0xf5),
    93. new ByteIndexPair(0xc0, 0xe1),
    94. new ByteIndexPair(0x80, 0xe2),
    95. new ByteIndexPair(0x40, 0xe7),
    96. new ByteIndexPair(0x0, 0xe4),
    97. new ByteIndexPair(0x80, 0xee),
    98. new ByteIndexPair(0xc0, 0xed),
    99. new ByteIndexPair(0x0, 0xe8),
    100. new ByteIndexPair(0x40, 0xeb),
    101. new ByteIndexPair(0x0, 0xc0),
    102. new ByteIndexPair(0x40, 0xc3),
    103. new ByteIndexPair(0x80, 0xc6),
    104. new ByteIndexPair(0xc0, 0xc5),
    105. new ByteIndexPair(0x40, 0xcf),
    106. new ByteIndexPair(0x0, 0xcc),
    107. new ByteIndexPair(0xc0, 0xc9),
    108. new ByteIndexPair(0x80, 0xca),
    109. new ByteIndexPair(0x80, 0xde),
    110. new ByteIndexPair(0xc0, 0xdd),
    111. new ByteIndexPair(0x0, 0xd8),
    112. new ByteIndexPair(0x40, 0xdb),
    113. new ByteIndexPair(0xc0, 0xd1),
    114. new ByteIndexPair(0x80, 0xd2),
    115. new ByteIndexPair(0x40, 0xd7),
    116. new ByteIndexPair(0x0, 0xd4),
    117. new ByteIndexPair(0xc0, 0x81),
    118. new ByteIndexPair(0x80, 0x82),
    119. new ByteIndexPair(0x40, 0x87),
    120. new ByteIndexPair(0x0, 0x84),
    121. new ByteIndexPair(0x80, 0x8e),
    122. new ByteIndexPair(0xc0, 0x8d),
    123. new ByteIndexPair(0x0, 0x88),
    124. new ByteIndexPair(0x40, 0x8b),
    125. new ByteIndexPair(0x40, 0x9f),
    126. new ByteIndexPair(0x0, 0x9c),
    127. new ByteIndexPair(0xc0, 0x99),
    128. new ByteIndexPair(0x80, 0x9a),
    129. new ByteIndexPair(0x0, 0x90),
    130. new ByteIndexPair(0x40, 0x93),
    131. new ByteIndexPair(0x80, 0x96),
    132. new ByteIndexPair(0xc0, 0x95),
    133. new ByteIndexPair(0x80, 0xbe),
    134. new ByteIndexPair(0xc0, 0xbd),
    135. new ByteIndexPair(0x0, 0xb8),
    136. new ByteIndexPair(0x40, 0xbb),
    137. new ByteIndexPair(0xc0, 0xb1),
    138. new ByteIndexPair(0x80, 0xb2),
    139. new ByteIndexPair(0x40, 0xb7),
    140. new ByteIndexPair(0x0, 0xb4),
    141. new ByteIndexPair(0x0, 0xa0),
    142. new ByteIndexPair(0x40, 0xa3),
    143. new ByteIndexPair(0x80, 0xa6),
    144. new ByteIndexPair(0xc0, 0xa5),
    145. new ByteIndexPair(0x40, 0xaf),
    146. new ByteIndexPair(0x0, 0xac),
    147. new ByteIndexPair(0xc0, 0xa9),
    148. new ByteIndexPair(0x80, 0xaa),
    149. new ByteIndexPair(0x81, 0xfe),
    150. new ByteIndexPair(0xc1, 0xfd),
    151. new ByteIndexPair(0x1, 0xf8),
    152. new ByteIndexPair(0x41, 0xfb),
    153. new ByteIndexPair(0xc1, 0xf1),
    154. new ByteIndexPair(0x81, 0xf2),
    155. new ByteIndexPair(0x41, 0xf7),
    156. new ByteIndexPair(0x1, 0xf4),
    157. new ByteIndexPair(0x1, 0xe0),
    158. new ByteIndexPair(0x41, 0xe3),
    159. new ByteIndexPair(0x81, 0xe6),
    160. new ByteIndexPair(0xc1, 0xe5),
    161. new ByteIndexPair(0x41, 0xef),
    162. new ByteIndexPair(0x1, 0xec),
    163. new ByteIndexPair(0xc1, 0xe9),
    164. new ByteIndexPair(0x81, 0xea),
    165. new ByteIndexPair(0xc1, 0xc1),
    166. new ByteIndexPair(0x81, 0xc2),
    167. new ByteIndexPair(0x41, 0xc7),
    168. new ByteIndexPair(0x1, 0xc4),
    169. new ByteIndexPair(0x81, 0xce),
    170. new ByteIndexPair(0xc1, 0xcd),
    171. new ByteIndexPair(0x1, 0xc8),
    172. new ByteIndexPair(0x41, 0xcb),
    173. new ByteIndexPair(0x41, 0xdf),
    174. new ByteIndexPair(0x1, 0xdc),
    175. new ByteIndexPair(0xc1, 0xd9),
    176. new ByteIndexPair(0x81, 0xda),
    177. new ByteIndexPair(0x1, 0xd0),
    178. new ByteIndexPair(0x41, 0xd3),
    179. new ByteIndexPair(0x81, 0xd6),
    180. new ByteIndexPair(0xc1, 0xd5),
    181. new ByteIndexPair(0x1, 0x80),
    182. new ByteIndexPair(0x41, 0x83),
    183. new ByteIndexPair(0x81, 0x86),
    184. new ByteIndexPair(0xc1, 0x85),
    185. new ByteIndexPair(0x41, 0x8f),
    186. new ByteIndexPair(0x1, 0x8c),
    187. new ByteIndexPair(0xc1, 0x89),
    188. new ByteIndexPair(0x81, 0x8a),
    189. new ByteIndexPair(0x81, 0x9e),
    190. new ByteIndexPair(0xc1, 0x9d),
    191. new ByteIndexPair(0x1, 0x98),
    192. new ByteIndexPair(0x41, 0x9b),
    193. new ByteIndexPair(0xc1, 0x91),
    194. new ByteIndexPair(0x81, 0x92),
    195. new ByteIndexPair(0x41, 0x97),
    196. new ByteIndexPair(0x1, 0x94),
    197. new ByteIndexPair(0x41, 0xbf),
    198. new ByteIndexPair(0x1, 0xbc),
    199. new ByteIndexPair(0xc1, 0xb9),
    200. new ByteIndexPair(0x81, 0xba),
    201. new ByteIndexPair(0x1, 0xb0),
    202. new ByteIndexPair(0x41, 0xb3),
    203. new ByteIndexPair(0x81, 0xb6),
    204. new ByteIndexPair(0xc1, 0xb5),
    205. new ByteIndexPair(0xc1, 0xa1),
    206. new ByteIndexPair(0x81, 0xa2),
    207. new ByteIndexPair(0x41, 0xa7),
    208. new ByteIndexPair(0x1, 0xa4),
    209. new ByteIndexPair(0x81, 0xae),
    210. new ByteIndexPair(0xc1, 0xad),
    211. new ByteIndexPair(0x1, 0xa8),
    212. new ByteIndexPair(0x41, 0xab),
    213. new ByteIndexPair(0xc1, 0x1),
    214. new ByteIndexPair(0x81, 0x2),
    215. new ByteIndexPair(0x41, 0x7),
    216. new ByteIndexPair(0x1, 0x4),
    217. new ByteIndexPair(0x81, 0xe),
    218. new ByteIndexPair(0xc1, 0xd),
    219. new ByteIndexPair(0x1, 0x8),
    220. new ByteIndexPair(0x41, 0xb),
    221. new ByteIndexPair(0x41, 0x1f),
    222. new ByteIndexPair(0x1, 0x1c),
    223. new ByteIndexPair(0xc1, 0x19),
    224. new ByteIndexPair(0x81, 0x1a),
    225. new ByteIndexPair(0x1, 0x10),
    226. new ByteIndexPair(0x41, 0x13),
    227. new ByteIndexPair(0x81, 0x16),
    228. new ByteIndexPair(0xc1, 0x15),
    229. new ByteIndexPair(0x81, 0x3e),
    230. new ByteIndexPair(0xc1, 0x3d),
    231. new ByteIndexPair(0x1, 0x38),
    232. new ByteIndexPair(0x41, 0x3b),
    233. new ByteIndexPair(0xc1, 0x31),
    234. new ByteIndexPair(0x81, 0x32),
    235. new ByteIndexPair(0x41, 0x37),
    236. new ByteIndexPair(0x1, 0x34),
    237. new ByteIndexPair(0x1, 0x20),
    238. new ByteIndexPair(0x41, 0x23),
    239. new ByteIndexPair(0x81, 0x26),
    240. new ByteIndexPair(0xc1, 0x25),
    241. new ByteIndexPair(0x41, 0x2f),
    242. new ByteIndexPair(0x1, 0x2c),
    243. new ByteIndexPair(0xc1, 0x29),
    244. new ByteIndexPair(0x81, 0x2a),
    245. new ByteIndexPair(0x41, 0x7f),
    246. new ByteIndexPair(0x1, 0x7c),
    247. new ByteIndexPair(0xc1, 0x79),
    248. new ByteIndexPair(0x81, 0x7a),
    249. new ByteIndexPair(0x1, 0x70),
    250. new ByteIndexPair(0x41, 0x73),
    251. new ByteIndexPair(0x81, 0x76),
    252. new ByteIndexPair(0xc1, 0x75),
    253. new ByteIndexPair(0xc1, 0x61),
    254. new ByteIndexPair(0x81, 0x62),
    255. new ByteIndexPair(0x41, 0x67),
    256. new ByteIndexPair(0x1, 0x64),
    257. new ByteIndexPair(0x81, 0x6e),
    258. new ByteIndexPair(0xc1, 0x6d),
    259. new ByteIndexPair(0x1, 0x68),
    260. new ByteIndexPair(0x41, 0x6b),
    261. new ByteIndexPair(0x1, 0x40),
    262. new ByteIndexPair(0x41, 0x43),
    263. new ByteIndexPair(0x81, 0x46),
    264. new ByteIndexPair(0xc1, 0x45),
    265. new ByteIndexPair(0x41, 0x4f),
    266. new ByteIndexPair(0x1, 0x4c),
    267. new ByteIndexPair(0xc1, 0x49),
    268. new ByteIndexPair(0x81, 0x4a),
    269. new ByteIndexPair(0x81, 0x5e),
    270. new ByteIndexPair(0xc1, 0x5d),
    271. new ByteIndexPair(0x1, 0x58),
    272. new ByteIndexPair(0x41, 0x5b),
    273. new ByteIndexPair(0xc1, 0x51),
    274. new ByteIndexPair(0x81, 0x52),
    275. new ByteIndexPair(0x41, 0x57),
    276. new ByteIndexPair(0x1, 0x54)
    277. };


    Kannst du nochmal erklären wie die byte lookup liste hier funktioniert, ich verstehe das nicht ganz?
    Ohne lookup geht es wahrscheinlich nicht oder, also das man die Liste in den Loop einbaut?
    C# Developer
    Learning C++

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Rikudo“ ()

    @Rikudo
    Betrachte die Zeile Dim TableValue As UInt16 = CrcTable(CByte(crc And &HFF) Xor data(i)) bzw. aufgeteilt, damit es besser erkennbar ist:

    VB.NET-Quellcode

    1. Dim Index As Byte = CByte(crc And &HFF) Xor data(i)
    2. Dim TableValue As UInt16 = CrcTable(Index)

    Hier wird der Eintrag in der Tabelle an dem Index geholt.
    Wenn Du Dir die originale CrcTable anguckst, und davon nur jeweils das höherwertige Byte nimmst, dann siehst Du, dass es keine Duplikate gibt. Also für jeden möglichen Index kommt ein eindeutiges TableValue.Byte1 heraus. Dadurch kann man es umkehren: Für jedes TableValue.Byte1 kann man eindeutig feststellen, an welchem Index sich dieser Eintrag befindet. Das macht Dim IndexInCrcTable = CrcTable.IndexOfFirst(Function(i) i.Byte1 = X). Und da man TableValue.Byte0 auch noch benötigt, holt man sich das aus der Tabelle: CrcTable(IndexInCrcTable).Byte0.
    Da man sowieso alle dies Werte umkehren können muss, kann man das optimieren, indem man es vorausberechnet. Es gilt:

    VB.NET-Quellcode

    1. Dim Byte1 As Byte = ... 'Ein beliebiges Byte.
    2. 'Mit Umkehrungstabelle:
    3. Dim Pair = CrcReverseTable(Byte1)
    4. Debug.Assert(CrcTable(Pair.Index).Byte1 = Byte1)
    5. Debug.Assert(CrcTable(Pair.Index).Byte0 = Pair.Byte0)
    6. 'Oder halt manuell gesucht:
    7. Dim IndexInCrcTable = CByte(CrcTable.IndexOfFirst(Function(i) i.Byte1 = Byte1))
    8. Debug.Assert(CrcTable(IndexInCrcTable).Byte1 = Byte1)
    9. 'Byte0 muss nochmal extra rausgeholt werden mit CrcTable(IndexInCrcTable).Byte0


    Du kannst es Dir auch so denken:

    VB.NET-Quellcode

    1. Private Shared Function GetByte0AndIndex(Byte1 As Byte) As Byte0IndexPair
    2. 'Manuell gesucht:
    3. Dim IndexInCrcTable = CByte(CrcTable.IndexOfFirst(Function(i) i.Byte1 = Byte1))
    4. Return New Byte0IndexPair(CrcTable(IndexInCrcTable).Byte0, IndexInCrcTable)
    5. 'Oder vorausberechnet:
    6. Return CrcReverseTable(Byte1)
    7. End Function

    Du kannst das Ergebnis entweder bei jedem Funktionsaufruf neu berechnen, oder Du kannst die Ergebnisse für jeden möglichen Parameterwert vorausberechnen und dann einfach das vorausberechnete Ergebnis verwenden.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Niko Ortner“ ()