Ответ 1
Расширение ответа Johan: UNIX долгое время разрабатывался на PDP-11, 16-битном компьютере от DEC, который имел довольно простой набор команд. Почти каждая команда имеет два операнда, каждый из которых может иметь один из следующих восьми режимов адресации, как показано на языке ассемблера MACRO 16:
0n Rn register
1n (Rn) deferred
2n (Rn)+ autoincrement
3n @(Rn)+ autoincrement deferred
4n -(Rn) autodecrement
5n @-(Rn) autodecrement deferred
6n X(Rn) index
7n @X(Rn) index deferred
Непосредственные адреса и прямые адреса могут быть использованы путем умного повторного использования некоторых режимов адресации на R7, счетчик программ:
27 #imm immediate
37 @#imm absolute
67 addr relative
77 @addr relative deferred
В качестве драйвера UNIX tty в качестве управляющих символов использовались @
и #
, вместо #
и *
для @
вместо @
была заменена $
.
Этот синтаксис был адаптирован к процессору 8086 и его режимам адресации:
mr0 X(bx,si) bx + si indexed
mr1 X(bx,di) bx + di indexed
mr2 X(bp,si) bp + si indexed
mr3 X(bp,di) bp + di indexed
mr4 X(si) si indexed
mr5 X(di) di indexed
mr6 X(bp) bp indexed
mr7 X(bx) bx indexed
3rR R register
0r6 addr direct
Где m
равно 0, если индекс отсутствует, m
равно 1, если есть однобайтовый индекс, m
равно 2, если есть двухбайтовый индекс, а m
равно 3, если вместо этого операнда памяти используется регистр. Если существуют два операнда, другой операнд всегда является регистром и закодирован в цифре r
. В противном случае r
кодирует еще три бита кода операции.
В этой схеме адресации невозможны немедленные действия, все инструкции, которые принимают немедленно, кодируют этот факт в своем коде операции. Immediates пишется $imm
точно так же, как в синтаксисе PDP-11.
Инструкции по прыжкам и вызовам преследуют цель. Для косвенного перехода цель имеет префикс *
(например, jump *%eax
). Это необходимо, чтобы отличить jump foo
(перейти к foo
) от jump *foo
(перейти к адресу, сохраненному в местоположении foo
). Они могли бы спроектировать прямые прыжки, чтобы иметь свои операнды с префиксом $
, но из-за редкости косвенных прыжков это синтаксическое исключение обеспечивает приятное удобство.
Этот синтаксис был расширен для указания префикса сегмента с использованием двоеточия:
seg:addr
Когда был введен 80386, эта схема была адаптирована к новым режимам SIB-адресации с использованием четырехэтапного режима общей адресации:
disp(base,index,scale)
где disp
- это смещение, базой является базовый регистр, index
индексный регистр и scale
равен 1, 2, 4 или 8, чтобы масштабировать регистр индекса на одну из этих сумм. Это соответствует синтаксису Intel:
[disp+base+index*scale]
Еще одна замечательная особенность PDP-11 заключается в том, что большинство инструкций доступны в байте и варианте слова. Какой из них вы используете, указывается суффиксом b
или w
для кода операции, который напрямую переключает первый бит кода операции:
010001 movw r0,r1
110001 movb r0,r1
это также было адаптировано для синтаксиса AT & T, поскольку большинство команд 8086 действительно доступны также в режиме байта и в режиме слова. Позже в 80386 и AMD K6 были введены 32-битные команды (суффикс l
для long
) и 64-битные команды (суффикс q
для квадроцикла).
И последнее, но не менее важное: изначально соглашение состояло в том, чтобы префикс символов языка C с подчеркиванием (как это делается в Windows), поэтому вы можете отличить функцию C с именем ax
от регистра ax
. Когда SUN Microsystems разработали бинарный формат ELF, они решили избавиться от этого украшения. Поскольку нет способа отличить прямой адрес от регистра в противном случае, они добавили префикс %
к каждому регистру:
mov direct,%eax # move memory at direct to %eax
И вот как мы получили синтаксис AT & T.