Недавно я читал архивы SO и встречал утверждения против архитектуры x86.
Зачем нам нужна другая архитектура ЦП для серверов, мини / мэйнфреймов и смешанных ядер? говорит:
« Архитектура ПК - беспорядок, любой разработчик ОС скажет вам это ».Стоит ли изучать язык ассемблера усилий?(в архиве ):
" Поймите, что архитектура x86 в лучшем случае ужасна "Есть ли простой способ изучить ассемблер x86? говорит:
« Большинство колледжей преподают сборку на чем-то вроде MIPS, потому что это намного проще понять, сборка x86 действительно уродлива »
и многие другие комментарии вроде
Я пробовал искать, но не нашел причин. Я не считаю x86 плохим, вероятно, потому что это единственная архитектура, с которой я знаком.
Может ли кто-нибудь любезно дать мне основания считать x86 уродливым / плохим / неполноценным по сравнению с другими.
Ответы:
Пара возможных причин:
IN
иOUT
)Ассемблерный код x86 сложен, потому что x86 - это сложная архитектура со множеством функций. Список инструкций для типичной машины MIPS помещается на листе бумаги размером с одну букву. Эквивалентный список для x86 занимает несколько страниц, а инструкции просто делают больше, поэтому вам часто требуется более подробное объяснение того, что они делают, чем может дать листинг. Например,
MOVSB
инструкции нужен относительно большой блок кода C, чтобы описать, что она делает:Это одна инструкция, выполняющая загрузку, сохранение и два сложения или вычитания (управляемых вводом флага), каждая из которых будет отдельными инструкциями на RISC-машине.
Хотя простота MIPS (и подобных архитектур) не обязательно делает их лучше, для обучения введению в класс ассемблера имеет смысл начать с более простого ISA . Некоторые классы ассемблера обучают ультра-упрощенному подмножеству x86, называемому y86 , которое упрощено до такой степени, что бесполезно для реального использования (например, без инструкций сдвига), или некоторые учат только базовым инструкциям x86.
Обновление 2016: Anandtech опубликовал обсуждение размеров опкодов для x64 и AArch64 .
РЕДАКТИРОВАТЬ: Это не должно быть bash x86! партия. У меня не было другого выбора, кроме как нанести некоторый удар, учитывая формулировку вопроса. Но за исключением (1), все это было сделано по уважительным причинам (см. Комментарии). Дизайнеры Intel не глупы - они хотели чего-то добиться с помощью своей архитектуры, и это некоторые из налогов, которые им пришлось заплатить, чтобы воплотить эти вещи в жизнь.
источник
На мой взгляд, главный удар по x86 - это его происхождение от CISC - набор инструкций содержит множество неявных взаимозависимостей. Эти взаимозависимости затрудняют выполнение таких вещей, как переупорядочение инструкций на микросхеме, поскольку артефакты и семантика этих взаимозависимостей должны сохраняться для каждой инструкции.
Например, большинство инструкций сложения и вычитания целых чисел x86 изменяют регистр флагов. После выполнения сложения или вычитания следующей операцией часто является просмотр регистра флагов на предмет переполнения, бит знака и т. Д. Если после этого есть еще одно добавление, очень сложно определить, безопасно ли начинать выполнение второго сложения. до того, как станет известен результат 1-го добавления.
В архитектуре RISC инструкция добавления будет определять входные операнды и выходные регистры, и все, что касается операции, будет происходить с использованием только этих регистров. Это значительно упрощает разделение операций добавления, которые находятся рядом друг с другом, потому что нет регистра флагов bloomin, заставляющего все выстраиваться в линию и выполнять один файл.
Микросхема DEC Alpha AXP, выполненная в стиле RISC в стиле MIPS, была болезненно спартанской в доступных инструкциях, но набор инструкций был разработан так, чтобы избежать неявных зависимостей регистров между инструкциями. Не было аппаратного регистра стека. Регистр аппаратно определяемых флагов отсутствовал. Даже указатель инструкции был определен ОС - если вы хотели вернуться к вызывающей стороне, вы должны были решить, как вызывающая сторона собиралась сообщить вам, по какому адресу вернуться. Обычно это определялось соглашением о вызовах ОС. Однако на x86 это определяется аппаратным обеспечением чипа.
В любом случае, за 3 или 4 поколения микросхем Alpha AXP аппаратное обеспечение превратилось из буквальной реализации спартанского набора инструкций с 32 регистрами int и 32 регистрами с плавающей запятой в механизм массового неупорядоченного выполнения с 80 внутренними регистрами, переименованием регистров и т.д. пересылка результатов (где результат предыдущей инструкции перенаправляется более поздней инструкции, которая зависит от значения) и всевозможные дикие и сумасшедшие бустеры производительности. И, несмотря на все эти навороты, кристалл чипа AXP был все еще значительно меньше, чем сопоставимый кристалл чипа Pentium того времени, а AXP был чертовски быстрее.
Вы не увидите такого рода всплесков производительности, повышающих производительность, в генеалогическом дереве x86 в основном потому, что сложность набора инструкций x86 делает многие виды оптимизации выполнения непомерно дорогими, если не невозможными. Гениальный ход Intel заключался в отказе от реализации набора инструкций x86 на оборудовании - все современные чипы x86 на самом деле являются ядрами RISC, которые в определенной степени интерпретируют инструкции x86, переводя их во внутренний микрокод, сохраняющий всю семантику исходного x86. инструкция, но допускает небольшую часть этого неупорядоченного RISC и другие оптимизации микрокода.
Я написал много ассемблера x86 и могу полностью оценить удобство его корней CISC. Но я не осознавал, насколько сложна x86, пока не потратил некоторое время на написание ассемблера Alpha AXP. Я был потрясен простотой и единообразием AXP. Различия огромны и глубоки.
источник
add
за другимadd
. Правила ясны. Вам также не нужно заниматься переупорядочиванием инструкций. Начиная с Pentium Pro в середине 90-х, ЦП делает это за вас. То, о чем вы говорите, могло быть проблемой 20 лет назад, но я не вижу причин противопоставлять это архитектуре x86 в настоящее время.Архитектура x86 восходит к дизайну микропроцессора 8008 и его родственников. Эти процессоры были разработаны в то время, когда память была медленной, и если вы могли сделать это на кристалле процессора, он часто был намного быстрее. Однако место на кристалле ЦП также было дорогим. Эти две причины заключаются в том, что существует лишь небольшое количество регистров, которые, как правило, имеют специальное назначение, и сложный набор инструкций со всеми видами ошибок и ограничений.
Другие процессоры той же эпохи (например, семейство 6502) также имеют аналогичные ограничения и особенности. Интересно, что и серия 8008, и серия 6502 предназначались как встраиваемые контроллеры. Уже тогда ожидалось, что встроенные контроллеры будут программироваться на ассемблере и во многом ориентированы на программиста сборки, а не на автора компилятора. (Посмотрите на микросхему VAX, чтобы узнать, что происходит, когда вы обслуживаете компилятор.) Разработчики не ожидали, что они станут вычислительными платформами общего назначения; вот для чего были нужны вещи, подобные предшественникам архива POWER. Революция домашних компьютеров, конечно, изменила это.
источник
У меня есть несколько дополнительных аспектов:
Представьте, что операция "a = b / c" x86 реализует это как
В качестве дополнительного бонуса инструкции div edx будет содержать остаток.
Процессору RISC потребуется сначала загрузить адреса b и c, загрузить b и c из памяти в регистры, выполнить деление и загрузить адрес a, а затем сохранить результат. Синтаксис dst, src:
Здесь обычно не бывает остатка.
Если какие-либо переменные должны быть загружены через указатели, обе последовательности могут стать длиннее, хотя это менее вероятно для RISC, поскольку он может иметь один или несколько указателей, уже загруженных в другой регистр. x86 имеет меньше регистров, поэтому вероятность того, что указатель окажется в одном из них, меньше.
Плюсы и минусы:
Команды RISC могут быть смешаны с окружающим кодом для улучшения планирования команд, это менее вероятно с x86, который вместо этого выполняет эту работу (более или менее хорошо в зависимости от последовательности) внутри самого процессора. Приведенная выше последовательность RISC обычно будет иметь длину 28 байтов (7 инструкций по 32 бита / 4 байта каждая) в 32-битной архитектуре. Это заставит внешнюю память работать больше при выборке инструкций (семь выборок). Более плотная последовательность x86 содержит меньше инструкций, и, хотя их ширина варьируется, вы, вероятно, также видите в среднем 4 байта на инструкцию. Даже если у вас есть кеши инструкций для ускорения этого процесса, семь выборок означают, что вам придется восполнить дефицит трех в другом месте по сравнению с x86.
Архитектура x86 с меньшим количеством регистров для сохранения / восстановления означает, что она, вероятно, будет переключать потоки и обрабатывать прерывания быстрее, чем RISC. Для сохранения и восстановления большего количества регистров требуется больше временного пространства стека ОЗУ для прерываний и больше постоянного пространства стека для хранения состояний потоков. Эти аспекты должны сделать x86 лучшим кандидатом для запуска чистой ОСРВ.
В более личном плане мне кажется, что писать RISC-сборку труднее, чем x86. Я решаю эту проблему, написав процедуру RISC на C, скомпилировав и изменив сгенерированный код. Это более эффективно с точки зрения создания кода и, вероятно, менее эффективно с точки зрения выполнения. Все 32 регистра, которые нужно отслеживать. В x86 все наоборот: 6-8 регистров с «настоящими» именами делают проблему более управляемой и вселяют больше уверенности в том, что созданный код будет работать должным образом.
Некрасиво? Это в глазах смотрящего. Я предпочитаю «другое».
источник
there typically won't be a reminder
но вики говорит, что это есть у mips: en.wikipedia.org/wiki/MIPS_instruction_set#IntegerЯ думаю, что этот вопрос основан на ложном предположении. В основном просто одержимые RISC ученые называют x86 уродливым. На самом деле, x86 ISA может выполнять операции с одной инструкцией, которые потребуют 5-6 инструкций на RISC ISA. Поклонники RISC могут возразить, что современные процессоры x86 разбивают эти «сложные» инструкции на микрооперации; тем не мение:
mov %eax, 0x1c(%esp,%edi,4)
режимы адресации, и они не разбиты на части.x86 действительно вобрал в себя все хорошие аспекты RISC около 10-15 лет назад, а остальные качества RISC (собственно определяющее - минимальный набор инструкций) вредны и нежелательны.
Помимо стоимости и сложности изготовления процессоров и их требований к энергии, x86 - лучший ISA . Любой, кто говорит вам обратное, позволяет идеологии или повестке дня мешать их рассуждениям.
С другой стороны, если вы ориентируетесь на встроенные устройства, где учитывается стоимость ЦП, или встроенные / мобильные устройства, где потребление энергии является главной проблемой, ARM или MIPS, вероятно, имеют больше смысла. Имейте в виду, что вам все равно придется иметь дело с дополнительным оперативной памятью и двоичным размером, необходимым для обработки кода, который легко в 3-4 раза больше, и вы не сможете приблизиться к производительности. Будет ли это иметь значение, во многом зависит от того, что вы на нем будете запускать.
источник
Язык ассемблера x86 не так уж и плох. Когда вы дойдете до машинного кода, он станет действительно уродливым. Кодирование инструкций, режимы адресации и т. Д. Намного сложнее, чем для большинства процессоров RISC. И для целей обратной совместимости встроено дополнительное развлечение - вещи, которые срабатывают только тогда, когда процессор находится в определенном состоянии.
Например, в 16-битных режимах адресация может показаться совершенно причудливой; есть режим адресации для
[BX+SI]
, но не для[AX+BX]
. Подобные вещи, как правило, усложняют использование регистров, так как вам нужно убедиться, что ваше значение находится в регистре, который вы можете использовать по мере необходимости.(К счастью, 32-битный режим намного разумнее (хотя иногда сам по себе все еще немного странный - например, сегментация), а 16-битный код x86 в значительной степени больше не актуален за пределами загрузчиков и некоторых встроенных сред.)
Также есть остатки былых времен, когда Intel пыталась сделать x86 лучшим процессором. Инструкции длиной в пару байтов, которые выполняли задачи, которые на самом деле никто больше не выполняет, потому что они были, откровенно говоря, слишком медленными или сложными. Инструкции ENTER и LOOP для двух примеров - обратите внимание, что код фрейма стека C похож на «push ebp; mov ebp, esp», а не «enter» для большинства компиляторов.
источник
Я не эксперт, но мне кажется, что многие функции, которые не нравятся людям, могут быть причиной того, что он работает хорошо. Несколько лет назад наличие регистров (вместо стека), регистровых фреймов и т. Д. Рассматривалось как хорошее решение, позволяющее сделать архитектуру более простой для людей. Однако в настоящее время важна производительность кеша, и слова переменной длины x86 позволяют хранить в кеше больше инструкций. «Декодирование инструкций», на которое, как я полагаю, указали оппоненты, когда-то занимало половину чипа, уже не совсем так.
Я думаю, что параллелизм - один из наиболее важных факторов в настоящее время - по крайней мере, для алгоритмов, которые уже работают достаточно быстро, чтобы их можно было использовать. Выражение высокого параллелизма в программном обеспечении позволяет оборудованию амортизировать (или часто полностью скрывать) задержки памяти. Конечно, будущее архитектуры, вероятно, находится в чем-то вроде квантовых вычислений.
Я слышал от nVidia, что одна из ошибок Intel заключалась в том, что они хранили двоичные форматы рядом с оборудованием. PTX CUDA выполняет некоторые быстрые вычисления использования регистров (раскрашивание графиков), поэтому nVidia может использовать регистровую машину вместо стековой, но все же имеет путь обновления, который не нарушает все старое программное обеспечение.
источник
Помимо причин, о которых уже упоминалось:
__cdecl
,__stdcall
,__fastcall
и т.д.источник
Я думаю, вы получите часть ответа, если когда-нибудь попытаетесь написать компилятор, ориентированный на x86, или если вы напишете эмулятор машины x86, или даже если попытаетесь реализовать ISA в конструкции оборудования.
Хотя я так понимаю "х86 урод!" Я все еще думаю, что писать сборку x86 веселее, чем MIPS (например) - последнее просто утомительно. Это всегда должно было быть приятным для компиляторов, а не для людей. Я не уверен, что чип мог бы быть более враждебным по отношению к разработчикам компиляторов, если бы попытался ...
Самая уродливая часть для меня - это способ (в реальном режиме) работы сегментации - то, что любой физический адрес имеет 4096 псевдонимов сегмент: смещение. Когда в последний раз это было нужно ? Все было бы намного проще, если бы сегментная часть была строго старшими битами 32-битного адреса.
источник
x86 имеет очень и очень ограниченный набор регистров общего назначения
он продвигает очень неэффективный стиль разработки на самом низком уровне (ад CISC) вместо эффективной методологии загрузки / сохранения
Intel приняла ужасающее решение ввести явно глупую модель адресации сегмента / смещения памяти, чтобы оставаться совместимой с (уже сейчас!) Устаревшей технологией.
В то время, когда все переходили на 32-разрядную версию, x86 сдерживал массовый мир ПК, будучи скудным 16-разрядным (большинство из них - 8088 - даже только с 8-разрядными внешними путями данных, что еще страшнее!).
Для меня (а я ветеран DOS, который видел каждое поколение ПК с точки зрения разработчиков!) Пункт 3. был худшим.
Представьте себе такую ситуацию, которая была у нас в начале 90-х (мейнстрим!):
а) Операционная система, которая имела безумные ограничения по устаревшим причинам (640 КБ легкодоступной ОЗУ) - DOS
б) Расширение операционной системы (Windows), которое могло делать больше с точки зрения ОЗУ, но было ограничено, когда дело доходило до таких вещей, как игры и т. д ... и было не самым стабильным на Земле (к счастью, позже это изменилось, но я Я здесь про начало 90-х)
c) Большая часть программного обеспечения все еще была DOS, и нам часто приходилось создавать загрузочные диски для специального программного обеспечения, потому что был этот файл EMM386.exe, который нравился некоторым программам, а другим не нравился (особенно геймеры - а я в то время был геймером AVID - знаю, что я я говорю здесь)
г) Мы были ограничены битами MCGA 320x200x8 (ладно, было немного больше со специальными приемами, было возможно 360x480x8, но только без поддержки библиотеки времени выполнения), все остальное было беспорядочно и ужасно ("VESA" - смеется)
д) Но с точки зрения оборудования у нас были 32-битные машины с довольно большим количеством мегабайт ОЗУ и карты VGA с поддержкой разрешения до 1024x768.
Причина такой плохой ситуации?
Простое дизайнерское решение от Intel. Совместимость уровня машинных инструкций (НЕ двоичного уровня!) С чем-то, что уже умирало, я думаю, это был 8085. Другие, казалось бы, не связанные проблемы (графические режимы и т. Д.) Были связаны по техническим причинам и из-за очень узкой Архитектура, ориентированная на мыслительную деятельность, принесла с собой платформу x86.
Сегодня ситуация иная, но спросите любого разработчика ассемблера или людей, которые создают серверные части компилятора для x86. Безумно малое количество регистров общего назначения - не что иное, как ужасный убийца производительности.
источник