Вопросы по дизайну синтаксиса AT & T x86

  • Может ли кто-нибудь объяснить мне, почему каждая константа в синтаксисе AT & T имеет перед ним "$"?
  • Почему у всех регистров есть "%"?
  • Является ли это еще одной попыткой заставить меня сделать много хромого ввода?
  • Кроме того, я единственный, кто находит: 16(%esp) действительно противоречивый по сравнению с [esp+16]?
  • Я знаю, что он компилируется в одно и то же, но почему кто-то хочет набирать много "$" и "% без необходимости? - Почему GNU выбрал этот синтаксис по умолчанию?
  • Другое дело, почему каждая инструкция в синтаксисе & t предшествует: l? - Я знаю его для размеров операндов, однако почему бы просто не позволить ассемблеру понять это? (хотел ли я когда-нибудь сделать movl на операндах, которые не являются такими размерами?)
  • Последнее: почему аргументы mov инвертированы?

Не логичнее ли:

eax = 5
mov eax, 5

где как при & t:

mov 5, eax
5 = a (? wait what ?)

Примечание: Я не пытаюсь троллировать. Я просто не понимаю, какие дизайнерские решения они сделали, и я пытаюсь понять, почему они сделали то, что они сделали.

Ответ 1

1, 2, 3 и 5: нотация несколько избыточна, но я считаю, что это хорошо, когда вы развиваетесь в сборке. Резервирование помогает читать. Точка о том, "пусть ассемблер выясняет это", легко превращается в "пусть программист, который читает код, выясняет это", и мне это не нравится, когда я делаю чтение. Программирование не является задачей только для записи; даже сам программист должен прочитать свой собственный код, а избыточность синтаксиса помогает совсем немного.

Другое дело, что "%" и "$" означают, что новые регистры могут быть добавлены без нарушения обратной совместимости: никаких проблем при добавлении, например, в регистр с именем xmm4, поскольку он будет выписан как %xmm4, который нельзя путать с переменной с именем xmm4, которая была бы написана без "%" .

Что касается количества ввода: обычно при программировании в сборке узким местом является мозг, а не рука. Если "$" и "%" замедляют вас, то либо вы думаете быстрее, чем обычно считаете выполнимым для человека, или, что более вероятно, ваша задача под рукой слишком механична и не должна выполняться в монтаж; он должен быть оставлен автогенератору кода, который в некотором смысле известен как "компилятор C".

Суффикс 'l' был добавлен для обработки некоторых ситуаций, когда ассемблер "не может" понять это. Например, этот код:

mov  [esp], 10

является неоднозначным, поскольку он не указывает, хотите ли вы написать байт значения 10 или 32-битное слово с таким же числовым значением. Затем синтаксис Intel требует:

mov  byte ptr [esp], 10

который довольно уродлив, когда вы об этом думаете. Люди из AT & T хотели сделать что-то более рациональное, поэтому они придумали:

movb   $10, (%esp)

и они предпочли быть систематическими и иметь суффикс "b" (или "l" или "w" ) повсюду. Обратите внимание, что суффикс не всегда требуется. Например, вы можете написать:

mov   %al, (%ebx)

и пусть ассемблер GNU "выяснит", что, поскольку вы говорите о "% al", это перемещение для одного байта. Это действительно работает! Тем не менее, мне все же лучше указать размер (это действительно помогает читателю, а сам программист является первым и главным читателем его собственного кода).

