Last updated
Was this helpful?
Last updated
Was this helpful?
Below you will find side-by-side comparisons of v7.2 and v7.3 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 side-by-side differences. There are many other improvements and new features that are not mentioned on this page. We just got tired selecting them. Some of the improvements that did not do to this page:
objc-related improvements
value range analysis can eliminate more useless code
better resolving of got-relative memory references
too big shift amounts are converted to lower values (e.g. 33->1)
more for-loops
better handling of fragemented variables
many other things...
When a constant looks nicer as a hexadecimal number, we print it as a hexadecimal number by default. Naturally, beauty is in the eye of the beholder, but the new beahavior will produce more readable code, and less frequently you will fell compelled to change the number representation. By the way, this tiny change is just one of numerious improvements that we keep adding in each release. Most of them go literally unnoticed. It is just this time we decided to talk about them
EfiBootRecord points to a structure that has RecordExtents[0] as the last member. Such structures are considered as variable size structures in C/C++. Now we handle them nicely.
We were printing UTF-8 and other string types, UTF-32 was not supported yet. Now we print it with the 'U' prefix.
The difference between these outputs is subtle but pleasant. The new version managed to determine the variable types based on the printf format string. While the old version ended up with int a2, int a3
, the new version correctly determined them as one __int64 a2
.
A similar logic works for scanf-like functions. Please note that the old version was misdetecting the number of arguments. It was possible to correct the misdetected arguments using the Numpad-Minus hotkey but it is always better when there is less routine work on your shoulders, right?
While seasoned reversers know what is located at fs:0
, it is still better to have it spelled out. Besides, the type of v15
is automatically detected as struct _EXCEPTION_REGISTRATION_RECORD *
.
Again, the user can specify the union field that should be used in the output (the hotkey is Alt-Y
) but there are situations when it can be automatically determined based on the access type and size. The above example illustrates this point. JFYI, the type of entry
is:
While we can not handle bitfields yet, their presence does not prevent using other, regular fields, of the structure.
I could not resist the temptation to include one more example of automatic union selection. How beautiful the code on the right is!
No comments needed, we hope. The new decompiler managed to fold constant expressions after replacing EABI helpers with corresponding operators.
Now it works better especially in complex cases.
In this case too, the user could set the prototype of sub_1135FC
as accepting a char *
and this would be enough to reveal string references in the output, but the new decompiler can do it automatically.
The code on the left had a very awkward sequence to copy a structure. The code on the right eliminates it as unnecessary and useless.
Do you care about this improvement? Probably you do not care because the difference is tiny. However, in additon to be simpler, the code on the right eliminated a temporary variable, v5
. A tiny improvement, but an improvement it is.
Another tiny improvement made the output considerably shorter. We like it!
This is a very special case: a division that uses the rcr
instruction. Our microcode does not have the opcode for it but we implemented the logic to handle some special cases, just so you do not waste your time trying to decipher the meaning of convoluted code (yes, rcr
means code that is difficult to understand).
Well, we can not say that we produce less gotos in all cases, but there is some improvement for sure. Second, note that the return type got improved too: now it is immediately visible that the function returns a boolean (0/1) value.
What a surprise, the code on the right is longer and more complex! Indeed, it is so, and it is because now the decompiler is more careful with the division instructions. They potentially may generate the zero division exception and completely hiding them from the output may be misleading. If you prefer the old behaviour, turn off the division preserving in the configuration file.
Do you notice the difference? If not, here is a hint: the order of arguments of sub_88
is different. The code on the right is more correct because the the format specifiers match the variable types. For example, %f
matches float a
. At the first sight the code on the left looks completely wrong but (surprise!) it works correctly on x64 machines. It is so because floating point and integer arguments are passed at different locations, so the relative order of floating/integer arguments in the call does not matter much. Nevertheless, the code on the right causes less confusion.
This is a never ending battle, but we advance!