1

アセンブラで次のコードスニペットを理解するのに苦労しています。

if ( EAX >= 5 )
  EBX = 1;
else
  EBX = 2;"

アセンブラでは、これは次のように記述できます(私の本によると)。これは、一度に1つのフラグのみを参照する「より単純な」ブランチに関して通常使用するjge命令をエミュレートします。

1     cmp eax, 5       ;(assuming eax is signed)
2     js signon        ;goto signon if SF = 1
3     jo elseblock     ;goto elseblock if OF = 1 and SF = 0
4     jmp thenblock    ;goto thenblock if SF = 0 and OF = 0
5 signon:
6     jo thenblock     ;goto thenblock if SF = 1 and OF = 1
7 elseblock:
8     mov ebx, 2
9     jmp next
10 thenblock:
11    mov ebx, 1
12    next:

結果のフラグは次のようになる可能性があることを理解できます:(if(EAX> = 5)):

SF = 0&OF = 0しかし、フラグがどのようになり得るか理解できません:SF = 1&OF = 1?どのような計算がこれを与えますか?

私が何を意味するかを明確にするために:

eaxが負の下限にある場合、5を引くことによって正にオーバーフローする可能性があります。正の上限にある場合、5を引くことによって負にオーバーフローすることはできません。

4

2 に答える 2

1

これらを3ビット数で考えるとはるかに簡単で、すべてがスケーリングされます。うーん、これが署名されている場合(高水準コードで指定/投稿しなかった場合)、5を使用したため、4ビットの方が適しています。5に近い数値をウォークスルーします(これはaluの出力を示します)

cmp reg,5
0111 - 0101 = 0111 + 1010 + 1 = 10010
0110 - 0101 = 0110 + 1010 + 1 = 10001
0101 - 0101 = 0101 + 1010 + 1 = 10000
0100 - 0101 = 0100 + 1010 + 1 = 01111
0011 - 0101 = 0011 + 1010 + 1 = 01110

ここで、ハードウェアがどのように機能するかを理解する必要があります。減算を実行すると、aluから出てくるキャリーフラグが反転するプロセッサフ​​ァミリもあれば、そうでないプロセッサフ​​ァミリもあります。どちらの方法でも、5〜5ポイントで状態変化を確実に確認できます。そして、とにかくここでキャリーフラグは必要ありません、コードはそれを使用しません。

符号付きの数学を行っている場合は、負の数も試してください。

0000 - 0101 = 0000 + 1010 + 1 = 01011  
1111 - 0101 = 1111 + 1010 + 1 = 11010
1110 = 0101 = 1110 + 1010 + 1 = 11001

そして、それは問題にいくらかの光を当てます。

符号付きオーバーフローは、キャリーインが加算器のmsbitでのキャリーアウトと等しくないこととして定義されます。それは厄介になる可能性があるので、その境界がどこにあるかを知る必要があります。

0111 - 0101 = 7 - 5 = 2
0110 - 0101 = 6 - 5 = 1
0101 - 0101 = 5 - 5 = 0
0100 - 0101 = 4 - 5 = -1
0011 - 0101 = 3 - 5 = -2

等々。この4ビットモデルを使用すると、符号付きの解釈では、+ 7(0b0111)から-8(0b1000)までに制限されます。したがって、-3-5の後、問題が発生します。

1110 - 0101 = 1110 + 1010 + 1 = 11001 , -2 - 5 = -7
1101 - 0101 = 1101 + 1010 + 1 = 11000 , -3 - 5 = -8
1100 - 0101 = 1100 + 1010 + 1 = 10111 , -4 - 5 = 7 (-9 if we had more bits)
1011 - 0101 = 1011 + 1010 + 1 = 10110 , -5 - 5 = 6 (-10 if we had more bits)
1010 - 0101 = 1010 + 1010 + 1 = 10101 , -6 - 5 = 5 (-11 if we had more bits)
1001 - 0101 = 1001 + 1010 + 1 = 10100 , -7 - 5 = 4 (-12 if we had more bits)
1000 - 0101 = 1000 + 1010 + 1 = 10011 , -8 - 5 = 3 (-13 if we had more bits)

後者の5つは符号付きオーバーフローであり、符号付きの結果を使用可能なビット数で表すことはできません。(今のところ4ビットシステムで遊んでいることを思い出してください。その一番上のビットはキャリービットです。結果を見るときに視覚的に削除してください)。

符号付きフラグは単に結果のmsbitであり、興味深い境界も変更しています。符号付きフラグ(結果のmsbit)が設定されている場合は、5未満の正(eax)値と、符号付きオーバーフロー(+4から-3まで)をもたらさない負の数値です。これらはすべて<5カテゴリに含まれているため、2の結果が必要です。最初のテストでは、符号が設定されているケースを探します。なぜ、符号付きオーバーフローをテストする必要があるのでしょうか。それは意味がありません。署名されたすべての結果が5未満のカテゴリにあることはすでにわかっています。署名されたオーバーフローが問題にならない場合は、余分なジャンプが発生します。

したがって、jsサインオンに失敗すると、5以上の数値(1の結果が必要)または符号付きオーバーフローを引き起こすのに十分な負の結果(2の結果が必要)の符号ビットがオフになります。したがって、jo elseblockは、2つのケース(符号付きオーバーフロー、非常に負)の結果を取得することにより、これら2つのケースを分類します。jmp thenblockは、5を超える正の数を取ります。

ここで署名された計算を行っているように見えます(署名されたオーバーフローフラグを使用することからある程度明らかです)。符号付き数学と比較するために5を使用しているため、このコードを実装するにはシステムに4ビット以上が必要です。したがって、8、32、64、123456ビット、すべてが4ビットシステムと同じように機能するかどうかは関係ありません。 (この比較のために)。分析を行うためのビット数を最小限に抑える方が簡単だと思います。このようにハードコードされた比較を行うと、上記のように、すぐ上、上、下で結果を計算できるため、はるかに簡単になります。次に、符号付き数値の場合はすべてゼロ(ゼロ)からすべて1(マイナス1)まで進み、符号付きオーバーフロー範囲に非常に負になります。符号なしの数値の場合は少し簡単ですが、同じプロセスです。

于 2012-12-31T16:00:18.713 に答える
-1

if(EAX> = 5)EBX = 1; それ以外の場合、EBX = 2; "

cmp eax,5
jae biggerthan
mov ebx,2
jmp out
.biggerthan
mov ebx,1
.out
于 2013-05-24T13:02:09.627 に答える