Hex-Rays v1.2 vs. v1.1 Decompiler Comparison Page

Hex-Rays v1.2 vs. v1.1 Decompiler Comparison Page

Below you will find side-by-side comparisons of v1.1 and v1.2 decompilations. Please maximize the window too see both columns simultaneously.

The following examples are displayed on this page:

NOTE: these are just some selected examples that can be illustrated as a side-by-side difference. Hex-Rays Decompiler v1.2 includes are many other improvements and new features that are not mentioned on this page - simply because there was nothing to compare them with. Also, some improvements have already been illustrated in the previous comparisons. We continue to improve 64-bit arithmetics and inline function recognition, but the examples would somewhat repeat older stuff, so we did not include them. Please refer to the news page for more details.


Intrinsic functions

Intrinsic functions are generally superior to inline assembly and the above text shows it.

return _InterlockedIncrement(a1);

Scalar SSE floating point instructions

The decompiler can handle SSE scalar floating point instructions directly, without any need of intrinsic functions. Mac OS X users will appreciate this improvement very much because short SSE scalar sequences are very popular in Mach-O files.

int __cdecl sub_578C(int _30, double arg4)
{
  int varC; // [sp+1Ch] [bp-Ch]@1

  varC = 0;
  tclStubsPtr->tcl_CreateTimerHandler((signed int)floor(arg4 * 1000.0),
                  (Tcl_TimerProc *)sub_54CB, &varC);
  while ( !varC )
    tclStubsPtr->tcl_DoOneEvent(0);
  return 0;
}

SSE intrinsic functions

While operations on packed values are difficult to decipher with and without intrinsic functions, there is still a side effect: the decompiler has more information about the data flows and unknown assembly instructions do not disrupt the analysis. See how the v6 temporary variable disappears.

    xmm0_3 = _mm_sub_pd(
               (__m128d)_mm_unpacklo_epi32(
                          _mm_unpacklo_epi32(_mm_cvtsi32_si128(eax0->fC),
                                             _mm_cvtsi32_si128(eax0->f8)),
                          (__m128i)xmmword_C1E0),
               (__m128d)xmmword_C1F0);
    result = printf("\t%s: %.*f(%sbytes)",
                    edx0,
                    0,
                    *(_OWORD *)&_mm_hadd_pd(xmm0_3, xmm0_3),
                    &unk_B36C);

SSE scalar operations - 2

The old version was producing a page of code, the new version - just one line. Always a pleasure to have a shorter text: no intermediary variables, no inline assembly, just straightforward code.

signed int __cdecl casual(signed int arg0, int arg4)
{
  return (signed int)floor((double)arg0 
       + (double)(random() & 0x7FFFFFFF) / 2147483647.0
         * (double)(arg4 - arg0));
}

SSE scalar operations - 3

The decompiler could recognize an unsigned conversion and represented in concisely. It looks surprising but the line on the right side is identical to the long text on the right side.

long double __cdecl auto_time_interval(__int64 arg0, __int64 arg8)
{
  return (double)(unsigned __int64)(arg0 - arg8) / 1000000.0;
}

Better ternary operations

Yet another common compiler idiom is recognized and the output becomes better.

 v36 = sub_804CF6C(v20, v40 < 1 ? 2 : 35);

Better recognition of inlined functions

More inlined string functions are recognized.

if ( strcmp(a2[1], "1234567") )
   result = 0;
 else
   result = 6;

Recognition of signed power2 modulos

One more common compiler idiom. There are many others, we chose only one sample.

result = (v4 + a1) % 4;

Last updated