Before we start discussing the topic of developing 64-bit program code, let us speak about backward compatibility of 64-bit Windows versions, with 32-bit applications. Backward compatibility is arranged through the mechanisms implemented in WoW64.
WoW64 (Windows-on-Windows 64-bit) is a subsystem of Windows operating system, which allows you to execute 32-bit applications on all the 64-bit versions of Windows.
The WoW64 subsystem does not support the following programs:
- programs compiled for 16-bit operating systems;
- kernel-mode programs compiled for 32-bit operating systems.
There are differences in WoW64 depending on the CPU architecture. For example, the 64-bit Windows version developed for Intel Itanium 2 processor, employs WoW64 to emulate x86 instructions. This emulation is rather resource-intensive in comparison to WoW64 for Intel 64 architecture, because the system has to switch from the 64-bit mode to compatibility mode when executing 32-bit programs.
WoW64 on Intel 64 (AMD64 / x64) does not require instruction emulation. In this case the WoW64 subsystem emulates only the 32-bit environment through an additional layer between a 32-bit application, and the 64-bit Windows API. In some places this layer is thin, in others a bit thicker. For an average program, you may expect 2% performance loss because of this layer. For some programs, it can be larger. Two per cent is not very much, but keep in mind that 32-bit applications work a bit slower under the 64-bit Windows than in the 32-bit environment.
Compilation of 64-bit code does not only allow you to avoid using WoW64, but also gives you additional performance gain. This is explained by architectural modifications in the microprocessor, such as an increased number of general-purpose registers. For an average program, you may expect a 5-15% performance gain after simple recompilation.
Benefits of the 64-bit environment for 32-bit programs
Because of the WoW64 layer, 32-bit programs are less efficient in the 64-bit environment than in their native 32-bit one. However, simple 32-bit applications can still get one benefit of being executed in the 64-bit environment. Perhaps, you know that a program built with the switch “/LARGEADDRESSAWARE:YES” can allocate up to 3 Gbytes of memory, if a 32-bit Windows is launched with the switch “/3gb”. Well, the same 32-bit program built on a 64-bit system can allocate almost 4 Gbytes of memory (in practice it is usually about 3.5 Gbytes).
The WoW64 subsystem isolates 32-bit programs from 64-bit ones by redirecting calls to files and the register. It helps to keep 32-bit programs from accidentally accessing the data of 64-bit ones. For example, a 32-bit application that launches a DLL file from the catalogue “%systemroot%\System32” can accidentally address a 64-bit DLL, which is incompatible with the 32-bit program. To avoid this, the WoW64 subsystem redirects the access from the folder %systemroot%\System32 into the folder %systemroot%\SysWOW64. This redirection helps you avoid compatibility errors because the 32-bit application will need a special DLL file created to work with 32-bit applications.
To learn more about the mechanisms of file system and register redirection see MSDN section “Running 32-bit Applications“.
Why can’t 32-bit DLL’s be used in a 64-bit program? Is there a way to evade this limitation?
It is impossible to load a 32-bit DLL from a 64-bit process, and execute its code. It is impossible due to the design of 64-bit systems. It is impossible in general. No tricks and undocumented workarounds will help you. To do this you will have to load and initialize WoW64, not to mention the kernel structures. Actually, it means that a 64-bit process must be made 32-bit “on the fly”. This topic is described more thoroughly in the post “Why can’t you thunk between 32-bit and 64-bit Windows?”. The only thing we can recommend is to create a surrogate process, and work with it through the COM technology. You may read about it in the article “Accessing 32-bit DLLs from 64-bit code“.
But it is quite easy to load resources from a 32-bit DLL into a 64-bit process. You may do it if you specify the flag LOAD_LIBRARY_AS_DATAFILE when calling LoadLibraryEx.