シフト
算術シフトと論理シフト
論理演算の次は、シフト命令について詳しく説明しましょう
アセンブリ言語のシフトは、高水準言語のそれよりももっと細かい操作ができます
シフトとは、ビット配列を右、または左にずらすものですが
これには算術シフトと論理シフトと呼ばれるものがあります
算術シフトとは、シフトしても最も端のビットの値が変化しないもので
論理シフトとは、シフトしてできた端の空白は必ず0を挿入するものです
算術シフト
|
---|
1 | 0 | 1 | 1 | 0 | 1 | 0 | 1
|
---|
↓右に1シフト
|
---|
1 | 1 | 0 | 1 | 1 | 0 | 1 | 0 | -> | 1
|
---|
論理シフト
|
---|
1 | 0 | 1 | 1 | 0 | 1 | 0 | 1
|
---|
↓右に1シフト
|
---|
0 | 1 | 0 | 1 | 1 | 0 | 1 | 0 | -> | 1
|
---|
赤い部分に注目してください
算術シフトは最上位ビットから全てのビットを右にシフトしていますが
最上位ビットはそのままの状態を保持しています
因みに、コンピュータ科学の分野ですが、最上位ビットはMSBと呼びます
論理シフトは、シフトすることによってできたMSBの空白を0で埋めます
多くの高水準言語でのシフトは、この論理シフトですね
なぜ、算術シフトと論理シフトなどややこしいものがあるのかというと
符号付整数を右に論理シフトすると、符合まで変わってしまうという自体が発生します
ところが、算術シフトであれば符号を変えることなくシフトさせることができますね
(符号の考え方については、2の補数を学習してください)
算術シフトの左シフトの存在に意味はないですが(論理シフトと同じ)
8086アセンブリでは、これをサポートしています(機械語にすると同じ)
算術シフトの左シフトはSAL、右シフトはSAR、
論理シフトの左シフトはSHL、右シフトはSHRとなります
第一オペランド(ディスティネーション・オペランド)には、レジスタまたはメモリを指定します
第二オペランドは、何ビットシフトするかを指定することができます
ここには即値かCLレジスタを指定することができます
例えば、第二オペランドを2と指定すれば2回シフトしますが、即値の場合
8086CPUではつねに1を指定します(それ以外の即値はサポートされていません)
ここに別の値を指定することができるのは186以降のCPUとなります
また、桁あふれしたビットはキャリーフラグにセットされます
-A 100
15F2:0100 MOV AL , FF
15F2:0102 SHR AL , 1
15F2:0104
-G =100 104
AX=007F BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=15F2 ES=15F2 SS=15F2 CS=15F2 IP=0104 OV UP EI PL NZ AC PO CY
-A 100
15F2:0100 MOV AL , FE
15F2:0102 SHR AL , 1
15F2:0104
-G =100 104
AX=007F BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=15F2 ES=15F2 SS=15F2 CS=15F2 IP=0104 OV UP EI PL NZ AC PO NC
最初に実行しているプログラムは、ビット列 1111 1111 を右に論理シフトしています
その結果は 0111 1111 となり、最下位ビット 1 がキャリーフラグにセットされています
その次のプログラムは 1111 1110 を右シフトしているので、キャリーフラグが0になっていますね
-A 100
15F2:0100 MOV AL , C6
15F2:0102 SAR AL , 1
15F2:0104
-G =100 104
AX=00E3 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 NC
今度は、算術シフトで右にシフトしています
ビット列 1100 0110 を算術シフトで右にシフトすると 1110 0011 となるので
16進数では E3 となるのがわかると思います