はじめに 算術左シフト(マイコン) 算術右シフト(マイコン) 論理左シフト(マイコン) 論理右シフト(マイコン)
CY付き左ローテート(マイコン) CY付き右ローテート(マイコン) 左ローテート(マイコン) 右ローテート(マイコン)
C言語におけるシフト まとめ おまけ
マイコンを直接操作することのできる組み込み系の制御プログラムでは複数のシフト演算を利用することができます。 C言語で素直に命令を記述した場合はC言語の制限により利用できる演算の種類は少なくなりますが、コンパイラが提供する機種依存性の強いライブラリを利用すると特殊なシフト演算を利用することができますので、機会があれば是非挑戦してみてください。 本章では、 ・マイコンを直接利用した場合に利用できるシフト演算の動作例 ・C言語で「ベタ」に記述した場合のシフト演算の動作例 に分けて解説したいと思います。 |
▲ |
ビット列全体を左にシフトし、MSBのビットはCYに移動し、LSBには0が格納されます。 MSBは最上位ビット、LSBは最下位ビットを示します。CYはキャリーフラグです。 MSBという表現は非常に都合がよく、値が複数バイトで構成され、最上位ビットのビット位置が何ビット目であろうと、MSBという表現で誰もが納得します。LSBも同様です。 私はLSBをビット0として扱いますが、人によってはLSBをビット1と表現する場合があります。かつて受験した試験ではLSBがビット1であり、かつ図ではLSBが向かって左、MSBが向かって右に描かれていて戸惑ったことがあります(試験問題作成者の意地悪?)。 業務を通じて他の会社の技術者と接すると思いますが、仕様書上でLSBがビット0(もしくは1)であることをお互いに確認しておかないと接続試験で動作しない場合があるので注意が必要です。教育環境、国、そして会社によって文化が違うのです。ですが、少なくとも最上位ビット、最下位ビットについてはMSB、LSBという表現であれば万国共通であると思っても差し支えありません。 |
さて、このシフト演算は算術演算なので、まずはプラスのバイト型の値で実行してみます。 |
CY | MSB | 16進数 | 10進数 | シフト回数 | |||
0 | 0 0 0 0 0 0 0 1 | 0x01 | 1 | 0回目 | |||
0 | 0 0 0 0 0 0 1 0 | 0x02 | 2 | 1回目 | |||
0 | 0 0 0 0 0 1 0 0 | 0x04 | 4 | 2回目 | |||
0 | 0 0 0 0 1 0 0 0 | 0x08 | 8 | 3回目 | |||
0 | 0 0 0 1 0 0 0 0 | 0x10 | 16 | 4回目 | |||
0 | 0 0 1 0 0 0 0 0 | 0x20 | 32 | 5回目 | |||
0 | 0 1 0 0 0 0 0 0 | 0x40 | 64 | 6回目 | |||
0 | 1 0 0 0 0 0 0 0 | 0x80 | -128 | 7回目 | |||
1 | 0 0 0 0 0 0 0 0 | 0x00 | 0 | 8回目 | |||
0 | 0 0 0 0 0 0 0 0 | 0x00 | 0 | 9回目 |
シフトを重ねるたびに値が2倍されます。唯一、7回目のシフトで10進数表現が「-128」になっていますが、符号なし表現であれば「+128」になります。また、総てのビットをシフトすると、以後は「0」となります。 |
続いて、マイナスのバイト型の値で実行してみます。 |
CY | MSB | 16進数 | 10進数 | シフト回数 | |||
0 | 1 1 1 1 1 1 1 1 | 0xFF | -1 | 0回目 | |||
1 | 1 1 1 1 1 1 1 0 | 0xFE | -2 | 1回目 | |||
1 | 1 1 1 1 1 1 0 0 | 0xFC | -4 | 2回目 | |||
1 | 1 1 1 1 1 0 0 0 | 0xF8 | -8 | 3回目 | |||
1 | 1 1 1 1 0 0 0 0 | 0xF0 | -16 | 4回目 | |||
1 | 1 1 1 0 0 0 0 0 | 0xE0 | -32 | 5回目 | |||
1 | 1 1 0 0 0 0 0 0 | 0xC0 | -64 | 6回目 | |||
1 | 1 0 0 0 0 0 0 0 | 0x80 | -128 | 7回目 | |||
1 | 0 0 0 0 0 0 0 0 | 0x00 | 0 | 8回目 | |||
0 | 0 0 0 0 0 0 0 0 | 0x00 | 0 | 9回目 |
元の値がマイナスでもシフトを重ねるたびに値が2倍されています。唯一、8回目以降のシフトでは総てのビットをシフトされたために値は「0」となります。 |
マイナスを示すMSBはシフトを実行することでマイナス符号としての意味を持たなくなる場合があることに注意が必要です(見かけ上はMSBには1つ右のビットが移動しています)。例えば「-65」を示す10進数(16進数では0xBF)を算術左シフトした場合、「-130」になって欲しいところですが、MSBが消失するために「+126」(16進数では0x7E)になります。 |
CY | MSB | 16進数 | 10進数 | シフト回数 | |||
0 | 1 0 1 1 1 1 1 1 | 0xBF | -65 | 0回目 | |||
1 | 0 1 1 1 1 1 1 0 | 0x7E | 126 | 1回目 |
この現象はバイト型の符号付き整数であるために生じる課題です。 バイト型の符号付整数における値の有効範囲は「+127〜-128」です。つまり「-130」という値は表現可能な値の有効範囲を超えているのです。この課題については、より大きなデータ型を利用することで回避することができます。 以上のことから、値がプラス、マイナスに関わらず、符号型、シフト回数、そして、データ型に応じた値の有効範囲に注意すれば算術演算での2倍(4倍、8倍、…)をシフト演算で代用することができます。 |
▲ |
ビット全体を右にシフトし、LSBのビットはCYに移動し、MSBの値は変化しません。 MSBの値が変化しないところが算術右シフトならではの特徴です。 |
では、算術右シフトについてもプラスのバイト型の値で実行してみます。 |
CY | MSB | 16進数 | 10進数 | シフト回数 | |||
0 | 0 1 0 0 0 0 0 0 | 0x40 | 64 | 0回目 | |||
0 | 0 0 1 0 0 0 0 0 | 0x20 | 32 | 1回目 | |||
0 | 0 0 0 1 0 0 0 0 | 0x10 | 16 | 2回目 | |||
0 | 0 0 0 0 1 0 0 0 | 0x08 | 8 | 3回目 | |||
0 | 0 0 0 0 0 1 0 0 | 0x04 | 4 | 4回目 | |||
0 | 0 0 0 0 0 0 1 0 | 0x02 | 2 | 5回目 | |||
0 | 0 0 0 0 0 0 0 1 | 0x01 | 1 | 6回目 | |||
1 | 0 0 0 0 0 0 0 0 | 0x00 | 0 | 7回目 | |||
0 | 0 0 0 0 0 0 0 0 | 0x00 | 0 | 8回目 |
シフトを重ねるたびに値が2分の1されます。そして、総てのビットをシフトすると、以後は「0」となります。 予断ですが、CYに移動したビット(0もしくは1)をバイトデータに加算すると、2で割った際に生じた小数点以下第1位を四捨五入した事になります(詳しくは2進数の解説へ)。 |
続いて、マイナスのバイト型の値で実行してみます。 |
CY | MSB | 16進数 | 10進数 | シフト回数 | |||
0 | 1 0 0 0 0 0 0 0 | 0x80 | -128 | 0回目 | |||
0 | 1 1 0 0 0 0 0 0 | 0xC0 | -64 | 1回目 | |||
0 | 1 1 1 0 0 0 0 0 | 0xE0 | -32 | 2回目 | |||
0 | 1 1 1 1 0 0 0 0 | 0xF0 | -16 | 3回目 | |||
0 | 1 1 1 1 1 0 0 0 | 0xF8 | -8 | 4回目 | |||
0 | 1 1 1 1 1 1 0 0 | 0xFC | -4 | 5回目 | |||
0 | 1 1 1 1 1 1 1 0 | 0xFE | -2 | 6回目 | |||
0 | 1 1 1 1 1 1 1 1 | 0xFF | -1 | 7回目 | |||
1 | 1 1 1 1 1 1 1 1 | 0xFF | -1 | 8回目 | |||
1 | 1 1 1 1 1 1 1 1 | 0xFF | -1 | 9回目 |
シフトを重ねるたびに値が2分の1されます。総てのビットをシフトすると以後は「-1」になります。 |
以上のことから、値がプラス、マイナスに関わらず、符号型、シフト回数に注意すれば算術演算での2分の1(4分の1、8分の1、…)をシフト演算で代用することができます。 |
▲ |
ビット列全体を左にシフトし、MSBのビットはCYに移動し、LSBには0が格納されます。 動作内容は前述の「算術左シフト」と同じですが。 算術シフトと異なり、主に符号なし整数の左シフトに用います。例えばビット位置を移動したりする場合に用います。 |
では、バイト型の値で実行してみます。 |
CY | MSB | 16進数 | 10進数 | シフト回数 | |||
0 | 0 0 0 0 0 0 0 1 | 0x01 | 1 | 0回目 | |||
0 | 0 0 0 0 0 0 1 0 | 0x02 | 2 | 1回目 | |||
0 | 0 0 0 0 0 1 0 0 | 0x04 | 4 | 2回目 | |||
0 | 0 0 0 0 1 0 0 0 | 0x08 | 8 | 3回目 | |||
0 | 0 0 0 1 0 0 0 0 | 0x10 | 16 | 4回目 | |||
0 | 0 0 1 0 0 0 0 0 | 0x20 | 32 | 5回目 | |||
0 | 0 1 0 0 0 0 0 0 | 0x40 | 64 | 6回目 | |||
0 | 1 0 0 0 0 0 0 0 | 0x80 | 128 | 7回目 | |||
1 | 0 0 0 0 0 0 0 0 | 0x00 | 0 | 8回目 | |||
0 | 0 0 0 0 0 0 0 0 | 0x00 | 0 | 9回目 |
シフトを重ねるたびに結果的に値が2倍されます。そして、総てのビットをシフトすると、以後は「0」となります。 算術シフト、論理シフトに共通しますが、シフトにより消失するビットがあることに注意してください。 |
▲ |
ビット全体を右にシフトし、LSBのビットはCYに移動し、MSBには0が格納されます。 算術右シフトと異なりMSBには常に0が格納されます。 算術シフトと異なり、主に符号なし整数の右シフトに用います。例えばビット位置を移動したりする場合に用います。 |
では、バイト型の値で実行してみます。 |
CY | MSB | 16進数 | 10進数 | シフト回数 | |||
0 | 1 0 0 0 0 0 0 0 | 0x80 | 128 | 0回目 | |||
0 | 0 1 0 0 0 0 0 0 | 0x40 | 64 | 1回目 | |||
0 | 0 0 1 0 0 0 0 0 | 0x20 | 32 | 2回目 | |||
0 | 0 0 0 1 0 0 0 0 | 0x10 | 16 | 3回目 | |||
0 | 0 0 0 0 1 0 0 0 | 0x08 | 8 | 4回目 | |||
0 | 0 0 0 0 0 1 0 0 | 0x04 | 4 | 5回目 | |||
0 | 0 0 0 0 0 0 1 0 | 0x02 | 2 | 6回目 | |||
0 | 0 0 0 0 0 0 0 1 | 0x01 | 1 | 7回目 | |||
1 | 0 0 0 0 0 0 0 0 | 0x00 | 0 | 8回目 | |||
0 | 0 0 0 0 0 0 0 0 | 0x00 | 0 | 9回目 |
シフトを重ねるたびに結果的に値が2分の1されます。そして、総てのビットをシフトすると、以後は「0」となります。 算術シフト、論理シフトに共通しますが、シフトにより消失するビットがあることに注意してください。 |
▲ |
ビット列全体を左にシフトし、CYのビットはLSBに、そしてMSBのビットはCYに移動します。 主に符号なし整数の左シフトで用いられ、ビット位置を移動する場合に用います。 これまでのシフトと異なり、CYにビットが移動している場合はありますが、ビットが完全消失することはありません。 |
では、バイト型の値で実行してみます。 |
CY | MSB | 16進数 | 10進数 | シフト回数 | |||
0 | 0 0 0 0 0 1 0 1 | 0x05 | 5 | 0回目 | |||
0 | 0 0 0 0 1 0 1 0 | 0x0A | 10 | 1回目 | |||
0 | 0 0 0 1 0 1 0 0 | 0x14 | 20 | 2回目 | |||
0 | 0 0 1 0 1 0 0 0 | 0x28 | 40 | 3回目 | |||
0 | 0 1 0 1 0 0 0 0 | 0x50 | 80 | 4回目 | |||
0 | 1 0 1 0 0 0 0 0 | 0xA0 | 160 | 5回目 | |||
1 | 0 1 0 0 0 0 0 0 | 0x40 | 64 | 6回目 | |||
0 | 1 0 0 0 0 0 0 1 | 0x81 | 129 | 7回目 | |||
1 | 0 0 0 0 0 0 1 0 | 0x02 | 2 | 8回目 | |||
0 | 0 0 0 0 0 1 0 1 | 0x05 | 5 | 9回目 |
ビットが消失しないので算術演算用途よりも論理演算や移動用途として利用することが多いです。 |
▲ |
ビット列全体を右にシフトし、CYのビットはMSBに、そしてLSBのビットはCYに移動します。 主に符号なし整数の右シフトで用いられ、ビット位置を移動する場合に用います。 これまでのシフトと異なり、CYにビットが移動している場合はありますが、ビットが完全消失することはありません。 |
では、バイト型の値で実行してみます。 |
CY | MSB | 16進数 | 10進数 | シフト回数 | |||
0 | 0 0 0 0 0 1 0 1 | 0x05 | 5 | 0回目 | |||
1 | 0 0 0 0 0 0 1 0 | 0x02 | 2 | 1回目 | |||
0 | 1 0 0 0 0 0 0 1 | 0x81 | 129 | 2回目 | |||
1 | 0 1 0 0 0 0 0 0 | 0x40 | 64 | 3回目 | |||
0 | 1 0 1 0 0 0 0 0 | 0xA0 | 160 | 4回目 | |||
0 | 0 1 0 1 0 0 0 0 | 0x50 | 80 | 5回目 | |||
0 | 0 0 1 0 1 0 0 0 | 0x28 | 40 | 6回目 | |||
0 | 0 0 0 1 0 1 0 0 | 0x14 | 20 | 7回目 | |||
0 | 0 0 0 0 1 0 1 0 | 0x0A | 10 | 8回目 | |||
0 | 0 0 0 0 0 1 0 1 | 0x05 | 5 | 9回目 |
ビットが消失しないので算術演算用途よりも論理演算や移動用途として利用することが多いです。 |
▲ |
ビット列全体を左にシフトし、MSBのビットはCYとLSBに移動します。 主に符号なし整数の左シフトで用いられ、ビット位置を移動する場合に用います。 これまでのシフトと異なり、ビットが完全消失することはありません。 |
では、バイト型の値で実行してみます。 |
CY | MSB | 16進数 | 10進数 | シフト回数 | |||
0 | 0 0 0 0 0 1 0 1 | 0x05 | 5 | 0回目 | |||
0 | 0 0 0 0 1 0 1 0 | 0x0A | 10 | 1回目 | |||
0 | 0 0 0 1 0 1 0 0 | 0x14 | 20 | 2回目 | |||
0 | 0 0 1 0 1 0 0 0 | 0x28 | 40 | 3回目 | |||
0 | 0 1 0 1 0 0 0 0 | 0x50 | 80 | 4回目 | |||
0 | 1 0 1 0 0 0 0 0 | 0xA0 | 160 | 5回目 | |||
1 | 0 1 0 0 0 0 0 1 | 0x41 | 65 | 6回目 | |||
0 | 1 0 0 0 0 0 1 0 | 0x82 | 130 | 7回目 | |||
1 | 0 0 0 0 0 1 0 1 | 0x05 | 5 | 8回目 | |||
0 | 0 0 0 0 1 0 1 0 | 0x0A | 10 | 9回目 |
ビットが消失しないので算術演算用途よりも論理演算や移動用途として利用することが多いです。 |
▲ |
ビット列全体を右にシフトし、LSBのビットはCYとMSBに移動します。 主に符号なし整数の右シフトで用いられ、ビット位置を移動する場合に用います。 これまでのシフトと異なり、ビットが完全消失することはありません。 |
では、バイト型の値で実行してみます。 |
CY | MSB | 16進数 | 10進数 | シフト回数 | |||
0 | 0 0 0 0 0 1 0 1 | 0x05 | 5 | 0回目 | |||
1 | 1 0 0 0 0 0 1 0 | 0x82 | 130 | 1回目 | |||
0 | 0 1 0 0 0 0 0 1 | 0x41 | 65 | 2回目 | |||
1 | 1 0 1 0 0 0 0 0 | 0xA0 | 160 | 3回目 | |||
0 | 0 1 0 1 0 0 0 0 | 0x50 | 80 | 4回目 | |||
0 | 0 0 1 0 1 0 0 0 | 0x28 | 40 | 5回目 | |||
0 | 0 0 0 1 0 1 0 0 | 0x14 | 20 | 6回目 | |||
0 | 0 0 0 0 1 0 1 0 | 0x0A | 10 | 7回目 | |||
0 | 0 0 0 0 0 1 0 1 | 0x05 | 5 | 8回目 | |||
1 | 1 0 0 0 0 0 1 0 | 0x82 | 130 | 9回目 |
ビットが消失しないので算術演算用途よりも論理演算や移動用途として利用することが多いです。 |
▲ |
C言語でシフト演算を利用する時は ・左シフト … << (代入演算のときは「<<=」を利用できます) ・右シフト … >> (代入演算のときは「>>=」を利用できます) を使います。 基本的にはシフト動作のみでローテーション動作は行われません。また、CYビットを直視することはできません。 それでは実際にプログラムを作成してシフト動作を確認してみましょう。 実験用に作成したサンプルプログラムがありますので、これをダウンロードして追試することもできます。 さて結果ですが…(実行記録) 2進数のビットで見た場合、左シフトは符号の影響を受けませんが、右シフトの場合は符号の影響を受けています。私自身、シフトを行う変数は符号なしで定義していますが、今回の結果は結果は予測できるにせよ、符号ありで定義されている人は要注意です。特にビットを移動しようとしている場合は混乱を招きます。 この特性を理解した上で使用する分には問題ありません。意図的に解析が困難なトリッキーな処理ができるかもしれませんが、見易さと言う面では符号なし変数を利用したほうが無難です。 |
(1)左シフト (1−1)符号付き変数 |
最初の値はプラス | 最初の値はマイナス | ||||||||
回数 | 16進数 | 10進数 | 2進数 | 回数 | 16進数 | 10進数 | 2進数 | ||
0回目 | 0x01 | 1 | 00000001 | 0回目 | 0xFF | -1 | 11111111 | ||
1回目 | 0x02 | 2 | 00000010 | 1回目 | 0xFE | -2 | 11111110 | ||
2回目 | 0x04 | 4 | 00000100 | 2回目 | 0xFC | -4 | 11111100 | ||
3回目 | 0x08 | 8 | 00001000 | 3回目 | 0xF8 | -8 | 11111000 | ||
4回目 | 0x10 | 16 | 00010000 | 4回目 | 0xF0 | -16 | 11110000 | ||
5回目 | 0x20 | 32 | 00100000 | 5回目 | 0xE0 | -32 | 11100000 | ||
6回目 | 0x40 | 64 | 01000000 | 6回目 | 0xC0 | -64 | 11000000 | ||
7回目 | 0x80 | -128 | 10000000 | 7回目 | 0x80 | -128 | 10000000 | ||
8回目 | 0x00 | 0 | 00000000 | 8回目 | 0x00 | 0 | 00000000 | ||
9回目 | 0x00 | 0 | 00000000 | 9回目 | 0x00 | 0 | 00000000 |
(1−2)符号なし変数 |
最初の値はプラス相当 | 最初の値はマイナス相当 | ||||||||
回数 | 16進数 | 10進数 | 2進数 | 回数 | 16進数 | 10進数 | 2進数 | ||
0回目 | 0x01 | 1 | 00000001 | 0回目 | 0xFF | 255 | 11111111 | ||
1回目 | 0x02 | 2 | 00000010 | 1回目 | 0xFE | 254 | 11111110 | ||
2回目 | 0x04 | 4 | 00000100 | 2回目 | 0xFC | 252 | 11111100 | ||
3回目 | 0x08 | 8 | 00001000 | 3回目 | 0xF8 | 248 | 11111000 | ||
4回目 | 0x10 | 16 | 00010000 | 4回目 | 0xF0 | 240 | 11110000 | ||
5回目 | 0x20 | 32 | 00100000 | 5回目 | 0xE0 | 224 | 11100000 | ||
6回目 | 0x40 | 64 | 01000000 | 6回目 | 0xC0 | 192 | 11000000 | ||
7回目 | 0x80 | 128 | 10000000 | 7回目 | 0x80 | 128 | 10000000 | ||
8回目 | 0x00 | 0 | 00000000 | 8回目 | 0x00 | 0 | 00000000 | ||
9回目 | 0x00 | 0 | 00000000 | 9回目 | 0x00 | 0 | 00000000 |
(2)右シフト (2−1)符号付き変数 |
最初の値はプラス | 最初の値はマイナス | ||||||||
回数 | 16進数 | 10進数 | 2進数 | 回数 | 16進数 | 10進数 | 2進数 | ||
0回目 | 0x40 | 64 | 01000000 | 0回目 | 0x80 | -128 | 10000000 | ||
1回目 | 0x20 | 32 | 00100000 | 1回目 | 0xc0 | -64 | 11000000 | ||
2回目 | 0x10 | 16 | 00010000 | 2回目 | 0xe0 | -32 | 11100000 | ||
3回目 | 0x08 | 8 | 00001000 | 3回目 | 0xf0 | -16 | 11110000 | ||
4回目 | 0x04 | 4 | 00000100 | 4回目 | 0xf8 | -8 | 11111000 | ||
5回目 | 0x02 | 2 | 00000010 | 5回目 | 0xfc | -4 | 11111100 | ||
6回目 | 0x01 | 1 | 00000001 | 6回目 | 0xfe | -2 | 11111110 | ||
7回目 | 0x00 | 0 | 00000000 | 7回目 | 0xff | -1 | 11111111 | ||
8回目 | 0x00 | 0 | 00000000 | 8回目 | 0xff | -1 | 11111111 | ||
9回目 | 0x00 | 0 | 00000000 | 9回目 | 0xff | -1 | 11111111 |
(2−2)符号なし変数 |
最初の値はプラス相当 | 最初の値はマイナス相当 | ||||||||
回数 | 16進数 | 10進数 | 2進数 | 回数 | 16進数 | 10進数 | 2進数 | ||
0回目 | 0x40 | 64 | 01000000 | 0回目 | 0x80 | 128 | 10000000 | ||
1回目 | 0x20 | 32 | 00100000 | 1回目 | 0x40 | 64 | 01000000 | ||
2回目 | 0x10 | 16 | 00010000 | 2回目 | 0x20 | 32 | 00100000 | ||
3回目 | 0x08 | 8 | 00001000 | 3回目 | 0x10 | 16 | 00010000 | ||
4回目 | 0x04 | 4 | 00000100 | 4回目 | 0x08 | 8 | 00001000 | ||
5回目 | 0x02 | 2 | 00000010 | 5回目 | 0x04 | 4 | 00000100 | ||
6回目 | 0x01 | 1 | 00000001 | 6回目 | 0x02 | 2 | 00000010 | ||
7回目 | 0x00 | 0 | 00000000 | 7回目 | 0x01 | 1 | 00000001 | ||
8回目 | 0x00 | 0 | 00000000 | 8回目 | 0x00 | 0 | 00000000 | ||
9回目 | 0x00 | 0 | 00000000 | 9回目 | 0x00 | 0 | 00000000 |
▲ |
シフト演算を利用する時、その実現方法に関わらず。 ・符号の有無 ・シフト回数によるオーバーフローの可能性 ・データ型に応じた有効範囲を意識したシフト について十二分に机上検証してから使うことが大切です。 |
▲ |
シフトの実行により値を2倍、4倍…。2分の1、4分の1…を容易に、かつ高速に行うことができます。 ですが、ここで注意点。 シフトを使用した割り算には余りが発生せず、常に小数点以下切捨ての値になってしまいます。 例えば、5を2で割る。つまり、右に1回シフトすると2を得られますが、何でもかんでも必要回数分右にシフトで済ませてしまうと必ず理想値に対してアンダーになってしまいます。時にはアンダーのままで良いのですが、値を平均化する場合には支障があります。 そこで、これを回避するために小数点以下第1位を四捨五入することが求められますが、シフトによる余りが生成されないので少し「コツ」が必要になります。 マイコンを直接利用することができ、かつ、アセンブラで命令を記述できる場合は、必要回数分シフトした後でCYを含めて0を加算、もしくはCY=1の場合に+1することで小数点以下第1位を四捨五入した事になります。 一方、C言語だけで記述する場合には少しだけ命令を加えます。 必要なシフト回数を1回だけ少なく右シフトした後で、LSBの1ビットを論理演算(AND)して抽出します。その後、更に右1回シフトし、先に抽出したLSBを加算します。 あえて図は掲載しませんので、各自で机上検証してみましょう。 |
▲ |