Как я могу создать исполняемый файл для запуска на определенной архитектуре процессора (вместо определенной ОС)? - PullRequest
6 голосов
/ 28 августа 2009

Итак, я беру свою программу на C ++ в Visual Studio, компилирую, и она выдает хороший маленький EXE-файл. Но EXE будут работать только на Windows, и я много слышал о том, как C / C ++ компилируется в язык ассемблера, который работает непосредственно на процессоре. EXE запускается с помощью Windows, или я мог бы иметь программу, которая делает исполняемый файл, который работает на Mac. Но разве я не компилирую код C ++ в язык ассемблера, который зависит от процессора?

Мои идеи:

  1. Наверное, нет. Я знаю, что есть компилятор Intel C ++, поэтому он будет делать сборочный код для конкретного процессора? EXE работают на Windows, поэтому они имеют преимущество от множества уже установленных вещей, от графических пакетов до массивной среды .NET. Исполняемый файл, специфичный для процессора, буквально начинался бы с нуля, только с набором команд процессора.

  2. Будет ли этот исполняемый файл иметь тип файла? Мы могли бы запускать окна и открывать их, но тогда будет ли управление переключением только на процессор? Я предполагаю, что этот исполняемый файл будет чем-то похожим на операционную систему в том смысле, что он должен быть запущен до того, как что-либо еще будет загружено, и только для инструкции процессора установлено «использование».

Ответы [ 10 ]

17 голосов
/ 28 августа 2009

Давайте подумаем о том, что значит «бежать» ...

Что-то должно загрузить двоичные коды в память. Это особенность ОС. .EXE или двоичный исполняемый файл или пакет или что-то еще, отформатировано очень специфичным для ОС способом, чтобы ОС могла загрузить его в память.

Что-то должно передать управление этим двоичным кодам. Опять же, есть ОС.

Подпрограммы ввода / вывода (в C ++, но в большинстве случаев это так) - это просто библиотека, которая инкапсулирует OS API. Дратите эту ОС, она везде.

Воспоминание .

В старые времена (да, я такой старый) я работал на машинах без ОС. У нас также не было C.

Мы написали машинные коды, используя такие инструменты, как «ассемблеры» и «линкеры», для создания больших двоичных изображений, которые мы могли бы загрузить в машину. Нам пришлось загружать эти двоичные изображения через болезненный процесс начальной загрузки.

Мы использовали бы клавиши на передней панели для загрузки достаточного количества кода в память для чтения удобного устройства, такого как перфорированный считыватель бумажных лент. Это приведет к загрузке небольшого фрагмента довольно стандартного программного обеспечения загрузчика с загрузкой. (Мы использовали майларовую ленту, чтобы она не изнашивалась.)

Затем, когда у нас был этот загрузчик ссылок в памяти, мы могли передать ленту, которую мы подготовили ранее, ассемблером.

Мы написали наши собственные драйверы устройств. Или мы использовали библиотечные процедуры в исходном виде, перфорированные на бумажных лентах.

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

Позже у нас были простые ОС с простыми API, простые драйверы устройств и несколько утилит, таких как «файловая система», «редактор» и «компилятор». Это было для языка под названием Jovial, но мы также иногда использовали Fortran.

Нам пришлось припаять платы последовательного интерфейса, чтобы мы могли подключить устройство. Пришлось писать драйверы устройств.

Итог .

Вы можете легко писать программы на C ++, для которых не требуется ОС.

  1. Узнайте об аппаратных средствах BIOS (или аналогичных BIOS), которые являются частью набора микросхем вашего процессора. Большинство современного оборудования имеет простую ОС, подключенную к ПЗУ, которая выполняет самотестирование при включении питания (POST), загружает несколько простых драйверов и находит блоки загрузки.

  2. Узнайте, как написать свой собственный загрузочный блок. Это первая правильная программа, загружаемая после POST. Это не так уж сложно. Вы можете использовать различные инструменты для создания разделов, чтобы перенести программу блокировки загрузки на диск, и вы получите полный контроль над оборудованием. Нет ОС.

  3. Узнайте, как GRUB, LILO или BootCamp запускают ОС. Это не сложно. Как только они загрузятся, они смогут загрузить вашу программу, и вы запустите ее. Это немного проще, потому что вы создаете раздел, который хочет загрузить загрузчик. Основывайтесь на ядре Linux, и вы будете счастливее. Не пытайтесь понять, как загружается Windows - это слишком сложно.

  4. Читайте на ELF. http://en.wikipedia.org/wiki/Executable_and_Linkable_Format

  5. Узнайте, как пишутся драйверы устройств. Если вы не используете ОС, вам нужно написать драйверы устройств.

