Как написать дизассемблер?

Мне интересно писать x88-дизассемблер как образовательный проект.

Единственный реальный ресурс, который я нашел, это Spiral Space, " Как написать дизассемблер". Хотя это дает хорошее описание высокого уровня различных компонентов дизассемблера, я заинтересован в более подробных ресурсах. Я также быстро посмотрел на исходный код NASM, но это немного тяжелый, чтобы учиться.

Я понимаю, что одной из главных задач этого проекта является довольно большой набор команд x86, с которыми мне придется справиться. Меня также интересуют базовая структура, базовые ссылки дизассемблера и т.д.

Может ли кто-нибудь указать мне какие-либо подробные ресурсы при написании дизассемблера x86?

Ответ 1

Посмотрите раздел 17.2 80386 Справочник по программисту. Дисассемблер - это просто прославленный конечный автомат. Шаги в разборке:

  • Проверьте, является ли текущий байт байтом префикса команд (F3, F2 или F0); если да, то у вас есть префикс REP/REPE/REPNE/LOCK. Перейти к следующему байту.
  • Убедитесь, что текущий байт является байтом размера адреса (67). Если это так, декодировать адреса в остальной части инструкции в 16-битном режиме, если в настоящее время находится в 32-битном режиме, или декодировать адреса в 32-битном режиме, если в настоящее время в 16-разрядном режиме
  • Убедитесь, что текущий байт является байтом размера операнда (66). Если это так, декодируйте непосредственные операнды в 16-битном режиме, если в настоящее время в 32-битном режиме, или декодируйте непосредственные операнды в 32-битном режиме, если в настоящее время в 16-битном режиме
  • Проверьте, является ли текущий байт байтом переопределения сегмента (2E, 36, 3E, 26, 64 или 65). Если это так, используйте соответствующий регистр сегментов для декодирования адресов вместо регистра сегмента по умолчанию.
  • Следующий байт - это код операции. Если код операции 0F, то это расширенный код операции и считывает следующий байт в виде расширенного кода операции.
  • В зависимости от конкретного кода операции читайте и декодируйте байт Mod R/M, байт индекса индекса (SIB), смещение (0, 1, 2 или 4 байта) и/или немедленное значение ( 0, 1, 2 или 4 байта). Размеры этих полей зависят от кода операции, переопределения размера адреса и переопределения размера операнда, предварительно декодированного.

Код операции сообщает вам о выполняемой операции. Аргументы кода операции могут быть декодированы в виде значений Mod R/M, SIB, смещения и немедленного значения. Существует множество возможностей и множество особых случаев из-за сложного характера x86. См. Ссылки выше для более подробного объяснения.

Ответ 2

Я бы рекомендовал проверить некоторые дизассемблеры с открытым исходным кодом, желательно distorm и особенно "disOps (Instructions Sets DataBase)" (ctrl + find это на странице).

Документация сама по себе наполнена сочной информацией о кодах операций и инструкциях.

Цитата из https://code.google.com/p/distorm/wiki/x86_x64_Machine_Code

80x86 Инструкция:

Инструкция 80x86 делится на количество элементов:

  • Префиксы инструкций влияют на поведение инструкции работа.
  • Обязательный префикс, используемый в качестве байта кода операции для инструкций SSE.
  • Окод байтов может быть один или несколько байтов (до 3 целых байтов).
  • Модем ModR/M является необязательным и иногда может содержать часть сам код операции.
  • Байт SIB является необязательным и представляет собой сложную память. формы.
  • Смещение необязательно, и это значение разного размера байтов (байт, слово, длинный) и используется как смещение.
  • Immediate является необязательным и используется как общее числовое значение, построенное от разного размера байтов (байт, слово, длинное).

Формат выглядит следующим образом:

/-------------------------------------------------------------------------------------------------------------------------------------------\
|*Prefixes | *Mandatory Prefix | *REX Prefix | Opcode Bytes | *ModR/M | *SIB | *Displacement (1,2 or 4 bytes) | *Immediate (1,2 or 4 bytes) |
\-------------------------------------------------------------------------------------------------------------------------------------------/
* means the element is optional.

Структуры данных и фазы декодирования описаны в https://code.google.com/p/distorm/wiki/diStorm_Internals

Цитата:

Фазы декодирования

  • [Префиксы]
  • [Fetch Opcode]
  • [Фильтровать опкод]
  • [Извлечь операнды (ов)]
  • [Форматирование текста]
  • [Hex Dump]
  • [Декодированная инструкция]

Также объясняется каждый шаг.


Исходные ссылки хранятся по историческим причинам:

http://code.google.com/p/distorm/wiki/x86_x64_Machine_Code и http://code.google.com/p/distorm/wiki/diStorm_Internals p >

Ответ 3

Начните с некоторой небольшой программы, которая была собрана, и которая дает вам как сгенерированный код, так и инструкции. Получите ссылку на архитектура команд и проработайте с помощью некоторого сгенерированного кода с помощью ссылки на архитектуру. Вы обнаружите, что инструкции имеют очень стереотипную структуру inst op op op с различным количеством операндов. Все, что вам нужно сделать, это перевести шестнадцатеричное или восьмеричное представление кода в соответствии с инструкциями; немного поиграет, покажет это.

Этот процесс, автоматизированный, является ядром дизассемблера. В идеале вам, вероятно, захочется построить n массив структур инструкций внутри (или извне, если программа действительно большая). Затем вы можете перевести этот массив в инструкции в формате ассемблера.

Ответ 4

Для загрузки требуется таблица кодов операций.

Фундаментальная структура данных поиска - это trie, однако таблица будет достаточно хорошо, если вам не все равно о скорости.

Чтобы получить базовый тип кода операции, начните с соответствия таблице.

Существует несколько способов хранения аргументов регистратора; однако есть достаточно особых случаев, требующих выполнения большинства из них индивидуально.

Так как это образовательный, посмотрите на ndisasm.

Ответ 5

Оформить заказ objdump источники - это отличный инструмент, он содержит много таблиц опкодов, и его источники могут стать хорошей базой для создания вашего собственного дизассемблера.