ビットとは?/ アットローン
[ 557] ビット演算 - Wikipedia
[引用サイト] http://ja.wikipedia.org/wiki/%E3%83%93%E3%83%83%E3%83%88%E6%BC%94%E7%AE%97
|
ビット演算(ビットえんざん)とは、ひとつあるいはふたつのビットパターンまたは二進数を個々のビットの列として操作することである。 CPUからすればビット演算は簡単な論理回路で実現できるが、四則演算、特に乗除算は複雑な論理回路を必要とするため、多くのコンピュータでは、ビット演算は加減算より若干速く、乗除算よりずっと高速である。 ビット単位NOTは二進数値の1の補数を作るのに使える。そして2の補数を作るときの途中の段階にも使われる。 ビット単位ORは、ふたつの同じ長さのビットパターンを入力とし、同じ位置のビット毎に論理的ORを行って同じ長さのビットパターンを出力する操作である。各ビット位置で、入力のふたつのビットのどちらかでも 1 であれば、出力ビットは 1 となる。 ビット単位ORは、ビット列がフラグ列として扱われるときによく使われる。つまり、各ビットが個別にブーリアン値を表している場合である。ある二進数値とひとつ以上の1を含むビット列とをビット単位ORを行うと、後者のビット列で 1 となっている位置が結果として出てくるビット列でも1となる。 このテクニックはメモリが少ない環境でプログラムを書く人がよく使う。ひとつのビットパターンで各種ステータスを一度に表現するのである。 また、MIPSアーキテクチャでは、命令セットを縮小するためにこれを使っている。MIPSではレジスタ間ロード(レジスタからレジスタへの値のコピー)命令がない。その代わりにゼロレジスタという常に内容がゼロで、何かを書き込んでも値が変わらないレジスタがある。そこで、レジスタ間ロードはビット単位OR命令を使って、ゼロレジスタとあるレジスタの ビット単位OR の結果を別のレジスタに格納することで実現される。 ビット単位XORは、ふたつの同じ長さのビットパターンを入力とし、同じ位置のビット毎に論理的XORを行って同じ長さのビットパターンを出力する操作である。各ビット位置で、入力するふたつのビットが違う値であれば、出力ビットは1となる。 アセンブリ言語プログラマはレジスタの内容をゼロにしたいときに XOR 操作を行う。多くのアーキテクチャでは、ゼロという値をロードしてレジスタに格納するよりもXORを行う方がCPUクロックサイクルを消費しない。同じ値をビット単位XORのふたつの入力として使うと、出力は常にゼロになる。つまり、同じレジスタを指定したXOR命令を実行して同じレジスタに戻すことでその内容をゼロにすることができる。もちろん、MIPSアーキテクチャの場合は入力としてゼロレジスタを使えば、ORでも XORでもANDでもADDでも結果をゼロにすることができる。 このビットパターンで1番目のビットと3番目のビットを同時に変更したい場合、もうひとつのビットパターンで、その変えたい位置に1を置いておく。 ビット単位ANDは、ふたつの同じ長さのビットパターンを入力とし、同じ位置のビット毎に論理的ANDを行って同じ長さのビットパターンを出力する操作である。各ビット位置で、入力するふたつのビットがどちらも1であれば、出力ビットは 1 となる。 ビット単位ANDはビットマスク操作として使われることもある。これは、ビット列の一部を取り出すのに使われたり、ある特定のビットが1か0かを調べるのにも使われる。 この例で、三番目のビットが 1 かどうかを調べるには、ビット単位ANDに対して、その調べたいビット位置だけを1にしたビットパターンを入力する。 この結果はゼロなので、三番目のビットは0であったことがわかる。このようなビット単位ANDの使い方はビットマスクと呼ばれる。このとき、関心のないビット位置は0にする。 ビットシフトはときにビット演算の一種とみなされる。というのは、それがビット列に対する操作だからである。それとは逆にビットシフトは数値全体に対するものでビット毎に操作するものではないという考え方もある。この操作では各桁を右か左に移動させる。コンピュータのプロセッサ内のレジスタは固定のビット長を持っていて、数値を格納する。これに対するビットシフトはいくつかのビットがレジスタからはみ出すことを意味する。ビットシフトにいろいろな種類があるのは、このはみ出した部分をどう扱うかが違うためである。 シフトの一般的な形式のひとつが算術シフトである。このシフトではあふれたビットは単に消える。シフトによって空いたビット部分には、左シフトではゼロが入り、右シフトでは符号ビットと同じ内容が入る。ここでいう符号ビットとは最上位ビットのことである。下記の例は 4ビットレジスタの場合である。 前者の例は、左端の0はあふれて消え、あらたな0が右端に入れられている。後者の例は、右端の1はあふれて消え(多くの場合、それがキャリーフラグにセットされる)、符号ビット0が左端にコピーされている。マルチプルシフトはシングルシフトの回数を減らすものである。 左算術シフトは2倍するのと同じで(ただし、オーバーフローは起きない)、右算術シフトは2で割ってあまりを捨てるのと同じである。 論理シフトは算術シフトと似ているが、右シフトのときに常に空いたビットをゼロにして、符号拡張はしない。したがって、論理シフトは符号無しの二進数を扱うのに適していて、算術シフトは2の補数表現の符号付き二進数を扱うのに適している。 もうひとつのシフトとして環状シフトまたはビット・ローテーションがある。これはビット列の左端と右端がつながっているように扱ってシフトするものである。シフト方向の端をあふれた桁は逆の端に置かれる。これは、存在するビットを残しておく必要があるとき、ビットの位置を変えるのに使われたりする。 こちらはローテート操作の際にキャリーフラグを考慮に入れるものである。これは、論理シフトあるいは算術シフトであふれた桁をキャリーフラグに格納するために使われる。このため、PICのようなマイクロコントローラではローテートとキャリー付きローテートだけを用意して、算術シフトや論理シフト命令は用意しない。キャリー付きローテートは特にプロセッサのレジスタのビット幅より大きな数値のシフトを実現する場合に便利である。 マシンは算術演算や論理演算をするのに十分な命令を持っているが、実際全ての演算はビット演算の組み合わせと何らかのゼロ判定機能があれば実現できる。例えば、下記の例はふたつの任意の整数 a と b の乗算をビットシフトと加算で実現する擬似コードである。 |