2009-08-28 2 views
6

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

Мои Insights:

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

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

+3

Компилятор Intel - это не то, что вы думаете - это просто другой компилятор Windows (или Linux, они делают оба), который, по-видимому, написан Intel. Это делает EXE или стандартные Linux-файлы. –

ответ

16

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

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

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

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

Reming.

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

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

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

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

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

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

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

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

Практический результат.

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

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

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

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

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

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

+0

добавление к «Вы можете легко писать программы на C++, для которых не требуется ОС». Вы можете наиболее легко сделать это с помощью микроконтроллеров, большинство (возможно, все) из них имеют C++ или, по крайней мере, компиляторы C сегодня. – vsz

6

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

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

1

Несомненно, они существуют. Их называют cross compilers. Например, я могу программировать платформу iPhone с помощью Xcode.

Связанный тип компилятора - это тот, который компилируется для виртуальной платформы. That's how Java works.

+0

Я не думаю, что это было задано. Вопрос в том, что делает исполняемый OS-специфический. – sleske

0

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

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

+4

Похоже, вы вводите в заблуждение «библиотеку» с «динамически загруженной библиотекой». Каждый компилятор без компромиссов (или, по крайней мере, почти каждый) включает статически связуемую копию стандартной библиотеки C, которая связана во время компиляции, поэтому соответствующие функции становятся частью исполняемого файла, и он отлично работает. Многие поставщики оборудования включают в себя дополнительные библиотеки для взаимодействия со своим конкретным оборудованием, и вы даже можете купить библиотеки TCP/IP и т. Д. Многие поставщики оборудования и компиляторов также поставляют необходимый базовый код загрузки для платы, чтобы перейти от «включен» к «invokes main()». –

+0

Важным моментом является то, что это заменяет операционную систему. Большинство ОС не позволяют прямого доступа к некоторым аппаратным средствам, необходимым для запуска. Таким образом, вы можете написать программу, которая заменяет Windows или Linux, но не такую, которая может быть запущена в пределах существующей ОС. (Если вы не пишете для одной ОС и не подражаете другим). – KeithB

1

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

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

3

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

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

5

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

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

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

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

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

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

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

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

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

0

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

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

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

0

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

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

0

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

+1

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