Для "инверсии": это наоборот. Синтаксис Intel имитирует то, что происходит на C, в котором значения вычисляются справа, а затем записывается в то, что находится слева. Таким образом, запись идет справа налево, в обратном направлении, учитывая, что чтение идет слева направо. Синтаксис AT & T возвращается в "нормальное" направление. По крайней мере, они рассматривали; поскольку в любом случае они решили использовать собственный синтаксис, они подумали, что они могут использовать операнды в том, что они считают "правильным упорядочением". Это в основном конвенция, но нелогичная. Сценарий C имитирует математическую нотацию, за исключением того, что математика посвящена определению значений ( "пусть x - значение 5" ), а не о присвоении значений ( "мы записываем значение 5 в слот под названием" x "). Выбор AT & T имеет смысл. Это запутывает только тогда, когда вы конвертируете C-код в сборку, задачу, которая обычно должна быть оставлена ​​компилятору C.

Последняя часть вашего вопроса 5 интересна с исторической точки зрения. Инструменты GNU для x86 соответствовали синтаксису AT & T, поскольку в то время они пытались занять место в мире Unix ( "GNU" означает "GNU is Un Unix" ) и конкурируют с инструментами Unix; Unix находилась под контролем AT & T. Это до дней Linux или даже Windows 3.0; ПК были 16-битными системами. Unix использовал синтаксис AT & T, поэтому GNU использовал синтаксис AT & T.

Хороший вопрос заключается в следующем: почему AT & T счел разумным изобретать собственный синтаксис? Как описано выше, у них были некоторые причины, которые не лишены заслуг. Стоимость использования собственного синтаксиса, конечно же, заключается в том, что он ограничивает взаимодействие. В те дни компилятор C или ассемблер не имели реального смысла в качестве отдельного инструмента: в системе Unix они должны были предоставляться поставщиком ОС. Кроме того, Intel не была большим игроком в мире Unix; большие системы в основном использовали производные VAX или Motorola 680x0. Никто не понял, что MS-Dos PC превратится, через двадцать лет, в доминирующую архитектуру в настольных и серверных мирах.

Ответ 2

1-2, 5: они, вероятно, выбрали регистры префикса и, таким образом, упростили анализ; вы знаете непосредственно у первого персонажа, какой это токен.

4: Нет.

6: Опять же, возможно, чтобы парсер смог понять, какую команду выводить.

7: На самом деле это имеет больше смысла в грамматическом значении, перемещает что к чему. Возможно, инструкция mov должна быть инструкцией ld.

Не поймите меня неправильно, я думаю, что синтаксис AT & T ужасен.

Ответ 3

Синтаксис AT & T для ассемблера GNU прослеживает свое происхождение на ассемблере Unix 1 который сам взял свой синтаксис ввода в основном из ассемблера PAL-11 PDP-11 (около 1970 г.).

Может ли кто-нибудь объяснить мне, почему каждая константа в синтаксисе AT & T имеет перед ним "$"?

Это позволяет отличать непосредственные константы от адресов памяти. Синтаксис Intel делает это по-другому, с ссылками на память как [foo].

Кстати, MASM (Microsoft Assembler) не нуждается в различии на уровне синтаксиса, так как он может определить, является ли операнд символической константой или меткой. Другие ассемблеры для x86 активно избегают таких догадок, поскольку они могут вводить в заблуждение читателей, например: TASM в режиме IDEAL (он предупреждает о ссылках на память не в скобках), nasm, fasm.

PAL-11 использовал # для режима немедленной адресации, где операнд следовал за инструкцией. Константа без # означала режим относительной адресации, где относительный адрес следовал за инструкцией.

Unix использует тот же синтаксис для режимов адресации, что и DEC-сборщики, с * вместо @ и $ вместо #, так как @ и # были, по-видимому, неудобны для ввода 2.

Почему у всех регистров есть "%"?

В PAL-11 регистры были определены как R0 =% 0, R1 =% 1,... с R6, также называемым SP, а R7 также упоминается как ПК. Макро-ассемблер DEC MACRO-11 разрешил ссылаться на регистры как %x, где x может быть произвольным выражением, например. %3+1 относится к %4.

Является ли это еще одной попыткой заставить меня сделать много хромого ввода?

Неа.

Кроме того, я единственный, который находит: 16 (% esp) действительно противоречивым по сравнению с [esp + 16]?

Это происходит из режима адресной адресации PDP-11, где адрес памяти формируется путем суммирования содержимого регистра и индексного слова, следующего за инструкцией.

Я знаю, что он компилируется в одно и то же, но почему кто-то хочет набирать много "$" и "% без необходимости? - Почему GNU выбирает этот синтаксис по умолчанию?

Он появился из PDP-11.

Другое дело, почему каждая инструкция в синтаксисе & t предшествует: l? - Я знаю его для размеров операндов, однако почему бы просто не позволить Ассемблер это понял? (хотел бы я когда-нибудь сделать операндов, которые не являются такими размерами?)

газ обычно может понять это. Другие ассемблеры также нуждаются в помощи в особых случаях.

PDP-11 будет использовать b для байтовых инструкций, например: CLR vs CLRB. Другие суффиксы появились в VAX-11: l для long, w для слова, f для float, d для double, q для quad-word,...

Last thing: why are the mov arguments inverted?

Возможно, поскольку PDP-11 предшествует микропроцессорам Intel, это наоборот.


  • В соответствии с информационной страницей газа через ассемблер BSD 4.2.
  • Справочное руководство по Unix Assembler §8.1 - Деннис М. Ричи

Ответ 4

Синтаксис AT & T инвертирует порядок операндов по сравнению с Intel, скорее всего, потому, что PDP-11, на котором был первоначально разработан Unix, использует тот же порядок операндов.

Intel и DEC просто выбрали противоположные порядки.