Bitweise Operationen in VB.NET

VB.NET unterstützt Bit-Level-Operationen nicht direkt. Mit Framework 1.1 (VB.NET 2003) wurden Bitverschiebungsoperatoren eingeführt (<< und >>), aber es gibt keine allgemeine Möglichkeit, einzelne Bits zu manipulieren. Bit-Operationen können sehr nützlich sein. Beispielsweise muss Ihr Programm möglicherweise eine Schnittstelle zu einem anderen System herstellen, das eine Bitmanipulation erfordert. Darüber hinaus gibt es viele Tricks, die mit einzelnen Bits durchgeführt werden können. Dieser Artikel beschreibt, was mit Bit-Manipulation unter Verwendung von VB.NET getan werden kann.

Du musst verstehen bitweise Operatoren vor allem anderen. In VB.NET sind dies:

  • Und
  • Oder
  • Xor
  • Nicht

Bitweise bedeutet einfach, dass die Operationen bitweise mit zwei Binärzahlen ausgeführt werden können. Microsoft verwendet Wahrheitstabellen bitweise Operationen zu dokumentieren. Die Wahrheitstabelle für Und ist:

1. Bit 2. Bit Ergebnis
    1 1 1
    100
    0 1 0
    0 0 0

In meiner Schule haben sie unterrichtet Karnaugh Karten statt. Die Karnaugh-Karte für alle vier Operationen ist in der folgenden Abbildung dargestellt.

--------
Klicken Sie hier, um die Abbildung anzuzeigen
Klicken Sie in Ihrem Browser auf die Schaltfläche Zurück, um zurückzukehren
--------

Hier ist ein einfaches Beispiel mit dem Und Operation mit zwei, vier Bit Binärzahlen:

Das Ergebnis von 1100 Und 1010 ist 1000.

Das liegt daran, 1 Und 1 ist 1 (das erste Bit) und der Rest ist 0.

Zunächst werfen wir einen Blick auf die Bit-Operationen, die sind direkt in VB.NET unterstützt: Bit verschieben. Obwohl sowohl Linksverschiebung als auch Rechtsverschiebung verfügbar sind, funktionieren sie auf die gleiche Weise, sodass nur die Linksverschiebung behandelt wird. Die Bitverschiebung wird am häufigsten in der Kryptographie, Bildverarbeitung und Kommunikation eingesetzt.

Bitverschiebungsoperationen von VB.NET…

  • Arbeiten Sie nur mit den vier Arten von Ganzzahlen: Byte, Kurz, Ganze Zahl, und Lange
  • Sind Arithmetik Schaltvorgänge. Dies bedeutet, dass Bits, die über das Ende des Ergebnisses hinaus verschoben wurden, weggeworfen werden und die am anderen Ende geöffneten Bitpositionen auf Null gesetzt werden. Die Alternative heißt zirkuläre Bitverschiebung, und die Bits, die über ein Ende hinaus verschoben werden, werden einfach zum anderen hinzugefügt. VB.NET unterstützt keine direkte zirkuläre Bitverschiebung. Wenn Sie es brauchen, müssen Sie es auf die altmodische Weise codieren: Multiplizieren oder Teilen mit 2.
  • Generieren Sie niemals eine Überlaufausnahme. VB.NET kümmert sich um mögliche Probleme und ich zeige Ihnen, was das bedeutet. Wie bereits erwähnt, können Sie Ihre eigene Bitverschiebung durch Multiplizieren oder Teilen mit 2 codieren. Wenn Sie jedoch den Ansatz "Code your own" verwenden, müssen Sie auf Überlaufausnahmen prüfen, die zum Absturz Ihres Programms führen können.

Eine Standard-Bitverschiebungsoperation würde ungefähr so ​​aussehen:

Dim StartingValue As Integer = 14913080
Dim ValueAfterShifting As Integer
ValueAfterShifting = StartingValue << 50

