2016-12-30 9 views
-6

私は学んだ約2's Complementと署名されていないと署名されたint。だから私は、負の数が2's complementウェイに格納されていることを知っている限り、私の知識をテストすることにしました。そのため、加減算には異なるアルゴリズムや回路がないでしょう。私はアセンブリでは、符号なしint作業に負数をどのように割り当てますか?

int main() 
{ 
    int a = -1 ; 
    unsigned int b = - 1 ; 

    printf("%d %u \n %d %u" , a ,a , b, b); 
} 

を書く場合

は今、出力が-1 4294967295 -1 4294967295されるようになります。さて、私はビットパターンと様々なものを見て、次に、2の補数のが11111111 11111111 11111111 11111111であることを認識したので、%dを使って解釈すると、-1となりますが、%uを使って解釈すると、したがって、4294967295となります。私は、コードの組み立てが今ここに-1が符号なしと署名の両方倍レジスタに移動され

.LC0: 
    .string "%d %u \n %d %u" 
main: 
    push rbp 
    mov  rbp, rsp 
    sub  rsp, 16 
    mov  DWORD PTR [rbp-4], -1 
    mov  DWORD PTR [rbp-8], -1 
    mov  esi, DWORD PTR [rbp-8] 
    mov  ecx, DWORD PTR [rbp-8] 
    mov  edx, DWORD PTR [rbp-4] 
    mov  eax, DWORD PTR [rbp-4] 
    mov  r8d, esi 
    mov  esi, eax 
    mov  edi, OFFSET FLAT:.LC0 
    mov  eax, 0 
    call printf 
    mov  eax, 0 
    leave 
    ret 

でチェック。私は再解釈が重要であることを知りたいのですが、なぜunsignedsignedの2種類があるのですか?printfのフォーマット文字列%d%uが重要ですか?

さらに、符号なし整数に負の数を代入すると、実際に何が起こるのですか(私は初期化子がintからにこの値を変換することを学びましたが)アセンブリコードでこのようなことは見ませんでした。だから本当に何が起こるのですか?

そして、機械はそれが何をしなければならないかをどうやって知っていますか?そうでなければ、負の符号を見て2's complementを実行しますか?

私はほとんどすべての質問と答えを読んだことがあります。この質問は重複していると思うかもしれませんが、満足できる解決策を見つけることができませんでした。

+3

*「それは2の補数を行う必要があるときどのようにマシンが知っているんやないときは」* - 私はこのことを理解していない - すべてはプログラミングにおけるバイナリであることにダウンしています。マシン命令は、上位レベルの構造体である 'signed'や' unsigned'を気にしません。 – UnholySheep

+0

@UnholySheep私が意味するのは、署名付きのint = -1を書くとき、それは2の補数として格納されるので、このように格納されているかどうかにかかわらずすべての負の数は同じですか? –

+1

C言語の場合、負数は3つの表現の1つになる可能性があります。したがって、必ずしも2の補数である必要はありません。 printf形式も入力と一致する必要があります。そうしないとプログラムが作成されません。現行のC標準では、符号付きの型を符号なしの型に変換したり、符号なしの型から符号付きの型に変換したりしても、2の補数の計算機のビット表現は変更されません。マシンは、変数がレジスタに入っているときに、変数の署名について実際にはわかりません。コンパイラが知っているので、プログラムが知っているので、それで十分です。 – user3528438

答えて

2

署名されたものと署名されていないものの両方がメモリの一部であり、操作に応じて動作に関係します。

2の補数の演算がまったく同じであるため、加算または減算しても差はありません。

私たちは2つの数字を比較すると重要です:-1は0よりも低く、4294967295は明らかにそうではありません。

変換について - 同じサイズの場合、可変コンテンツを別のコンテンツに移動して別のコンテンツに移動するため、4294967295は-1になります。より大きなサイズの場合は最初に署名が拡張され、その後コンテンツは動きます。

マシンは現在どのように使用していますか?マシンは、符号付きと符号なしを比較するための異なる命令を持つか、または異なるフラグを提供します(x86は符号なしオーバーフロー用にキャリーを持ち、符号付きオーバーフロー用にはオーバーフローします)。

