Является ли сборочный мнемоник x86 стандартизированным?

Стандарт x86 включает в себя мнемонику или он просто определяет коды операций?

Если это не включает их, есть ли другой стандарт для различных ассемблеров?

2 ответа

Решение

Мнемоника не стандартизирована, и разные ассемблеры используют разные мнемоники. Некоторые примеры:

  • Применяются сборщики в стиле AT&T b, w, l, а также q суффиксы ко всем мнемоникам для указания размера операнда. Ассемблеры в стиле Intel обычно указывают это с помощью ключевых слов byte, word, dword, а также qword
  • Сборщики в стиле AT&T признают cbtw, cwtl, cltq, а также cqto в то время как сборщики в стиле Intel распознают те же инструкции, что и cbw, cwd, cdq, а также cqo
  • Сборщики в стиле AT&T признают movz?? а также movs?? где ?? два суффикса размера для того, что ассемблеры в стиле Intel называют movzx, movsx, а также movsxd
  • некоторые сборщики в стиле Intel распознают только 63 /r как movsxd в то время как другие признают movsx как вариант этой инструкции тоже
  • Ассемблеры в стиле Plan 9 (например, используемые в Go) просто странные и отличаются во многих отношениях, например, используя мнемонику в стиле Motorola для условных переходов
  • Исторически, ассемблер NEC, предусмотренный для клона NEC V20 8086, имел почти совершенно другую мнемонику. Например, int назывался brk,

К сожалению, на самом деле на бумаге не написано ни одного "стандарта x86", который бы определял все минимальные требования, которым должен соответствовать процессор, чтобы быть x86.

Документация Intel очень близка к тому, чтобы быть "стандартом x86", но в некоторых случаях дает более надежные гарантии, чем на современных процессорах AMD. Например, Intel гарантирует атомарность загрузки 1/2/4/8 байт или сохранение из / в кешируемой памяти с любым выравниванием, которое не пересекает границу строки кеша. Но AMD гарантирует это только для кэшируемых загрузок / хранилищ, которые не пересекают 8-байтовую границу.

Почему целочисленное присваивание для естественно выровненной переменной атомарно в x86? цитирует руководство Intel, показывающее, что все гарантии даны как "Процессор Intel486 (и более новые процессоры с тех пор)" гарантирует то-то и то-то. Не существует базовых данных, применимых ковсем процессорам x86 (или, что более важно, ко всем процессорам x86-64). Я думаю, что фактическая общая базовая линия на практике для x86 (включая pre-x86-64) составляет 1 байт из-за 8088.

Таким образом, программное обеспечение, которое хочет работать на современных процессорах x86-64, не может предполагать атомарность для 8-байтовых загрузок / хранилищ, если они фактически не выровнены. Я думаю, что мы все можем согласиться с тем, что гарантии атомарности являются неотъемлемой частью современного многоядерного процессора x86. Атомарность некэшированного доступа MMIO имеет значение даже на одном ядре; современные Intel и AMD согласны с этим, но опять же Intel только документирует это в терминах "Pentium и более поздние процессоры". Неявно "поздниепроцессоры Intel".


Тем не менее, документация Intel определяет мнемонику для каждого кода операции и регистрирует имена.Документация AMD согласуется с документацией Intel по всем этим вопросам.

См. Том 2 Руководства по разработке программного обеспечения Intel x86. HTML-выдержки только из записей руководства для каждой инструкции (без разделов, объясняющих формат записи и инструкции) можно найти по адресу https://www.felixcloutier.com/x86/index.html и https://github.com/HJLebbink/asm-dude/wiki и другие другие места имеют старые версии, отформатированные по-разному.


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

Intel должна присваивать имена инструкциям, чтобы они могли говорить о них на английском языке в остальных своих руководствах, а не потому, что им нужно, чтобы все в мире использовали такой же синтаксис asm.


Я не уверен, что руководства Intel даже полностью определяют полный синтаксис asm (например, как указать префиксы переопределения сегментов в режиме адресации).

В некоторых случаях они выходят далеко за рамки описания того, что делает машинный код, например, в строковых инструкциях lods/stos/movs/cmps/scas (и, вероятно, входы / выходы), вы найдете такие параграфы в томе Intel 2 руководство:

На уровне кода ассемблера допускаются две формы этой инструкции: форма "явные операнды" и форма "без операндов". Форма явных операндов (указывается с помощью мнемоники MOVS) позволяет явно указывать исходный и целевой операнды. Здесь операнды источника и назначения должны быть символами, которые указывают размер и местоположение значения источника и назначения, соответственно. Эта форма явных операндов предоставляется для разрешения документации; Однако обратите внимание, что документация, предоставленная этой формой, может вводить в заблуждение. То есть символы операнда источника и назначения должны указывать правильныйтип(размер) операндов (байты, слова или двойные слова), но они не должны указывать правильное местоположение. Расположение операндов источника и получателя всегда указывается регистрами DS:(E)SI и ES:(E)DI, которые должны быть правильно загружены перед выполнением команды перемещения строки.

(выделение воспроизведено из (HTML-фрагмент) исходного PDF)

Некоторые ассемблеры Intel-синтаксиса, такие как NASM, игнорируют это и разрешают использовать толькоmovsс размером как часть мнемоники, какmovsb, NASM также имеет синтаксис для указания префикса переопределения сегмента, например fs lodsd это не требует операндов, так что это полностью исключает возможность использования операндов, которые указывают на неправильный операнд памяти, но все же собираются.

(Строковые инструкции используют только неявные операнды памяти, а не режим адресации ModR/M.)

NASM: parser: инструкция ожидаемая rep movs

Конвертировать инструкцию в коде ассемблера lods и stos, чтобы NASM мог скомпилировать


Так что да, существует несколько разновидностей синтаксической сборки Intel, не говоря уже об очень разных синтаксисах, таких как AT&T.

AT&T намеренно использует разные мнемоники для некоторых инструкций, даже разделяя некоторые коды операций, которые разделяют мнемонику в синтаксисе Intel, на отдельные мнемоники, такие как movzb за movzx-байт-источником, и movzw для версии слова источника. (Обычно используется с суффиксом размера, например, movzbl, но l может быть выведен из 32-битного регистра назначения, если хотите.)

И синтаксис AT&T непреднамеренно меняет fsubr с fsub при использовании с двумя операндами регистра, что является ошибкой синтаксического проектирования, с которой мы застряли. (К счастью, x87 в целом устарел.)

Другие вопросы по тегам