Почему исполняемые файлы зависят от ОС, а не от процессора?

16

Если я напишу программу на C и скомпилирую ее в .exeфайл, .exeфайл будет содержать необработанные машинные инструкции для CPU. (Я думаю).

Если да, то как я могу запустить скомпилированный файл на любом компьютере с современной версией Windows? Каждое семейство процессоров имеет свой набор команд. Так почему же любой компьютер, на котором установлена ​​соответствующая ОС, может понимать инструкции в моем .exeфайле, независимо от его физического процессора?

Кроме того, часто на веб-сайтах на странице «загрузки» какого-либо приложения имеется загрузка для Windows, для Linux и для Mac (часто две загрузки для каждой ОС, для 86 и 64-разрядных компьютеров). Почему не так много загрузок для каждого семейства процессоров?

Авив Кон
источник
4
Стандартные процессоры, такие как x86, 64b и т. Д., Исполняемые файлы зависят от процессора. Вы не можете запустить свой exe, который вы упомянули, на каком-то специальном процессоре, таком как RISC, также есть множество процессоров специального назначения
InformedA
ОС состоят из исполняемых файлов, и они зависят от процессора, а не от ОС, потому что они являются ОС.
Тулаинс Кордова
Из-за обратной совместимости.
MiKL
2
часто две загрузки для каждой ОС, для 86 и 64-битных компьютеров : я интерпретирую это как зависимость исполняемых файлов от процессоров.
Mouviciel

Ответы:

37

Исполняемые файлы зависят как от ОС, так и от процессора:

  • Набор инструкций: двоичные инструкции в исполняемом файле декодируются процессором в соответствии с некоторым набором инструкций. Большинство потребительских процессоров поддерживают наборы команд x86 («32 бита») и / или AMD64 («64 бита»). Программа может быть скомпилирована для любого из этих наборов команд, но не для обоих. Есть расширения для этих наборов команд; их поддержка может быть запрошена во время выполнения. Такие расширения предлагают поддержку SIMD, например. Оптимизирующие компиляторы могут попытаться воспользоваться этими расширениями, если они есть, но обычно также предлагают путь к коду, который работает без каких-либо расширений.

  • Двоичный формат: исполняемый файл должен соответствовать определенному двоичному формату, который позволяет операционной системе правильно загружать, инициализировать и запускать программу. Windows в основном использует формат Portable Executable, в то время как Linux использует ELF.

  • Системные API: Программа может использовать библиотеки, которые должны присутствовать в исполняющей системе. Если программа использует функции из Windows API, она не может быть запущена в Linux. В мире Unix API центральной операционной системы были стандартизированы для POSIX: программа, использующая только функции POSIX, сможет работать в любой совместимой системе Unix, такой как Mac OS X и Solaris.

Таким образом, если две системы предлагают одни и те же системные API-интерфейсы и библиотеки, работают с одним и тем же набором команд и используют один и тот же двоичный формат, то программа, скомпилированная для одной системы, также будет работать на другой.

Однако есть способы добиться большей совместимости:

  • Системы, работающие на наборе инструкций AMD64, также обычно запускают исполняемые файлы x86. Двоичный формат указывает, какой режим запустить. Обработка 32-битных и 64-битных программ требует дополнительных усилий со стороны операционной системы.

  • Некоторые двоичные форматы позволяют файлу содержать несколько версий программы, скомпилированных для разных наборов команд. Такие «толстые двоичные файлы» были поощрены Apple, когда они переходили с архитектуры PowerPC на x86.

  • Некоторые программы компилируются не в машинный код, а в какое-то промежуточное представление. Это тогда преобразовано на лету к фактическим инструкциям, или могло бы быть интерпретировано. Это делает программу независимой от конкретной архитектуры. Такая стратегия использовалась в р-системе UCSD.

  • Одна операционная система может поддерживать несколько двоичных форматов. Windows вполне обратно совместима и по-прежнему поддерживает форматы эпохи DOS. В Linux Wine позволяет загружать форматы Windows.

  • API одной операционной системы могут быть переопределены для другой операционной системы. В Windows Cygwin и подсистема POSIX могут использоваться для получения (в основном) POSIX-совместимой среды. В Linux Wine переопределяет многие из API Windows.

  • Кроссплатформенные библиотеки позволяют программе быть независимой от API ОС. Многие языки программирования имеют стандартные библиотеки, которые пытаются достичь этого, например, Java и C.

  • Эмулятор имитирует другую систему путем анализа иностранных двоичный формат, интерпретации инструкции, и предлагает перевыполнение всех необходимых API. Эмуляторы обычно используются для запуска старых игр Nitendo на современном ПК.

Амон
источник
10
Следует отметить, что и java, и .net являются примерами использования промежуточного формата - промежуточные форматы сегодня очень популярны, а не просто реликт системы 1970-х годов, в которой использовалось 5 1/4 дискет.
Jmoreno
@AKoscianski спасибо за предложенное редактирование . Тем не менее, я думаю, что дизайн безопасности - это не причина, по которой исполняемые файлы зависят от ОС, а причина, по которой мы в первую очередь разделяем ОС и пользовательское пространство. Различные API для такой защищенной функциональности операционной системы уже были рассмотрены в разделе «Системные API» этого ответа.
Амон
2

99% современных компьютеров под управлением Windows имеют 64-битный процессор, который также способен работать с 32-битным программным обеспечением. Другой процент имеет 32-битные процессоры. Таким образом, программное обеспечение, созданное для 32-битных процессоров, работает везде. Программное обеспечение, созданное для 64-разрядных процессоров, работает на каждом ПК, о котором заботится создатель программного обеспечения.

MacOS X и iOS поддерживают «толстые двоичные файлы» - то, что вы загружаете, может содержать версии для разных процессоров. Никто больше не создает приложения для процессоров PowerPC, но в какой-то момент несколько лет назад исполняемый файл мог содержать PowerPC, 32-разрядную версию Intel и 64-разрядную версию Intel, и правильная версия была бы выполнена. В настоящее время на iOS, когда вы загружаете приложение, вы получаете версию, подходящую для процессора на вашем устройстве. Скачайте на другое устройство, и вы получите другую версию. Абсолютно невидим для пользователя.

gnasher729
источник
-1

Exe содержит больше информации, чем просто необработанный машинный код. ОС читает это при загрузке и может выяснить, как она должна работать.

Когда вы компилируете, вы обычно устанавливаете целевой процессор, если вы этого не сделаете, компилятор выберет ваш текущий процессор и ограничится выбором инструкций, которые являются общими для вашего процессора и более старых версий. Если вы хотите использовать необычную новую инструкцию, специфичную для определенной версии вашего целевого процессора, вы можете либо сообщить компилятору, либо вручную кодировать его с помощью встроенного или встроенного кода сборки. Однако ваша программа будет аварийно завершена, если она будет запущена на процессоре, который не поддерживает эту инструкцию.

Джеймс
источник