What it takes to write 64-bit apps

Matt Pietrek has written a nice new article on MSDN about everything that you need to know to get started writing applications for 64-bit versions of Windows - otherwise known as x64. It is available here:

http://msdn.microsoft.com/msdnmag/issues/06/05/x64/default.aspx

For your quick reference (and mine :) I've jotted down the important points here if you haven't got the time or inclination to read the article. Here goes.

  • Moving from 32-bit to 64-bit is not just a re-compile away.
  • You get to address really really large chunks of memory (on the order of terabytes and even larger). Each process gets its own 8TB chunk of memory from the OS.
  • All system DLLs are loaded above 4GB typically at addresses around 0x7FF00000000.
  • The x64 linker assigns the default load address for 64-bit applications to just above 32 bits. This is being done so that you can quickly discover porting bugs. If you are for instance using a 32-bit pointer where you should have used a 64-bit pointer, because the base address is greater than what can be accommodated in 32 bits the pointer will effectively get truncated resulting in an access violation.
  • Most Win32 datatypes continue to retain the size from the 32-bit world. INTs, LONGs, WORDs and DWORDs continue to be 32-bits wide. HANDLEs have become 64-bits wide though.
  • x64 versions of Windows include a sub-system called WOW64 that allows 32-bit applications to just work on x64.
  • A 64-bit application cannot load 32-bit DLLs and vice versa. However 64 and 32-bit applications can still talk to each other using inter-process communication mechanisms (shared memory, named pipes, synchronization objects).
  • x64 is officially off limits for 16-bit applications.
  • Two copies of system DLLs are maintained - one for 64-bit applications and one for 32-bit applications. WOW64 silently re-directs file I/O on the system folder for 32-bit applications to \Windows\SysWow64. If you want to figure out the path to the 32-bit system folder from a 64-bit app then you can do that by calling GetSystemWow64Directory.
  • Just like the file system, WOW64 silently re-directs access to the registry also for 32-bit applications. This is to prevent each type of application from stepping on each other's toes, as can happen when a 64-bit app CoCreateInstances a 32-bit COM component! So, a 32-bit application would see a different HKEY_CLASSES_ROOT (and a few other keys) as opposed to a 64-bit app.
  • x64 now includes a feature called PatchGuard which basically BSODs your system if any kernel mode code alters important kernel mode data structures such as the Interrupt Dispatch Table (IDT). Hmm. Now there's a challenge for rootkit writers and tools such as Regmon that rely on being able to mess around with the IDT.
  • CPU registers are now 64-bits wide (obviously) and are called RAX, RBX, RCX, RDX, RSI and so forth. 8 new general purpose registers have been added and are called R8, R9, R10 and so on till R15.
  • No more __cdecl, __stdcall, __fastcall or __thiscall! There is only a single calling convention in x64 which passes the first 4 parameters to a function via RCX, RDX, R8 and R9 and the remaining parameters via the stack.

A few quick points on writing code that works on 32-bit and 64-bit computers:

  • Pointers cannot be stored in 32-bit types such as ints, longs or DWORDs.
  • Use DWORD_PTRs, INT_PTRs and LONG_PTRs when you want to store pointer values. These types automatically become 64-bits wide on x64 systems (after a recompile that is).
  • When you use functions like printf and sprintf do not use %X to print pointer values. Use %p and you're automagically protected.
  • Inline assembly is not supported in the 64-bit C++ compiler. Boo! hoo!
comments powered by Disqus