x86 命令INC
(インクリメント) とDEC
(デクリメント)CF
が FLAGSREGISTER の (キャリー フラグ) に影響しないのはなぜですか?
4 に答える
おそらく、32 ビット値と 64 ビット値を持つ現在の「x86」CPU が、Intel 8008 にさかのぼる、はるかに制限された 8 ビット マシンとして誕生したことを覚えておく必要がある理由を理解するために。覚えておいてください(うーん!)。
その世界では、レジスターは貴重で小さいものでした。さまざまな目的でINC
/が必要ですが、最も一般的なのはループ制御です。DEC
多くのループでは、「多精度演算」 (たとえば、16 ビット以上!) を実行する必要がありましたINC
。ZeroDEC
フラグ ( Z
) を設定することで、それらを使用してループを適切に制御できます。ループ制御命令がキャリー フラグを変更しないことを主張することにより ( CF
)、キャリーはループの反復間で保持され、キャリー状態を記憶するための大量のコードを記述することなく、多倍精度演算を実装できます。
醜い命令セットに慣れると、これはかなりうまくいきました。
ワードサイズが大きい最新のマシンでは、これはあまり必要ないためINC
、DEC
意味的にはADD
...,1 などと同等である可能性があります。実際、キャリーセットが必要な場合はこれを使用します:-}
ほとんどの場合、私はINC
and DEC
now には近づきません。これは、部分的な条件コードの更新を行うためです。これにより、パイプラインでおかしな停止が発生する可能性があり、ADD
/SUB
しないでください。そのため、問題にならない場所 (ほとんどの場所) では、屋台を避けるためにADD
/を使用します。/SUB
を使用するのは、コードを小さな問題に保つ場合のみです。たとえば、1 つまたは 2 つの命令のサイズが問題になるのに十分な違いがあるキャッシュ ラインに適合させる場合などです。これはおそらく無意味なナノ最適化です。INC
DEC
私の説明は、その理由を教えてくれますINC
/DEC
ゼロフラグ ( Z
) を設定します。INC
/DEC
符号 (およびパリティ フラグ) を設定する理由について、特に説得力のある説明はありません。
EDIT 2016 年 4 月: 最新の x86 では、ストールの問題がより適切に処理されているようです。INC 命令と ADD 1を参照してください: 重要ですか?
inc/dec によってゼロフラグが設定されている場合に、なぜ符号を付けるのかという問題は、次の質問で対処するのが最適です。
a) for (n=7;n>=0;n--) // translates to `dec + jns`
b) for (n=8;n>0;n--) // translates to `dec + jnz`
Ira Baxterが既に明らかにしたように、Carry フラグは多くのアルゴリズムで使用されます。多精度演算だけでなく、モノクロ/CGA/EGA 時代のビットマップ処理にも使用されます。これにより、80 ピクセル幅の行が 1 ピクセル右にシフトされます...
mov cx, 10
begin: lodsb
rcr al,1 // this is rotate though carry:
stosb // for the algorithm to work, carry must not be destroyed
LOOP begin //
しかし、なぜパリティなのですか?
答えは、そうしない理由だと思います。この命令セットは、トランジスタが不足していた 70 年代後半のものです。特定の命令のパリティ フラグの計算を拒否しても意味がありませんが、CPU の複雑さが増すだけです。
影響を与える必要がないからです。Zero フラグをチェックするだけで十分です。したがって、 inc および dec 命令の後、キャリーフラグは同じままであり、場合によってはこれが役立ちます。