在以下使用 Ida pro 的 Hex 射线的反编译函数中:

int sub_409650()
{
  int v0; // ecx@1
  int result; // eax@1
  bool v2; // zf@1
  bool v3; // sf@1
  unsigned __int8 v4; // of@1
  unsigned __int16 v5; // cx@2
  unsigned int v6; // ecx@2

  v0 = gS1_dword_62EEA8 & 7;
  result = gS1_dword_62EEA8 - v0;
  v4 = __OFSUB__(gS1_dword_62EEA8 - v0, 16);
  v2 = gS1_dword_62EEA8 - v0 == 16;
  v3 = gS1_dword_62EEA8 - v0 - 16 < 0;
  gS1_dword_62EEA8 -= v0;
  gs2_dword_62EFB4 >>= v0;
  if ( (unsigned __int8)(v3 ^ v4) | v2 )
  {
    v5 = *dword_62EFB0;
    ++dword_62EFB0;
    v6 = (v5 << result) | gs2_dword_62EFB4;
    result += 16;
    gs2_dword_62EFB4 = v6;
    gS1_dword_62EEA8 = result;
  }
  return result;
}

它调用 __OFSUB__ 但这有什么作用?我认为这与溢出有关 - 但如果这是真的那么为什么不是条件:
// Checking if subtracting v0 is 16 or negative?
if ( v3 | v2 )

更新:原始汇编是(现在重命名了一些东西):
.text:00409650 sub_409650 proc near
.text:00409650                 mov     eax, gBitCounter_62EEA8
.text:00409655                 push    esi
.text:00409656                 mov     esi, gFirstAudioFrameDWORD_dword_62EFB4
.text:0040965C                 mov     ecx, eax
.text:0040965E                 and     ecx, 7
.text:00409661                 shr     esi, cl
.text:00409663                 sub     eax, ecx
.text:00409665                 cmp     eax, 10h
.text:00409668                 mov     gBitCounter_62EEA8, eax
.text:0040966D                 mov     gFirstAudioFrameDWORD_dword_62EFB4, esi
.text:00409673                 jg      short loc_4096A5
.text:00409675                 mov     edx, gAudioFrameDataPtr
.text:0040967B                 xor     ecx, ecx
.text:0040967D                 mov     cx, [edx]
.text:00409680                 add     edx, 2
.text:00409683                 mov     esi, ecx
.text:00409685                 mov     ecx, eax
.text:00409687                 shl     esi, cl
.text:00409689                 mov     ecx, gFirstAudioFrameDWORD_dword_62EFB4
.text:0040968F                 mov     gAudioFrameDataPtr, edx
.text:00409695                 or      ecx, esi
.text:00409697                 add     eax, 10h
.text:0040969A                 mov     gFirstAudioFrameDWORD_dword_62EFB4, ecx
.text:004096A0                 mov     gBitCounter_62EEA8, eax
.text:004096A5
.text:004096A5 loc_4096A5:                             ; CODE XREF: sub_409650+23j
.text:004096A5                 pop     esi
.text:004096A6                 retn
.text:004096A6 sub_409650 endp

最佳答案

没有什么好说的。 HexRays 在将这些函数反编译为可读的东西方面做得非常糟糕,但它没有出错。

给定程序集的快速分析:

mov     eax, gBitCounter_62EEA8                 ; eax = gBitCounter_62EEA8
push    esi
mov     esi, gFirstAudioFrameDWORD_dword_62EFB4 ; esi = gFirstAudioFrameDWORD_dword_62EFB4
mov     ecx, eax
and     ecx, 7

; esi = gFirstAudioFrameDWORD_dword_62EFB4 >> (gBitCounter_62EEA8 & 7)
; i.e, esi got shiftted by the 3 LSB's of gBitCounter_62EEA8
shr     esi, cl

; eax = gBitCounter_62EEA8 - (gBitCounter_62EEA8 & 7)
sub     eax, ecx

cmp     eax, 10h

; gBitCounter_62EEA8 -= gBitCounter_62EEA8 & 7
mov     gBitCounter_62EEA8, eax

; gFirstAudioFrameDWORD_dword_62EFB4 >>= gBitCounter_62EEA8 & 7
mov     gFirstAudioFrameDWORD_dword_62EFB4, esi

; if gBitCounter_62EEA8 > 0x10 { return; }
jg      short loc_4096A5

; else... continue work
....

loc_4096A5:                             ; CODE XREF: sub_409650+23j
pop     esi
retn

更好的反编译应该是:
gBitCounter_62EEA8 -= gBitCounter_62EEA8 & 7
gFirstAudioFrameDWORD_dword_62EFB4 >>= gBitCounter_62EEA8 & 7

if (gBitCounter_62EEA8 > 0x10)
{
    return;
}
else
{
    // rest of code
}

但是,您可能会注意到 HexRays 逆转了这种情况。它产生了这个条件:
if ( (unsigned __int8)(
    (gBitCounter_62EEA8 - 16 < 0)  ^
    (__OFSUB__(gBitCounter_62EEA8 - (gBitCounter_62EEA8 & 7), 16))) // when this is actually the gBitCounter_62EEA8 var before modifications
        |
        (gBitCounter_62EEA8 == 16) )

根据 Intel's reference ,如果 jg ,则采用 ZF = 0 and SF = OF

条件紧密地代表它:
  • 要么 Counter == 16 - 意思是 ZF = 0 所以 jg 不被采用
  • 要么 Counter < 16 XOR __OFSUB__(gBitCounter_62EEA8 - (gBitCounter_62EEA8 & 7), 16) ,这意味着:
  • Counter < 16(我们称之为 A) - 这意味着 SF=1
  • __OFSUB__(gBitCounter_62EEA8 - (gBitCounter_62EEA8 & 7), 16)(我们称之为 B),意思是 OF=1

  • 如果 A=trueB=false 表示 SF=1,OF=0 => SF!=OF 。如果 A=falseB=true 表示 SF=0,OF=1 = > SF!=OF ,这意味着如果 A^BSF!=OF ,这意味着如果 A^B => jg not taken
    通常,如果不采用 jg,则将执行“其余代码”。

    我希望这有助于您理解 HexRays 的行为。它的反编译是正确的,但非常多余(它没有清除它可以清除的大量垃圾)并且它无法预测确定条件的适当方法(它采取了更“困难”的路径)

    关于c - HexRays - "__OFSUB__()"的目的是什么?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30499274/

    10-13 05:35