¿Por qué un progtwig ejecutable para una CPU específica no funciona en Linux y Windows?

Un problema ejecutable como exe no funciona en Linux (sin vino). Al comstackr el comstackdor de código fuente produce un código de objeto que es específico para una architecture de CPU particular. Pero la misma aplicación no funciona con otro sistema operativo con la misma CPU. Sé que el código puede incluir instrucciones específicas para el sistema operativo que impidan que se ejecute el ejecutable. Pero ¿qué pasa con un progtwig simple 2 + 2? Parte confusa es qué demonios ese código de máquina impide trabajar. Código de máquina específico para la CPU ¿verdad? Si eliminamos el formato de archivo ejecutable, ¿podríamos ver el mismo código de máquina (como 2 + 2) para ambos sistemas operativos?

Una pregunta más: ¿qué pasa con el lenguaje ensamblador? ¿DO Windows y Linux usan un lenguaje ensamblador diferente para la misma CPU ?.

Hay muchas diferencias Entre ellos:

  1. Formato ejecutable : todo sistema operativo requiere que los binarios se ajusten a un formato binario específico. Para Windows, este es el formato Portable Executable (PE). Para Linux, es ELF la mayor parte del tiempo (también es compatible con otros tipos).

  2. Interfaz binaria de aplicación : cada sistema operativo define un conjunto de funciones principales del sistema y la forma en que un progtwig las llama. Esto es fundamentalmente diferente entre Linux y Windows. Si bien las instrucciones que computan 2 + 2 son idénticas en Linux y Windows en la architecture x86, la forma en que se inicia la aplicación, la forma en que imprime la salida y la forma en que sale difiere entre los sistemas operativos.

Sí, tanto los progtwigs de Linux como los de Windows en la architecture x86 usan el conjunto de instrucciones que admite la CPU que define Intel.

Se debe a la diferencia de cómo el progtwig se carga en la memoria y se le asignan recursos para ejecutar. Incluso los progtwigs más simples necesitan tener espacio de código, espacio de datos y la capacidad de adquirir memoria de tiempo de ejecución y hacer E / S. La infraestructura para realizar estas tareas de bajo nivel es completamente diferente entre las plataformas, a menos que tenga algún tipo de capa de adaptación, como WINE o Cygwin.

Asumiendo, sin embargo, que podría simplemente insertar instrucciones de CPU ensambladas arbitrariamente en el segmento de código de un proceso en ejecución y lograr que ese código se ejecute, entonces, sí, el mismo código se ejecutaría en cualquiera de las plataformas. Sin embargo, sería bastante restringido, y hacer cosas complejas como incluso saltos a módulos externos fallaría, debido a cómo estas cosas se hacen de manera diferente en diferentes plataformas.

El problema 1 es el formato de imagen. Cuando se inicia una aplicación en ejecución, el OS debe cargar la imagen del aplicativo, conocer su punto de entrada e iniciarlo desde allí. Eso significa que el sistema operativo debe comprender el formato de la imagen y que hay diferentes formatos entre varios sistemas operativos.

El problema 2 es el acceso a los dispositivos. Una vez lanzada, una aplicación puede leer y escribir registros en la CPU y eso es todo. Para hacer algo interesante, como mostrar un personaje en una consola, necesita acceso a los dispositivos y eso significa que tiene que solicitar dicho acceso desde el sistema operativo. Cada Os tiene una API diferente que se ofrece para acceder a dichos dispositivos.

El problema 3 es instrucciones privilegiadas. El proceso recién lanzado tal vez necesite una ubicación de memoria para almacenar algo, no puede lograr todo con regiestries. Esto significa que necesita asignar RAM y configurar la traducción de VA a la dirección física. Estas son operaciones privilegiadas que solo el sistema operativo puede hacer y, una vez más, la API para acceder a estos servicios varía según el sistema operativo.

La conclusión es que las aplicaciones no están escritas para una CPU, sino para un conjunto de servicios primitivos que ofrece el sistema operativo. la alternativa es escribir las aplicaciones en un conjunto de servicios primitivos que ofrece una Máquina Virtual, y esto lleva a aplicaciones que son más o menos portátiles, como las aplicaciones Java.

Sí, pero el código llama invariablemente a las funciones de la biblioteca para hacer casi cualquier cosa, como imprimir “4” en la terminal. Y estas bibliotecas son específicas de la plataforma y difieren entre Linux y Windows. Esta es la razón por la cual no es portátil, no es un problema de nivel de instrucción.

Estas son algunas de las razones por las que puedo pensar en la parte superior de mi cabeza:

  1. Diferentes formatos de contenedor (que hasta ahora parece ser el principal diferenciador en esta respuesta, sin embargo, no es la única razón).
  2. diferente semántica dinámica del enlazador .
  3. ABI diferente
  4. diferentes mecanismos de manejo de excepciones – Windows tiene SEH – sobre el cual se construye el manejo de excepciones C ++
  5. diferentes semánticas de llamadas al sistema y diferentes llamadas al sistema, por lo tanto, diferentes bibliotecas de bajo nivel.

A la segunda pregunta: Windows solo se ejecuta en x86, x64 e IA64 (no estoy seguro acerca de las versiones móviles). Para Linux, mira aquí .