Перейти к основному содержимому

Система команд (ISA) и синтаксис Intel/AT&T

Разработчику Архитектору

Контекст: раздел учит x86/x86-64 в Intel-синтаксисе (NASM). Эта статья объясняет, почему листинг objdump на Linux выглядит иначе, и чем система команд отличается от стиля записи asm.


Система команд — ISA

Система команд (англ. instruction set, ISAInstruction Set Architecture) — соглашение о том, какие операции умеет выполнять процессор и как они кодируются в машинных словах (опкод + поля операндов).

ISA задаёт:

  • набор операций (сложение, переход, загрузка из памяти, системный вызов через инструкции вроде syscall);
  • регистры и их размеры;
  • режимы адресации (регистр, память, константа);
  • правила флагов и прерываний.

Разные микропроцессоры с одинаковой ISA могут иметь разную внутреннюю реализацию (конвейер, кэш), но программа, собранная под эту ISA, остаётся совместимой на уровне команд. Пример — процессоры Intel и AMD с семейством x86-64: общая система команд, разный «железный» дизайн.

Язык ассемблера — человекочитаемая запись той же ISA. Мнемоника mov на x86 и ldr на ARM — разные слова для разных систем команд. Подробнее о терминах — в о разделе и Основах.


CISC и RISC — два подхода к ISA

Исторически архитектуры делят на CISC (Complex Instruction Set Computer) и RISC (Reduced Instruction Set Computer). Это не «лучше/хуже», а разный компромисс между сложностью одной команды и гибкостью компилятора.

ПризнакCISC (пример x86)RISC (пример ARM, RISC-V, MIPS)
ИнструкцииЧасто сложные, переменной длины (x86)Чаще фиксированной длины, проще
АдресацияМного режимовОграниченный набор
Типичный asmmov eax, [ebx+8*4+offset]ldr w0, [x1, #32]
Учебный фокус разделаДа — NASM, Linux/Windows PCУпоминается для сравнения

Современные x86-процессоры внутри декодируют CISC-команды в более простые микрооперации, но программист и ассемблер по-прежнему оперируют классическими мнемониками ISA x86.

Семейства ISA в энциклопедии

Краткий обзор x86, ARM, MIPS, RISC-V — в справочнике и в таблице архитектур в истории. Регистры x86-64 разбираются в типах данных и регистрах.


Диалект синтаксиса — Intel и AT&T

Для одной и той же ISA x86 существуют два распространённых стиля текста. Машинные байты после сборки могут совпадать; меняется только запись для человека.

ПравилоIntel (NASM, MASM, многие учебники)AT&T (GAS по умолчанию, objdump на Linux)
Порядок операндов movкуда, откудаmov dst, srcоткуда, кудаmov src, dst
Регистрыeax, rax, без префикса%eax, %rax
Константа (immediate)42, 0x10$42, $0x10
Память[rbx + 8] — адрес в скобках8(%rbx) — смещение перед скобками
Размер операндачасто по имени регистра (mov eax, …)суффикс b/w/l/qmovl, movq
Сегментные именаредко в 64-bit user code(%rip) для PC-relative

★ Запомнить проще так: в Intel «слева получатель», как в присваивании C: x = y. В AT&T порядок как у мнемоники «переместить» — сначала источник, потом приёмник.


Одна операция — два записи

Загрузка константы в 32-битный регистр (EAX = 10):

; Intel (NASM)
mov eax, 10
# AT&T (GAS)
movl $10, %eax

Копирование между регистрами (EBX = EAX):

; Intel
mov ebx, eax
# AT&T
movl %eax, %ebx

Сложение с памятью (EAX += dword по адресу RBX):

; Intel
add eax, [rbx]
# AT&T
addl (%rbx), %eax

Условный переход «если равно — на метку» после cmp eax, ebx:

; Intel
cmp eax, ebx
je equal_label
# AT&T
cmpl %ebx, %eax
je equal_label

Вызов функции по метке helper:

; Intel
call helper
# AT&T
call helper

call/ret и метки в обоих стилях читаются похоже; чаще всего путают mov и add из‑за порядка операндов и обозначения памяти.


PC-relative адрес строки (x86-64 Linux)

Типичный фрагмент из Первой программы — адрес буфера для write:

; Intel (NASM), Linux x86-64
lea rsi, [rel msg]
# AT&T (GAS)
lea msg(%rip), %rsi

Смысл один: сформировать адрес msg относительно текущей инструкции (позиционно-независимый код, PIE).


Кто какой синтаксис использует

ИнструментСинтаксис по умолчаниюПримечание
NASM, MASM, FASMIntelучебный стандарт раздела
GAS (as)AT&Tключ -intel-syntax или директива .intel_syntax noprefix
gcc -SAT&T в .sможно -masm=intel
objdump -d на LinuxAT&Tobjdump -d -M intel — Intel-стиль в листинге
GDB disassembleAT&Tset disassembly-flavor intel
Inline asm в GCC/ClangAT&Tрасширенный asm с constraints
Inline asm в MSVCIntelблок __asm { … }
Практика на Linux

Собрали программу NASM (Intel), открыли в отладчике — видите AT&T. Это нормально: байты те же. Для сравнения с исходником: objdump -d -M intel prog или в GDB set disassembly-flavor intel. Разбор ELF — в чтении бинарника.


GAS в режиме Intel

Если нужно писать .s для GCC в привычном стиле:

.intel_syntax noprefix
mov rax, 1
mov rdi, 1
syscall
.att_syntax prefix

Директивы секций у GAS (.globl, .data) отличаются от NASM (section .data, global) — см. взаимодействие с C и несколько модулей.


Как не смешивать уровни абстракции

При чтении кода полезно держать три вопроса отдельно:

  1. Какая ISA? (x86-64, ARM, …) — от этого зависят мнемоники и регистры.
  2. Какой диалект записи? (Intel или AT&T) — от этого зависит порядок операндов в листинге.
  3. Какой транслятор? (NASM, GAS, MASM) — от этого зависят директивы section / .section.

Ошибка новичка — спорить «как правильно писать mov», имея в виду разные диалекты одной ISA. В этом разделе эталон — Intel + NASM; AT&T нужен, чтобы понимать вывод GNU-инструментов и листинги компилятора C.


Куда дальше

ШагМатериал
1Основы — структура строки, стек, секции
2Типы данных и регистры — размеры, флаги, endianness
3Управляющие конструкцииCMP, Jcc, циклы
4Первая программа — сборка NASM под Linux x86-64
5Справочник — таблицы мнемоник

См. также

Другие статьи этого же раздела в боковом меню (как на странице "О разделе").