Подтвердить что ты не робот

Какова цель использования языка ассемблера в программе C?

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

4b9b3361

Ответ 1

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

По причинам ненужного, возможно, будет:

  • совместимость с платформой
  • выступление относительно
  • оптимизация кода
  • и т.д..

Я считаю выше лишним, потому что когда-нибудь они могут быть отброшены или реализованы с помощью чистого C. Например, совместимость с платформой, вы можете полностью реализовать определенную версию для каждой платформы, однако использование встроенных сборок может уменьшить усилия. Здесь мы не будем говорить слишком много о ненужных причинах.

По необходимым причинам они могут быть:

  • что-то со стандартными библиотеками было недостаточно для выполнения
  • некоторый набор команд не поддерживался компиляторами
  • неверно сформирован код объекта
  • запись стекового кода
  • и т.д..

Эти причины считаются необходимыми, поскольку они почти не выполняются с чистым языком C. Например, в старых DOS es прерывание программного обеспечения INT21 было не повторно. Если вы хотите полностью использовать Virtual Dirve полностью INT21, поддерживаемый компилятором, это было невозможно сделать. В этой ситуации вам нужно будет зацепить оригинальный INT21 и сделать его повторно действующим. Однако скомпилированный код завершает ваш вызов с помощью пролога/эпилога. Таким образом, вы никогда не сможете сломать что-то ограниченное, или вы просто разбили код. Вы можете попробовать любой трюк, используя чистый язык C с библиотеками; но даже вы можете успешно найти трюк, это означает, что вы нашли конкретный заказ, который компилятор генерирует машинный код; это подразумевает: вы пытались позволить компилятору компилировать ваш код точно для машинного кода. Итак, почему не просто писать встроенные сборки напрямую?

В этом примере объяснялось все вышеперечисленное по причинам, кроме instruction set not supported, но я думаю, что об этом было легко думать. На самом деле, есть больше причин писать встроенные сборки, но теперь у вас есть некоторые идеи о них и т.д.

Ответ 2

В дополнение к тому, что все говорили: не все функции ЦП подвержены C. Иногда, особенно в программировании драйверов и операционной системы, необходимо явно работать со специальными регистрами и/или командами, которые в противном случае недоступны.

Также векторные расширения.

Это было особенно верно до появления встроенных компиляторов. Это облегчает необходимость создания встроенной сборки.

Еще один пример использования встроенной сборки связан с взаимодействием C с отображенными языками. В частности, сборка необходима, если вам нужно вызвать функцию, когда ее прототип неизвестен во время компиляции. Другими словами, когда количество и типы данных аргументов функции являются только переменными времени выполнения. C и функции stdarg не помогут вам в этом случае - они помогут вам разобрать фрейм стека, но не построить его. С другой стороны, в сборке это вполне выполнимо.

Это не сценарий OS/driver. Есть как минимум две технологии - JNI и COM Automation - где это необходимо. В случае автоматизации я говорю о том, как среда выполнения COM выполняет марширование двух интерфейсов с использованием их библиотек типов.

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

Я занимаюсь только случаями, когда сборка необходима. Ручная оптимизация производительности приведена в других ответах.

РЕДАКТИРОВАТЬ: просто подумал о еще одном случае использования: сообщение об ошибке сбоя/времени выполнения. Для отладки postmortem вы хотите захватить как можно больше состояния программы в момент сбоя (то есть все регистры процессора), а сборка является гораздо лучшим средством для этого, чем C.

Ответ 3

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

В этих случаях многие компиляторы C допускают встроенную сборку.

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

Ответ 4

В целом, это производительность, но производительность очень определенного типа. Например, параллельные команды SIMD процессора могут не генерироваться компилятором. Используя специфические для процессора форматы данных, а затем выдавая параллельные инструкции, специфичные для процессора (например, ARM NEON или Intel SSE), может возникнуть очень высокая производительность при работе с графикой или обработкой сигналов. Даже тогда некоторые компиляторы позволяют их выражать в C, используя внутренние функции.

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

Ответ 5

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

Ответ 6

Как любопытство, я добавляю здесь конкретный пример того, что не так низкоуровнево, что вы можете делать только в сборке. Я прочитал это в сборнике из моего университетского времени, где он был использован, чтобы показать присущее ограничение C/С++ и как его преодолеть с помощью сборки.

Проблема в том, как вызвать функцию, когда точное количество параметров известно только во время выполнения? На самом деле, в C/С++ вы можете легко определить функцию, которая принимает переменное число аргументов типа printf. Но когда дело доходит до вызова этой функции, компилятор хочет точно знать, сколько параметров необходимо передать. Вы можете передать больше паремов, чем требуется, что не повредит. Но что, если число неожиданно растет до 100 или 1000 параметров и должно быть выбрано из массива? Разумеется, решение - это сборка, где вы можете динамически создавать фрейм стека нужного размера, копировать параметры в стеке, вызывать функцию и, наконец, reset стек.

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