如何简化32 Xor绝对数和值的装配平移右移

use*_*580 2 assembly xor shift ida absolute-value

我不知道原始代码,但我不相信这是复杂的右移和abs.

以下是重命名的反编译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;
}
Run Code Online (Sandbox Code Playgroud)

这是IDEOne测试http://ideone.com/Q2bEjU

似乎NewShip = abs(frequency) & 7);是我真正需要的所有似乎我通过循环它测试所有可能性永远不会搞砸.

另一个反编译器给了我这个结果

 asm("cdq ");
 NewShip = ((Var1 ^ Var2) - Var2 & 7 ^ Var2) - Var2;
Run Code Online (Sandbox Code Playgroud)

没有任何正确的转变或任何看起来对我来说仍然陌生的东西,可能表明绝对数字是如何运作的,并且仍然不知道右移32的来源.

请告诉我NumberToFrequency该做的是使频率一样的船,但过程中的频率超出过去7所以剩余价值还是应该翻译成船舶价值的,所以我认为它只是一个模量%的7.

但为什么这么复杂的代码可能意味着完全不同的东西?我只是问问代码意味着什么.我将在下面添加汇编代码.我甚至无法在下面的装配中找到Shift右边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
Run Code Online (Sandbox Code Playgroud)

编辑:我发现自己的答案似乎是那些转移32 >> 32是无用的垃圾添加到一些旧的C编译支持类型匹配32位DWORD或类似的废话.

exa*_*ple 5

这些转变并非毫无用处.这是Hexray无法在其拆解中重现的一种无法解释的逻辑形式.

.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
Run Code Online (Sandbox Code Playgroud)

是重要的代码.EDX:EAX是符号扩展版本SI,因此EDX是0或-1.该xor要么保留eax不变或反转它的sub叶子是不变或全部等增加了一个:

if (si < 0) {
    eax = ~si;
    eax += 1;
    eax &= 0x7;
    eax = ~eax;
    eax += 1;
} else {
    eax = si & 0x7;
}
Run Code Online (Sandbox Code Playgroud)

第一个分支仍然可以简化,但我留给你...


更新

分支只是差异si<0已经给出了正在发生的事情的暗示.序列eax = ~si; eax += 1;可以理解为二进制补码,所以我们得到了这个补码的知识

if (si < 0) {
    eax = -1 * si;
    eax &= 0x7;
    eax *= -1;
} else {
    eax = si & 0x7;
}
Run Code Online (Sandbox Code Playgroud)

或简而言之

eax = (abs(si) & 0x7) * sign(si);
Run Code Online (Sandbox Code Playgroud)

或者使用带符号的模数运算符

al = si % 8;
Run Code Online (Sandbox Code Playgroud)