Вопросы о дизайне синтаксиса AT & T x86 - PullRequest
18 голосов
/ 16 ноября 2010
  1. Может ли кто-нибудь объяснить мне, почему перед каждой константой в синтаксисе AT & T стоит «$»?
  2. Почему у всех регистров есть «%»?
  3. это просто еще одна попытка заставить меня делать много неубедительного набора текста?
  4. Кроме того, я единственный, кто находит: 16(%esp) действительно нелогичным по сравнению с [esp+16]?
  5. Я знаюон компилируется в одно и то же, но зачем кому-то хотеть набирать много '$' и '%' без необходимости?- Почему GNU выбрал этот синтаксис по умолчанию?
  6. Другое дело, почему каждой инструкции в синтаксисе at & t предшествует: l?- Я знаю это для размеров операндов, однако, почему бы просто не позволить ассемблеру понять это?(Хотел бы я когда-нибудь сделать movl для операндов не такого размера?)
  7. Последнее: почему аргументы mov инвертируются?

Разве это не подробнее логично, что:

eax = 5
mov eax, 5

где at & t:

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

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

Ответы [ 4 ]

26 голосов
/ 16 ноября 2010

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 * 1032»). * в слот, называемый «х» "). Выбор AT & T имеет смысл. Это сбивает с толку только тогда, когда вы конвертируете код C в сборку, задача, которую обычно следует оставлять компилятору C.

Последняя часть вашего вопроса 5 интересна с исторической точки зрения. Инструменты GNU для x86 следовали синтаксису AT & T, потому что в то время они пытались завладеть миром Unix («GNU» означает «GNU - это не 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 через двадцать лет превратится в доминирующую архитектуру в мире настольных компьютеров и серверов.

9 голосов
/ 16 ноября 2010

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

4: Нет.

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

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

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

7 голосов
/ 05 марта 2016

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

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

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

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

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

Unix as использовал тот же синтаксис для режимов адресации, что и ассемблеры 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 Index , где адрес памяти формируется путем суммирования содержимого регистра и индексного слова, следуя инструкции.

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

Это пришло с PDP-11.

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

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

PDP-11 будет использовать b для байтовых инструкций, например: CLR против CLRB. В VAX-11 появились другие суффиксы: l для длинных, w для слов, f для чисел с плавающей запятой, d для двойных, q для четырехзначных слов, ...

Last thing: why are the mov arguments inverted?

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


  1. Согласно информации о газе, через ассемблер BSD 4.2.
  2. Справочное руководство Unix Assembler §8.1 - Деннис М. Ритчи
2 голосов
/ 18 сентября 2015

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

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

...