Se eu escrever um programa C e compilá-lo em um .exe
arquivo, o .exe
arquivo conterá instruções brutas da máquina na CPU. (Eu acho que).
Em caso afirmativo, como é possível executar o arquivo compilado em qualquer computador que execute uma versão moderna do Windows? Cada família de CPUs possui um conjunto de instruções diferente. Então, como é que qualquer computador que executa o sistema operacional apropriado pode entender as instruções do meu .exe
arquivo, independentemente da CPU física?
Além disso, geralmente em sites na página "download" de algum aplicativo, você tem um download para Windows, Linux e Mac (geralmente dois downloads para cada SO, para computadores de 86 e 64 bits). Por que não há muito mais downloads, para cada família de CPUs?
fonte
Respostas:
Os executáveis dependem do sistema operacional e da CPU:
Conjunto de instruções: As instruções binárias no executável são decodificadas pela CPU de acordo com algum conjunto de instruções. A maioria das CPUs de consumidor suporta os conjuntos de instruções x86 ("32 bits") e / ou AMD64 ("64 bits"). Um programa pode ser compilado para um desses conjuntos de instruções, mas não para ambos. Existem extensões para esses conjuntos de instruções; o suporte para estes pode ser consultado em tempo de execução. Tais extensões oferecem suporte SIMD, por exemplo. A otimização de compiladores pode tentar tirar proveito dessas extensões se elas estiverem presentes, mas geralmente também oferece um caminho de código que funciona sem nenhuma extensão.
Formato binário: o executável deve estar em conformidade com um determinado formato binário, que permite ao sistema operacional carregar, inicializar e iniciar corretamente o programa. O Windows usa principalmente o formato Executável Portátil, enquanto o Linux usa o ELF.
APIs do sistema: o programa pode estar usando bibliotecas, que precisam estar presentes no sistema em execução. Se um programa usa funções das APIs do Windows, ele não pode ser executado no Linux. No mundo Unix, as APIs do sistema operacional central foram padronizadas para POSIX: um programa usando apenas as funções POSIX poderá ser executado em qualquer sistema Unix compatível, como Mac OS X e Solaris.
Portanto, se dois sistemas oferecerem as mesmas APIs e bibliotecas do sistema, executar no mesmo conjunto de instruções e usar o mesmo formato binário, um programa compilado para um sistema também será executado no outro.
No entanto, existem maneiras de obter mais compatibilidade:
Os sistemas executados no conjunto de instruções AMD64 geralmente também executam executáveis x86. O formato binário indica qual modo executar. A manipulação de programas de 32 e 64 bits requer um esforço adicional do sistema operacional.
Alguns formatos binários permitem que um arquivo contenha várias versões de um programa, compilado para diferentes conjuntos de instruções. Esses "binários gordos" foram incentivados pela Apple durante a transição da arquitetura PowerPC para o x86.
Alguns programas não são compilados no código da máquina, mas em alguma representação intermediária. Isso é traduzido imediatamente para instruções reais ou pode ser interpretado. Isso torna um programa independente da arquitetura específica. Essa estratégia foi usada no UCSD p-System.
Um sistema operacional pode suportar vários formatos binários. O Windows é bastante compatível com versões anteriores e ainda suporta formatos da era DOS. No Linux, o Wine permite que os formatos do Windows sejam carregados.
As APIs de um sistema operacional podem ser reimplementadas para outro SO host. No Windows, o Cygwin e o subsistema POSIX podem ser usados para obter um ambiente (principalmente) compatível com POSIX. No Linux, o Wine reimplementa muitas das APIs do Windows.
As bibliotecas de plataforma cruzada permitem que um programa seja independente das APIs do SO. Muitas linguagens de programação possuem bibliotecas padrão que tentam conseguir isso, por exemplo, Java e C.
Um emulador simula um sistema diferente analisando o formato binário externo, interpretando as instruções e oferecendo uma reimplementação de todas as APIs necessárias. Emuladores são comumente usados para rodar jogos antigos do Nitendo em um PC moderno.
fonte
99% dos PCs atuais com Windows possuem um processador de 64 bits, que também é capaz de executar software de 32 bits. O outro por cento possui processadores de 32 bits. Portanto, o software criado para processadores de 32 bits funciona em qualquer lugar. O software criado para processadores de 64 bits é executado em todos os PCs com os quais o criador se importa.
O MacOS X e o iOS suportam "binários gordos" - o que você baixa na verdade pode conter versões para diferentes processadores. Ninguém mais constrói aplicativos para processadores PowerPC, mas há alguns anos um executável poderia conter uma versão PowerPC, Intel de 32 bits e Intel de 64 bits, e a versão correta seria executada. Atualmente, no iOS, ao baixar um aplicativo, você obtém uma versão adequada para o processador no seu dispositivo. Faça o download em um dispositivo diferente e você obtém uma versão diferente. Totalmente invisível para o usuário.
fonte
Um exe contém mais informações do que apenas código de máquina bruto. O sistema operacional lê isso ao carregá-lo e pode descobrir como deve ser executado.
Quando você compila, geralmente define uma CPU de destino; caso contrário, o compilador selecionará sua CPU atual e se restringirá a escolher apenas instruções comuns à sua CPU e versões mais antigas. Se você quiser usar uma nova e sofisticada instrução específica para determinada revisão da CPU de destino, poderá informar ao compilador ou codificá-lo manualmente com código de montagem intrínseco ou embutido. No entanto, seu programa falhará se for executado em uma CPU que não suporta essa instrução.
fonte