6 голосов
/ 28 августа 2009

Проблема в том, что ОС действительно много делает для запуска ваших программ. Сам файл EXE содержит заголовочную информацию, которую Windows распознает, идентифицируя себя как файл EXE. Ваше приложение делает все, от доступа к файловой системе до распределения памяти, через ОС.

Но да, вы МОЖЕТЕ запускать приложения, скомпилированные для Windows / intel, на других платформах без эмуляции. Если вы хотите запустить свой EXE на Mac или UNIX, вам нужно установить немного больше программного обеспечения, чтобы выполнить работу, которую Windows сделает для запуска вашей программы - взгляните на проект Wine.

5 голосов
/ 28 августа 2009

То, о чем вы говорите, это то, что известно во встроенном мире как «голое железо». Они очень распространены в таких вещах, как ARM Cortex-M3, который входит, скажем, в блок валидатора дебетовых карт или в интерактивную игрушку, и не имеет достаточного количества памяти или возможностей для запуска полноценной операционной системы. Таким образом, вместо того, чтобы получить компилятор "ARM / Linux", который скомпилирует приложение для запуска в Linux на процессоре ARM, вы получите компилятор "ARM bare-metal", который компилирует вещи для запуска на процессоре ARM без операционной системы. (Я использую ARM, а не x86 в качестве примера, потому что x86-приложения на голом металле действительно довольно редки в наши дни.)

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

Во-первых, он должен инициализировать систему памяти, векторы прерываний и различные другие биты goo платы. Обычно это то, что компилятор с голым металлом сделает для вас, хотя если у вас странная плата, вам, возможно, придется рассказать ей, как это сделать. Это приводит к тому, что плата включается в точку запуска функции main ().

Затем вам нужно взаимодействовать с внешними процессорами и оперативной памятью. Операционная система включает в себя все виды функций для этого - дисковый ввод / вывод, вывод на экран, ввод с клавиатуры и мыши, работа в сети и т. Д. И т. Д. И т. Д. Без операционной системы вы должны получить это откуда-то еще. Вы можете получить это из библиотек вашего производителя оборудования; например, доска, на которой я недавно играл, имеет светодиодный экран размером 40x200 пикселей, и он поставляется с библиотекой с кодом, чтобы включить его и установить для него значения отдельных пикселей. И есть несколько компаний, продающих библиотеки для реализации стека TCP / IP и тому подобных вещей, для работы в сети или чего-то еще.

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

О, и мы упоминали, что сначала вы должны выяснить, как загрузить программу в процессор? Типичный компьютер имеет немного программируемого ПЗУ, с которого он будет загружать инструкции при запуске. На x86 это BIOS, и он обычно уже содержит удобную программу, которая запускает ЦП, настраивает дисплей, ищет диски и загружает программу с диска, который он находит. Во встроенной системе это, как правило, куда идет ваша программа - а это значит, что вам нужен какой-то способ поместить вашу программу туда. Часто это означает, что у вас есть устройство, называемое «отладчик», которое физически подключено к вашей встроенной плате, которая загружает программу, а также может выполнять действия, позволяющие приостановить работу процессора и определить его состояние, чтобы вы могли выполнить шаг через вашу программу так же, как если бы вы запускали ее в программном отладчике на вашем компьютере. Но я отвлекся.

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

Вы заметите, что, когда у вас есть много этих библиотек, они делают большую часть того, что делает операционная система, и есть своего рода пространство между кучей библиотек и реальной операционной системой. , В этом пространстве идет то, что называется ОСРВ - «операционная система реального времени». Меньшие из них на самом деле являются просто коллекциями библиотек, которые работают вместе для выполнения всех функций операционной системы, а иногда также включают в себя такие вещи, что вы можете запускать несколько потоков одновременно (и тогда вы можете иметь разные потоки, действующие как разные программы) - хотя все это все скомпилировано в одну и ту же скомпилированную «программу», а RTOS на самом деле является не чем иным, как библиотекой, которую вы включили. Более крупные из них начинают хранить части кода в разных местах, и я думаю, что некоторые из них могут даже загружать части кода с дисков - как это делают Windows и Linux при запуске программы. Это своего рода континуум, а не / или.

Система FreeRTOS - это ОСРВ с открытым исходным кодом, расположенная ближе к концу пространства ОСРВ; они могут быть хорошим местом, чтобы взглянуть на это, если вам больше интересно. У них есть несколько примеров приложений x86, которые дадут вам представление о том, какие системы x86 будут запускать программы на основе «голого железа» или RTOS и как вы скомпилируете что-то для запуска на одном; ссылка здесь: http://www.freertos.org/a00090.html#186.

