2

元のコードはわかりませんが、右シフトと腹筋でこれほど複雑だとは思いません。

これは、名前が変更された逆コンパイルされたIDA PROコードがどのように見えるかです

char Ship; //Could be 0-7 (8 is reversed for special purpose)
char NewShip = 1; //Could be 0-7  (8 is reversed for special purpose)
short Frequency = 0; //This could be from 0 to 9999
bool NumberToFrequency = true;

Frequency = GetNextFrequencyToJoin(player->MyArena);
if ( NumberToFrequency )
{ //TODO: maybe the below is just Frequency % 7; ?
  NewShip = (((unsigned long)Frequency >> 32) ^ abs(Frequency) & 7) - ((unsigned long)Frequency >> 32);
  Ship = NewShip;
} else {
  Ship = NewShip;
}

これがIDEOneテストですhttp://ideone.com/Q2bEjU

NewShip = abs(frequency) & 7);が本当に必要としているのはそれだけのようです。ループしてすべての可能性をテストしたようです。

別の逆コンパイラでこの結果が得られました

 asm("cdq ");
 NewShip = ((Var1 ^ Var2) - Var2 & 7 ^ Var2) - Var2;

これには右シフトがないか、私にはまだ異質に見えますが、おそらく絶対数がどのように機能するかを示しており、右シフト32がどこから来たのかまだ手がかりがありません.

周波数NumberToFrequencyを船と同じにすることを想定していますが、もちろん周波数は7を超えているため、残りの値はまだ船の値に変換されるはずなので、モジュラス%は7であると想定しています.

しかし、なぜこのような複雑なコードがまったく別の意味を持っているのでしょうか? コードの意味を尋ねているだけです。以下にアセンブリコードを追加します。下のアセンブリには Shift right 32 さえ見つかりませんが、同じ場所にあると確信しています。

.text:0040DD3A                 mov     ecx, [ebp+1Ch]  ; arena
.text:0040DD3D                 call    GetNextFrequencyToJoin
.text:0040DD42                 mov     ecx, [ebp+1Ch]
.text:0040DD45                 mov     si, ax
.text:0040DD48                 mov     [esp+220h+var_20C], si
.text:0040DD4D                 cmp     [ecx+1ACCEh], ebx
.text:0040DD53                 jz      short loc_40DD98
.text:0040DD55                 movsx   eax, si
.text:0040DD58                 cdq
.text:0040DD59                 xor     eax, edx
.text:0040DD5B                 sub     eax, edx
.text:0040DD5D                 and     eax, 7
.text:0040DD60                 xor     eax, edx
.text:0040DD62                 sub     eax, edx
.text:0040DD64                 mov     [esp+220h+var_20F], al

編集:私は自分で答えを見つけました.シフト32>> 32は、32ビットDWORDまたはそのようながらくたに一致するタイプの古いCコンパイルサポートのために追加された役に立たないガベージであるようです.

4

2 に答える 2

5

シフトは無駄ではありません。これは、Hexray がその c 分解で再現できなかったバンチレス ロジックの形式です。

.text:0040DD55                 movsx   eax, si
.text:0040DD58                 cdq
.text:0040DD59                 xor     eax, edx
.text:0040DD5B                 sub     eax, edx
.text:0040DD5D                 and     eax, 7
.text:0040DD60                 xor     eax, edx
.text:0040DD62                 sub     eax, edx

重要なコードです。EDX:EAXは の符号拡張バージョンなSIので、EDXは 0 または -1 のいずれかです。はそのxorままにするかeax反転させます。 はそのsubままにするか、1 つ追加します。

if (si < 0) {
    eax = ~si;
    eax += 1;
    eax &= 0x7;
    eax = ~eax;
    eax += 1;
} else {
    eax = si & 0x7;
}

最初のブランチはまだ単純化できますが、それはあなたに任せます...


アップデート

枝がsi<0すでに異なっているだけで、何が起こっているのかについてのヒントが得られます。シーケンスは2 の補数eax = ~si; eax += 1;として理解できるため、この補数の知識を挿入すると、次のようになります。

if (si < 0) {
    eax = -1 * si;
    eax &= 0x7;
    eax *= -1;
} else {
    eax = si & 0x7;
}

または要するに

eax = (abs(si) & 0x7) * sign(si);

または符号付きモジュラス演算子を使用

al = si % 8;
于 2014-04-26T11:55:45.917 に答える
0

I think I figured it out, the decompiler I used IDA-PRO seems to generate these Shift right 32's >> 32 all over the place and in all cases where I see this a abs() function is used it just seems like a useless wrapper for Absolute number Function.

Some examples I found.

//1
((((unsigned long)i >> 32) ^ abs(i)) - ((unsigned long)i >> 32))
//2
(((unsigned long)encryption->field_25E >> 32) ^ abs(encryption->field_25E)) - ((unsigned long)encryption->field_25E >> 32);
//3
((((unsigned long)i >> 32) ^ abs(i)) - ((unsigned long)i >> 32))
//4
(((unsigned long)(v104->field_A8 + 1) >> 32) ^ abs(*((unsigned char*)&(v104->field_A8)) + 1) & 7) - ((unsigned long)(v104->field_A8 + 1) >> 32);
//5
(((unsigned long)v11 >> 32) ^ abs(v11)) - ((unsigned long)v11 >> 32);
//6
(((unsigned long)v4->field_262 >> 32) ^ abs(v4->field_262)) - ((unsigned long)v4->field_262 >> 32)
//7
(((unsigned long)v18 >> 32) ^ abs(v18)) - ((unsigned long)v18 >> 32);
//8 (not refactored yet).
((((unsigned long)*(unsigned int *)(v1 + 610) >> 32) ^ abs(*(unsigned int *)(v1 + 610))) - ((unsigned long)*(unsigned int *)(v1 + 610) >> 32)

You may also see these >> 32's in 1 more place which I already know is just optimized division from researching and it looks much more different.

Something crazy like this (I fixed this with my regular expression tool)

(signed int)((unsigned int)v130 + ((unsigned long)(18446744071705233545i64 * (signed int)v130) >> 32)) >> 5;

//Originally it looked something like this
LODWORD(v202) = (signed int)((_DWORD)v202 + (0xFFFFFFFF88888889ui64 * (signed int)v202 >> 32)) >> 5;

//Or without the hexadecimal values
LODWORD(v202) = (signed int)((_DWORD)v202 + ((unsigned __int64)(18446744071705233545i64 * (signed int)v202) >> 32)) >> 5;

//You will see it getting used like this
(signed int)(((unsigned int)v202 >> 31) + v202)

But what it really means is
v202 / 60

The equations used to convert it back to / 60 is talked about on http://www.hexblog.com/?p=17

于 2014-04-26T11:42:15.093 に答える