Disclaimer: Eu nunca escrevi um sistema operacional na minha vida. É melhor esperar alguém mais competente para responder e ler alguns artigos do OSDev nesse meio tempo.
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?
São ambos.
-
Todos os arquivos executáveis do Windows (.exe, .dll, ... - executáveis do PE em geral) têm um cabeçalho informando ao SO qual arquitetura eles foram compilados. Pode ser Intel x86 (16 bits ou 32 bits) ou x86_64 ou Itanium ou Alpha AXP…
Se o SO vir uma arquitetura incompatível no cabeçalho, ele se recusará completamente a executar o programa. Em outros casos - se você tentar executar um programa x86 em x86_64, por exemplo - ele saberá que o programa precisa ser executado em um modo diferente do restante.
-
Por outro lado, as instruções reais do código de máquina dentro do programa são diferentes. (A propósito, esse é o ponto de ter arquiteturas diferentes.) A arquitetura x86_64 de 64 bits tem mais instruções do que x86 de 32 bits, e x86 de 32 bits tinha mais instruções que 16 bits. (E coisas como Alpha ou ARM ou Itanium são tão diferentes que há muito pouco que pode ser comparado.)
(Até CPUs x86 diferentes têm diferentes conjuntos de instruções - ao longo do tempo, acumularam várias dezenas de extensões sobre as mais básicas, por exemplo, conjuntos de instruções "SSE" ou "MMX" ou "AES-NI", então é possível que um programa não rodará em processadores antigos como o Pentium se o compilador tiver permissão para otimizá-lo para os mais novos.)
E mesmo para instruções básicas que são as mesmas em ambas as arquiteturas, os tamanhos de dados podem ser maiores e, mais importante, os endereços de memória são maiores - as arquiteturas de 64 bits são geralmente chamadas de "64 bits" porque usam 64 bits exprima localizações na memória e assim por diante.
Assim, mesmo que você tenha editado o cabeçalho manualmente para informar ao SO uma arquitetura diferente, você só acabaria com um programa que falhava todas as vezes.
-
Por outro lado, x86_64 ainda tem as mesmas instruções que o x86 (simplesmente adiciona mais delas), então é relativamente fácil para o SO rodar programas de 32 bits enquanto no modo de 64 bits; na maioria das vezes apenas se preocupa em usar apenas recursos do x86 ao lidar com esse programa. No entanto, o mesmo não se aplica na outra direção - mesmo que o sistema operacional de 32 bits tenha sido escrito para mudar a CPU para o modo de 64 bits para o seu programa, então, de volta, ainda pode acontecer facilmente que o programa tenha feito algo que o sistema operacional não conseguia lidar.
Se você tiver o código-fonte, você pode compilá-lo facilmente para arquiteturas diferentes (supondo que ele esteja escrito corretamente - alguns programas ainda têm suposições como ponteiros de memória sempre com 32 bits…) Mas se você tiver um binário compilado, está sem sorte.