3 голосов
/ 28 августа 2009

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

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

1 голос
/ 28 августа 2009

Любой данный компилятор / набор инструментов создает код для конкретной комбинации процессора / ОС. Итак, ваш пример компиляции Visual Studio создает код для x86 / Windows. Этот .EXE будет работать только на x86 / Windows, а не на (например) ARM / Windows (как используется некоторыми мобильными телефонами).

Для создания кода для комбинации процессор / ОС, отличной от той, на которой работает компилятор, требуется то, что обычно называется кросс-компилятором. Если у вас есть полная профессиональная подписка на Visual Studio, вы можете получить кросс-компилятор ARM, который позволит вам создавать файлы ARM / Windows .EXE, которые не будут работать на вашем настольном компьютере, но будут работать на мобильном телефоне на базе ARM / Windows или наладонник.

1 голос
/ 28 августа 2009

Конечно, они существуют. Они называются кросс-компиляторы . Например, вот как я могу программировать для платформы iPhone, используя Xcode.

Связанный тип компилятора - это тот, который компилируется для виртуальной платформы. Так работает Java .

0 голосов
/ 27 декабря 2010

Не забывайте и о библиотеках Windows. Посмотрите на QT и GTK +

0 голосов
/ 28 августа 2009

Основная проблема - формат файла. PE очень отличается от ELF (используется в Unix-подобных системах). Действительная программа PE не может быть действительной ELF. Таким образом, вы либо загружаете бинарный файл динамически с разных стартеров, либо вам приходится сдаваться.

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

0 голосов
/ 28 августа 2009

Абсолютно! Вот что такое встроенное программирование. Как многие, наверное, уже говорили, операционная система делает для вас совсем немного. И даже во встроенном мире без операционной системы ряд инструментов разработки предоставит код запуска, чтобы процессор работал достаточно для перехода к вашей программе. Некоторые / многие предоставляют полноценные библиотеки C / C ++, так что вы можете вызывать такие функции, как memcpy (), а иногда даже malloc () и printf ().

Вы можете предоставить каждую строку кода и каждую инструкцию и не использовать пакет инструментов разработки, но по-прежнему использовать компилятор, например, gcc. Некоторые из двоичных форматов являются общими для тех, которые работают в операционных системах, таких как, например, elf. Вы можете выполнять elf-файлы в Linux, но ваша встроенная программа может привести к созданию двоичного файла elf. Процессор не может выполнить elf в этом формате, но независимо от того, какие программы загрузочный выпуск или оперативная память в некоторых случаях извлекают двоичную программу из файла elf, в отличие от операционной системы, извлекающей программу для запуска из файла elf. EXE не является одним из тех форматов файлов. Ваш любимый компилятор Windows-приложений, вероятно, также не является встроенным компилятором, хотя иногда вы можете использовать его для выполнения языковых задач высокого уровня, а затем использовать альтернативный ассемблер и компоновщик. Больше работы, чем обычно стоит. Например, вы пишете функцию на C (которая НЕ выполняет никаких библиотечных или системных вызовов), компилируете ее в объект. Напишите свой собственный или найдите утилиту для извлечения скомпилированного двоичного файла из этого объекта, преобразования его в другой формат объекта или в ассемблер (дизассемблирование). Добавьте свой код запуска и другие сборки к нему. Соберите и свяжите все вместе как встроенную программу. Я сделал это однажды со встроенным Visual C в Microsoft, просто чтобы посмотреть, как он соотносится с другими компиляторами, это не было ужасно, но, конечно, не стоило усилий взломать, чтобы получить на выходе.

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

0 голосов
/ 28 августа 2009

Да, вы можете создать исполняемый файл, работающий на «голом железе» процессора. Очевидно, именно так работают ядра операционной системы. Главное, что вам нужно сделать, это создать исполняемый файл, который не использует никаких библиотек. Однако в ограничение «нет библиотек» входит стандартная библиотека C! Это означает, что нет malloc, нет printf и т. Д. Вы должны быть в основном своей собственной ОС и управлять памятью и вводом / выводом самостоятельно. Это неизбежно потребует немалой работы непосредственно на этапе сборки.

Вы также теряете несколько других предметов роскоши, таких как main (), которые не могут быть отправной точкой вашей программы, поскольку main () - это то, что вызывается ОС и средой выполнения C.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...