Если я напишу программу на C и скомпилирую ее в .exe
файл, .exe
файл будет содержать необработанные машинные инструкции для CPU. (Я думаю).
Если да, то как я могу запустить скомпилированный файл на любом компьютере с современной версией Windows? Каждое семейство процессоров имеет свой набор команд. Так почему же любой компьютер, на котором установлена соответствующая ОС, может понимать инструкции в моем .exe
файле, независимо от его физического процессора?
Кроме того, часто на веб-сайтах на странице «загрузки» какого-либо приложения имеется загрузка для Windows, для Linux и для Mac (часто две загрузки для каждой ОС, для 86 и 64-разрядных компьютеров). Почему не так много загрузок для каждого семейства процессоров?
low-level
cpu
machine-code
Авив Кон
источник
источник
Ответы:
Исполняемые файлы зависят как от ОС, так и от процессора:
Набор инструкций: двоичные инструкции в исполняемом файле декодируются процессором в соответствии с некоторым набором инструкций. Большинство потребительских процессоров поддерживают наборы команд 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 на современном ПК.
источник
99% современных компьютеров под управлением Windows имеют 64-битный процессор, который также способен работать с 32-битным программным обеспечением. Другой процент имеет 32-битные процессоры. Таким образом, программное обеспечение, созданное для 32-битных процессоров, работает везде. Программное обеспечение, созданное для 64-разрядных процессоров, работает на каждом ПК, о котором заботится создатель программного обеспечения.
MacOS X и iOS поддерживают «толстые двоичные файлы» - то, что вы загружаете, может содержать версии для разных процессоров. Никто больше не создает приложения для процессоров PowerPC, но в какой-то момент несколько лет назад исполняемый файл мог содержать PowerPC, 32-разрядную версию Intel и 64-разрядную версию Intel, и правильная версия была бы выполнена. В настоящее время на iOS, когда вы загружаете приложение, вы получаете версию, подходящую для процессора на вашем устройстве. Скачайте на другое устройство, и вы получите другую версию. Абсолютно невидим для пользователя.
источник
Exe содержит больше информации, чем просто необработанный машинный код. ОС читает это при загрузке и может выяснить, как она должна работать.
Когда вы компилируете, вы обычно устанавливаете целевой процессор, если вы этого не сделаете, компилятор выберет ваш текущий процессор и ограничится выбором инструкций, которые являются общими для вашего процессора и более старых версий. Если вы хотите использовать необычную новую инструкцию, специфичную для определенной версии вашего целевого процессора, вы можете либо сообщить компилятору, либо вручную кодировать его с помощью встроенного или встроенного кода сборки. Однако ваша программа будет аварийно завершена, если она будет запущена на процессоре, который не поддерживает эту инструкцию.
источник