Синтаксис AT&T
Синтаксис AT&T — это один из двух основных способов записи инструкций (мнемоник) и операндов в языке ассемблера для архитектуры x86 (и её расширений, таких как x86-64). Назван в честь компании AT&T (American Telephone and Telegraph), в недрах которой в 1970-х годах была разработана операционная система UNIX, а также ассемблеры для процессоров PDP-11 и VAX, которые впоследствии повлияли на синтаксис для x86. В отличие от альтернативного, более распространённого в среде MS-DOS и Windows синтаксиса Intel, синтаксис AT&T отличается рядом строгих правил, особенно в отношении порядка операндов, обозначения размера данных и способа записи адресов. Основное применение он находит в среде операционных систем семейства UNIX и Linux, в частности, в ассемблере GNU Assembler (GAS), который является частью набора компиляторов GCC.
История
Синтаксис AT&T возник в контексте разработки операционной системы UNIX. Исходные версии UNIX были написаны на ассемблере для PDP-11, где использовался синтаксис, ставший предшественником AT&T. Когда архитектура x86 (Intel 8086, 80286, 80386) стала популярной, компания AT&T портировала на неё свои инструменты, включая ассемблер. В результате для x86 был принят синтаксис, основанный на традициях PDP-11 и VAX, а не на синтаксисе, предложенном Intel.
В 1980-х годах, с распространением UNIX-систем на платформе x86 (например, Xenix, System V), синтаксис AT&T стал стандартом де-факто для этой операционной среды. Позднее, с появлением проекта GNU и созданием ассемблера GAS (GNU Assembler), синтаксис AT&T был выбран в качестве основного режима работы по умолчанию. Это было обусловлено тем, что GAS разрабатывался как часть набора компиляторов GNU, ориентированного на UNIX-подобные системы. Хотя GAS поддерживает и синтаксис Intel (через директиву .intel_syntax), синтаксис AT&T остаётся его родным и наиболее тесно интегрированным с другими инструментами GNU, такими как GCC и GDB.
Основные отличия от синтаксиса Intel
Синтаксис AT&T принципиально отличается от синтаксиса Intel по нескольким ключевым параметрам. Эти различия часто вызывают путаницу у программистов, переходящих с одной платформы на другую.
Порядок операндов
Самое заметное отличие — порядок операндов в инструкции.
- Синтаксис Intel:
инструкция назначение, источник(например,mov eax, ebx— скопировать значение изebxвeax). - Синтаксис AT&T:
инструкция источник, назначение(например,movl %ebx, %eax— скопировать значение из%ebxв%eax). Источник всегда указывается первым, назначение — вторым.
Обозначение регистров
В синтаксисе AT&T имена всех регистров предваряются символом процента (%).
- Intel:
eax,ebx,ax,cl - AT&T:
%eax,%ebx,%ax,%cl
Обозначение непосредственных значений
Непосредственные значения (константы) в синтаксисе AT&T предваряются символом доллара ($).
- Intel:
mov eax, 5(загрузить число 5 в регистрeax) - AT&T:
movl $5, %eax(загрузить число 5 в регистр%eax)
Суффиксы размера операндов
В синтаксисе AT&T мнемоника инструкции часто содержит суффикс, указывающий на размер обрабатываемых данных. В синтаксисе Intel размер обычно определяется типом операндов (регистром или размером памяти).
b(byte) — 1 байт (8 бит)w(word) — 2 байта (16 бит)l(long) — 4 байта (32 бита)q(quad) — 8 байт (64 бита, для x86-64)
Примеры:
movb— переместить байтmovw— переместить словоmovl— переместить двойное слово (32-битное)movq— переместить четверное слово (64-битное)
Синтаксис адресации памяти
Синтаксис адресации памяти в AT&T является более сложным для восприятия, но более формальным. Общая форма записи: смещение(базовый_регистр, индексный_регистр, множитель). В синтаксисе Intel та же адресация записывается как [базовый_регистр + индексный_регистр * множитель + смещение].
Примеры:
- Intel:
mov eax, [ebx + ecx*4 + 8] - AT&T:
movl 8(%ebx, %ecx, 4), %eax - Intel:
mov eax, [var](загрузка значения из переменнойvar) - AT&T:
movl var, %eax(в AT&T переменная без скобок и префикса $ означает адрес в памяти).
Классификация инструкций
Инструкции в синтаксисе AT&T, как и в любом ассемблере x86, можно классифицировать по функциональному назначению. Ниже приведены основные группы с примерами записи в синтаксисе AT&T.
Инструкции передачи данных
movl %eax, %ebx— копирование 32-битного значения из%eaxв%ebx.pushl %ecx— помещение 32-битного значения регистра%ecxв стек.popl %edx— извлечение 32-битного значения из стека в регистр%edx.leal 4(%esp), %eax— загрузка эффективного адреса (адреса%esp + 4) в регистр%eax.
Арифметические и логические инструкции
addl $10, %eax— прибавление 10 к значению в регистре%eax.subl %ebx, %eax— вычитание значения%ebxиз%eax(результат в%eax).imull %ecx, %eax— умножение%eaxна%ecx(результат в%eax).andl $0xFF, %edx— логическое И между%edxи маской0xFF.orl %eax, %eax— логическое ИЛИ (часто используется для проверки на ноль).xorl %eax, %eax— исключающее ИЛИ (обнуление регистра).
Инструкции управления потоком
jmp label— безусловный переход на меткуlabel.je label— переход, если равенство (флаг ZF установлен).jne label— переход, если не равно.call function— вызов подпрограммыfunction.ret— возврат из подпрограммы.cmpl %eax, %ebx— сравнение%eaxи%ebx(вычисление%ebx - %eaxбез сохранения результата, только установка флагов).
Строковые и прочие инструкции
rep movsl— повторение инструкцииmovsl(перемещение строки 32-битных слов) число раз, указанное в регистре%ecx.cld— сброс флага направления (DF) для строковых операций.
Применение
Синтаксис AT&T является доминирующим в следующих областях:
- Разработка под Linux и другие UNIX-подобные системы: Абсолютное большинство встроенного ассемблерного кода в ядре Linux, драйверах и системных библиотеках написано с использованием синтаксиса AT&T. Компилятор GCC, при вставке ассемблерного кода на C (inline assembly), по умолчанию использует именно этот синтаксис.
- Обратная разработка (Reverse Engineering) в среде Linux: Дизассемблеры, такие как
objdump(с флагом-d), по умолчанию выводят код в синтаксисе AT&T. Для получения синтаксиса Intel требуется явно указать флаг-M intel. - Отладка с использованием GDB: Отладчик GNU GDB (GNU Debugger) по умолчанию отображает дизассемблированный код в синтаксисе AT&T. Это может быть изменено командой
set disassembly-flavor intel. - Образовательные курсы по системному программированию: Многие университетские курсы, особенно в рамках изучения операционных систем и архитектуры компьютеров, используют синтаксис AT&T, так как он тесно связан с инструментарием GNU.
Критика
Синтаксис AT&T часто подвергается критике за его неинтуитивность для начинающих и за избыточную многословность по сравнению с синтаксисом Intel.
- Обратный порядок операндов: Главный источник ошибок. Программисты, привыкшие к синтаксису Intel, где назначение стоит слева, часто путают источник и назначение в AT&T, что приводит к неверным результатам.
- Избыточные символы: Необходимость ставить
%перед регистрами и$перед константами делает код более громоздким и менее читаемым, особенно при работе с длинными строками. - Сложность адресации: Синтаксис адресации памяти
смещение(база, индекс, множитель)считается менее наглядным, чем[база + индекс * множитель + смещение]в синтаксисе Intel. - Неочевидность суффиксов: Хотя суффиксы размера (
b,w,l,q) делают размер операнда явным, они добавляют лишний символ к каждой инструкции, что увеличивает объём кода.
Несмотря на критику, синтаксис AT&T остаётся стандартом для инструментов GNU и широко используется в сообществе разработчиков открытого программного обеспечения. Его изучение необходимо для глубокого понимания работы операционных систем семейства UNIX и низкоуровневого программирования на платформе x86.
Интересные факты
- Ассемблер GNU Assembler (GAS) может работать как в режиме AT&T, так и в режиме Intel. Переключение между ними осуществляется директивой
.intel_syntax noprefix(для синтаксиса Intel без префиксов%и$) и.att_syntaxдля возврата к AT&T. - Несмотря на то, что синтаксис AT&T ассоциируется с UNIX, он также поддерживается некоторыми ассемблерами для Windows, например, в составе инструментов Cygwin и MinGW.
- В документации к процессорам Intel и AMD официально используется синтаксис Intel, что делает синтаксис AT&T вторичным по отношению к аппаратной документации.
Источники
- Intel 64 and IA-32 Architectures Software Developer's Manual, Volume 2: Instruction Set Reference.
- GNU Assembler (GAS) Manual.
- «Язык ассемблера для процессоров Intel» (К. Ирвин).
- «Low-Level Programming: C, Assembly and Program Execution on Intel 64 Architecture» (И. Жуков).
BFOmetr — база данных и аналитика по компаниям России.
На главную BFOmetr →