さらに、Cは符号付き数値がどのように格納されているかが緩和されており、2つの補数である必要はありません。しかし、今日では、すべての一般的なアーキテクチャがこのように署名しています。

+0

私は-1を符号なしintに代入すると、何が起こりますか。 –

+4

@SurajJainこれは、2の補数表現では、値*が同じであるためです。それらは同じバイナリビットパターンです。それは彼らがどのように異なったものになるかということです。 –

+0

@WeatherVane私は何を求めているすべての負の数は、2の補数として表され、また、私は符号なしint http://stackoverflow.com/a/7152835/5473170に負の数を格納する場合は、署名されていないint。それはどこで起こるのですか? –

0

符号付きと符号なし型の間にいくつかの違いがあります。

  1. 符号付きと符号なしを扱うときに、オペレータの行動は<<=>>=/%、および>>はすべて異なっています数字。

  2. 符号付き値の計算がその型の範囲を超えると、コンパイラは予測可能に動作する必要はありません。すべての定義されたケースで、符号付きおよび符号なしの値と同じように動作する演算子を使用する場合でも、一部のコンパイラは「面白い」方法で動作します。たとえば、x+1 > yを指定したコンパイラでは、xが署名されている場合はx>=yに置き換えられますが、xが署名されていない場合は置き換えられません。より興味深い例として

、「短い」は16ビットであり、「INT」は32ビットで、関数所定のコンパイラであるシステム上で:

unsigned mul(unsigned short x, unsigned short y) { return x*y; } 

ない状況ができたと仮定かもしれません生成物は、例えば、2147483647を超える場合、これまで発生し、それがunsigned x = mul(y,65535);yとして呼び出される関数は、unsigned shortた見た場合、それはyより大きい37268.

+0

私たちはチャットすることはできますか? –

+0

@SurajJain:そうです。どこに私に教えてください。 – supercat

-1

た場合にのみ適用されることを他の場所にコードを省略してもよいです符号付き整数表現の選択はプラットフォームに委ねられます。例えば、11012(-5)が01012(5)の2の補数である場合、01012(5)はでもの2の補数で、11012(-5)であるなど、負の値と負の値の両方に適用されます。

プラットフォームは、符号付きおよび符号なし整数の操作に別々の命令を提供する場合もあれば、提供しない場合もあります。たとえば、x86では、符号付き(idivおよびimul)および符号なし(divおよびmul)の整数に対して異なる乗算および除算命令が提供されますが、同じ加算(add)および減算(sub)の両方の命令が使用されます。

同様に、x86では、符号付き整数と符号なし整数の両方の比較命令(cmp)が提供されます。

算術演算と比較演算は、1つ以上のステータスレジスタフラグ(キャリー、オーバーフロー、ゼロなど)を設定します。これらは、符号付きの値と符号なしの値を表すはずの単語を扱うときに、異なる方法で使用できます。

は限り懸念しているprintfとして、あなたは変換指定は、引数の型はと一致しない場合ことを覚えているが、ビットパターン0xFFFFは、-14294967295としてを表示するかどうかを判断することが絶対に正しいているもの変換指定子が予期している場合、その動作は未定義です。 %uを使用して、負の値signed intを表示すると、期待される同等の符号なし値が得られる場合もあります。

+0

イニシャライザの意味はint型をunsigned型に変更するときです。 –

+0

この質問は-2を生成するのに十分なほど悪く、さらに6ヶ月間質問を投稿することを阻止します。 –

0

符号付き整数と符号なし整数の両方で0101 = 5という事実を忘れてしまったようですが、次に符号なし整数に負の数を割り当てました。 、therfore、signed intに修正してください。符号なし整数型が0の下に値を格納することができないので、技術的にエラーが発生しなければならない-5 unsigned int型の設定

0

あなたはより大きなサイズの符号なし整数に負の値を代入しようとすると、それをよりよく理解することができ。コンパイラは、小さいサイズの負の値を大きなサイズの符号なし整数に転送するときに符号拡張を行うアセンブリコードを生成します。

see this blog post for assembly level explanation.

関連する問題