符号付きおよび符号なしの数字


17

マイクロプロセッサ内のALUは、1111で示される符号付き数値-7と1111で示される符号なし数値15をどのように区別しますか?


3
関連する質問の回答:cs.stackexchange.com/a/30047/28999を参照してください。ちなみに、符号付き-7は1111として表されません。つまり、-1です。次に、例えば1111-0001 =符号付きおよび符号なしの両方のケースで1110(-2対14)
アルバートヘンドリクス

2
@AlbertHendriks公平を期して、一部の古いコンピューターは「符号振幅表現」(1符号ビットと振幅ビット)を使用していますが、IEEEフロートなどにもそのスタイルを使用しています。彼らは、2の補数と比較して、優雅で、一緒に働くのが難しいです。n1
ドラコニス

1
主な違いは、greaterThan / lessThan演算子の動作方法と、右シフトが最上位ビットで埋められるかどうかです。実際に乗算して除算すると、結果は同じになります。
ロブ


2
@Robそれは完全に正しいわけではありません。加算、減算、および乗算は、符号なしと2の補数の間ですべて同じです-入力と出力が同じサイズであると仮定します。除算は同じではありません6/2は3ですが、-2 / 2は-1です。また、多くのCPUには乗算命令があり、2つの入力は同じサイズですが、出力はサイズの2倍です。この場合、符号なしと2の補数も同じではありません。
カスペルド

回答:


14

短く簡単な答えは、そうではありません。最新のメインストリームCPU ISAは、あなたが思うように動作しません。

CPUにとっては、ほんの少しのパターンです。そのビットパターンの意味を追跡するのは、プログラマーです。

一般的に、ISAはストレージに関しては異なるデータ型を区別しません。(FPUの浮動レジスタなどの特殊なレジスタを無視します。)これは、CPUにとって意味のないビットパターンです。ただし、ISAに、ビットパターンをさまざまな方法で解釈できるさまざまな種類の命令があります。例えば、算術命令のようなMULDIVADDSUB、数ある種のようなビットパターンを解釈するような論理命令に対しANDORXORブール値のアレイとしてそれを解釈します。したがって、正しい命令を選択するのは、プログラマー(または、より高水準の言語を使用する場合はインタープリターまたはコンパイラーの作成者)次第です。

たとえば、符号付きの番号と符号なしの番号には個別の指示がある場合があります。一部のISAには、2進化10進数を使用した算術演算の命令もあります。

ただし、上記の「現代の主流ISA」を書いたことに注意してください。実際、動作が異なる主流ではない、または歴史的なISAがあります。たとえば、IBM AS / 400の元の48ビットCISC ISAと、現在IBM iと呼ばれるシステムの現在のPOWERベースの64ビットRISC ISAは、ポインターと他の値を区別します。ポインターには常にタグが付けられ、タイプ情報と権利管理が含まれます。CPUは、値がポインターであるかどうかを認識しており、特権i / OSカーネルのみがポインターを自由に操作できます。ユーザーアプリケーションは、少数の安全な命令を使用して、所有するポインターを操作して、所有するメモリをポイントすることしかできません。

また、少なくともいくつかの限定された形式認識を含むいくつかの歴史的なISAデザインがありました。


JavaバイトコードもISAとしてカウントされることに注意してください。そして、それはかなり...データ型についてのケアを行います
ジョン・ドヴォルザーク

Javaバイトコードは、シリコンに実装されているという意味で、ISAとして分類されます。ただし、この種の基本的な型チェックはクラスローダーによって実行されるため、実行時に型をほとんど無視できます。そしてもちろん、Javaバイトコードにはそもそも符号なしの型はありません。
仮名

@Pseudonym:まあ、技術的には、16ビットの符号なし型であるを持ってますchar。もちろん、Javaバイトコードには符号なしの算術命令はまだありません。これは、算術のためにchar値がint(32ビット符号付き)に自動的に昇格されるためです。
イルマリカロネン

42

ショートバージョン:それは知りません。伝える方法はありません。

1111-7を表す場合、最初のビットが符号で、残りのビットが絶対値である符号絶対値表現があります。この場合、符号なし加算と符号付き加算では異なるロジックが使用されるため、算術演算はやや複雑になります。したがって、おそらくオペコードがあり、間違っSADDUADDオペコードを選択すると、無意味な結果が得られます。

