Si escribo un programa en C y lo compilo en un .exe
archivo, el .exe
archivo contiene instrucciones de máquina sin procesar para la CPU. (Yo creo que).
Si es así, ¿cómo es posible que ejecute el archivo compilado en cualquier computadora que ejecute una versión moderna de Windows? Cada familia de CPU tiene un conjunto de instrucciones diferente. Entonces, ¿cómo es que cualquier computadora que ejecuta el sistema operativo apropiado puede entender las instrucciones en mi .exe
archivo, independientemente de su CPU física?
Además, a menudo en sitios web en la página de "descarga" de alguna aplicación, tiene una descarga para Windows, Linux y Mac (a menudo dos descargas para cada sistema operativo, para computadoras de 86 y 64 bits). ¿Por qué no hay muchas más descargas, para cada familia de CPU?
fuente
Respuestas:
Los ejecutables dependen tanto del sistema operativo como de la CPU:
Conjunto de instrucciones: las instrucciones binarias en el ejecutable son decodificadas por la CPU de acuerdo con algún conjunto de instrucciones. La mayoría de las CPU de consumo admiten los conjuntos de instrucciones x86 ("32 bits") y / o AMD64 ("64 bits"). Se puede compilar un programa para cualquiera de estos conjuntos de instrucciones, pero no para ambos. Hay extensiones de estos conjuntos de instrucciones; El soporte para estos puede consultarse en tiempo de ejecución. Tales extensiones ofrecen soporte SIMD, por ejemplo. Los compiladores de optimización podrían intentar aprovechar estas extensiones si están presentes, pero generalmente también ofrecen una ruta de código que funciona sin ninguna extensión.
Formato binario: el ejecutable debe ajustarse a un determinado formato binario, lo que permite que el sistema operativo cargue, inicialice e inicie correctamente el programa. Windows usa principalmente el formato ejecutable portátil, mientras que Linux usa ELF.
API del sistema: el programa puede estar utilizando bibliotecas, que deben estar presentes en el sistema en ejecución. Si un programa usa funciones de las API de Windows, no se puede ejecutar en Linux. En el mundo de Unix, las API del sistema operativo central se han estandarizado para POSIX: un programa que use solo las funciones POSIX podrá ejecutarse en cualquier sistema Unix compatible, como Mac OS X y Solaris.
Entonces, si dos sistemas ofrecen las mismas API y bibliotecas del sistema, se ejecutan en el mismo conjunto de instrucciones y usan el mismo formato binario, entonces un programa compilado para un sistema también se ejecutará en el otro.
Sin embargo, hay formas de lograr más compatibilidad:
Los sistemas que se ejecutan en el conjunto de instrucciones AMD64 también suelen ejecutar ejecutables x86. El formato binario indica qué modo ejecutar. El manejo de los programas de 32 bits y 64 bits requiere un esfuerzo adicional por parte del sistema operativo.
Algunos formatos binarios permiten que un archivo contenga múltiples versiones de un programa, compiladas para diferentes conjuntos de instrucciones. Apple alentó tales "binarios gordos" mientras realizaban la transición de la arquitectura PowerPC a x86.
Algunos programas no están compilados en código máquina, sino en alguna representación intermedia. Esto se traduce sobre la marcha a las instrucciones reales, o puede ser interpretado. Esto hace que un programa sea independiente de la arquitectura específica. Dicha estrategia se utilizó en el sistema p UCSD.
Un sistema operativo puede soportar múltiples formatos binarios. Windows es bastante compatible con versiones anteriores y aún admite formatos de la era de DOS. En Linux, Wine permite cargar los formatos de Windows.
Las API de un sistema operativo se pueden volver a implementar para otro sistema operativo host. En Windows, Cygwin y el subsistema POSIX se pueden usar para obtener un entorno (en su mayoría) compatible con POSIX. En Linux, Wine vuelve a implementar muchas de las API de Windows.
Las bibliotecas multiplataforma permiten que un programa sea independiente de las API del sistema operativo. Muchos lenguajes de programación tienen bibliotecas estándar que intentan lograr esto, por ejemplo, Java y C.
Un emulador simula un sistema diferente al analizar el formato binario extraño, interpretar las instrucciones y ofrecer una reimplementación de todas las API requeridas. Los emuladores se usan comúnmente para ejecutar juegos antiguos de Nitendo en una PC moderna.
fuente
El 99% de las PC actuales que ejecutan Windows tienen un procesador de 64 bits, que también es capaz de ejecutar software de 32 bits. El otro uno por ciento tiene procesadores de 32 bits. Por lo tanto, el software creado para procesadores de 32 bits se ejecuta en todas partes. El software creado para procesadores de 64 bits se ejecuta en cada PC que le interesa al creador del software.
MacOS X e iOS admiten "binarios gordos": lo que descarga realmente puede contener versiones para diferentes procesadores. Ya nadie crea aplicaciones para procesadores PowerPC, pero en algún momento hace unos años un ejecutable podía contener una versión PowerPC, una Intel de 32 bits y una Intel de 64 bits, y se ejecutaría la correcta. En iOS hoy en día, cuando descargas una aplicación, obtendrás una versión adecuada para el procesador en tu dispositivo. Descargue en un dispositivo diferente y obtendrá una versión diferente. Totalmente invisible para el usuario.
fuente
Un exe contiene más información que solo el código de máquina sin procesar. El sistema operativo lee esto al cargarlo y puede descubrir cómo debe ejecutarse.
Cuando compila, generalmente establece una CPU de destino, si no lo hace, el compilador elegirá su CPU actual y se limitará a elegir solo las instrucciones que son comunes a su CPU y versiones anteriores de la misma. Si desea utilizar una nueva y elegante instrucción que sea específica para cierta revisión de su CPU de destino, puede decirle al compilador o codificarla manualmente con código intrínseco o de ensamblaje en línea. Sin embargo, su programa se bloqueará si se ejecuta en una CPU que no admite esa instrucción.
fuente