Правильная интерпретация начинается с адреса, который, как известно, является началом инструкции.
(Этот ответ, конечно, относится к процессорам с инструкциями переменной длины, таким как архитектура Intel x86.)
Когда процессор интерпретирует инструкции, он всегда начинает интерпретацию в определенном месте, потому что:
- это было следующее местоположение после ранее интерпретированной инструкции,
- это былоцель инструкции перехода (включая возврат из ловушки и другие специальные инструкции),
- это было начальное начальное местоположение при инициализации процессора, или
- это был адрес в таблице прерываний илидругая специальная структура данных, используемая для управления системой.
Все это места, которые, как известно, являются началом инструкций, потому что они были разработаны таким образом: мы писали программное обеспечение, и в этих местах мыпоставить инструкцию.
При интерпретации инструкции процессор следует правилам кодирования команд.Он просматривает первый байт, и биты в этом байте указывают, являются ли следующие несколько байтов операционным кодом, модификаторами или операндами для текущей инструкции.Затем он интерпретирует следующие байты соответственно.Таким образом, E8 16 в первом байте инструкции будет интерпретироваться иначе, чем E8 16 байт в другом месте.
Дизассемблер запускается там, где пользователь говорит ему.Часто это адрес, заданный меткой в программе (такой как имя функции) или другой информацией, такой как значение счетчика текущей программы или адрес возврата, найденный в стеке.Эти адреса - все начало команд, поэтому дизассемблер интерпретирует байты так же, как процессор.
Иногда может не быть легкого доступа к информации о том, где начинаются инструкции в определенной области, и он может просто сказатьдизассемблер, чтобы начать дизассемблирование по произвольному адресу в середине региона.В этом случае первые несколько дизассемблированных инструкций могут быть неверными, поскольку дизассемблер интерпретирует байты, начиная с мест, которые обычно не являются началом инструкций.(Типичным примером этого является то, что кто-то отлаживает и знает текущий счетчик программы, но хочет оглянуться назад на последние дюжины или около того инструкций, не начиная с начала текущей подпрограммы. В этом случае можно сказать дизассемблеручтобы начать разборку 100 байт назад от счетчика текущей программы.) Однако часто случается так, что, по сути, случайно, одна из неправильно интерпретированных инструкций заканчивается в том месте, где начинается правильная инструкция.Затем дизассемблер правильно разбирает эту инструкцию, и она синхронизируется с правильной последовательностью команд, а оставшаяся разборка выполняется правильно.Поскольку большинство инструкций короткие, а длины инструкций значительно различаются, существует высокая вероятность, что это происходит в течение нескольких инструкций.
Можно поиграть с кодировками инструкций и создать последовательность байтов, которая представляет два разныхпотоки команд зависят от того, где вы начинаете выполнять его, так что байты кода операции одного потока являются байтами модификатора / операнда другого, и наоборот.Это не делается в обычном программировании, но демонстрирует, что интерпретация байтов инструкций зависит от начальной позиции.