Вопросы по дизайну синтаксиса 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 просто выбрали противоположные порядки.