最新のCodeProjectニュースレターを読んだ後、ビットごとの操作に関するこの記事に出会いました。興味深い読み物になります。整数が偶数か奇数かをチェックすることの利点は確かにわかりますが、n番目のビットが設定されているかどうかをテストしますか?これの利点は何でしょうか?
最新のCodeProjectニュースレターを読んだ後、ビットごとの操作に関するこの記事に出会いました。興味深い読み物になります。整数が偶数か奇数かをチェックすることの利点は確かにわかりますが、n番目のビットが設定されているかどうかをテストしますか?これの利点は何でしょうか?
回答:
組み込みシステムでハードウェアレジスタをプログラミングする場合、ビット演算は絶対に不可欠です。たとえば、これまで使用したすべてのプロセッサには、割り込みを有効にするか無効にするかを制御する1つ以上のレジスタ(通常は特定のメモリアドレス)があります。割り込みが通常のプロセスを起動できるようにするには、その重要な点として、レジスタ内の他のビットを変更せずに、その割り込みタイプのイネーブルビットを設定します。
割り込みが発生すると、通常、1つのサービスルーチンが割り込みの正確な理由を判断できるように、ステータスレジスタにビットを設定します。個々のビットをテストすると、割り込みソースの高速デコードが可能になります。
多くの組み込みシステムでは、使用可能なRAMの合計は64、128、または256バイト(つまり、キロバイトやメガバイトではなくバイト)になる場合があります。これらを設定して読み取る。
私は何年もの間、メッセージペイロードが10.5バイトの衛星通信システムで働いてきました。このデータパケットを最大限に活用するには、フィールド間に未使用のビットを残さずに情報をデータブロックにパックする必要があります。これは、ビット単位およびシフト演算子を広範囲に使用して、情報値を取得し、送信されるペイロードにパックすることを意味します。
基本的に、サイズと速度を考慮してこれらを使用します。ビット演算は非常に単純であるため、通常は算術演算よりも高速です。たとえば、rgb値の緑の部分を取得するための算術的アプローチは(rgb / 256) % 256
です。ビット単位の操作を使用すると、次のようになり(rgb >> 8) & 0xFF
ます。後者は非常に高速で、慣れると簡単になります。一般に、ビット単位の操作は、コンパクトで高速な方法でデータをエンコード/デコードする必要がある場合に多くの役割を果たします。
BYTE g1 = (rgb / 256) % 256;
00E51013...C1 E9 08...shr ecx,8
00E51016...88 0C 24...mov byte ptr [esp],cl
これらの種類の操作は、メモリまたはCPUの電力が制限されている組み込みシステム向けの書き込み時によく使用されます。
たとえば、スペースを節約するために、各ビットを使用してブール値を表すことにより、単一の8ビットint変数に複数の変数を格納できます。次に、特定のビットを設定するか、ビット値を取得する高速な方法が必要です。
一般に、ギガバイトのメモリを搭載したデスクトップPCでC#のような高レベル言語でプログラミングする場合、それぞれbool
が1バイト全体を占有することはあまり気にしません。ただし、2kbのメモリを備えたCでマイクロコントローラーをプログラミングしている場合、すべてのビットがカウントされるため、8つのブールを1バイトにパックする機能が重要になる場合があります。
[Flags]
使用を許可する属性がありますEnum
。たとえば、太字、斜体、下線、取り消し線を含むビットフィールドでFont
あるStyle
プロパティがあります。
ビットワイズ演算は、組み込み電子機器と同じ理由で、ビデオおよびオーディオコーデックでも頻繁に使用されます。5つのフラグと11ビットタイマーを半分のintにパックできることは、非常に効率的なビデオコーデックを作成する場合に非常に便利です。
実際、MPEG 4 は可変ビット長フィールドに指数ゴロムエンコーディングを使用します。最終パケットの幅が17ビットまたは19ビットだった値は、このパケットの幅が3ビットまたは5ビットに過ぎない可能性があります。ビット単位の操作ですべてを把握できます。
ビットごとの論理演算、ビットごとのシフト演算、および算術演算を組み合わせたトリックは、論理ゲートを使用してバイナリ加算器の構築を研究した人(および、そうでない人)に理解できます。そのサークルの外では、詳細なコメントなしに理解することは非常に困難です。
SIMDユニットをプログラミングするとき、特にCPUのアーキテクチャが一部のSIMD命令をエミュレートできるために意図的にSIMD命令を省略した場合に役立ちます。
たとえば、アーキテクチャは16バイトのグループの負の値を取得するための命令を定義しない場合がありますが、ビット単位の否定と1を加算することでエミュレートできます。同様に、減算もエミュレートできるため、省略できます。第2オペランドの負。「代替ルート」の利用可能性は、特定の指示を省略する理由です。
同様に、SIMDは16ビット、32ビット、64ビットなどのより広い要素の追加を実装せずに、パラレル8ビットの追加のみをサポートします。それらをエミュレートするには、8ビットの計算結果から符号ビットを抽出し、次の要素でキャリー演算を実行する必要があります。
データのパッキング、より速い操作(2のべき乗に合わせれば乗算、除算、およびモジュラスは大幅に高速化)、ビットフリッピングなど。それらを学習して使用し始めると、ほとんどの利点が徐々に自分でわかるようになります。