3

私はコンピューターの算数を学んでいます。私が使っている本(パターソンとヘネシー)には、以下の質問があります。

mipsコードを記述して、64ビットデータの倍精度整数減算を実行します。最初のオペランドがレジスタ$t4(hi)と$ t5(lo)にあり、2番目が$ t6(hi)と$ t7(lo)にあると仮定します。

答えに対する私の解決策は

sub  $t3, $t5, $t7   # Subtract lo parts of operands. t3 = t5 - t7
sltu $t2, $t5, $t7   # If the lo part of the 1st operand is less than the 2nd,
                     #   it means a borrow must be made from the hi part
add  $t6, $t6, $t2   # Simulate the borrow of the msb-of-low from lsb-of-high
sub  $t2, $t4, $t6   # Subtract the hi's. t2 = t4 - t6

ただし、この問題の解決策を示した作成者は次のとおりです。

符号付き倍精度整数の場合、

subu $t3, $t5, $t7   
sltu $t2, $t5, $t7  
add  $t6, $t6, $t2
sub  $t2, $t4, $t6

符号なし倍精度整数の場合、

subu $t3, $t5, $t7   
sltu $t2, $t5, $t7  
addu $t6, $t6, $t2
subu $t2, $t4, $t6

sub/addとの動作の違いについての私の理解はsubu/addu、オーバーフロー例外はで生成され、では生成されsub/addないということですsubu/addu。オペランドのビットの減算/加算sub/addsubu/addu、符号付きまたは符号なしのオペランドの解釈は、insltおよびsltu命令とは異なり、結果に違いはありません。

質問1
私は、オーバーフロー検出が処理されているという解決策を与えられた著者から推測していますが、私の解決策では同じことを考えていませんでした。私は正しいですか?他に足りないものはありますか?

質問2上記の推論が正しいと仮定すると、と
を使用して符号なし倍精度を減算する場合に、作成者が提供したソリューションのオーバーフロー検出がオフになっているのはなぜですか?addusubu

4

1 に答える 1

6

加算と減算では、オーバーフローの概念を除いて、符号付きオペランドと符号なしオペランドの間に違いはありません。オーバーフローは、結果の数値が取得したビット シーケンスの解釈と一致しない場合に発生します。

たとえば、8 ビットのシーケンスを考えてみましょう (MIPS には 32 ビットのレジスタがありますが、私の例では 8 ビットの方が簡単です)。符号なしの解釈を想定してみましょう。8 ビットのシーケンスは、0 から 255 までの数値を表します (両端を含む)。01110110 (数値 118) に 10010011 (数値 147) を足すと 00001001 (数値 9) になります。9 は 147+118 と等しくありません。数学的な値が 265 であり、8 ビットに収まらないため、この結果が得られます。加算結果には 9 ビットが必要でしたが、上位 9 番目のビットが削除されました。

ここで、署名された解釈で同じ例を想像してみてください。10010011 の数値は -109 になりました。01110110 にはまだ数値 118 があり、得られた結果 (00001001) の値は 9 です。-109 と 118 の数学的合計は 9 であるため、オーバーフローはありません。

これは、オーバーフローの概念が値の解釈方法に依存することを意味します。加算メカニズムは、符号付き解釈と符号なし解釈の両方で同じです (同じ入力ビット シーケンスに対して、同じ出力ビット シーケンスが得られます。これが負の符号付き値に 2 の補数を使用するポイントです) が、オーバーフロー処理が異なります。

MIPS アーキテクチャは、オーバーフロー時に例外をトリガーする手段を提供します。概念的には、32 ビット ワードには次の3 つの加算操作があります。

  • オーバーフローを静かに無視する追加 (結果は切り捨てられます)
  • 符号付きオーバーフローが発生したときに例外を発生させる加算 (入力シーケンスと出力シーケンスが符号付き数値として解釈される場合、オーバーフローが発生します)
  • 符号なしオーバーフローが発生したときに例外を発生させる加算 (入力シーケンスと出力シーケンスが符号なし数値として解釈される場合、オーバーフローが発生します)

MIPS は、最初の 2 種類の加算を実装し、それぞれオペコードadduaddオペコードを使用します。MIPS のドキュメントでは、それぞれunsignedおよびsigned 算術と呼ばれています。符号なしオーバーフローで例外を発生させるオペコードはありません。実際には、C コンパイラは のみadduを使用しますが、符号付きの型には を使用できaddます (これは C 標準で許可されていますが、非常に多くの既存のコードを壊してしまいます)。Ada コンパイラはadd、Ada がオーバーフロー チェックを必須にするために使用します。

そうは言っても…

Patterson と Hennessey は、64 ビット整数に符号付きおよび符号なしの算術演算を実装したいと考えています。符号なし算術演算の場合、例外は一切必要ないため、 and を使用addusubuます。符号付き演算の場合、数学的な結果が符号付き解釈の64 ビットシーケンスに収まらない場合に例外が発生することを望んでいます。下位 32 ビットの半分を処理する際に、誤ったオーバーフローのような状態が発生するため、例外を発生させたくありません。これがsubu、低域に a を使用する理由です。

すべきではない例外を発生させる可能性があるため、ソリューションは間違っています。-2000000000 (マイナス 20 億) から 2000000000 (20 億) を減算するとします。数学的な結果は 4000000000 (40 億) です。2 つのオペランドと結果は確かに 64 ビットに収まります (表現可能な範囲は -9223372036854775808 ~ 9223372036854775807)。したがって、64 ビットの符号付き演算の場合、オーバーフローはありません。例外はありません。ただし、その状況では、最初subにオーバーフローが報告されます。これsubは、32 ビット値と符号付き32ビットで動作します算数。そのオペランドは、01110111001101011001010000000000 および 10001000110010100110110000000000 になります。これらの値は両方とも 32 ビットに収まることに注意してください。これらの値の 32 ビット符号付き解釈は、それぞれプラス 20 億とマイナス 20 億です。ただし、減算結果は 40 億であり、32 ビット (符号付き数値として) に収まりません。したがって、sub例外が発生します。

経験則として、オーバーフロー検出は、最上位ビットの処理に影響を与える符号の解釈に依存することを行うことです。大整数演算の場合、最上位以外のすべての単語は符号なしとして扱われるため、どこでもaddu/が使用されます。subu最初のステップとして、最初に例外なく符号なし算術演算に集中すると、理解が容易になります (その後、 and のみを使用addusubu、orは使用しません )。addsub

于 2010-10-27T13:27:35.583 に答える