Почему исполняемая программа для конкретного процессора не работает в Linux и Windows? - PullRequest
13 голосов
/ 13 января 2010

Исполняемая проблема, такая как exe, не работает в Linux (без Wine). При компиляции исходного кода компилятор создает объектный код, который специфичен для конкретной архитектуры процессора. Но то же приложение не работает на другой ОС с тем же процессором. Я знаю, что код может включать инструкции для конкретной ОС, которые будут препятствовать запуску исполняемого файла. Но как насчет простой программы 2 + 2? Запутанная часть - то, что, черт возьми, этот машинный код мешает работать. Машинный код, специфичный для процессора, верно? Если мы удалим формат исполняемого файла, сможем ли мы увидеть один и тот же машинный код (например, 2 + 2) для обеих операционных систем?

Еще один вопрос: как насчет языка ассемблера? Windows и Linux используют разные языки ассемблера для одного и того же процессора?.

Ответы [ 6 ]

17 голосов
/ 13 января 2010

Есть много отличий. Среди них:

  1. Исполняемый формат : каждая ОС требует, чтобы двоичные файлы соответствовали определенному двоичному формату. Для Windows это формат Portable Executable (PE). Для Linux это ELF большую часть времени (он поддерживает и другие типы).

  2. Двоичный интерфейс приложения : Каждая ОС определяет набор основных функций системы и способ, которым программа их вызывает. Это принципиально отличается между Linux и Windows. Хотя инструкции, которые вычисляют 2 + 2, идентичны в Linux и Windows в архитектуре x86, способ запуска приложения, способ его вывода на печать и способ его выхода различаются в разных операционных системах.

Да, и программы для Linux и Windows на архитектуре x86 используют набор инструкций, поддерживаемый процессором, который определяется Intel.

13 голосов
/ 13 января 2010

Это связано с разницей того, как программа загружается в память и предоставляется ресурсы для запуска. Даже самые простые программы должны иметь пространство кода, пространство данных и способность получать память времени выполнения и выполнять ввод / вывод. Инфраструктура для выполнения этих низкоуровневых задач совершенно различна для разных платформ, если только у вас нет какого-либо уровня адаптации, такого как WINE или Cygwin.

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

4 голосов
/ 13 января 2010

Проблема 1 - формат изображения. Когда приложение запускается в исполнение, ОС должна загрузить образ приложения, выяснить его точку входа и запустить его оттуда. Это означает, что ОС должна понимать формат изображения, и между различными ОС существуют разные форматы.

Проблема 2 - доступ к устройствам. После запуска приложение может читать и записывать реестры в CPU, и это все. Чтобы сделать что-нибудь интересное, например, отобразить символ на консоли, ему нужен доступ к устройствам, а это значит, что он должен запросить такой доступ у ОС. У каждой ОС есть свой API, который предлагается для доступа к таким устройствам.

Проблема 3 - инструкции привилегий. Вновь запущенному процессу, возможно, понадобится место в памяти для хранения чего-либо, и не все можно сделать с помощью реестров. Это означает, что он должен выделить оперативную память и настроить перевод с виртуального адреса на физический. Это операции привилегий, которые может выполнять только ОС, и опять-таки, API для доступа к этим службам различается в разных ОС.

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

2 голосов
/ 15 января 2010

Вот некоторые из причин, которые я могу придумать из головы:

  1. Различные форматы контейнеров (которые до сих пор, по-видимому, являются основным отличием в этом ответе - однако это не единственная причина).
  2. различная семантика динамического компоновщика .
  3. отличается ABI .
  4. различные механизмы обработки исключений - Windows имеет SEH - на котором построена обработка исключений C ++
  5. разная семантика системных вызовов и разные системные вызовы - следовательно, разные низкоуровневые библиотеки.
2 голосов
/ 13 января 2010

Да, но код всегда обращается к функциям библиотеки, чтобы делать что угодно - например, выводить «4» на терминал. И эти библиотеки зависят от платформы и отличаются в Linux и Windows. Вот почему он не переносимый - на самом деле это не проблема уровня команд.

1 голос

На второй вопрос: Windows работает только на x86, x64 и IA64 (не уверен насчет мобильных версий). Для Linux см. здесь .

...