現時点では、非常に大きな符号なし整数の算術演算および論理演算用の独自の小さなライブラリを作成しています。パフォーマンスを向上させるために、アセンブリにいくつかの関数を実装することにしました。だから私の質問です。 2つの符号なし整数を減算しているときに、0から任意の数を減算すると、キャリーフラグが設定されます。
しかし、この状況でキャリーフラグが設定されるのはなぜですか?キャリーフラグはオーバーフローが発生したときにのみ設定されますが、ゼロから任意の数を減算すると、オーバーフローは発生しません。または私は間違っていますか?
キャリーフラグは、最上位ビット(MSb)からのキャリーまたはボローです。
CF(ビット0)キャリーフラグ—算術演算が結果の最上位ビットからキャリーまたはボローを生成するかどうかを設定します。そうでなければクリアされました。このフラグは、符号なし整数演算のオーバーフロー条件を示します。また、倍精度演算にも使用されます。
CFを符号ビットに関連付けないでください。減算では、符号なしとして扱われる被減数が符号なしとして扱われる減数よりも小さいときにCFが設定されます。
これはオーバーフロー条件に相当します。符号付き数値の場合、相当するフラグはOFです。
(不要?)視覚的な手がかりのために、この4-5の操作では、CFを設定するのは2番目の借用、赤いものです
ゼロから減算するのではなく、当然、任意の数に対してゼロになりますが、減数には少なくとも1つのビットセットがあるため、常にCFが設定されます。
最後に、一部の命令では、CFに影響を与えずに符号ビットを変更できます(たとえば、論理演算やneg
の動作を参照)。
小学校から、a-b = a +(-b)であることがわかります。そして、それが私たちが否定を加えることを私たちが減算しないようにするロジックです。また、初心者向けプログラミングクラスから、2の補数を使用してネガを取得し、反転して1を追加することもわかっています。 a-b = a +(〜b)+ 1.小学校から持ち運びの概念も知っています。 9 + 3 = 2が1を実行します。 2進数で同じで、2つのオペランドを使用すると、1 + 1 = 0に1を運ぶことができます。したがって、ロジックの各列にはキャリーが必要です。それぞれが2ビットで3ビット、2つのオペランドがプラスでキャリーイン、キャリーアウト、結果が出力されます。これらの各論理blobには入力ビット、キャリーイン、通常の加算があり、最初のキャリーインはゼロですが、減算の場合、そのキャリーを1にして、2番目のオペランドを反転してa + b = a +(〜 b)+ 1
したがって、いくつかの簡単な例を使用して作業する場合、またはオペランドの3ビットの組み合わせごとに自分で試してみる場合は、減算が加算されます。符号付きと符号なしの加算(または減算)のようなものはないことがわかります。2の美しさがエンコーディングを補完します。
これらすべてを知って、減算は加算であり、さらにUNSIGNEDオーバーフローでキャリーが発生します。符号付きオーバーフロービットは、msbitのキャリーとキャリーが一致しない場合で、通常はVフラグとして表されます。現在、一部のアーキテクチャーでは、すでにbオペランドを途中で反転し、キャリーインを途中で反転しているため、キャリーアウトを途中で反転しています。しないでください。したがって、キャリーアウトが符号なし加算オーバーフローと見なされるのか、それとも借用であるのかを理解するには、特定のアーキテクチャを調べる必要があります。借りたりしない.
ゼロから何かを引いたものは、常に足し算が行われるとは限りません。
0b000 - 0b111
0001
000
+ 000
=====
001
加算のキャリーはゼロです。あなたのアーキテクチャはそれをそのままにすることを選択するかもしれませんし、それを反転させて借用と呼ぶかもしれません。
アーキテクチャファミリ内。すべてのx86またはすべてのARMでは、同じように永遠に実行し続ける可能性があります。しかし、ARMとMIPSとx86とXYZがすべて同じように実行することを期待する理由はありません。
それを逆にして借用として定義することは、用語の観点からは理にかなっています。
(符号付き/符号なし)より大きい、より小さい、より大きい、等しい、より小さい、または等しいの定義はすべて、そのアーキテクチャのキャリー/ボローの選択に基づいていることに注意してください。これらのフラグの比較は、同じ定義。