Курс СРС SRS18
до ЛР9 рівень 3 → «5»↔ Лабораторна 9↔ Лекція 9⌨️ команди 4 · 1 нова
Самостійна робота · ~3 год

Інструменти дизасемблювання: objdump та wasm-objdump, синтаксис AT&T проти Intel

🌌 Розтин бінарника — Один і той самий байт-код охорони дизасемблер покаже у двох дзеркальних записах — AT&T чи Intel, з переставленими операндами. С.І.Д. читає обидва не змигнувши й хоче навчити ранера так само впевнено ходити і кварталом іменованих комірок, і Стосовою стійкою: прочитати mov задом наперед — значить повірити в брехню про те, що робить код.

📚 ТЕОРЕТИЧНІ ВІДОМОСТІ

Два синтаксиси однієї й тієї самої машинної мови

Машинний код x86-64 — це послідовність байтів; асемблерний текст — лише один із кількох можливих людяних записів для тих самих байтів (не «вихідний код», а виведене, реконструйоване представлення). Історично склалися два конкуруючі синтаксиси запису однієї й тієї самої інструкції: AT&T (традиційний для Unix-світу, використовується objdump за замовчуванням і асемблером GNU as) і Intel (використовується офіційною документацією Intel, MASM, NASM і доступний в objdump через прапорець -M intel). Обидва синтаксиси описують ту саму операцію — різниця суто нотаційна, але здатна повністю збити з пантелику, якщо переплутати їх під час читання чужого коду.

Ключові відмінності: порядок операндів — в AT&T джерело йде першим, призначення другим (mov %rax, %rbx означає «скопіювати значення з rax у rbx»), в Intel — навпаки, призначення першим (mov rbx, rax — та сама операція, той самий напрямок копіювання, просто операнди переставлені). Префікси регістрів — AT&T вимагає % перед іменем регістра (%rax), Intel — ні (rax). Позначення безпосередніх значень (immediate) — AT&T використовує $ ($42), Intel обходиться без префікса (42). Синтаксис адресації пам'яті — найпомітніша відмінність: AT&T пише disp(base, index, scale) (наприклад, -4(%rbp,%rax,4)), Intel — [base + index*scale + disp] (те саме: [rbp + rax*4 - 4]) — обидва записи обчислюють ідентичну ефективну адресу, лише інакше групують компоненти.

objdump -d <файл> дизасемблює секцію з машинним кодом (типово .text) у людяний асемблерний текст, за замовчуванням у AT&T- синтаксисі; прапорець -M intel перемикає вивід на Intel-синтаксис без жодної зміни фактичних машинних байтів — це виключно питання представлення. Для дизасемблювання WebAssembly-модулів існує паралельний інструмент з пакета WABT — wasm-objdump (з прапорцями -d для дизасемблювання секції коду й -x для повного дампу всіх секцій модуля, включно з таблицею типів, імпортами й експортами) — концептуально та сама ідея «показати машинну мову людяно», але для стекової байткод-моделі WASM замість регістрової x86-64.

