が分割オーバーフローエラー(x86)
-
28-09-2019 - |
質問
いくつか質問を分割オーバーフローエラー x86またはx86_64です。最近私は読みつの整数があります。通常、算術演算結果を整数型オーバーフロー、ビットまたはオーバーフロートの旗の登録が設定されます。が明らかに この記事,溢れに伴う部事務んで設定をオーバーフロートではなくトリガーハードウェア例外と類似のとき分割によるゼロになります。
現在の整数であふれに伴う部門をく珍しいような、乗算を用意しています。丸の内にある南インド料理店。数の方でもトリガー部門オーバーフロー.片思いのようなもの:
int16_t a = -32768;
int16_t b = -1;
int16_t c = a / b;
この場合、二つの補数表現の署名の整数でないのは正の32768に符号付き16ビット整数での動作が溢れにより、誤った価値の-32768.
数の質問:
1)異なるこしているのだろう、というのは、上記のらせることにはならなかったハードウェア例外です。を使用しているx86_64機械Linux、および時分割によりゼロのプログラムが終了し、 Floating point exception
.が原因となるオーバーフロー部門は、プログラムとして、黙々を無視して、誤った商.では、なぜこの原因となるハードウェア例外?
2)なぜ部誤りのハードウェア、その他の演算が溢れる?なぜ倍オーバーフロー( 多く が誤って発生し)すると通知なしに無視されるハードウェアがオーバーフロー部門はトリガ致命的な割り込み?
=========== 編集 ==============
大丈夫、謝に対する反応。んで頂いており対応いは基本的には、上記の16ビット整数部門な原因となるハードウェア故障が商ており、今後シミュレーションとの登録サイズです。う必要はありません。この場合、登録の保管商が16ビットである 小さすぎ 店舗に署名し正の32768.なぜなハードウェア例外?
ようし、これを直接GCCインラインで組み立て、何が起こるか見てみてください:
int16_t a = -32768;
int16_t b = -1;
__asm__
(
"xorw %%dx, %%dx;" // Clear the DX register (upper-bits of dividend)
"movw %1, %%ax;" // Load lower bits of dividend into AX
"movw %2, %%bx;" // Load the divisor into BX
"idivw %%bx;" // Divide a / b (quotient is stored in AX)
"movw %%ax, %0;" // Copy the quotient into 'b'
: "=rm"(b) // Output list
:"ir"(a), "rm"(b) // Input list
:"%ax", "%dx", "%bx" // Clobbered registers
);
printf("%d\n", b);
では、このメソッドは単純出力誤った値: -32768
.まだまだハードウェアにおいても例外での登録の保管商(AX)が小さすぎて、商.思う思わないハードウェア故障上げます。
解決
C言語で作成している種の比 int
.何らかの試算に小さめのオペランドの、初の受積促進に変換するし int
.場合はお使いのプラットフォーム int
は、32ビット幅は、そのように力Cプログラムを16ビット。のコンパイラを生成する32ビット事業部です。このはなぜお客様の実験が発生しないのオーバーフローに関す。場合のプラットフォームにいた32ビット int
, その最良のベットもして同じもの32ビット演算のオペランド(分割 INT_MIN
による -1
).いうことができるでしょうが再現、オーバーフロー例外のものCコードです。
お組立てのコードを使用16ビット本部から指定した BX
のオペランドのための idiv
.16ビット本部x86分の32ビットの配当に格納され DX:AX
ペアの idiv
オペランド.これを確認することができまごのコードです。の DX:AX
ペアとして解釈される一つの複合32-bit登録いことを意味し、符号ビットがこのペアは実際に最も高いビ DX
.最高のビ AX
はファイナンシャルタイムビットです。
うかい DX
?するだけでクリアされます。設定して0になります。が DX
0に設定され、配当として解釈される 正!機械からの視点など DX:AX
ペア実際には 正 値 +32768
.I.。お組立言語での実験で分割 +32768
による -1
.その結果が -32768
, できます。も特別なものです。
したい場合を表すのに -32768
の DX:AX
対して登録している、すなわちで記入 DX
すべての一ビットパターンではなく、ゼロのままにしておそうでない xor DX, DX
すべての初期化 AX
ご -32768
その後行われ cwd
.こうしてサインを延長 AX
入 DX
.
例えば、私の実験はGCC)このコード
__asm {
mov AX, -32768
cwd
mov BX, -1
idiv BX
}
原因の例外では実際の試み分け -32768
による -1
.
他のヒント
きの整数オーバーフローとの整数2の補数の追加/減算/multiplyまだ有効な結果で欠高めます。この行動が有効になるそうなので、適切ではないかもしれませんを生成するための例外です。
整数部ただし、その結果、分化によるゼロにはならな浮動小数点値の2の補数てINF代表).
逆にどこしているのだろう、というのは、上記のらせることにはならなかったハードウェアの例外
第っているとは言えない。はい
...彼らは生部門のエラーの場合はソースのオペランド(divisor)がゼロの場合の指数が大きすぎて、指定され 登録
登録サイズはより大き16ビット(32||64)
とは異なり、追加、ul、imul instructions、インテル事業部 指示部とidivに設定しないでください のオーバーフローフラグ;彼らを生成する 部門のエラーの場合、ソースのオペランド (divisor)がゼロの場合や、商 大きなものを指定 登録できます。
の登録は、現代のトから32または64ビット;32768のままの方が登録するただし、以下のコードを変更するに捨て整数オーバーフロー execptionでは自分のcore DuoノートにVC8):
int x= INT_MIN;
int y= -1;
int z= x/y;
その理由を与えず、ハードウェアの例外はCの整数を推進。オペランドより小さい
int
自動昇格ints
前の操作を行います。理由としては、異なる種類のが溢れる取り扱いが異なると考えるのx86機レベルにあっかもしれませんの倍オーバーフロー.き掛けAXによるその他の登録の結果は、DX:AXペアがありませんが味は良かったでルームの結果、このような機会で信号を、オーバーフロー例外です。しかし、Cその他の言語を
ints
はっぴにint
, があるなんて、オーバーフローをしております。これにはx86は、セット(オーバーフローフラグ)MUL
s、それに高い結果の一部は非ゼロになります。
実施の32ビット int
, おば ものではありませんオーバーフロー分割.その結果として完全にrepresentable int
,32768、それを返しに変換され int16_t
に実装で定義されるときの課題が出てきます。これにより、安定したデフォルトの促進の指定されたC言語で、その結果、実装った例外をここでは非conformant.
ただし例外が(あるいは実際に起こるので、実施してみ:
int a = INT_MIN, b = -1, c = a/b;
なければならなくなるかもしれないかぎ防止のためのコンパイラからの最適化でコンパイルします。
私は予想することもある古いコンピュータもしくは分割によりゼロの一部の厳しい問題(例えばのハードウェアにエンドレスサイクルという引き算なので、残り以下の配当金までのオペレーターに駆けつけてくれたので修正しく、この伝統に分割であふれていると厳しい断層以上の整数があります。
からのプログラミングの観点から、理由はありませんが、予期せぬ分割オーバーフローすべきは深刻なより想定外の整数オーバーフロー(署名または符号なし).さらにコストの本部の限界費用を確認するオーバーフローフラグを後にするかは軽微であります。伝統の理由が見えるハードウェアにつきます。