Как код сборки кода кода C (например, оптимизированный strlen)?
Я всегда читаю о том, как определенные функции на языке программирования C оптимизируются, записываясь в сборку. Позвольте мне извиниться, если это предложение звучит немного ошибочно.
Итак, я четко сформулирую: как это происходит, когда вы вызываете некоторые функции, такие как strlen в системах UNIX/C, фактическая функция, которую вы вызываете, записывается в сборку? Можете ли вы написать сборку прямо в C-программы, или это внешняя ситуация вызова? Является ли это частью стандарта C, чтобы это можно было сделать, или это конкретная операционная система?
Ответы
Ответ 1
Стандарт C определяет, что должна выполнять каждая библиотечная функция, а не как она реализована.
Почти все известные реализации C компилируются в машинный язык. Разработчики компилятора/библиотеки C могут реализовать такие функции, как strlen
. Они могли бы реализовать его в C и скомпилировать его к объекту, или они могли бы записать его в сборке и собрать его для объекта. Или они могли бы реализовать это по-другому. Это не имеет значения, если вы получите правильный эффект и результат, когда вы вызываете strlen
.
Теперь, как это бывает, многие инструменты C позволяют писать встроенную сборку, но это абсолютно не является частью стандарта. Любые такие возможности должны быть включены в качестве расширений стандарта C.
Ответ 2
В конце дороги скомпилированные программы и программы в сборке - все машинные языки, поэтому они могут звонить друг другу. То, как это делается, заключается в том, что код сборки использует те же соглашения о вызовах (способ подготовки к вызову, подготовка параметров и т.д.), Как программа, написанная на C. Обзор общих вызовов вызовов для процессоров x86 можно найти здесь.
Ответ 3
Многие (большинство?) компиляторов C действительно поддерживают встроенную сборку, хотя она не входит в стандарт. Тем не менее, нет никакой строгой необходимости в компиляторе для поддержки любой такой вещи.
Во-первых, признайте, что сборка - это, в основном, только человеческий (полу-) читаемый машинный код, и что C заканчивается как машинный код в любом случае.
"Вызов" C-функции просто генерирует набор инструкций, которые готовят регистры, стек и/или какой-либо другой механизм, зависящий от машины, в соответствии с некоторым установленным соглашением о вызовах, а затем переходит к началу вызываемой функции.
Блок кода сборки может соответствовать соответствующему соглашению о вызове и, таким образом, генерировать блок-код машинного кода, который может вызвать другой код машинного кода, который был первоначально написан на C. Реверс, конечно, также возможен.
Детали соглашения о вызове, процесса сборки и процесса связывания (для связывания созданного с помощью сборки объектного файла с C-генерируемым объектным файлом) могут сильно различаться между платформами, компиляторами и компоновщиками. Хороший учебник по сборке для вашей платформы выбора, вероятно, будет охватывать такие детали.
Мне нравится x86-ориентированный Руководство по сборке ПК, в котором конкретно рассматриваются интерфейсные сборки и код C.
Ответ 4
Когда код C скомпилирован gcc, он сначала компилируется в инструкции ассемблера, которые затем снова скомпилируются в двоичный исполняемый файл. Вы можете увидеть сгенерированные инструкции ассемблера, указав -S
, как в gcc file.c -S
.
Ассемблерный код просто передает первый этап компиляции C-to-ассемблера и затем неотличим от кода, скомпилированного с C.
Ответ 5
Один из способов сделать это - использовать встроенный ассемблер. Это означает, что вы можете написать код ассемблера непосредственно в свой код C. Специфический синтаксис специфичен для компилятора. Например, см. синтаксис GCC и синтаксис MS Visual С++.
Ответ 6
Вы можете написать встроенную сборку в свой код C. Синтаксис для этого является специфичным для компилятора, но ключевое слово asm
используется обычным образом. Посмотрите на встроенную сборку для получения дополнительной информации.