In Worten, diese Operation nimmt den Binärwert an 0000 0000 1110 0011 1000 1110 0011 1000 (14913080 ist der äquivalente Dezimalwert. Beachten Sie, dass es sich nur um eine Reihe von drei Nullen und drei Einsen handelt, die einige Male wiederholt werden.) Verschiebt den Wert um 50 Stellen nach links. Da eine Ganzzahl jedoch nur 32 Bit lang ist, ist es bedeutungslos, sie um 50 Stellen zu verschieben. VB.NET löst dieses Problem durch Maskierung die Schichtzahl mit einem Standardwert, der dem verwendeten Datentyp entspricht. In diesem Fall, ValueAfterShifting ist ein Ganze Zahl Das Maximum, das verschoben werden kann, beträgt 32 Bit. Der Standardmaskenwert, der funktioniert, ist 31 Dezimal oder 11111.

Maskierung bedeutet, dass der Wert in diesem Fall 50 ist Undmit der Maske bearbeitet. Dies gibt die maximale Anzahl von Bits an, die tatsächlich für diesen Datentyp verschoben werden können.

In Dezimalzahl:

50 und 31 ist 18 - Die maximale Anzahl von Bits, die verschoben werden können

Es macht eigentlich mehr Sinn in binären. Die höherwertigen Bits, die für den Schaltvorgang nicht verwendet werden können, werden einfach entfernt.

110010 und 11111 ist 10010

Wenn das Code-Snippet ausgeführt wird, lautet das Ergebnis 954204160 oder binär 0011 1000 1110 0000 0000 0000 0000 0000. Die 18 Bits auf der linken Seite der ersten Binärzahl werden verschoben, und die 14 Bits auf der rechten Seite werden verschoben links.

Das andere große Problem beim Verschieben von Bits ist, was passiert, wenn die Anzahl der zu verschiebenden Stellen eine negative Zahl ist. Verwenden wir -50 als Anzahl der zu verschiebenden Bits und sehen, was passiert.

ValueAfterShifting = StartingValue << -50

Wenn dieses Code-Snippet ausgeführt wird, erhalten wir -477233152 oder 1110 0011 1000 1110 0000 0000 0000 als Binärdatei. Die Zahl wurde um 14 Stellen nach links verschoben. Warum 14? VB.NET geht davon aus, dass die Anzahl der Stellen eine vorzeichenlose Ganzzahl ist, und führt eine aus Und Operation mit der gleichen Maske (31 für ganze Zahlen).

1111 1111 1111 1111 1111 1111 1100 1110
0000 0000 0000 0000 0000 0000 0001 1111
(Und)----------------------------------
0000 0000 0000 0000 0000 0000 0000 1110

1110 in binär ist 14 dezimal. Beachten Sie, dass dies das Gegenteil einer Verschiebung von positiven 50 Stellen ist.

Auf der nächsten Seite gehen wir zu einigen anderen Bitoperationen über, beginnend mit Xor-Verschlüsselung!

Ich erwähnte, dass eine Verwendung von Bitoperationen die Verschlüsselung ist. Die Xor-Verschlüsselung ist eine beliebte und einfache Methode zum "Verschlüsseln" einer Datei. In meinem Artikel Very Simple Encryption using VB.NET zeige ich Ihnen eine bessere Möglichkeit, stattdessen Zeichenfolgen zu manipulieren. Die Xor-Verschlüsselung ist jedoch so verbreitet, dass sie zumindest eine Erklärung verdient.

Das Verschlüsseln einer Textzeichenfolge bedeutet, dass diese in eine andere Textzeichenfolge übersetzt wird, die keine offensichtliche Beziehung zur ersten hat. Sie brauchen auch eine Möglichkeit, es wieder zu entschlüsseln. Die Xor-Verschlüsselung übersetzt den binären ASCII-Code für jedes Zeichen in der Zeichenfolge mithilfe der Xor-Operation in ein anderes Zeichen. Für diese Übersetzung benötigen Sie eine andere Nummer, die Sie in Xor verwenden können. Diese zweite Nummer wird als Schlüssel bezeichnet.

Die Xor-Verschlüsselung wird als "symmetrischer Algorithmus" bezeichnet. Dies bedeutet, dass wir den Verschlüsselungsschlüssel auch als Entschlüsselungsschlüssel verwenden können.

Verwenden wir "A" als Schlüssel und verschlüsseln wir das Wort "Basic". Der ASCII-Code für "A" lautet:

