1

Меня всегда интересовало, как на самом деле работают исполняемые двоичные файлы. Компиляция всегда указывается как

взять исходный код и перевести его на машинный язык

Но что это на самом деле означает? А именно:

  1. Могу ли я переместить двоичный файл с компьютера A на компьютер B и ожидать, что он будет работать? (при условии, что я также перенесу соответствующие библиотеки)
  2. Каждый исполняемый двоичный файл предназначен для работы с конкретным процессором?
  3. Какая информация находится внутри исполняемого двоичного файла?
  4. Почему исполняемые файлы на Windows могут быть запущены на любой версии Windows? (Это другая история, если они работают)
  5. Почему я не могу запустить исполняемый файл Linux в Windows? Это имеет отношение к ядру (так не процессору)?

Имейте в виду, что у меня есть ограниченные знания о процессорах и компиляторах и ничего о сборке.

2 ответа2

1
  1. Не обязательно. Если это сборка для переносимости и платформы совместимы, то да (например, 64-разрядные версии Windows могут выполнять 32-разрядные и 64-разрядные исполняемые файлы Windows, но больше не 16-разрядные).
  2. Не обязательно. Они сделаны для определенного набора инструкций. Поскольку они обычно являются расширениями и имеют обратную совместимость, вы можете запускать старые файлы на более новых процессорах, но не обязательно наоборот. Например, программа, скомпилированная для Windows 95, вероятно, все еще будет работать на современном оборудовании, но вы не можете запустить программу, скомпилированную для сегодняшнего оборудования, на старой машине с Windows 95. Однако, если на двух машинах выполняются совершенно разные инструкции, исполняемые файлы не будут совместимы (например, Intel и ARM).
  3. Это зависит от платформы, есть несколько форматов с разными заголовками и прочим, но в основном всегда есть какой-то заголовок, работающий как индекс, указывающий операционной системе, где искать конкретные вещи (такие как главная точка входа).
  4. Они на самом деле не могут (см. № 2 выше).
  5. Прежде всего, Windows и Linux используют разные форматы для своих исполняемых файлов. Но даже тогда есть различия, например, для всей среды и предоставляемых платформ API/ библиотек. Например, исполняемый файл Linux обычно пытается общаться с оконным менеджером, таким как X11, в то время как программа Windows пытается вызвать Windows API. Однако есть способы заставить такие вещи работать. Старые версии Windows (NT?) На самом деле, у меня были расширения POSIX, поэтому вы могли запускать ограниченный набор программ для Linux, насколько мне известно, хотя я никогда не пробовал этого и не рассматривал их поближе. С другой стороны, для Linux существуют такие инструменты, как Wine, которые будут пытаться эмулировать среду Windows, предоставляя файлы API, преобразование путей и т.д. Это не полная эмуляция (как при использовании виртуальной машины).
1
  1. Только при очень контролируемых обстоятельствах: оба компьютера должны иметь совместимый процессор и операционную систему.

  2. Не конкретный процессор, а набор совместимых процессоров. Например, файл, скомпилированный для совместимости с x86, и никакие расширения не будут работать на каждом процессоре Intel или AMD x86 или x64, при условии, что ОС совместима.

  3. В первую очередь машинный код с этапа компиляции. В дополнение к этому, несколько других так называемых "разделов" будут иметь, например, ресурсы (когда-либо задумывались, почему исполняемый файл имеет выделенный значок в Windows, даже если он не запущен, а только показан в проводнике), описание бинарной совместимости и Больше.

  4. Это побочный эффект 1: всякий раз, когда ОС обеспечивает совместимость с исполняемым форматом, она может быть запущена. Современные версии Windows обеспечивают широкий диапазон совместимости: наиболее важными являются DOS, Win16, Win32, Win64, dotnet.

  5. ОС предоставляет исполняемому файлу среду, которая необходима для выполнения. Эти среды сильно отличаются между Linux и Windows. Это означает, что вы не можете напрямую запускать исполняемые файлы из одного в другой. Существуют проекты, направленные на преодоление этого разрыва: проект WINE нацелен на обеспечение запуска исполняемых файлов Windows в Linux (и других ОС), а проект Cygwin нацелен на обеспечение возможности запуска программного обеспечения Linux на Windows. Cygwin не стремится к бинарной совместимости, но позволяет перекомпилировать немодифицированный источник.

Важно понимать, что исполняемый файл (например, .exe) не является результатом процесса компиляции - он является результатом процесса компоновки , который объединяет выходные данные компиляции с другими компонентами, необходимыми для создания того, что я описал в 3.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .