Сравнение синтаксисов Intel и AT&T

Тема в разделе "GAS/AT&T", создана пользователем Mikl___, 11 сен 2026 в 12:29.

  1. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    4.282
    Синтаксисы Intel и AT&T — это два разных способа записи ассемблерных инструкций для архитектуры x86/x64. Описывают одни и те же машинные команды, но по‑разному оформляют их в исходном коде.
    История
    Синтаксис 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.
    Ассемблеры, поддерживающие синтаксис AT&T
    • GAS (GNU Assembler) — входит в комплект компиляторов GCC, используется в Unix-подобных системах. Синтаксис AT&T характерен для Unix-подобных систем, так как Unix изначально разрабатывался в AT&T Bell Labs. GAS может работать как в режиме AT&T, так и в режиме Intel. Переключение между режимами осуществляется директивами .intel_syntax noprefix и .att_syntax для возврата к AT&T
    • LLVM Integrated Assembler (llvm-mc) — встроенный ассемблер инфраструктуры LLVM. Поддерживает синтаксис GAS и может использоваться как его прямая замена.
    • Free Pascal (встроенный ассемблер) — для процессоров x86 Free Pascal использует AT&T-синтаксис во встроенном ассемблере, исторически опирается на GAS.
    • AS (System V/386 Assembler) — ассемблер, давший название синтаксису. Разработан в AT&T Bell Labs для PDP-11 и унаследован в Unix-системах. В современных дистрибутивах Linux as символическая ссылка на GAS
    • Rust (asm! macro) — встроенный ассемблер Rust использует LLVM IAS "под капотом" и по умолчанию работает в режиме Intel на x86-64, но поддерживает AT&T-синтаксис через опцию options(att_syntax)
    • YASM (Yet Another Assembler) — первоначально задуман как переработка NASM. YASM кроссплатформенный, распространяется под лицензией BSD и поддерживает несколько форматов выходных файлов (ELF32/ELF64 (Linux/Unix), Mach‑O (macOS), COFF/MS COFF/MS64 COFF (Windows), RDOFF2 (чистый бинарный файл)). Поддерживает оба синтаксиса, выбор делается через опцию -p (например, -p gas).
    Основные отличия синтаксисов Intel и AT&T
    синтаксис
    IntelAT&T
    Порядок
    операндов
    mnemonic dest, src (приёмник источник)
    imul ebx, eax, 69
    mnemonic src, dest (источник приёмник)
    imull $69, %eax, %ebx
    Префикс
    регистров
    Просто имя: eax, ebxПеред именами регистров всегда ставится %:
    • 64-битные регистры %rax, %rbx, %rcx, %rdx, %rdi, %rsi, %rbp, %rsp, %r8-%r15
    • 32-битные регистры %eax, %ebx, %ecx, %edx, %edi, %esi, %ebp, %esp, %r8d-%r15d
    • 16-битных их младших половин: %ax, %bx, %cx, %dx, %di, %si, %bp, %sp, %r8w-%r15w.
    • 8-битные регистры: %ah, %al, %bh, %bl, %ch, %cl, %dh, %dl, %dil, %sil, %bpl, %spl, %r8b-%r15b
    • сегментные регистры %cs, %ds, %ss, %es, %fs, %gs.
    • yпpавляющие регистры %cr0, %cr2 , %cr3.
    • регистры отладки %db0, %db1, %db2, %db3, %db6 и %db7
    • тестовые регистры %tr6 и %tr7
    • регистры FPU: %st или %st(0), %st(1), %st(2), %st(3), %st(4), %st(5), %st(6) и %st(7)
    то, что вы должны ставить префикс % перед именем регистра, позволяет создавать переменные с тем же именем, что и регистры, что невозможно в синтаксисе Intel
    Размер
    операнда
    Задаётся явно в операнде или подразумевается контекстом:
    mov eax, ebx
    Размер операнда задается суффиксом, замыкающим инструкцию:
    movl %ebx, %eax
    movb %al,%ah
    movw %ax,%bx
    movq %rsi,%rbp
    addl, subl, incl, decl, divl, imull, lcall (call far)/call (call near), ljmp (jmp far)/jmp (jmp near), lret (retf)/ret (retn), pushl, leal, andl, orl, xorl, cmpl
    • b — байт (8-bit)
    • w — слово (16-bit)
    • l — двойное слово (32-bit)
    • q — учетверенное слово (64-bit)
    • x — 16 байт (128-bit vector)
    • y — 32 байта (256-bit vector)
    • z — 64 байта (512-bit vector)
    для чисто векторных операций (вроде addps) суффиксы обычно совпадают с синтаксисом Intel
    Константы
    • десятичное: mov rsi,11
      (mov rsi,11d)
    • двоичное: mov rsi,1011b
      (mov rsi,1011y)
    • шестнадцатеричное: mov rsi,0Bh
    • восьмеричное: mov rsi, 13o
      (mov rsi, 13q)
    используем $, числовые константы записываются в Си-соглашении:
    • десятичное: movq $11,%rsi
    • двоичное: movq $0b1011, %rsi
    • шестнадцатеричное: movq $0xb, rsi
    • восьмеричное: movq $013,%rsi
    Адреса
    памяти
    Квадратные скобки:
    [ebx+4]
    [rbp-8]
    Круглые скобки, смещение перед регистром:
    4(%ebx)
    -8(%rbp)
    Косвенная
    адресация/
    переходы

    • jmp eax
    • jmp [addr]
    • mov RDI,[RBX]
    • jmp table[ecx*4]
    • lea eax,[ebx+ecx]
    звёздочка для косвенности:
    • jmp *%eax
    • jmp *addr
    • movq (%rbx), %rdi
    • jmp *(table, %ecx, 4)
    • leal (%ebx,%ecx),%eax
    Переход
    по метке
    jmp label

    jmp dword ptr [label]
    jmp label
    # метка — адрес перехода
    jmp *label
    # в ячейке label хранится адрес перехода
    Масштабируемая
    индексация
    [ebx + ecx*4 + 8]
    база+индекс*масштаб+смещение
    8(%ebx, %ecx, 4)
    смещение (база, индекс, масштаб)
    ОСWindows, DOSLinux/Unix
    Комментарий
    однострочный
    ;
    • #
    • //
    • /* */
    Комментарий
    многострочный
    comment/* */
    Получить
    адрес
    переменной
    mov RSI, offset message
    lea RSI,message
    используем $:
    movq $message,%rsi
    lea message(%rip), %rsi
    Значение
    переменной
    mov count,ecxне используем $:
    movl %ecx,count
    Типы
    целочисленных
    данных
    • DB (BYTE, SBYTE)
    • DW (WORD, SWORD)
    • DD (DWORD, SDWORD)
    • DQ (QWORD)
    • OWORD
    • .byte
    • .short (.word)
    • .long
    • .quad
    • .octa
    Типы
    вещественных
    данных
    • DD (REAL4)
    • DQ (REAL8)
    • DT (TBYTE, REAL10)
    • .float
    • .double
    • .tfloat
    Повторениеzeros dd 10 dup (0)zeros: .fill 10, 4, 0
    Определение
    константы
    Имя equ значение
    Имя = значение
    MAX_BUFFER TEXTEQU 1024
    ; Символ, созданный через TEXTEQU, можно переопределять (изменять) в коде сколько угодно раз. Директива EQU такого не позволяет
    name_macro TEXTEQU <"Hello, World!">
    ;Применяется для макросов, замены фрагментов текста, инструкций или имен регистров
    .equ Имя значение
    Имя = значение
    .equ MAX_BUFFER, 1024
    # Определение константы
    .set TEMP_REG, %eax
    # Еще один вариант, часто используется для регистров
    Определение
    данных
    Имя тип значениеИмя: .тип значение
    Строка из символов
    • Hello db 'Hello, world!',0
    • Alphabet db 'abcdef'

    • Hello: .asciz "Hello, world!"
    • Alphabet: .ascii "abcdef"
    Внутри кавычек могут быть \n \t \r
    Команды преобразования размера
    • cbw
    • cwde
    • cwd
    • cdq
    • cdqe
    • cqo
    • cbtw
    • cwtl
    • cwtd
    • cltd
    • cltq
    • cqto
    Строковые
    команды
    • lodsb/lodsw/lodsd/lodsq
    • stosb/stosw/stosd/stosq
    • movsb/movsw/movsd/movsq
    • scasb/scasw/scasd/scasq
    • cmpsb/cmpsw/cmpsd/cmpsq

    • lodsb/lodsw/lodsl/lodsq
    • stosb/stosw/stosl/stosq
    • movsb/movsw/movsl/movsq
    • scasb/scasw/scasl/scasq
    • cmpsb/cmpsw/cmpsl/cmpsq
    Префиксы REP, REPE, REPNE совпадают: rep movsl
    могут указываться регистры: movsb %esi, %edi
    movsx/movzxmovsx edx,almovsbl %al,%edx
    Команды SIMD практически совпадают, но придется учитывать порядок операндов
    Пересылка данныхmovd xmm0, eaxmovd %eax, %xmm0
    # Перенос 32-бит из CPU в SIMD
    movaps xmm1, [rbx]movaps (%rbx), %xmm1
    # Загрузка 128-бит вектора (выровненного)
    Сложениеpaddd xmm0, [rcx]paddd (%rcx), %xmm0
    # Поэлементное сложение четырех 32-битных целых
    addps xmm0, xmm1addps %xmm1, %xmm0
    # Сложение 4-х single float (SSE)
    vaddps ymm0, ymm1, ymm2vaddps %ymm2, %ymm1, %ymm0
    # Сложение 8-ми single float (AVX, 3 операнда)
    Умножениеmulpd xmm0, xmm1mulpd %xmm1, %xmm0
    # Векторное умножение double float
    Применение
    Синтаксис 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.
    Критика со стороны приверженцев синтаксиса Intel
    Синтаксис AT&T неинтуитивен для начинающих и избыточно многословен по сравнению с синтаксисом Intel.
    • Обратный порядок операндов: Главный источник ошибок для человека привыкшего к синтаксису Intel, путаница источника и приемника в AT&T приведет к неверным результатам.
    • Избыточные символы: Необходимость ставить % перед регистрами и $ перед константами делает текст программы более громоздким и менее читаемым, особенно при работе с длинными строками.
    • Сложность адресации
    • Неочевидность суффиксов: Хотя суффиксы размера (b, w, l, q) делают размер операнда явным, но добавляют лишний символ к каждой инструкции, что увеличивает объём программ.
    Тем не менее, синтаксис AT&T — стандарт для инструментов GNU, используется в сообществе разработчиков открытого программного обеспечения. Изучение синтаксиса AT&T необходимо для понимания работы ОС семейства UNIX и низкоуровневого программирования на платформе x86-64.
    Источники
     

    Вложения:

    Последнее редактирование: 13 сен 2026 в 06:22
    Application и MaKsIm нравится это.
  2. TermoSINteZ

    TermoSINteZ Синоби даоса Команда форума

    Публикаций:
    2
    Регистрация:
    11 июн 2004
    Сообщения:
    3.570
    Адрес:
    Russia
    опечатка

    так же пункт "Получить значение в переменной" звучит невалидно
    надо переделать на "записать значение в переменную"
     
  3. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    4.282
    TermoSINteZ,
    спасибо, поправил. В MASM постфиксы двоичного числа B (старое) и Y (новое) чтобы не путать с шестнадцатеричным числом, у которого последняя цифра B, .radix 16 позволяет не ставить после шестнадцатеричного числа постфикс H/h. При включенном .radix 16 число 10B это 2 или 267?
    Сводная таблица для основных языков:
    C/C++PascalBASICMASM
    DEC12121212 (отсутствие постфикса),12d, 12t
    HEX0xC$C&hC0Ch, 3F800000r
    OCT014&o1414o, 14q
    BIN&b11001100b, 1100y
    «Microsoft Macro Assembler Programmer's Guide» MASM 6.1 Глава 1 «Understanding Global Concepts», раздел «Integer Constants and Constant Expressions», стр 31 — «y for binary (or b if the default radix is not hexadecimal)»
    И чтобы не упрекнули что R не используется для 16-ричных чисел «Microsoft Macro Assembler Programmer's Guide», глава 6, стр 157 — «Using Floating-Point Numbers». «The number must begin with a decimal digit (0–9) and end with the real-number designator (R). For example, the hexadecimal number 3F800000r can serve as an initializer for a doubleword-sized variable.»
    Правила для суффикса R
    Из Programmer's Guide:
    • Количество шестнадцатеричных цифр должно точно соответствовать размеру типа: 8 цифр для REAL4 (32 бита), 16 цифр для REAL8 (64 бита), 20 цифр для REAL10 (80 бит).
    • Если добавляется ведущий ноль, то 9, 17 и 21 цифра соответственно.
    • Точка (.) в записи с суффиксом R не допускается — это шестнадцатеричное кодирование числа, а не десятичная запись.
     

    Вложения:

    Последнее редактирование: 13 сен 2026 в 04:59
    Ahimov нравится это.