マイクロプロセッサ内のALUは、1111で示される符号付き数値-7と1111で示される符号なし数値15をどのように区別しますか?
マイクロプロセッサ内のALUは、1111で示される符号付き数値-7と1111で示される符号なし数値15をどのように区別しますか?
回答:
短く簡単な答えは、そうではありません。最新のメインストリームCPU ISAは、あなたが思うように動作しません。
CPUにとっては、ほんの少しのパターンです。そのビットパターンの意味を追跡するのは、プログラマーです。
一般的に、ISAはストレージに関しては異なるデータ型を区別しません。(FPUの浮動レジスタなどの特殊なレジスタを無視します。)これは、CPUにとって意味のないビットパターンです。ただし、ISAには、ビットパターンをさまざまな方法で解釈できるさまざまな種類の命令があります。例えば、算術命令のようなMUL
、DIV
、ADD
、SUB
、数ある種のようなビットパターンを解釈するような論理命令に対しAND
、OR
、XOR
ブール値のアレイとしてそれを解釈します。したがって、正しい命令を選択するのは、プログラマー(または、より高水準の言語を使用する場合はインタープリターまたはコンパイラーの作成者)次第です。
たとえば、符号付きの番号と符号なしの番号には個別の指示がある場合があります。一部のISAには、2進化10進数を使用した算術演算の命令もあります。
ただし、上記の「現代の主流ISA」を書いたことに注意してください。実際、動作が異なる主流ではない、または歴史的なISAがあります。たとえば、IBM AS / 400の元の48ビットCISC ISAと、現在IBM iと呼ばれるシステムの現在のPOWERベースの64ビットRISC ISAは、ポインターと他の値を区別します。ポインターには常にタグが付けられ、タイプ情報と権利管理が含まれます。CPUは、値がポインターであるかどうかを認識しており、特権i / OSカーネルのみがポインターを自由に操作できます。ユーザーアプリケーションは、少数の安全な命令を使用して、所有するポインターを操作して、所有するメモリをポイントすることしかできません。
また、少なくともいくつかの限定された形式認識を含むいくつかの歴史的なISAデザインがありました。
char
。もちろん、Javaバイトコードには符号なしの算術命令はまだありません。これは、算術のためにchar
値がint
(32ビット符号付き)に自動的に昇格されるためです。
ショートバージョン:それは知りません。伝える方法はありません。
1111
-7を表す場合、最初のビットが符号で、残りのビットが絶対値である符号絶対値表現があります。この場合、符号なし加算と符号付き加算では異なるロジックが使用されるため、算術演算はやや複雑になります。したがって、おそらくオペコードがあり、間違っSADD
たUADD
オペコードを選択すると、無意味な結果が得られます。
ただし、2の補数表現1111
と呼ばれる-1を表すことがよくあります。この場合、ALUは数字が符号付きか符号なしかを単純に気にしません!たとえば、の操作を見てみましょう。符号付き算術では、これは「-2 + 1」を意味し、結果は-1()になります。符号なし算術では、これは「14 + 1」を意味し、結果は15()になります。したがって、ALUは、署名された結果が必要か署名されていない結果が必要かを認識せず、気にしません。それは単に符号なしであるかのように加算を行い、その後それを符号付き整数として扱いたいなら、それはあなた次第です。1110 + 0001
1111
1111
編集:RuslanとDaniel Scheplerがコメントで非常に正しく指摘しているように、2の補数のマシンであっても、いくつかのオペランドはまだ別々の署名付きバージョンと署名なしバージョンを必要とします。加算、減算、乗算、等式などはすべて、数字が符号付きかどうかを知らなくても正常に機能します。ただし、除算と大なり/小なりの比較には、個別のバージョンが必要です。
編集編集:one's-complementのような他の表現もいくつかありますが、これらは基本的に使用されないため、心配する必要はありません。
<
<=
>=
>
符号付きオペランド==
と符号なしオペランドでは異なりますが、と!=
は符号に依存しません。
最新のすべてのアーキテクチャで使用される2の補数演算の大きな利点の1つは、加算命令と減算命令が符号付きオペランドと符号なしオペランドの両方でまったく同じであることです。
多くのCPUには、乗算、除算、またはモジュラス命令さえありません。使用する場合は、命令の符号付き形式と符号なし形式を別々に用意する必要があり、コンパイラー(またはアセンブリ言語プログラマー)が適切な形式を選択します。
また、CPUには通常、符号付きまたは符号なしの比較用の異なる命令があります。例えば、x86は、以下の可能性があるCMP
とのJL
比較は、署名されるべきか(ジャンプ未満の場合)、またはJB
比較が符号なしであるかどうか(ジャンプ以下であれば)。繰り返しますが、コンパイラーまたはプログラマーは、データ型に適した命令を選択します。
他のいくつかの命令には、符号拡張の有無にかかわらず、右シフトやより幅の広いレジスタへの値のロードなど、符号付きおよび符号なしのバリアントがあります。
smulh
とumulh
、そのリターンのみ乗算の上位ビットと符号付きおよび符号なしの命令そのソースオペランドの2倍の幅のレジスタに結果を返します。
そうではありません。プロセッサは命令セットに依存して、どのタイプのデータを調べてどこに送信するかを伝えます。オペランド自体には、データがchar、float、int、signed intなどであるかどうかをALUに本質的に通知できる1と0については何もありません。 2の補数として解釈されます。
char
ハードウェアレベルでのようなものはありません。たぶん昔々、機械式テレプリンターの時代に遡ります。しかし、今日、ハードウェアに関する限り、a char
は単なる数字です。異なる数字が画面上の異なる文字形状に対応する理由は、それらの数字を使用して、大きなテーブル(つまり「フォント」)から異なるビットマップまたは異なる描画ルーチンを選択するためです。
すでに行った回答に追加を加えたい:
他のほとんどの答えでは、2の補数演算では、符号付き数値と符号なし数値の結果は同じであることに注意してください。
-2 + 1 = -1 1110 + 0001 = 1111
14 + 1 = 15 1110 + 0001 = 1111
ただし、例外があります。
Division:
-2 / 2 = -1 1110 / 0010 = 1111
14 / 2 = 7 1110 / 0010 = 0111
Comparison:
-2 < 2 = TRUE 1110 < 0010 = TRUE
14 < 2 = FALSE 1110 < 0010 = FALSE
"Typical" (*) multiplication:
-2 * 2 = -4 1110 * 0010 = 11111100
14 * 2 = 28 1110 * 0010 = 00011100
(*)多くのCPUでは、2つのnビット数の乗算の結果は(2 * n)ビット幅です。
このような操作の場合、CPUには、符号付き演算と符号なし演算の異なる命令があります。
つまり、プログラマー(またはコンパイラー)は、符号付きおよび符号なしの算術演算に他の命令を使用する必要があります。
たとえば、x86 CPUには、div
符号なし除算を行うための名前が付いた命令と、符号付き除算を行うための名前が付いた命令がありますidiv
。
また、異なる「条件付き」命令(条件付きジャンプ、条件付きビット設定)、および符号付きおよび符号なし算術用の乗算命令もあります。