12

C/C++ で書かれたコードの逆アセンブルを見ていると、いつも混乱します。

何らかの値を持つレジスタがあります。符号付きの数値か符号なしの数値かを知りたいです。どうすればこれを見つけることができますか?

私の理解では、それが符号付き整数の場合、MSB が負の場合は設定され、正の場合は設定されません。符号なし整数であることがわかった場合、MSB は問題ではありません。これは正しいです?

とにかく、これは役に立たないようです。この情報を使用する前に、整数が署名されているかどうかを確認する必要があります。これはどのように行うことができますか?

4

4 に答える 4

9

あなたの最善の策は、比較と関連するアクション/ブランチのようなフラグの使用法を探すことです。タイプに応じて、コンパイラは異なるコードを生成します。ほとんどの (関連する) アーキテクチャは、符号付きの値を処理するためのフラグを提供します。x86 を例にとると、次のようになります。

jg, jge, jl, jle = branch based on a signed comparison (They check for the SF flag)
ja, jae, jb, jbe = branch based on a unsigned comparison (They check for the CF flag)

最近では 2 の補数表現を使用しているため、CPU のほとんどの命令は、符号付き/符号なし演算で同じになります。しかし、例外があります。

例として右シフトを考えてみましょう。X86 で符号なしの値を使用すると、SHR を使用して何かを右にシフトします。これにより、左側のすべての「新しく作成されたビット」にゼロが追加されます。

ただし、符号付きの値の場合、通常は SAR が使用されます。これは、MSB がすべての新しいビットに拡張されるためです。これは「符号拡張」と呼ばれ、2 の補数を使用しているためにのみ機能します。

最後になりましたが、符号付き/符号なしの乗算/除算にはさまざまな命令があります。

idiv or one-operand imul = signed
div or mul/mulx = unsigned

コメントに記載されているようにimul、2 つまたは 3 つのオペランドを使用しても何も意味しません。imul上位半分の結果を書くのに時間を無駄にしない形式でのみ存在するため、コンパイラ (および人間) は、特に上位半分の結果が必要な場合 (最適化など) を除いて、符号の有無に関係なく を使用imuluint64_t = u32 * (uint64_t)u32します。唯一の違いは、特にコンパイラによって生成されたコードではめったに見られないフラグが設定されていることです。

また、NEG 命令は通常、2 の補数の否定であるため、符号付きの値でのみ使用されます。( の一部として使用された場合abs()、結果は INT_MIN でのオーバーフローを避けるために符号なしと見なされる場合があります。)

于 2012-06-26T12:23:56.883 に答える
4

一般的には、できません。整数値で発生する多くのことは、符号付きまたは符号なしの値でも同じように発生します。たとえば、割り当て。唯一の方法は、コードがたまたま算術を行っているかどうかです。値を見ただけでは絶対にわかりません。考えられるすべてのビット パターンはどちらの方法でも有効です。

于 2012-06-26T10:43:18.813 に答える
2

ほとんどのプロセッサ (少なくとも 2 の補数演算を使用するプロセッサ) では、レジスタまたはメモリに格納された整数に固有の符号性はありません。解釈は、使用される指示によって異なります。簡単な要約:

  1. 加算と減算は、符号付きと符号なしの数値に対してまったく同じビット パターンを生成するため、通常、符号付きの加算または減算はありません。(ただし、MIPS には、操作がオーバーフローした場合にトラップを引き起こす別の命令があります)。

  2. 除算と乗算では、符号付きの数値と符号なしの数値では異なる結果が生成されるため、プロセッサがサポートしている場合はペアになります (x86: mul/imul、div/idiv)。

  3. 条件分岐も、比較結果の解釈によって異なる場合があります (通常は減算として実装されます)。たとえば、x86 にはjgfor signed greaterjafor unsigned aboveがあります。

浮動小数点数 (少なくとも IEEE 形式) は明示的な符号ビットを使用するため、上記は適用されないことに注意してください。

于 2012-06-26T13:52:43.387 に答える
0

言われていることに加えて、実行時の値を調べることも役立ちます。

たとえば、

add eax, edx    ; eax = 0xFFFFFFF0, edx = 100

eaxおそらく符号付き変数を保持します。ここには保証はありませんが、どこにも保証はありません。コードが単に間違っている可能性は常にあります。(意図的または非意図的な)符号なしオーバーフローを含むコードが存在しますが、実際には符号付き非オーバーフローとして解釈されることを意図している可能性がはるかに高くなります。

于 2012-06-26T12:42:13.513 に答える