# Hex-Rays v1.3 vs. v1.2 Decompiler Comparison Page

## Hex-Rays v1.3 vs. v1.2 Decompiler Comparison Page

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

The following examples are displayed on this page:

1. [Better 64-bit arithmetics](https://hex-rays.com/products/decompiler/compare/v13_vs_v12/#c1)
2. [Better 64-bit arithmetics - 2](https://hex-rays.com/products/decompiler/compare/v13_vs_v12/#c2)
3. [64-bit comparisons](https://hex-rays.com/products/decompiler/compare/v13_vs_v12/#c3)
4. [Nested pointer, array, and structure references](https://hex-rays.com/products/decompiler/compare/v13_vs_v12/#c4)
5. [Assignments and comma operators](https://hex-rays.com/products/decompiler/compare/v13_vs_v12/#c5)
6. [Global propagation of calculated values](https://hex-rays.com/products/decompiler/compare/v13_vs_v12/#c6)
7. [Calculated values - 2](https://hex-rays.com/products/decompiler/compare/v13_vs_v12/#c7)
8. [Improved register argument detection](https://hex-rays.com/products/decompiler/compare/v13_vs_v12/#c8)
9. [Simpler arithmeric operations](https://hex-rays.com/products/decompiler/compare/v13_vs_v12/#c9)
10. [References to arrays of structures](https://hex-rays.com/products/decompiler/compare/v13_vs_v12/#c10)
11. [Improved optimizer](https://hex-rays.com/products/decompiler/compare/v13_vs_v12/#c11)
12. [Improved optimizer - 2](https://hex-rays.com/products/decompiler/compare/v13_vs_v12/#c12)
13. [Fast structural analysis](https://hex-rays.com/products/decompiler/compare/v13_vs_v12/#c13)
14. [Floating point constants](https://hex-rays.com/products/decompiler/compare/v13_vs_v12/#c14)
15. [More precise variable creation](https://hex-rays.com/products/decompiler/compare/v13_vs_v12/#c15)
16. [Postincrement/decrement with comparisons](https://hex-rays.com/products/decompiler/compare/v13_vs_v12/#c16)
17. [Constant strings](https://hex-rays.com/products/decompiler/compare/v13_vs_v12/#c17)
18. [Shorter output](https://hex-rays.com/products/decompiler/compare/v13_vs_v12/#c18)

NOTE: these are just some selected examples that can be illustrated as a side-by-side difference. Hex-Rays Decompiler v1.3 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. Please refer to the [news page](https://hex-rays.com/products/decompiler/news/) for more details.

***

### Better 64-bit arithmetics

It seems that 64-bit support is a never ending story. The [previous](https://docs.hex-rays.com/9.0sp1/archive/hex-rays-v1.2-vs.-v1.1-decompiler-comparison-page) version of the decompiler could not recognize the 64-bit addition because it was interleaved with other operations and the value of an operand changed midway. The new version can handle it, and the output is much simpler.

{% tabs %}
{% tab title="PSEUDOCODE V1.3" %}

```javascript
    v3 = v27;
    v27 = 0xB23199F3u;
    v25 = v28 + (unsigned int)v3;
    if ( !v25 )
```

{% endtab %}

{% tab title="PSEUDOCODE V1.2" %}

```python
    v3 = (_DWORD)v28 >= (unsigned int)-v27;
    v4 = v28 + v27;
    v27 = 0xB23199F3u;
    LODWORD(v25) = v4;
    HIDWORD(v25) = HIDWORD(v28) + v3;
    if ( !((HIDWORD(v28) + v3) | v4) )
```

{% endtab %}
{% endtabs %}

### Better 64-bit arithmetics - 2

An unrecognized 64-bit addition may lead to other complications. On the left, we have `v9` and `v10` 32-bit variables, on the right there is one simple 64-bit `v10` variable. Note the difference.

{% tabs %}
{% tab title="PSEUDOCODE V1.3" %}

```javascript
    if ( ReadPtr(v10, HIDWORD(v10), &v39) )
      ExtensionApis.lpOutputRoutine(
        "Cannot read DebugInfo adddress at 0x%p.\n",
        v10);
```

{% endtab %}

{% tab title="PSEUDOCODE V1.2" %}

```python
    v9 = a2 + v29;
    v8 = (int)&v5[(_DWORD)a2 >= (unsigned int)-v29];
    if ( ReadPtr(a2 + v29, &v5[(_DWORD)a2 >= (unsigned int)-v29], &v39) )
      ExtensionApis.lpOutputRoutine(
        "Cannot read DebugInfo adddress at 0x%p.\n",
        v9,
        v8);

```

{% endtab %}
{% endtabs %}

### 64-bit comparisons

We added more rules to recognize 64-bit comparisons. The results are pleasing.

{% tabs %}
{% tab title="PSEUDOCODE V1.3" %}

```javascript
  if ( xll == yll )
    result = 1;
  else
    result = 2;
```

{% endtab %}

{% tab title="PSEUDOCODE V1.2" %}

```python
  if ( (_DWORD)xll != (_DWORD)yll || HIDWORD(xll) != HIDWORD(yll) )
    result = 2;
  else
    result = 1;
```

{% endtab %}
{% endtabs %}

### Nested pointer, array, and structure references

Complex references like pointers to arrays to pointers to (the list may go on) were not always recognized and represented nicely. Only one level of indirection was handled nicely, deeper references might look ugly. Now the decompiler does a much better job. (the type of `a3g` is `char (**a3g)[5]`, so the expression on the left is correct too)

{% tabs %}
{% tab title="PSEUDOCODE V1.3" %}

```javascript
char __cdecl fa3g(int i, int j, int k)
{
  return a3g[i][j][k];
}
```

{% endtab %}

{% tab title="PSEUDOCODE V1.2" %}

```python
char __cdecl fa3g(int i, int j, int k)
{
  return *(&(*a3g[i])[5 * j] + k);
}

```

{% endtab %}
{% endtabs %}

### Assignments and comma operators

Nobody likes comma operators but the decompiler has to revert to them to get rid of `goto`s. In some cases they can still be eliminated and that's what the new version does.

{% tabs %}
{% tab title="PSEUDOCODE V1.3" %}

```javascript
    if ( !ptr || (v3 = *ptr) == 0 )
      do_something...;
```

{% endtab %}

{% tab title="PSEUDOCODE V1.2" %}

```python
    if ( !ptr || (v3 = *ptr, !*ptr) )
      do_something...;
```

{% endtab %}
{% endtabs %}

### Global propagation of calculated values

Note that the decompiler replaced the `result` variable with its known value, zero. Knowing a variable value enables many other optimizations and can simplify the output very much. It also removes false dependencies: for example, the previous version had to introduce a cast to `LPCSTR`.

{% tabs %}
{% tab title="PSEUDOCODE V1.3" %}

```javascript
  if ( !result )
  {
    if ( !v5 )
      return 0;
    v4 = SysAllocStringByteLen(0, v5 - 2);
```

{% endtab %}

{% tab title="PSEUDOCODE V1.2" %}

```python
  if ( !result )
  {
    if ( !v5 )
      return result;
    v4 = SysAllocStringByteLen((LPCSTR)result, v5 - 2);
```

{% endtab %}
{% endtabs %}

### Calculated values - 2

Since we know that value of `v1` in the `if`-branch, we can replace it with zero, which leads to simplifications. The output is much cleaner.

{% tabs %}
{% tab title="PSEUDOCODE V1.3" %}

```javascript
    if ( !RegEnumValueW(hKey, 0, &ValueName, &cbValueName, 0, 0, 0, 0) && ValueName )
      return 1;
```

{% endtab %}

{% tab title="PSEUDOCODE V1.2" %}

```python
    v1 = RegEnumValueW(hKey, 0, &ValueName, &cbValueName, 0, 0, 0, 0);
    if ( !v1 && ValueName )
      return v1 + 1;
```

{% endtab %}
{% endtabs %}

### Improved register argument detection

The heurstics to detect register arguments has been improved. The output does not require any comments.

{% tabs %}
{% tab title="PSEUDOCODE V1.3" %}

```javascript
result = pStm->lpVtbl->Write(pStm, pvarSrc, 2u, 0);
```

{% endtab %}

{% tab title="PSEUDOCODE V1.2" %}

```python
  result = ((int (__thiscall *)(void *, IStream *, void *, signed int, _DWORD))pStm->lpVtbl->Write)(
             pvarSrc,
             pStm,
             pvarSrc,
             2,
             0);
```

{% endtab %}
{% endtabs %}

### Simpler arithmeric operations

{% tabs %}
{% tab title="PSEUDOCODE V1.3" %}

```javascript
bytevar = ai[arg0] + ai[arg0] + 2 * uai[arg0];
```

{% endtab %}

{% tab title="PSEUDOCODE V1.2" %}

```python
bytevar = ai[arg0] + LOBYTE(ai[arg0]) + 2 * LOBYTE(uai[arg0]);
```

{% endtab %}
{% endtabs %}

### References to arrays of structures

First, references to arrays of structures are much better. Second, the decompiler could determine that v20 is used only to access the array and divided it by the array element size (12).

{% tabs %}
{% tab title="PSEUDOCODE V1.3" %}

```javascript
do
{
  if ( v27 & GlobalFlagInfo[v20].flags )
  {
    v21 = GlobalFlagInfo[v20].cmd;
    if ( v21 )
      ExtensionApis.lpOutputRoutine("    %s - %s\n", v21,
        GlobalFlagInfo[v20].desc);
  }
  ++v20;
}
while ( v20 < 32 );
```

{% endtab %}

{% tab title="PSEUDOCODE V1.2" %}

```python
do
{
  if ( v29 & *(int *)((char *)&GlobalFlagInfo[0].flags + v20) )
  {
    v23 = *(int *)((char *)&GlobalFlagInfo[0].cmd + v20);
    if ( v23 )
      ExtensionApis.lpOutputRoutine("    %s - %s\n", v23,
        *(void **)((char *)&GlobalFlagInfo[0].desc + v20));
  }
  v20 += 12;
}
while ( v20 < 0x180 );

```

{% endtab %}
{% endtabs %}

### Improved optimizer

It is difficult to say what exactly improvement of the decompiler led to this result, but we like it anyway. The decompiler could get rid of intermediate variables and simplify the code to the maximum.

{% tabs %}
{% tab title="PSEUDOCODE V1.3" %}

```javascript
  while ( *v2 )
    *v5++ = *v2++;
  *v5 = 0;
```

{% endtab %}

{% tab title="PSEUDOCODE V1.2" %}

```python
  while ( 1 )
  {
    v7 = *v3;
    if ( !*v3 )
      break;
    *v6++ = v7;
    ++v3;
  }
  *v6 = v7;
```

{% endtab %}
{% endtabs %}

### Improved optimizer - 2

Yet another example of improved output. There are many other improved things, like inlined `strcpy`, `strlen` and other functions, we are just getting too many examples anyway...

{% tabs %}
{% tab title="PSEUDOCODE V1.3" %}

```javascript
return (char)(a1 % 661);
```

{% endtab %}

{% tab title="PSEUDOCODE V1.2" %}

```python
 return (char)(a1 - -107 * (unsigned __int16)(a1 / 661));
```

{% endtab %}
{% endtabs %}

### Fast structural analysis

We tweaked the structural analysis: now it is faster (especially on big functions) and produces more concise output. Note that there is only one `if` operator now. Since not everyone likes dense code, this is [configurable](https://hex-rays.com/products/decompiler/manual/config.shtml).

{% tabs %}
{% tab title="PSEUDOCODE V1.3" %}

```javascript
  if ( dword_8066AEC && filename )
    sub_805F18C(16, (int)"using configuration file %s", (char)filename);
```

{% endtab %}

{% tab title="PSEUDOCODE V1.2" %}

```python
  if ( dword_8066AEC )
  {
    if ( filename )
      sub_805F18C(16, (int)"using configuration file %s", (char)filename);
  }

```

{% endtab %}
{% endtabs %}

### Floating point constants

Floating point constants are detected even if they are moved around using integer manipulation commands (a simple `mov` instruction).

{% tabs %}
{% tab title="PSEUDOCODE V1.3" %}

```javascript
  v63 = 1.0;
  v62 = 1.0;
```

{% endtab %}

{% tab title="PSEUDOCODE V1.2" %}

```python
  LODWORD(v63) = 1065353216;
  LODWORD(v62) = 1065353216;
```

{% endtab %}
{% endtabs %}

### More precise variable creation

The decompiler determined that even if `v5` and `v6` variables are initialized as 32-bit entities, only 16-bits are used. It declared them as 16-bit variables. This leads to better output.

{% tabs %}
{% tab title="PSEUDOCODE V1.3" %}

```javascript
int __cdecl sub_8049CA0(struct_a1 *a1, __int16 a2, __int16 a3, int a4)
{
  int v4; // esi@1
  __int16 v5; // ax@2
  __int16 v6; // ax@4

  v4 = a4;
  a1->dword0 = a2 | (a1->dword0 << a3);
  if ( a3 )
    v5 = a1->word4 + a3;
  else
    v5 = 0;
  a1->word4 = v5;
  if ( v5 >= 0 )
  {
    do
    {
      *(_BYTE *)v4++ = a1->dword0 >> a1->word4;
      v6 = a1->word4 - 8;
      a1->word4 = v6;
    }
    while ( v6 >= 0 );
  }
  return v4;
}
```

{% endtab %}

{% tab title="PSEUDOCODE V1.2" %}

```python
int __cdecl sub_8049CA0(struct_a1 *a1, __int16 a2, __int16 a3, int a4)
{
  int v4; // esi@1
  int v5; // eax@2
  int v6; // eax@4

  v4 = a4;
  a1->dword0 = a2 | (a1->dword0 << a3);
  if ( a3 )
    v5 = a1->word4 + a3;
  else
    LOWORD(v5) = 0;
  a1->word4 = v5;
  if ( (_WORD)v5 >= 0 )
  {
    do
    {
      *(_BYTE *)v4++ = a1->dword0 >> a1->word4;
      v6 = a1->word4 - 8;
      a1->word4 = v6;
    }
    while ( (_WORD)v6 >= 0 );
  }
  return v4;
}
```

{% endtab %}
{% endtabs %}

### Postincrement/decrement with comparisons

Postincrement/decrement operators with comparisons were leading to ugly output, now it is simpler and ready to be simplified even more.

{% tabs %}
{% tab title="PSEUDOCODE V1.3" %}

```javascript
          --a1;
          if ( !a1 )
            break;
```

{% endtab %}

{% tab title="PSEUDOCODE V1.2" %}

```python
            v5 = a1-- == 1;
            if ( v5 )
              break;
```

{% endtab %}
{% endtabs %}

### Constant strings

References into the middle of constact strings were not recognized, forcing the user to jump to the string to learn its value. Now the life is simpler.

{% tabs %}
{% tab title="PSEUDOCODE V1.3" %}

```javascript
 fwrite("OK\n", 1u, 3u, _stderrp);
```

{% endtab %}

{% tab title="PSEUDOCODE V1.2" %}

```python
 fwrite(&aPimGraft[15], 1u, 3u, _stderrp);
```

{% endtab %}
{% endtabs %}

### Shorter output

It seems that the fast structural analysis combined with the improved loop recognition made it possible to shorten the output. Whatever the reason is, we like the output on the right.

\\

{% tabs %}
{% tab title="PSEUDOCODE V1.3" %}

```javascript
      while ( a1[v11] == 9 && v8 & 7 )
      {
        ++v8;
        sub_804A350(v10, *(_WORD *)(a2 + 49224), v20);
      }
```

{% endtab %}

{% tab title="PSEUDOCODE V1.2" %}

```python
      if ( a1[v11] == 9 )
      {
        if ( v9 & 7 )
        {
          do
          {
            ++v9;
            sub_804A350(v12, *(_WORD *)(a2 + 49224), v20);
          }
          while ( a1[v11] == 9 && v9 & 7 );
        }
      }
```

{% endtab %}
{% endtabs %}