0100 0001 (dezimal 65)

Der ASCII-Code für Basic lautet:

B - 0100 0010
a - 0110 0001
s - 0111 0011
i - 0110 1001
c - 0110 0011

Das Xor von jedem von diesen ist:

0000 0011 - dezimal 3
0010 0000 - Dezimalzahl 32
0011 0010 - Dezimalzahl 50
0010 1000 - Dezimalzahl 40
0010 0010 - Dezimalzahl 34

Diese kleine Routine macht den Trick:

-- Xor-Verschlüsselung --
Dimme ich so kurz
ResultString.Text = ""
Dim KeyChar As Integer
KeyChar = Asc (EncryptionKey.Text)
For i = 1 To Len (InputString.Text)
   ResultString.Text & = _
      Chr (KeyChar Xor _
      Asc (Mid (InputString.Text, i, 1)))
Nächster

Das Ergebnis ist in dieser Abbildung zu sehen:

--------
Klicken Sie hier, um die Abbildung anzuzeigen
Klicken Sie in Ihrem Browser auf die Schaltfläche Zurück, um zurückzukehren
--------

Um die Verschlüsselung umzukehren, kopieren Sie die Zeichenfolge aus der Ergebnis-Textbox und fügen Sie sie wieder in die Zeichenfolge-Textbox ein. Klicken Sie dann erneut auf die Schaltfläche.

Ein weiteres Beispiel für die Verwendung bitweiser Operatoren ist der Austausch von zwei Ganzzahlen, ohne dass eine dritte Variable für die temporäre Speicherung deklariert wird. Dies ist die Art von Dingen, die sie vor Jahren in Assembler-Programmen machten. Es ist jetzt nicht allzu nützlich, aber Sie könnten eines Tages eine Wette gewinnen, wenn Sie jemanden finden, der nicht glaubt, dass Sie das können. Auf jeden Fall, wenn Sie noch Fragen dazu haben, wie Xor Arbeiten durch diese sollten sie zur Ruhe bringen. Hier ist der Code:

Dim FirstInt As Integer
Dim SecondInt As Integer
FirstInt = CInt (FirstIntBox.Text)
SecondInt = CInt (SecondIntBox.Text)
FirstInt = FirstInt Xoder SecondInt
SecondInt = FirstInt Xoder SecondInt
FirstInt = FirstInt Xoder SecondInt
ResultBox.Text = "Erste Ganzzahl:" & _
   FirstInt.ToString & "-" & _
   "Zweite Ganzzahl:" & _
   SecondInt.ToString

Und hier ist der Code in Aktion:

--------
Klicken Sie hier, um die Abbildung anzuzeigen
Klicken Sie in Ihrem Browser auf die Schaltfläche Zurück, um zurückzukehren
--------

Herauszufinden, warum dies genau funktioniert, wird als "Übung für den Schüler" zurückgelassen..

Auf der nächsten Seite erreichen wir das Ziel: Allgemeine Bitmanipulation

Obwohl diese Tricks Spaß machen und lehrreich sind, sind sie dennoch kein Ersatz für allgemeine Bitmanipulationen. Wenn Sie wirklich auf die Ebene der Bits kommen, können Sie einzelne Bits untersuchen, festlegen oder ändern. Das ist der wahre Code, der in .NET fehlt.

Vielleicht fehlt es daran, dass es nicht so schwer ist, Unterprogramme zu schreiben, die dasselbe erreichen.

Ein typischer Grund, warum Sie dies tun möchten, besteht darin, das beizubehalten, was manchmal als a bezeichnet wird Flag-Byte. Einige Anwendungen, insbesondere solche, die in einfachen Sprachen wie Assembler geschrieben sind, verwalten acht Boolesche Flags in einem einzelnen Byte. Beispielsweise enthält das Statusregister eines 6502-Prozessorchips diese Informationen in einem einzelnen 8-Bit-Byte:

Bit 7. Negatives Flag
Bit 6. Überlaufflag
Bit 5. Nicht verwendet
Bit 4. Break Flag
Bit 3. Dezimalflag
Bit 2. Interrupt-Deaktivierungsflag
Bit 1. Null-Flag
Bit 0. Trage Flagge

