Intel и x86 отлично справляются с обратной совместимостью, что, безусловно, помогло им, но в то же время очень больно. Внутренние устройства от 8088/8086 до 286–386, до 486, Pentium, Pentium Pro и т. Д. До настоящего времени являются чем-то вроде редизайна каждый раз. Вначале добавление механизмов защиты для операционных систем для защиты приложений друг от друга и от ядра, а затем - от повышения производительности путем добавления исполнительных модулей, суперскалярных и всего, что с ними поставляется, многоядерных процессоров и т. Д. То, что раньше было настоящим единым AX Регистрация в оригинальном процессоре превращается в то, кто знает, сколько разных вещей в современном процессоре. Первоначально ваша программа выполнялась в том порядке, в котором она написана, сегодня она нарезается кубиками, разрезается и выполняется параллельно таким образом, что намерения представленных инструкций выполняются, но выполнение может быть не в порядке и параллельно. Множество новых трюков скрыто за тем, что на поверхности кажется очень старым набором инструкций.
Набор команд изменился с 8/16-битных корней на 32-битные, на 64-битные, поэтому язык ассемблера также пришлось менять. Например, добавление EAX в AX, AH и AL. Иногда были добавлены другие инструкции. Но исходные инструкции загрузки, хранения, сложения, вычитания, и / или и т. Д. Все есть. Я долгое время не делал x86 и был шокирован, увидев, что синтаксис изменился и / или конкретный ассемблер испортил синтаксис x86. Существуют миллионы инструментов, поэтому, если один из них не соответствует используемой вами книге или веб-странице, найдется один из них.
Таким образом, если рассматривать язык ассемблера для этого семейства правильно и неправильно, язык ассемблера, возможно, изменил синтаксис и не обязательно является обратно совместимым, но набор команд или машинный язык или другие подобные термины (коды операций / биты сборки представляет) сказал бы, что большая часть исходного набора инструкций все еще поддерживается на современных процессорах x86. Возможно, определенные нюансы не будут работать, как и в случае с другими новыми функциями определенных поколений, но основные инструкции: загрузить, сохранить, сложить, вычесть, нажать, выбросить и т. Д. Все еще работают и будут работать. Я чувствую, что лучше "проехать по центру полосы движения", не разбираться в особенностях ghee whizz для микросхем или инструментов, использовать базовую скучность, работал с начала временного синтаксиса языка.
Поскольку каждое поколение в семье пытается использовать определенные функции, обычно производительность, способ передачи отдельных инструкций различным исполнительным блокам меняется ... в каждом поколении ... Чтобы вручную настроить ассемблер на производительность, попытка превзойти компилятор, в лучшем случае может быть трудной. Вам нужны подробные знания о конкретном процессоре, для которого вы настраиваете. К сожалению, с первых дней x86 до настоящего времени то, что заставляло код выполняться быстрее на одном чипе, часто заставляло следующее поколение работать слишком медленно. Возможно, это был замаскированный маркетинговый инструмент, не уверенный: «Купите новый горячий процессор, который стоит вдвое дороже того, который у вас есть сейчас, рекламирует вдвое большую тактовую частоту, но при этом ваша копия Windows работает на 30% медленнее. Через несколько лет, когда будет скомпилирована следующая версия Windows (а этот чип устарел), производительность будет удвоена ». Другим побочным эффектом этого является то, что в данный момент вы не можете взять одну программу на C и создать один двоичный файл, который быстро работает на всех процессорах x86, для производительности вам нужно настроить конкретный процессор, то есть вам нужно как минимум сообщить компилятору оптимизировать и для какой семьи оптимизировать. И, например, окна или офис, или что-то, что вы распространяете в виде двоичного файла, вы, вероятно, не можете или не хотите как-то хоронить несколько по-разному настроенных копий одной и той же программы в одном пакете или в одном двоичном файле ... двигаясь по центру дороги.
В результате всех улучшений аппаратного обеспечения в ваших интересах не пытаться настраивать выходные данные компилятора или ручного ассемблера на какой-либо конкретный чип.В среднем улучшения оборудования компенсируют отсутствие настройки компилятора, и, надеюсь, одна и та же программа будет работать чуть быстрее с каждым поколением.Один из поставщиков микросхем имел обыкновение стремиться к тому, чтобы завтрашние популярные скомпилированные двоичные файлы работали быстрее завтра, другой поставщик улучшил внутренние компоненты так, что если вы перекомпилируете сегодняшний исходный код для новых внутренних компонентов, вы сможете работать быстрее завтра.Эти действия между поставщиками не обязательно продолжаются, каждое поколение выполняет двоичные файлы медленнее, но завтра перекомпилируется исходный код с той же скоростью или медленнее.Он будет запускать переписанные программы завтрашнего дня быстрее, иногда с тем же компилятором, иногда вам нужен компилятор завтрашнего дня.Разве это не весело!
Итак, как мы узнаем, что конкретная скомпилированная или собранная вручную программа настолько быстра, насколько это возможно?На самом деле, для x86 вы не можете гарантировать, что это не так, запускать его на одном чипе в семействе, и он медленный, запускать на другом - он может быть быстрым.x86 или нет, кроме очень коротких программ или очень детерминированных программ, которые вы можете найти на микроконтроллере, вы не можете определенно сказать, что это самое быстрое из возможных решений.Например, кеширование очень сложно, если это вообще возможно, и память за ним, особенно на ПК, где пользователь может выбирать различные размеры, скорости, ранги, банки и т. Д. И настраивать параметры BIOS, чтобы изменить еще больше настроек.действительно не могу сказать компилятору настроиться на это.Таким образом, даже на одном и том же компьютере, одном и том же процессоре, в том же скомпилированном бинарном файле вы можете повернуть некоторые из этих ручек и заставить эту программу работать намного быстрее или намного медленнее.Менять семейства процессоров, менять наборы микросхем, материнские платы и т. Д. И нет возможности настроить так много переменных.Природа бизнеса на базе x86 стала слишком хаотичной.
Другие семейства чипов не так проблематичны.Некоторые, возможно, но не все.Так что это не общие утверждения, а специфичные для семейства чипов x86.Семейство x86 является исключением, а не правилом.Вероятно, последний набор ассемблера / инструкций, который вы хотели бы потратить на изучение.
Есть множество веб-сайтов и книг по этому предмету, не могу сказать, что один лучше, чем другой.Я узнал из первоначального набора книг 8088/86 от Intel, а затем из книг 386 и 486, после этого не искал книг Intel (или каких-либо других издевательств).Вам понадобится ссылка на набор инструкций и ассемблер, такой как nasm или gas (gnu ассемблер, часть binutils, которая поставляется с большинством наборов инструментов компилятора на основе gcc).Что касается интерфейса ассемблера C to / from, вы можете, если ничего не выяснить, экспериментировать, написать небольшую программу на C с несколькими небольшими функциями C, разобрать или скомпилировать в ассемблер и посмотреть, какие регистры и / или как работает стек.используется для передачи параметров между функциями.Сохраняйте свои функции простыми и используйте только несколько параметров, и ваш ассемблер, вероятно, будет работать нормально.Если нет, посмотрите на ассемблер функции, вызывающей ваш код, и выясните, где находятся ваши параметры.Это все где-то хорошо документировано, и в наши дни, вероятно, намного лучше, чем старые.В начале 8088/86 дней у вас были крошечные, маленькие, средние, большие и огромные модели компиляторов, и соглашения о вызовах могли отличаться от одного к другому.Как и один компилятор для следующего, watcom (ранее zortech и, возможно, другие имена) передавался по регистру, borland и microsoft передавались в стек и довольно близко, если не совпадали.Теперь с 32- и 64-разрядным плоским пространством памяти и стандартами вы можете использовать одну модель и не нужно запоминать все нюансы (только один набор нюансов).Встроенная сборка возможна, но варьируется от компилятора C к компилятору C, и заставить ее работать правильно и эффективно сложнее, чем просто писать ассемблер в своем собственном файле.gcc и, возможно, другие компиляторы позволят вам поместить файл ассемблера в командную строку компилятора C, как если бы это был просто другой файл C, и он выяснит, что вы ему дали, и передаст его ассемблеру для вас.То есть, если вы не хотите вызывать программу на ассемблере самостоятельно и помещать объект в командную строку компилятора C.
, если больше ничего не разбираете множество простых функций, добавьте несколько параметров и верните их и т. Д.Настройки оптимизации компилятора и посмотрите, как это меняет используемые инструкции, часто радикально.Даже если вы не можете написать ассемблер с нуля, вы можете прочитать его очень ценно как с точки зрения отладки, так и с точки зрения производительности.
Не все компиляторы для всех процессоров хороши.Например, Gcc - это один размер, который подходит всем, как носок или бейсболка, который не подходит никому.Очень хорошо подходит для большинства целей, но не очень хорошо.Так что вполне возможно добиться большего успеха, чем компилятор с вручную настроенным ассемблером, но в среднем для большого количества кода вы не выиграете.Это относится к большинству процессоров, которые являются более детерминированными, а не только к семейству x86.Речь идет не о меньшем количестве инструкций, меньшее количество инструкций не обязательно означает более быстрое, чтобы превзойти даже средний компилятор в долгосрочной перспективе, вы должны понимать кеширование, выборку, декодирование, конечные автоматы выполнения, интерфейсы памяти, сами памяти и т. Д.Оптимизация компилятора отключена, поэтому очень легко создавать более быстрый код, чем компилятор, поэтому вы должны просто использовать оптимизатор, но также понимать, что это увеличивает риск ошибки компилятора.Вам нужно очень хорошо знать инструмент, который часто возвращается к разборке, чтобы понять, как ваш код C и используемый вами сегодня компилятор взаимодействуют друг с другом.Ни один компилятор не является полностью совместимым со стандартами, потому что сами стандарты нечетки, оставляя некоторые функции языка на усмотрение компилятора (езжайте по середине пути и не используйте эти части языка).
Подводя итог сути ваших вопросов, я бы порекомендовал написать кучу небольших функций или программ с некоторыми небольшими функциями, компилировать в ассемблер или компилировать в объект и дизассемблировать, чтобы увидеть, что делает компилятор. Обязательно используйте разные настройки оптимизации для каждой программы. Получите практические знания по чтению набора инструкций (если выходные данные компилятора или дизассемблера предоставлены в ассемблере, имеет много лишних ошибок, которые мешают удобочитаемости, вам нужно забыть об этом, вам практически не нужно ничего, если вы хотите написать ассемблер). Дайте себе 5-20 лет обучения и экспериментов, прежде чем вы сможете ожидать, что будете регулярно превосходить компилятор, если это ваша цель. К тому времени вы узнаете, что, особенно с этим семейством чипов, это бесполезное усилие, вы выигрываете несколько, но в основном проигрываете ... Было бы в вашу пользу скомпилировать (ассемблировать) тот же код для других семейств чипов, таких как arm и mips, и получить общее представление о том, что код C в целом хорошо компилируется, и что код C не компилируется хорошо, и делает ваше программирование на C лучше, чем пытается сделать ассемблер лучше. Также попробуйте другие компиляторы, такие как llvm. У Gcc есть много изюминок, которые многие считают стандартами языка Си, но вместо этого представляют собой нюансы или проблемы с конкретным компилятором. Умение читать и анализировать результаты сборки компиляторов и их опций предоставит эти знания. Поэтому я рекомендую вам поработать над чтением набора инструкций без необходимости учиться писать его с нуля.