マイクロプロセッサシステムが符号なしの数値を実装する理由がわかりません。より大きい、より小さい、など、符号付きとは異なるアルゴリズムが必要なので、コストは条件付きブランチの数の2倍であると思いますが、符号なしの数値が大きな利点であるアルゴリズムはまだありますか?
私の質問の一部は、コンパイラでサポートされるのではなく、命令セットに含まれる必要がある理由です。
マイクロプロセッサシステムが符号なしの数値を実装する理由がわかりません。より大きい、より小さい、など、符号付きとは異なるアルゴリズムが必要なので、コストは条件付きブランチの数の2倍であると思いますが、符号なしの数値が大きな利点であるアルゴリズムはまだありますか?
私の質問の一部は、コンパイラでサポートされるのではなく、命令セットに含まれる必要がある理由です。
回答:
符号なしの数値は、ビットシーケンスの1つの解釈です。また、アドレスとオペコードは単なるビットであるため、これは最も単純で、CPUの内部で最もよく使用される解釈です。メモリ/スタックのアドレス指定と演算は、マイクロプロセッサ、つまり処理の基礎です。抽象ピラミッドを上に移動すると、ビットのもう1つのよくある解釈は文字(ASCII、Unicode、EBCDIC)としてです。次に、IEEE浮動小数点、グラフィックス用のRGBAなど、他の解釈があります。これらはいずれも単純な符号付き数値ではありません(IEEE FPは単純ではなく、それらを使用した演算は非常に複雑です)。
また、符号なしの算術では、他のものを実装することは非常に簡単です(最も効率的でない場合)。その逆は真実ではありません。
比較演算のハードウェアコストの大部分は、減算です。比較で使用される減算の出力は、基本的に3ビットの状態です。
減算演算後にこれら3ビットをテストする適切な組み合わせにより、すべての符号付き関係演算とすべての符号なし関係演算を判別できます(これらのビットは、オーバーフローの検出方法、符号付きvs符号なし)。同じ基本的なALUハードウェアを共有して、これらのすべての比較(減算命令は言うまでもありません)を、これらの3ビットの状態の最終チェックまで実行できます。そのため、余分なハードウェアはそれほど多くありません。
唯一の本当のコストは、命令セットアーキテクチャで比較の追加モードをエンコードする必要があることです。これにより、命令密度がわずかに低下する可能性があります。それでも、ハードウェアには、特定の言語で使用されない命令がたくさんあるのはかなり普通です。
常に をカウントする必要がある場合>= 0
、符号付き整数を使用して、カウントスペースを不必要に半分に削減するためです。
データベーステーブルに配置する自動インクリメントINT PKを考慮してください。そこで符号付き整数を使用する場合、テーブルには同じフィールドサイズの場合と同じ数のレコードがHALFとして格納され、メリットはありません。
または、RGBaカラーのオクテット。この自然な正の数の概念を負の数で不自然に数え始めたくありません。符号付きの数字は、メンタルモデルを破壊するか、スペースを半分にします。符号なし整数は概念に一致するだけでなく、2倍の解像度を提供します。
ハードウェアの観点からは、符号なし整数は単純です。それらはおそらく、計算を実行するのに最も簡単なビット構造です。そして、間違いなく、コンパイラで整数型(または浮動小数点でさえ!)をシミュレートすることにより、ハードウェアを簡素化できました。では、なぜ符号なし整数と符号付き整数の両方がハードウェアに実装されているのですか?
まあ... パフォーマンス!
ソフトウェアよりもハードウェアで符号付き整数を実装する方が効率的です。ハードウェアは、単一の命令でどちらのタイプの整数でも計算を実行するように指示できます。そして、それは非常に良いことです。なぜなら、ハードウェアは多少なりとも並行してビットを破壊するからです。ソフトウェアでそれをシミュレートしようとすると、「シミュレート」することを選択した整数型は、間違いなく多くの命令を必要とし、著しく遅くなります。
質問は2つの部分で構成されています。
符号なし整数の目的は何ですか?
符号なし整数は問題の価値がありますか?
符号なしの数値は、非常に単純に、負の値が無意味な量のクラスを表します。確かに、「私はリンゴをいくつ持っていますか?」という質問に対する答えを言うかもしれません。あなたが誰かにリンゴを借りている場合は負の数になるかもしれませんが、「私はどれくらいのメモリを持っていますか?」という質問についてはどうですか?-負の量のメモリを持つことはできません。そのため、符号なし整数はそのような量を表すのに非常に適しており、符号付き整数よりも2倍の正の値の範囲を表すことができるという利点があります。たとえば、16ビットの符号付き整数で表現できる最大値は32767ですが、16ビットの符号なし整数では65535です。
符号なし整数は実際には問題を表すものではないため、その価値はあります。お分かりのように、彼らは余分な「アルゴリズム」のセットを必要としません。それらの実装に必要な回路は、符号付き整数の実装に必要な回路のサブセットです。
CPUには、符号付き整数用の乗算器と符号なし整数用の異なる乗算器がありません。乗算器は1つだけで、動作の性質に応じてわずかに異なる方法で動作します。符号付き乗算をサポートするには、符号なしよりわずかに多くの回路が必要ですが、とにかくサポートする必要があるため、符号なし乗算は実質的に無料で提供され、パッケージに含まれています。
加算と減算に関しては、回路にまったく違いはありません。整数のいわゆる2の補数表現を読むと、整数の性質に関係なく、これらの操作をまったく同じ方法で実行できるように巧妙に設計されていることがわかります。
比較も同じように機能します。これは結果の減算と破棄にすぎないため、唯一の違いは条件分岐(ジャンプ)命令にあり、CPUの異なるフラグを調べることで動作します。先行(比較)命令。この回答:https : //stackoverflow.com/a/9617990/773113では、Intel x86アーキテクチャでの動作の説明を見つけることができます。条件付きジャンプ命令の符号付きまたは符号なしの指定は、検査するフラグによって異なります。
マイクロプロセッサは本質的に署名されていません。符号付きの数値は実装されたものであり、その逆ではありません。
コンピューターは符号付きの数字がなくても問題なく機能しますが、負の数を必要とする人間であるため、符号付きが発明されました。
ストレージに簡単に利用できるもう1つのビットがあり、負の数を心配する必要がないためです。それ以上のものはありません。
ここで、この余分なビットが必要になる場所の例を必要とする場合、見ればたくさん見つかります。
私のお気に入りの例は、チェスエンジンのビットボードです。チェス盤には64個のマスがありunsigned long
、動きの生成を中心としたさまざまなアルゴリズムに最適なストレージを提供します。バイナリ演算(およびシフト演算!!)が必要であるという事実を考慮すると、MSBが設定されている場合にどのような特別なことが起こるかを心配する必要がない方が簡単な理由は簡単にわかります。符号付きlongで実行できますが、符号なしを使用する方がはるかに簡単です。
純粋な数学のバックグラウンドを持っているため、これは興味のある人にとっては少し数学的なものです。
8ビットの符号付きおよび符号なし整数で開始する場合、負の整数を表すために2の補数が使用される場合、加算と乗算に関する限り、基本的に256を法とする整数です(そしてこれはすべての現代のプロセッサがそれを行う方法です) 。
物事の違いは2つの場所にあります。1つは比較演算です。ある意味で、256を法とする整数は数字の円と最もよく考えられます(12を法とする整数が旧式のアナログ文字盤で行うように)。数値比較(x <y)を意味のあるものにするために、どの数値が他の数値よりも小さいかを判断する必要がありました。数学者の観点から、256を法とする整数を何らかの形ですべての整数のセットに埋め込みたいと思います。バイナリ表現がすべてゼロである8ビット整数を整数0にマッピングするのは明らかです。その後、他のマップに進み、「0 + 1」(レジスタ、たとえばaxをゼロにし、「inc ax」を介して1ずつインクリメントした結果)が整数1になるようにします。-1でも同じことができます。たとえば、「0-1」を整数-1にマッピングし、「0-1-1」をマッピングします。整数-2に。この埋め込みが関数であることを確認する必要があるため、単一の8ビット整数を2つの整数にマッピングすることはできません。そのため、これは、すべての数値を整数のセットにマッピングすると、0より小さい整数と0より大きい整数とともに0が存在することを意味します。8ビット整数でこれを行うには、本質的に255の方法があります( 0から-255までの最小値まで)。次に、「0 <y-x」の観点から「x <y」を定義できます。
ハードウェアサポートが賢明な2つの一般的なユースケースがあります。0より大きいすべてのゼロ以外の整数を持つものと、0を中心とした約50/50の分割を持つものです。そして、操作の前にこれを行う必要があり、現代のソフトウェアの明示的な例を考えることができないほど、この必要性は非常にまれです(16ビットなどのより大きな仮数で作業することができるからです)。
もう1つの問題は、8ビット整数を16ビット整数の空間にマッピングすることです。-1は-1になりますか?これは、0xFFが-1を表す場合に必要なものです。この場合、符号拡張は賢明なことであるため、0xFFは0xFFFFになります。一方、0xFFが255を表すことを意図していた場合は、0xFFFFではなく、255にマッピングされるため、0x00FFにマッピングされます。
これは、「シフト」操作と「算術シフト」操作の違いでもあります。
しかし、最終的には、ソフトウェアのintは整数ではなく、バイナリの表現であり、表現できるのは一部のみであるという事実に帰着します。ハードウェアを設計する場合、ハードウェアでネイティブに行う方法を選択する必要があります。2の補数では加算と乗算の演算が同一であるため、このように負の整数を表すことは理にかなっています。次に、バイナリ表現が表す整数に依存する操作の問題のみです。
既存の符号付き整数を使用してCPU設計に符号なし整数を追加するための実装コストを調べてみましょう。
一般的なCPUには、次の算術命令が必要です。
論理的な指示も必要です。
符号付き整数比較で上記の分岐を実行するための最も簡単な方法は、SUB命令に次のフラグを設定させることです。
次に、算術分岐は次のように実装されます。
これらの否定は、それらの実装方法から明らかに続くはずです。
そのため、既存の設計では、これらすべてを符号付き整数に既に実装しています。次に、符号なし整数を追加するために必要なことを考えてみましょう。
いずれの場合も、変更は非常に簡単であり、回路の小さなセクションをオンまたはオフにするか、新しいとにかく命令の実装。
したがって、無署名の命令を追加するコストは非常に小さいです。なぜそうするべきかについては、メモリアドレス(および配列内のオフセット)は本質的に符号なしの値であることに注意してください。プログラムはメモリアドレスの操作に多くの時間を費やすので、それらを正しく処理する型を持っていると、プログラムを作成しやすくなります。
符号なしの数値は、主にラッピング代数リングが必要な状況を処理するために存在します(16ビットの符号なしの型の場合、6565の合同の整数のリングになります)。値を取り、モジュラスより少ない量を追加すると、2つの値の差が追加された量になります。実際の例として、ユーティリティメーターが月の初めに9995を読み取り、23ユニットを使用する場合、メーターは月末に0018を読み取ります。代数リング型を使用する場合、オーバーフローに対処するために特別なことをする必要はありません。0018から9995を引くと、0023、正確には使用されたユニットの数が得られます。
Cが最初に実装されたマシンであるPDP-11には、符号なし整数型はありませんでしたが、符号付き型は、65535と0ではなく、32767と-32768の間をラップするモジュラー演算に使用できます。ただし、プラットフォームは物事をきれいにラップしませんでした。実装がPDP-11で使用される2の補数整数をエミュレートする必要があることを要求するのではなく、言語は代わりに、主に代数リングとして振る舞わなければならなかった符号なしの型を追加し、符号付き整数型がオーバーフローの場合に他の方法で振る舞うことを許可しました。
Cの初期には、32767(一般的なINT_MAX)を超えることができたが、65535(一般的なUINT_MAX)を超えることができなかった多くの量がありました。そのため、そのような量を保持するために符号なしの型を使用することが一般的になりました(たとえば、size_t)。残念ながら、言語には、正の範囲の余分なビットを持つ数値のように振る舞うタイプと、代数リングのように振る舞うタイプを区別するものはありません。代わりに、言語は「int」より小さい型を数値のように動作させ、フルサイズの型は代数リングのように動作させます。したがって、次のような関数を呼び出します。
uint32_t mul(uint16_t a, uint16_t b) { return a*b; }
with(65535、65535)は、int
16ビット(つまり、1を返す)のシステムで1つの定義済み動作、int
33ビット以上(0xFFFE0001を返す)の異なる動作、および「int」がどこかにあるシステムでの未定義の動作を持ちます。 between [gccは通常、INT_MAX + 1uとUINT_MAXの間の結果を伴う算術的に正しい結果を生成しますが、このような値で失敗する上記の関数のコードを生成する場合があることに注意してください!] あまり役に立たない。
それでも、一貫して数字のように、または常に代数環のように振る舞う型の欠如は、代数環型がいくつかの種類のプログラミングにほとんど不可欠であるという事実を変えません。