🌌 Розтин бінарника — Один і той самий байт-код охорони дизасемблер покаже у двох дзеркальних записах — 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) і порівняти вивід.
Чим вивід objdump -d відрізняється від objdump -d -M intel для однієї й тієї самої функції — і в якому порядку записані операнди в кожному з двох синтаксисів?
mov $0xc1d,%eax, в Intel — mov eax,0xc1d; байти b8 1d 0c 00 00 при цьому ті самі. С.І.Д. каже, що читає цей рядок в обох записах без запинки — «як власне ім'я, у якому б порядку не переставили літери», — і що на дні голопроєктора його вигравіювали саме в Intel-порядку: C1D.Кожна команда терміналу з цієї сторінки — одним реченням. Позначка нове — команда зустрічається в курсі вперше; далі вважаємо її знайомою.
objdumpobjdump -d f.o показує машинний код як інструкції з адресами й опкодами (-M intel — синтаксис Intel).grepps aux | grep bash).wasm-objdump-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.