Windows – What’s the difference between a 32-bit and 64-bit program in Windows

32-bit64-bitwindowswindows 7

Why can't a 64-bit program run on a 32-bit copy of Windows? How does my PC know that I'm running a 64-bit program? Does the program have a piece of code telling Windows that it's a 64-bit program or does Windows simply fail to execute it?

I saw a significant difference in file size of the two versions of the same program, so I think it's the code that's different. Is it possible to modify the code and make the program run?

Best Answer

Disclaimer: I've never written an OS in my life. Better wait for someone more competent to answer, and read some OSDev articles in the mean time.

Does the program have a piece of code telling Windows that it's a 64-bit program or does Windows simply fail to execute it?

It's both.

  • All Windows executable files (.exe, .dll, … – PE executables in general) have a header telling the OS what architecture they were compiled for. It could be Intel x86 (16-bit or 32-bit) or x86_64 or Itanium or Alpha AXP…

    If the OS sees an incompatible architecture in the header, it will completely refuse to run the program. In other cases – if you try to run an x86 program on x86_64, for example – it will know that the program needs to be run in a different mode than the rest.

  • For another, the actual machine-code instructions inside the program are different. (That's kind of the whole point of having different architectures, by the way.) The 64-bit x86_64 architecture has more instructions than 32-bit x86 had, and 32-bit x86 had more instructions than 16-bit. (And things like Alpha or ARM or Itanium are so different that there's very little that could even be compared.)

    (Even different x86 CPUs have different sets of instructions – over time, they accumulated several dozens of extensions on top of the basic ones, e.g. "SSE" or "MMX" or "AES-NI" instruction sets, so it's possible that a program won't run on old CPUs like Pentium if the compiler was allowed to optimize it for the newest ones.)

    And even for basic instructions that are the same across both architectures, the data sizes can be larger, and most importantly, memory addresses are larger – 64-bit architectures are usually called "64-bit" because they use 64 bits to express locations in memory, and so on.

    So even if you hand-edited the header to tell the OS a different architecture, you'd only end up with a program that crashed every time.

  • On the other hand, x86_64 still has the same instructions that x86 did (it simply adds more of them), so it's relatively easy for the OS to run 32-bit programs while in 64-bit mode; it mostly just takes care to only use x86 features when dealing with that program. However, the same doesn't apply in the other direction – even if the 32-bit OS had been written to switch the CPU to the 64-bit mode for your program, then back, it could still easily happen that the program did something that the OS couldn't cope with.

If you have the source code, you can easily compile it for different architectures (assuming it was correctly written – some programs still have assumptions like memory pointers always being 32 bits wide…) But if you just have a compiled binary, you're out of luck.