Выполнение программы |
---|
Общие понятия |
Типы кода |
Стратегии компиляции |
Известные времена выполнения |
|
Известные компиляторы и цепочки инструментов |
|
При вычислении исполняемый код , исполняемый файл или исполняемая программа , иногда называемая просто исполняемым или двоичным файлом , заставляет компьютер «выполнять указанные задачи в соответствии с закодированными инструкциями » [1] , в отличие от файла данных, который должен интерпретироваться ( анализироваться ) программой, чтобы иметь смысл.
Точная интерпретация зависит от использования. «Инструкции» традиционно означают инструкции машинного кода для физического процессора . [2] В некоторых случаях файл, содержащий инструкции по созданию сценариев (например, байт -код ), также может считаться исполняемым.
Исполняемые файлы могут быть закодированы вручную на машинном языке, хотя гораздо удобнее разрабатывать программное обеспечение в виде исходного кода на языке высокого уровня , понятном людям. В некоторых случаях вместо этого исходный код может быть указан на языке ассемблера , который остается удобочитаемым для человека, но тесно связан с инструкциями машинного кода.
Язык высокого уровня компилируется либо в исполняемый файл машинного кода, либо в неисполняемый машинный код — какой-то объектный файл ; эквивалентный процесс исходного кода на ассемблере называется сборкой . Несколько объектных файлов связаны для создания исполняемого файла. Объектные файлы — исполняемые или нет — обычно хранятся в контейнерном формате , таком как Executable and Linkable Format (ELF) или Portable Executable (PE), который зависит от операционной системы . [3] Это дает структуру сгенерированному машинному коду, например, разделяя его на разделы, такие как .text(исполняемый код), .data (инициализированные глобальные и статические переменные) и .rodata (данные только для чтения, такие как константы и строки).
Исполняемые файлы обычно также включают в себя систему среды выполнения , которая реализует функции языка среды выполнения (такие как планирование задач , обработка исключений , вызов статических конструкторов и деструкторов и т. д.) и взаимодействие с операционной системой, в частности передачу аргументов, среды и возврат статуса выхода . , а также другие функции запуска и завершения работы, такие как освобождение ресурсов, таких как дескрипторы файлов . Для C это делается путем связывания объекта crt0 , который содержит фактическую точку входа и выполняет настройку и завершение работы, вызывая библиотеку времени выполнения . [4]
Таким образом, исполняемые файлы обычно содержат существенный дополнительный машинный код, помимо того, который непосредственно генерируется из конкретного исходного кода. В некоторых случаях это желательно опустить, например, для разработки встраиваемых систем или просто для понимания того, как работают компиляция, компоновка и загрузка. В C это можно сделать, опустив обычную среду выполнения и вместо этого явно указав сценарий компоновщика, который генерирует точку входа и обрабатывает запуск и завершение работы, например, вызывая main
start и возвращая статус выхода ядру в конце. [5]
Для выполнения системой (например, операционной системой, прошивкой или загрузчиком ) исполняемый файл должен соответствовать двоичному интерфейсу системного приложения (ABI). [6] В простых интерфейсах файл выполняется путем его загрузки в память, перехода к началу адресного пространства и выполнения оттуда. В более сложных интерфейсах исполняемые файлы имеют дополнительные метаданные, указывающие на отдельную точку входа . Например, в ELF точка входа указана в поле заголовка e_entry
, в котором указывается (виртуальный) адрес памяти, с которого начинается выполнение. В GCC ( GNU Compiler Collection ) это поле устанавливается компоновщиком на основе_start
символ.