Система команд (ISA) и синтаксис Intel/AT&T
Контекст: раздел учит x86/x86-64 в Intel-синтаксисе (NASM). Эта статья объясняет, почему листинг
objdumpна Linux выглядит иначе, и чем система команд отличается от стиля записи asm.
Система команд — ISA
★ Система команд (англ. instruction set, ISA — Instruction 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) | Чаще фиксированной длины, проще |
| Адресация | Много режимов | Ограниченный набор |
| Типичный asm | mov eax, [ebx+8*4+offset] | ldr w0, [x1, #32] |
| Учебный фокус раздела | Да — NASM, Linux/Windows PC | Упоминается для сравнения |
Современные x86-процессоры внутри декодируют CISC-команды в более простые микрооперации, но программист и ассемблер по-прежнему оперируют классическими мнемониками ISA x86.
Краткий обзор 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/q — movl, 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, FASM | Intel | учебный стандарт раздела |
GAS (as) | AT&T | ключ -intel-syntax или директива .intel_syntax noprefix |
gcc -S | AT&T в .s | можно -masm=intel |
objdump -d на Linux | AT&T | objdump -d -M intel — Intel-стиль в листинге |
GDB disassemble | AT&T | set disassembly-flavor intel |
| Inline asm в GCC/Clang | AT&T | расширенный asm с constraints |
| Inline asm в MSVC | Intel | блок __asm { … } |
Собрали программу 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 и несколько модулей.
Как не смешивать уровни абстракции
При чтении кода полезно держать три вопроса отдельно:
- Какая ISA? (x86-64, ARM, …) — от этого зависят мнемоники и регистры.
- Какой диалект записи? (Intel или AT&T) — от этого зависит порядок операндов в листинге.
- Какой транслятор? (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 | Справочник — таблицы мнемоник |
См. также
Другие статьи этого же раздела в боковом меню (как на странице "О разделе"). Полный отказ от высокоуровневых языков нецелесообразен. Поэтому большинство компиляторов поддерживают встроенный ассемблер — механизм вставки ассемблерных инструкций непосредственно в код на C/C++. %macro, %define и %if в NASM — шаблоны инструкций без дублирования исходного текста. Разделение программы на .asm-файлы, global и extern, сборка объектников и линковка в ELF. Вызов ассемблерных функций из C и наоборот — System V AMD64 ABI, выравнивание стека, сборка. Секции ELF, символы, objdump и сопоставление дизассемблирования с исходным NASM-кодом. REP, MOVS, SCAS, STOS, флаг DF и доступ к данным по индексу через таблицу. SSE2 для float и double, регистры XMM, выравнивание; кратко про стек x87 и AVX. Microsoft x64 calling convention, shadow space, вывод в консоль и файлы через API вместо syscall. Основы ассемблера - синтаксис Intel/AT&T, базовые инструкции и принципы низкоуровневого программирования. Архитектура ассемблерных программ - взаимодействие с ОС, вызовы библиотек и организация низкоуровневого кода. Типизация, набор правил определения типа данных значений языка. Управляющие конструкции и команды процессора в ассемблере - регистр команд, переходы и управление потоком исполнения.История ассемблерных языков
Макросы и условная сборка
Несколько модулей и линковка
Взаимодействие с C и C++
Чтение исполняемого файла и листинга
Строковые инструкции и таблицы поиска
Числа с плавающей точкой и SIMD
Windows x64, WinAPI и отличия от Linux
Основы ассемблера
Архитектура ассемблерных программ
Типы данных и регистры
Управляющие конструкции и команды процессора