EXE Comparison From VDF 16 to DF 25
<< Back
I have just installed VDF 16.1 all the way up to DF 25.0 on my machine.
I did some comparison amoung different versions of VDF/DF in terms of the
final execuable. Here are the results. I am going to talk about the significance
of the results after the table. But first, I will present my code.
Use UI
Inkey FieldIndex
Version | Platform | Size | DateTime (UTC) | Linker | Minimum | Terminal | Data | .text |
16 | 32 | 155,648 | Now | 16.0 | 4.0 | ❌ | .rdata | 289 |
17 | 32 | 155,648 | Now | 17.0 | 4.0 | ❌ | .rdata | 289 |
18 | 32 | 155,648 | Now | 18.0 | 4.0 | ❌ | .rdata | 289 |
19 | 32 | 229,888 | 2024/02/15 15:03:24 | 14.16 | 6.0 | ✔️ | .rsrc | 55,926 |
20 | 32 | 232,960 | 2024/02/14 13:11:54 | 14.16 | 6.0 | ✔️ | .rsrc | 58,470 |
20 | 64 | 322,560 | 2024/02/14 13:19:16 | 14.16 | 6.0 | ✔️ | .rsrc | 63,075 |
23 | 32 | 233,472 | 2024/10/03 12:59:00 | 14.16 | 6.0 | ✔️ | .rsrc | 58,470 |
23 | 64 | 323,072 | 2024/10/03 13:07:19 | 14.16 | 6.0 | ✔️ | .rsrc | 63,075 |
24 | 32 | 233,472 | 2024/10/02 17:31:30 | 14.16 | 6.0 | ✔️ | .rsrc | 58,470 |
24 | 64 | 323,072 | 2024/10/02 17:40:53 | 14.16 | 6.0 | ✔️ | .rsrc | 63,075 |
25 | 32 | 234,496 | 2025/06/05 18:25:07 | 14.16 | 6.0 | ✔️ | .rsrc | 58,470 |
25 | 64 | 324,096 | 2025/06/05 18:32:59 | 14.16 | 6.0 | ✔️ | .rsrc | 63,075 |
- The first two columns are self-explantory
- It is to be expected that the size of the EXE will increase over each subsequent version. One thing to note is that the EXE size from VDF 16.1 to DF 18
didn't change
- Every Windows Portable Executable (AKA "PE", such as *.exe/*.dll/*.ocx etc.) contains the Build time internally. A typical Microsoft Visual C++
Linker would fill in that field. Prior to DF 19, VDF would follow that trend. For some odd reason, DF 19+ would have a fixed Build time. For example, with
the version of DF 19 on my machine, every EXE that is made by DF 19 would have the exact same Build time of 2024/02/15 15:03:24. One possible explanation is
something called reproducible builds. However DAW is not
putting a hash value of the EXE into the Build time field. I have a theory that I will explain later.
- The Visual C++ linker would usually put the version of itself in the PE that it builds. Prior to DF 19, the VDF/DF Compiler would do just that.
I like that fact that I could analyze the header of a PE to know which version of VDF the program was built with without running said PE.
Starting with DF 19, DF Compiler would put the Visual C++ linker version into the final PE, which is a bit odd. Also, Visual C++ linker version 14.16
represents Visual Studio 2017. A bit dated if you ask me. Visual Studio 2022 can catch a lot more logical errors than Visual Studio 2017. Also
Visual Studio 2017 support ended on April 12, 2022. Extended support ends on April 13, 2027. I hope that DAW is paying for that extended support...
- The "Terminal" column represents whether the PE is Windows terminal server environment aware. I remember that there was a time I had to
write a utility to flip the "Terminal Awareness" flag in my VDF EXE so that it would operate normally on a Windows Terminal Server environment.
I am glad that flag was finally turned on automatically without me doing some post-build magic.
-
The "Data" column is a bit technical. I will refer you to the article I wrote here. The fact of the "flx"
byte code got moved from the .rdata section to the .rsrc section within the PE means that we can finally load the "flx" file usually standard
Win32 API like FindResource and
LoadResource.
Stay turned for the updated version of this article.
-
Finally, the ".text" column, which represents the size of the C++ loader code. Remember that VDF/DF doesn't generate native code per se.
It generates kinda VDF byte codes and stores those byte codes in .rdata/.rsrc section as raw data, then the VDFVM.DLL executes/interprets said raw data.
If you need a refresher, read here and here.
Prior to DF 19, the .text column was always 289 bytes, cause the C++ loader code was super simple. In DF 19+, the loader code is also very simple,
but for some reason, the C runtime library was built into every EXE that DF produces. You can see that by looking at the import address table of
the EXE that DF produces. Also worth pointing out is that the C++ loader code from DF 20 to DF 25 is exactly the same size.
-
The above points are all observations. Now comes the speculation - Since DF 19+, the compiler is using a "template" to create DF EXE (At least
the header part of the PE), and that can explain why all the build time are the same for all the EXE it produces.
- You might ask - what's the point of this article? It's just for my own curiosity. I was given a free DF license and I had a free weekend.
