Bitweise Operationen sind beim Programmieren von Hardwareregistern in eingebetteten Systemen unbedingt erforderlich. Zum Beispiel hat jeder Prozessor, den ich jemals benutzt habe, ein oder mehrere Register (normalerweise eine bestimmte Speicheradresse), die steuern, ob ein Interrupt aktiviert oder deaktiviert ist. Damit ein Interrupt ausgelöst werden kann, muss das Aktivierungsbit für diesen einen Interrupttyp gesetzt werden, wobei vor allem keines der anderen Bits im Register geändert werden darf.
Wenn ein Interrupt ausgelöst wird, setzt er normalerweise ein Bit in einem Statusregister, sodass eine einzelne Serviceroutine den genauen Grund für den Interrupt bestimmen kann. Das Testen der einzelnen Bits ermöglicht ein schnelles Dekodieren der Interruptquelle.
In vielen eingebetteten Systemen kann der insgesamt verfügbare RAM 64, 128 oder 256 Byte betragen (dh Bytes, nicht Kilobytes oder Megabytes). In dieser Umgebung wird häufig ein Byte verwendet, um mehrere Datenelemente, Boolesche Flags usw. zu speichern und anschließend Bitoperationen zu verwenden um diese zu setzen und zu lesen.
Ich arbeite seit einigen Jahren mit einem Satellitenkommunikationssystem, bei dem die Nachrichtennutzlast 10,5 Bytes beträgt. Um dieses Datenpaket optimal zu nutzen, müssen die Informationen in den Datenblock gepackt werden, ohne dass nicht verwendete Bits zwischen den Feldern verbleiben. Dies bedeutet, dass bitweise Operatoren und Shift-Operatoren ausgiebig verwendet werden, um die Informationswerte in die zu übertragende Nutzlast zu packen.
Grundsätzlich verwenden Sie sie aus Gründen der Größe und Geschwindigkeit. Bitweise Operationen sind unglaublich einfach und daher normalerweise schneller als arithmetische Operationen. Um beispielsweise den grünen Teil eines RGB-Werts zu erhalten, lautet der arithmetische Ansatz
(rgb / 256) % 256
. Mit bitweisen Operationen würden Sie etwas wie tun(rgb >> 8) & 0xFF
. Letzteres ist deutlich schneller und wenn Sie sich erst einmal daran gewöhnt haben, ist es auch einfacher. Im Allgemeinen spielen bitweise Operationen eine große Rolle, wenn Sie Daten kompakt und schnell codieren / decodieren müssen.quelle
BYTE g1 = (rgb / 256) % 256;
00E51013...C1 E9 08...shr ecx,8
00E51016...88 0C 24...mov byte ptr [esp],cl
Diese Art von Operationen wird häufig beim Schreiben für eingebettete Systeme verwendet, bei denen der Arbeitsspeicher oder die CPU-Leistung eingeschränkt sind.
Um beispielsweise Platz zu sparen, können Sie mehrere Variablen in einer einzelnen 8-Bit-Int-Variablen speichern, indem Sie jedes Bit zur Darstellung eines Booleschen Werts verwenden. Dann brauchen Sie einen schnellen Weg, um ein bestimmtes Bit zu setzen oder den Bitwert abzurufen.
Im Allgemeinen ist es beim Programmieren in höheren Programmiersprachen wie C # auf einem Desktop-PC mit Gigabyte Arbeitsspeicher nicht wichtig, dass jedes
bool
ein ganzes Byte belegt . Wenn Sie jedoch einen Mikrocontroller in C mit 2 KB Arbeitsspeicher programmieren, zählt jedes einzelne Bit. Daher kann die Fähigkeit, 8 Bools in ein einzelnes Byte zu packen, von entscheidender Bedeutung sein.quelle
[Flags]
Attribut, das die Verwendung einesEnum
Feldes als Bit ermöglicht. Hat beispielsweiseFont
eineStyle
Eigenschaft, die ein Bitfeld ist, das fett, kursiv, unterstrichen und durchgestrichen ist.Bitweise Operationen werden auch häufig in Video- und Audio-Codecs verwendet, aus demselben Grund wie in eingebetteter Elektronik. Die Möglichkeit, fünf Flags und einen Elf-Bit-Timer in einen halben Int zu packen, ist sehr nützlich, wenn Sie einen supereffizienten Videocodec erstellen möchten.
MPEG 4 verwendet sogar die exponentielle Golomb-Codierung für Felder mit variabler Bitlänge. Ein Wert, der als letztes Paket 17 oder 19 Bit breit war, könnte in diesem Paket nur drei oder fünf Bit breit sein - und Sie würden das alles mit bitweisen Operationen herausfinden.
quelle
Tricks, die bitweise logische Operationen, bitweise Verschiebungsoperationen und arithmetische Operationen kombinieren, können von Personen verstanden werden, die die Konstruktion eines binären Addierers unter Verwendung von Logikgattern studiert haben (und / oder nicht). Außerhalb dieses Kreises ist es ohne einen detaillierten Kommentar sehr schwer zu verstehen.
Dies ist nützlich, wenn Sie SIMD- Einheiten programmieren , insbesondere wenn die CPU-Architektur absichtlich einige SIMD-Anweisungen ausgelassen hat, da sie von einigen anderen emuliert werden könnten.
Beispielsweise definiert die Architektur möglicherweise keine Anweisungen zum Aufnehmen der negativen Werte einer Gruppe von 16 Bytes, die jedoch durch bitweises Negieren und anschließendes Addieren von 1 emuliert werden können. Ebenso kann auch eine Subtraktion weggelassen werden, da sie durch Aufnehmen emuliert werden kann das Negativ des zweiten Operanden. Die Verfügbarkeit der "Alternativroute" ist der Grund für das Weglassen bestimmter Anweisungen.
Ebenso unterstützt die SIMD möglicherweise nur eine parallele 8-Bit-Addition, ohne eine Addition für breitere Elemente wie 16-Bit, 32-Bit oder 64-Bit zu implementieren. Um sie zu emulieren, muss man das Vorzeichenbit aus dem 8-Bit-Berechnungsergebnis extrahieren und dann die Übertragoperation für das nächste Element ausführen.
quelle
Packen von Daten, schnellere Operationen (Multiplikation, Division und Modul sind bei Potenzen von 2 wesentlich schneller), Bit-Flipping usw. Lernen Sie sie und beginnen Sie, sie zu verwenden, und Sie werden langsam beginnen, die meisten Vorteile auf eigene Faust zu erkennen.
quelle