(aus Wikipedia)

Wenn Ihr Code mit dieser Art von Daten arbeiten muss, benötigen Sie einen allgemeinen Bitmanipulationscode. Dieser Code erledigt die Arbeit!

'Das ClearBit-Sub löscht das 1-basierte n-te Bit
'(MyBit) einer ganzen Zahl (MyByte).
Sub ClearBit (ByRef MyByte, ByVal MyBit)
   Bitmaske als Int16 dimmen
   'Erstelle eine Bitmaske mit gesetztem 2 bis n-ten Potenzbit:
   BitMask = 2 ^ (MyBit - 1)
   'Lösche das n-te Bit:
   MyByte = MyByte und nicht BitMask
End Sub
'Die ExamineBit-Funktion gibt True oder False zurück
'abhängig vom Wert des 1-basierten, n-ten Bits (MyBit)
'einer ganzen Zahl (MyByte).
Funktion ExamineBit (ByVal MyByte, ByVal MyBit) als Boolean
   Bitmaske als Int16 dimmen
   BitMask = 2 ^ (MyBit - 1)
   ExamineBit = ((MyByte und BitMask)> 0)
Funktion beenden
'Das SetBit-Sub setzt das 1-basierte n-te Bit
'(MyBit) einer ganzen Zahl (MyByte).
Sub SetBit (ByRef MyByte, ByVal MyBit)
   Bitmaske als Int16 dimmen
   BitMask = 2 ^ (MyBit - 1)
   MyByte = MyByte oder BitMask
End Sub
'Das ToggleBit Sub ändert den Status
'des 1-basierten, n-ten Bits (MyBit)
'einer ganzen Zahl (MyByte).
Sub ToggleBit (ByRef MyByte, ByVal MyBit)
   Bitmaske als Int16 dimmen
   BitMask = 2 ^ (MyBit - 1)
   MyByte = MyByte Xor BitMask
End Sub

Um den Code zu demonstrieren, ruft diese Routine ihn auf (Parameter, die bei Click Sub nicht codiert sind):

Private Sub ExBitCode_Click (…
   Dim Byte1, Byte2 As Byte
   Dim MyByte, MyBit
   Dim StatusOfBit As Boolean
   Dim SelectedRB As String
   StatusLine.Text = ""
   SelectedRB = GetCheckedRadioButton (Me) .Name
   Byte1 = ByteNum.Text 'Nummer, die in Bitflags konvertiert werden soll
   Byte2 = BitNum.Text 'Zu umschaltendes Bit
   'Das Folgende löscht das höherwertige Byte und gibt nur das zurück
   Byte niedriger Ordnung:
   MyByte = Byte1 und & HFF
   MyBit = Byte2
   Wählen Sie Case SelectedRB
      Fall "ClearBitButton"
         ClearBit (MyByte, MyBit)
         StatusLine.Text = "Neues Byte:" & MyByte
      Fall "ExamineBitButton"
         StatusOfBit = ExamineBit (MyByte, MyBit)
         StatusLine.Text = "Bit" & MyBit & _
            "ist" & StatusOfBit
      Fall "SetBitButton"
         SetBit (MyByte, MyBit)
         StatusLine.Text = "Neues Byte:" & MyByte
      Fall "ToggleBitButton"
         ToggleBit (MyByte, MyBit)
         StatusLine.Text = "Neues Byte:" & MyByte
   Ende auswählen
End Sub
Private Funktion GetCheckedRadioButton (_
   ByVal Parent As Control) _
   Als RadioButton
   Dim FormControl als Steuerelement
   Dimmen Sie RB als RadioButton
   Für jedes FormControl in Parent.Controls
      Wenn FormControl.GetType () GetType (RadioButton) ist, dann
         RB = DirectCast (FormControl, RadioButton)
         Wenn RB.Checked dann Return RB
      End If
   Nächster
   Nichts zurückgeben
Funktion beenden

Der Code in Aktion sieht folgendermaßen aus:

--------
Klicken Sie hier, um die Abbildung anzuzeigen
Klicken Sie in Ihrem Browser auf die Schaltfläche Zurück, um zurückzukehren
--------