Практична навичка читання дизасембльованого виводу — вміти впевнено працювати з обома нотаціями x86-64, оскільки різні джерела (онлайн- дизасемблери, документація процесора, зневаджувачі типу gdb з різними налаштуваннями) можуть показувати той самий код у будь-якому з двох синтаксисів без попередження. Уміння «на льоту» впізнати, який синтаксис перед очима (наявність %/$ — явний маркер AT&T; квадратні дужки в адресації пам'яті — явний маркер Intel), і за потреби подумки чи інструментально перемкнутися на звичний — базова навичка низькорівневого аналізу коду незалежно від інструмента, яким цей код було спершу показано.

📖 ОПРАЦЮВАТИ

Прочитати man objdump (розділи -d/-M) і README wasm-objdump з пакета WABT; продизасемблювати один і той самий скомпільований файл двома способами (з опцією AT&T за замовчуванням і з опцією -M intel для objdump) і порівняти вивід.

🖥️ ТЕРМІНАЛ — СПРОБУЙ САМ
🎯 ЗАВДАННЯ
  1. Скомпілювати невелику функцію (наприклад, суму двох чисел) і продизасемблювати її двічі: objdump -d file (AT&T) і objdump -d -M intel file (Intel); зіставити рядок за рядком, які інструкції в AT&T відповідають яким в Intel.
  2. Знайти в отриманому виводі щонайменше одну інструкцію з адресацією пам'яті (наприклад, читання локальної змінної через зсув від rbp) і записати її вручну в обох синтаксисах, пояснивши компоненти адреси (base, index, scale, displacement).
  3. Скомпілювати .wat-модуль із попередньої теми у .wasm і виконати wasm-objdump -d на ньому, порівнявши структуру виводу (стекові інструкції) з тим, як виглядав дизасембльований x86-64-код тієї самої логічної операції.
  4. Виконати wasm-objdump -x на тому самому .wasm-модулі й знайти в повному дампі секції Type, Function, Export, зіставивши їх із відповідними частинами вихідного .wat-файлу.
  5. Написати короткий довідник-шпаргалку (5-6 рядків) з переліком головних відмінностей AT&T проти Intel синтаксису (порядок операндів, префікси регістрів/immediate, синтаксис адресації), який можна швидко звірити під час читання незнайомого дизасемблювання.
❓ КОНТРОЛЬНІ ПИТАННЯ
  1. Чим вивід objdump -d відрізняється від objdump -d -M intel для однієї й тієї самої функції, і в якому порядку записані операнди в кожному з синтаксисів?
  2. Які префікси використовує AT&T-синтаксис для позначення регістра і безпосереднього значення, і чим у цьому Intel-синтаксис відрізняється?
  3. Як записується адресація пам'яті виду «rbp мінус 4» в AT&T-синтаксисі, і як та сама адреса виглядає в Intel-синтаксисі?
  4. Чи змінюються фактичні машинні байти інструкції залежно від того, у якому синтаксисі objdump її показує?
  5. Яка утиліта з пакета WABT виконує для WebAssembly-модулів роль, аналогічну ролі objdump для x86-64?
  6. Що покаже прапорець -x утиліти wasm-objdump на відміну від -d?
  7. За якими двома візуальними маркерами можна швидко впізнати, у якому синтаксисі (AT&T чи Intel) записаний невідомий фрагмент асемблерного коду?
✅ САМОПЕРЕВІРКА

Чим вивід objdump -d відрізняється від objdump -d -M intel для однієї й тієї самої функції — і в якому порядку записані операнди в кожному з двох синтаксисів?

🥚 ПАСХАЛКА
В AT&T це mov $0xc1d,%eax, в Intel — mov eax,0xc1d; байти b8 1d 0c 00 00 при цьому ті самі. С.І.Д. каже, що читає цей рядок в обох записах без запинки — «як власне ім'я, у якому б порядку не переставили літери», — і що на дні голопроєктора його вигравіювали саме в Intel-порядку: C1D.
⌨️ КОМАНДИ НА ЦІЙ СТОРІНЦІ 4 · 1 нова

Кожна команда терміналу з цієї сторінки — одним реченням. Позначка нове — команда зустрічається в курсі вперше; далі вважаємо її знайомою.

objdump
Дизасемблер: objdump -d f.o показує машинний код як інструкції з адресами й опкодами (-M intel — синтаксис Intel).
grep
Фільтрує текст: виводить лише рядки, що містять шаблон (ps aux | grep bash).
wasm-objdump
З WABT: дизасемблер WebAssembly — -d показує опкоди й стекові інструкції, -x — секції та експорти.
sedнове
Потоковий редактор тексту; тут — sed -n '4,11p', щоб вивести лише рядки з 4-го по 11-й.

💡 Прочитати README прямо в терміналі: cat README.md (виведе весь файл) або less README.md (посторінково; вихід — клавіша q).
Довідка з будь-якої команди: man curl (повний посібник, вихід — q) або коротко curl --help; для підкоманд — docker run --help, cargo build --help.

← SRS17усі темиSRS19 →