ただし、2の補数表現1111と呼ばれる-1を表すことがよくあります。この場合、ALUは数字が符号付きか符号なしかを単純に気にしません!たとえば、の操作を見てみましょう。符号付き算術では、これは「-2 + 1」を意味し、結果は-1()になります。符号なし算術では、これは「14 + 1」を意味し、結果は15()になります。したがって、ALUは、署名された結果が必要か署名されていない結果が必要かを認識せず、気にしません。それは単に符号なしであるかのように加算を行い、その後それを符号付き整数として扱いたいなら、それはあなた次第です。1110 + 000111111111

編集:RuslanとDaniel Scheplerがコメントで非常に正しく指摘しているように、2の補数のマシンであっても、いくつかのオペランドはまだ別々の署名付きバージョンと署名なしバージョンを必要とします。加算、減算、乗算、等式などはすべて、数字が符号付きかどうかを知らなくても正常に機能します。ただし、除算と大なり/小なりの比較には、個別のバージョンが必要です。

編集編集:one's-complementのような他の表現もいくつかありますが、これらは基本的に使用されないため、心配する必要はありません。


ああ、落とした。これをありがとう:)
noorav

10
2の補数表現では、加算、減算、乗算(オペランドと同じ長さの積による)の3つの算術演算が符号付き不可知です。符号付きオペランドでは、除算のみが異なる方法で処理される必要があります。
ルスラン

4
また、比較もあります:< <= >= >符号付きオペランド==と符号なしオペランドでは異なりますが、と!=は符号に依存しません。
ダニエルシェプラー

乗算には、多くの場合、符号付きと符号なしの種類があります。0xFFFFFFFF* 0xFFFFFFFFは、符号なしの場合は0xFFFFFFFEFE000101、符号付きの場合は0x0000000000000001です。Intelのようなプロセッサーは2つのレジスターで結果を返し、最上位レジスターは符号付きと符号なしで異なります。どちらの場合も、最下位レジスタは1です。
ルディヴェルトゥイス

9

最新のすべてのアーキテクチャで使用される2の補数演算の大きな利点の1つは、加算命令と減算命令が符号付きオペランドと符号なしオペランドの両方でまったく同じであることです。

多くのCPUには、乗算、除算、またはモジュラス命令さえありません。使用する場合は、命令の符号付き形式と符号なし形式を別々に用意する必要があり、コンパイラー(またはアセンブリ言語プログラマー)が適切な形式を選択します。

また、CPUには通常、符号付きまたは符号なしの比較用の異なる命令があります。例えば、x86は、以下の可能性があるCMPとのJL比較は、署名されるべきか(ジャンプ未満の場合)、またはJB比較が符号なしであるかどうか(ジャンプ以下であれば)。繰り返しますが、コンパイラーまたはプログラマーは、データ型に適した命令を選択します。

他のいくつかの命令には、符号拡張の有無にかかわらず、右シフトやより幅の広いレジスタへの値のロードなど、符号付きおよび符号なしのバリアントがあります。


1
入力よりも多くのビットを結果に含める必要がない限り、乗算も符号なし整数と符号付き(2の補数)整数で同じです。ただし、8×8→16ビット(または16×16→32ビットなど)乗算のような場合は、入力(または中間結果)を符号拡張する必要があります
イルマリカロネン

@IlmariKaronenこれは本当です。ARM A32 / A64は、命令だけ下位ビットを書き込む符号に依存しない乗算-加算を含む乗算命令の多くの形態を有するセットもあるsmulhumulh、そのリターンのみ乗算の上位ビットと符号付きおよび符号なしの命令そのソースオペランドの2倍の幅のレジスタに結果を返します。
デイビスラー

6

そうではありません。プロセッサは命令セットに依存して、どのタイプのデータを調べてどこに送信するかを伝えます。オペランド自体には、データがchar、float、int、signed intなどであるかどうかをALUに本質的に通知できる1と0については何もありません。 2の補数として解釈されます。


charハードウェアレベルでのようなものはありません。たぶん昔々、機械式テレプリンターの時代に遡ります。しかし、今日、ハードウェアに関する限り、a char単なる数字です。異なる数字が画面上の異なる文字形状に対応する理由は、それらの数字を使用して、大きなテーブル(つまり「フォント」)から異なるビットマップまたは異なる描画ルーチンを選択するためです。
ソロモンスロー

3

すでに行った回答に追加を加えたい:

他のほとんどの答えでは、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

また、異なる「条件付き」命令(条件付きジャンプ、条件付きビット設定)、および符号付きおよび符号なし算術用の乗算命令もあります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.