論理演算
論理積と論理和
今回は、算術演算ではなく論理演算を行ってみましょう
アセンブリでも当然、ビット単位の論理演算をサポートしています
論理積を求めるにはAND命令を
論理和を求めるにはOR命令を用います
これらの命令は、第一オペランド(ディスティネーションオペランド)と
第二オペランド(ソースオペランド)を論理演算し、その結果を第一オペランドに格納します
ディスティネーションオペランドにはレジスタ、またはメモリを指定し
ソースオペランドには、レジスタ、メモリ、または即値を指定することができます
-A 100
15F2:0100 MOV AL , 35
15F2:0102 MOV BYTE PTR [0200] , AL
15F2:0105 AND AL , 0F
15F2:0107 MOV BYTE PTR [0201] , AL
15F2:010A
-G =100 10A
AX=0005 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=15F2 ES=15F2 SS=15F2 CS=15F2 IP=010A NV UP EI PL NZ NA PE NC
-D 200 201
15F2:0200 35 05 5.
これは、ニ進化十進数の性質を利用した変換プログラムです
最初にALレジスタに代入しているのは、ASCIIコードの '5' でバイナリの 5 ではありません
これを数値の5として扱うには、論理演算を利用して変換する方法が最も簡易です
C言語の講座でも似たようなことをやっていますが
この変換の応用で、アルファベットの小文字と大文字の変換も可能です
あるビットを除去するにはANDを使いますが、付加するにはORを用います
次のプログラムは、先ほどのプログラムの逆を行っています
-A 100
15F2:0100 MOV AL , 5
15F2:0102 OR AL , 30
15F2:0104 MOV BYTE PTR [0200] , AL
15F2:0107
-G =100 107
AX=0035 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=15F2 ES=15F2 SS=15F2 CS=15F2 IP=0107 NV UP EI PL NZ NA PE NC
-D 200 200
15F2:0200 35 5
論理否定
レジスタ、またはメモリのビット列を反転する否定も可能です
論理否定はNOT命令を指定します
NOTはディスティネーションオペランドのみを指定します
第一オペランドは、レジスタまたはメモリアドレスを指定します
ただビット列を反転されるだけなので、とくに難しいこともありません
また、フラグには一切影響を与えません
-A 100
15F2:0100 MOV AL , 5A
15F2:0102 NOT AL
15F2:0104
-G =100 104
AX=00A5 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=15F2 ES=15F2 SS=15F2 CS=15F2 IP=0104 NV UP EI PL NZ NA PO NC
ALレジスタの内容をNOT命令によって反転させています
ビットが反転していることが、結果からわかるでしょう
排他的論理和
最後に排他的論理和を学習しましょう
排他的論理和は、一方が1、もう一方が0の状態で1になる論理演算です
逆に、両方が0または1の状態であれば0になります
排他的論理和にはXOR命令を用います
第一オペランド(ディスティネーション・オペランド)には、レジスタまたはメモリを指定し
第二オペランド(ソース・オペランド)には、対象となるレジスタ、メモリ、または即値を指定します
二つのオペランドを排他的論理和で演算し、その結果をディスティネーションに格納します
-A 100
15F2:0100 MOV AL , FF
15F2:0102 XOR AL , CC
15F2:0104 MOV AH , AL
15F2:0106 XOR AL , CC
15F2:0108
-G =100 108
AX=33FF BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=15F2 ES=15F2 SS=15F2 CS=15F2 IP=0108 NV UP EI NG NZ NA PE NC
最初にビット列 1111 1111 に 1100 1100 で論理演算を行っています
この結果 0011 0011 は、AHに格納されています
次に、同じ値 1100 1100 で再び排他的論理演算を行います
この結果は、最初の 1111 1111 に再生されます
符号の反転
8086では、数値の符号を簡単に反転させることができます
すなわち、対象の2の補数を求めることができます
符号を反転させるにはNEG命令を用います
第一オペランド(ディスティネーション・オペランド)には、対象となるレジスタまたはメモリを指定します
NEG命令は、対象の2の補数を求めディスティネーションにストアします
-A 100
15F2:0100 MOV AL , 0F
15F2:0102 NEG AL
15F2:0104
-G =100 104
AX=00F1 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=15F2 ES=15F2 SS=15F2 CS=15F2 IP=0104 NV UP EI NG NZ AC PO CY
ビット列 0000 1111 の負数を求めています
0000 1111 をまず反転して1の補数にし、それに1を加算します
つまり 1111 0001 となるわけですね
結果を破棄する論理積
論理演算命令の中に、特殊な命令があります
これは、論理積を演算子結果を破棄するというものです
この命令の目的は CMP 命令と同じで、フラグをセットするためです
内容を破棄するということ以外は AND 命令と同じです
-A 100
15F2:0100 MOV AL , F0
15F2:0102 TEST AL , 00
15F2:0104
-G =100 104
AX=00F0 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=15F2 ES=15F2 SS=15F2 CS=15F2 IP=0104 NV UP EI PL ZR NA PE NC
AXレジスタの内容は変化していません
しかし、TEST命令でANDと同じ演算をしてフラグがセットされています
CFフラグはAND命令では必ず NC になりますし、TESTの結果は0なのでSFフラグもPLです