¿Por qué los ejecutables dependen del sistema operativo pero no de la CPU?

12

Si escribo un programa en C y lo compilo en un archivo .exe , el archivo .exe contiene instrucciones en bruto de la máquina para la CPU. (Creo).

Si es así, ¿cómo puedo ejecutar 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, ¿por qué cualquier computadora que ejecute el sistema operativo apropiado pueda entender las instrucciones en mi archivo .exe , independientemente de su CPU física?

También, a menudo en los sitios web en la página de "descarga" de alguna aplicación, tiene una descarga para Windows, para Linux y para Mac (a menudo dos descargas para cada SO, para computadoras de 86 y 64 bits). ¿Por qué no hay muchas más descargas para cada familia de CPU?

    
pregunta Aviv Cohn 26.07.2014 - 12:32

3 respuestas

30

Los ejecutables dependen tanto del sistema operativo como de la CPU:

  • Conjunto de instrucciones: la CPU decodifica las instrucciones binarias en el ejecutable de acuerdo con algún conjunto de instrucciones. La mayoría de las CPU de los consumidores 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 para estos conjuntos de instrucciones; El soporte para estos puede ser consultado en tiempo de ejecución. Tales extensiones ofrecen soporte SIMD, por ejemplo. La optimización de los compiladores podría 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 cumplir con un cierto formato binario, lo que permite que el sistema operativo cargue, inicialice e inicie correctamente el programa. Windows utiliza principalmente el formato Portable Executable, mientras que Linux usa ELF.

  • API del sistema: el programa puede usar 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 a POSIX: un programa que use solo las funciones de 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 una mayor compatibilidad:

  • Los sistemas que se ejecutan en el conjunto de instrucciones AMD64 también ejecutarán ejecutables x86. El formato binario indica qué modo ejecutar. El manejo de los programas de 32 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, compilado para diferentes conjuntos de instrucciones. Apple alentó a estos "binarios gordos" mientras hacían la transición de la arquitectura PowerPC a x86.

  • Algunos programas no se compilan a código de máquina, sino a alguna representación intermedia. Esto luego se traduce sobre la marcha a 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 de UCSD.

  • Un sistema operativo puede admitir múltiples formatos binarios. Windows es bastante compatible con versiones anteriores y todavía admite formatos de la era DOS. En Linux, Wine permite que se carguen 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 compatible con POSIX (en su mayoría). En Linux, Wine reimplementa 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 analizando el formato binario externo, interpretando las instrucciones y ofreciendo una reimplementación de todas las API necesarias. Los emuladores se usan comúnmente para ejecutar juegos antiguos de Nitendo en una PC moderna.

respondido por el amon 26.07.2014 - 13:32
2

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. Así que el software construido para procesadores de 32 bits se ejecuta en todas partes. El software creado para procesadores de 64 bits se ejecuta en todas las PC que le interesan al creador del software.

MacOS X y iOS admiten "binarios gruesos": lo que se descarga puede contener versiones para diferentes procesadores. Ya nadie crea aplicaciones para los procesadores PowerPC, pero en algún momento hace unos años, un ejecutable podría contener un PowerPC, un Intel de 32 bits y una versión de 64 bits de Intel, y se ejecutaría el correcto. En la actualidad, en iOS, cuando descargue una aplicación, obtendrá una versión adecuada para el procesador en su dispositivo. Descargue en un dispositivo diferente y obtendrá una versión diferente. Totalmente invisible para el usuario.

    
respondido por el gnasher729 09.01.2017 - 20:53
-1

Un archivo ejecutable contiene más información que un simple código de máquina en bruto. El sistema operativo lee esto cuando lo carga y puede averiguar cómo debe ejecutarse.

Cuando compilas, generalmente configuras una CPU de destino, si no lo haces, el compilador elegirá tu CPU actual y se limitará a elegir únicamente las instrucciones que sean comunes a tu CPU y las versiones anteriores. Si desea utilizar una nueva instrucción elegante específica para cierta revisión de su CPU objetivo, puede decirle al compilador o codificarla manualmente con código de ensamblaje intrínseco o en línea. Sin embargo, su programa se bloqueará si se ejecuta en una CPU que no admite esa instrucción.

    
respondido por el James 26.07.2014 - 13:27

Lea otras preguntas en las etiquetas