3.2.2. Синтаксис AT&T

На верх  Назад  Вперёд

В ранних версиях Free Pascal использовал только GNU в качестве ассемблера при генерации объектных файлов для процессоров Intel x86. только спустя некоторое время был создан встроенный ассемблер, который непосредственно создаёт объектный файл.

Так как ассемблер GNU использует синтаксис AT&T, написанный вами код должен использовать этот же синтаксис. Отличия между синтаксисом AT&T и Intel, который используется в Turbo Pascal, приведены ниже:

Имя кода операции включает в себя размер операнда. В общем, можно сказать, что имя кода операции AT&T является именем кода операции Intel с суффиксом l, w или b для, соответственно, типов longint (32 бита), word (16 бит) и byte (8 бит) памяти или регистров. Например, конструкция Intel mov al, bl эквивалентна инструкции стиля AT&T movb %bl,%al.

В AT&T непосредственные операнды обозначаются с $, в то время как в синтаксисе Intel не используется префикс для таких операндов. Таким образом, конструкция Intel mov ax, 2 становится movb $2, %al в синтаксисе AT&T.

В AT&T имена регистров начинаются с префикса %. Этого нет в синтаксисе Intel.

В AT&T абсолютные операнды jump/call обозначаются знаком *, синтаксис Intel не разграничивает эти адреса.

Порядок следования операндов источника и приёмника меняются местами. Синтаксис AT&T использует Источник, Приёмник, в то время как синтаксис Intel использует Приёмник, Источник. То есть конструкция Intel add eax, 4 трансформируется в addl $4, %eax на диалекте AT&T.

Непосредственные длинные переходы сопровождаются префиксом l. То есть конструкция Intel call/jmp section:offset трансформируется в lcall/ljmp $section,$offset. Аналогично для дальних возвратов – lret вместо ret far на Intel.

Ссылки на память определяются по разному в ассемблерах AT&T и Intel. Косвенная ссылка на память в Intel:

Section:[Base + Index*Scale + Offs]

В синтаксисе AT&T будет как:

Section:Offs(Base,Index,Scale)

где Base и Index являются не обязательными 32-разрядными регистрами базы и индекса, а Scale используется как множитель для Index. Он может принимать значения 1, 2, 4 и 8. Section используется для указания дополнительного регистра для операнда памяти.

Больше информации о синтаксисе AT&T можно найти в руководстве, хотя нужно принять во внимание следующие отличия от обычного ассемблера AT&T:

Поддерживаются только следующие директивы:

.byte

.word

.long

.ascii

.asciz

.globl

Следующие директивы распознаются, но не поддерживаются:

.align

.lcomm

В будущем они будут поддерживаться.

Директивы чувствительны к регистру, остальные идентификаторы НЕ чувствительны к регистру.

В отличие от gas, локальные метки/идентификаторы должны начинаться с .L.

Оператор ! не поддерживается.

Строковые выражения в операндах не поддерживаются.

CBTW, CWTL, CWTD и CLTD не поддерживаются, используйте вместо них обычные эквиваленты Intel.

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

const myid = 10;

movl $myid,%eax -- допускаетсяmovl

myid(%esi),%eax – НЕ допускается.

Если найдена директива .globl, то идентификатор, следующий непосредственно за ней, становится общедоступным и сразу же выделяется. Поэтому имена меток с этим именем будут игнорироваться.

Только коды операций Single и Double FPU поддерживаются.

Встроенный ассемблер AT&T поддерживает следующие макросы:

__RESULT представляет результат работы функции и возвращает значение.

__SELF представляет указатель на метод объекта в методах.

__OLDEBP представляет старый указатель базы в рекурсивных процедурах.