Ваша книга вводит в заблуждение, в один проход ассемблере, так как большинство людей будет понять термин, может генерировать перемещаемый объектный файл, испуская специальные данные, называемые репозициями, которые сообщают компоновщику/загрузчику, как переместить код. Кажется, что в книге используется конкретное определение «однопроходного ассемблера», которое по своему определению не может выводить «перемещаемый объектный файл» с перестановками.
Однако верно, что в целом вы не можете определить, может ли данная инструкция машинного кода перемещаться, если нет набора доступных перемещений, чтобы сообщить, что является или не перемещается (и как переместить инструкции, т). Некоторые инструкции делают это очевидным, например, вы можете определить, может ли инструкция JMP TO
перемещаться или не основываться на кодировании адреса назначения. Если адрес назначения закодирован как относительное смещение к адресу инструкции JMP, то он перемещается. С другой стороны, если кодируется как абсолютный адрес, инструкция не перемещается. В первом случае программа может быть перемещена в память без изменений, и инструкция JMP по-прежнему будет переходить к одному и тому же коду. Во втором случае команда JMP всегда будет переходить на тот же адрес независимо от того, где код был перемещен, если инструкция не изменена, чтобы перейти к правильному месту.
В x86 сборка конкретный пример первого случая будет следующим:
0056: EB 10 JMP LO
Первый байт в инструкции, является опкод EB
(номера я использую здесь все в шестнадцатеричном формате) , что указывает на приблизительную инструкцию JMP с 8-битным относительным смещением. Второй байт в инструкции - это 8-битное относительное смещение. Фактически это относится к началу следующей инструкции, поэтому адрес, подпрыгший, равен 0056 + 2 + 10
или 0068
.
В 6502 сборке пример второго случая будет:
0056: 4C 68 00 JMP LO
В этом случае байт кода операции 4C
указывает на команду JMP, которая имеет использует 2-байтовое абсолютный адрес в кодируются в инструкции. Следующие два байта составляют этот адрес в порядке байтов младшего порядка: 0068
.
Другой простой пример - это что-то вроде ADD 1,2
, в котором используются только регистры. Поскольку нет адресов, эта инструкция может быть перенесена без изменений, поскольку в инструкции нет адресов. Проблема связана с инструкцией типа ADD #1000,2
, которая добавляет буквальное значение 1000 к значению, хранящемуся в регистре 2. В этом случае число 1000 закодировано в инструкции, и нет способа узнать, используется ли этот номер в качестве адреса или не. Из контекста нет никакого способа узнать, имеет ли инструкция в нем закодированный адрес или нет.
Пример как ADD #1000,2
в 16-битном языке x86 сборки были бы следующие:
0068: 81 C3 EB 03 ADD BX, 1000
Последние два байта команды EB 03
является значение 1000 в десятичной системе и где непосредственный (дословный) закодирован операнд инструкции. Команда добавляет 1000 в регистр BX. Невозможно узнать, без каких-либо контекстов, должен ли 1000 быть адресом или нет. Например, код может вычислять адрес чего-либо, расположенного в таблице, начиная с адреса 1000.
Возможно, вам захочется найти другую книгу, поскольку она, как представляется, проводит много времени на машинных архитектурах, которые были устаревшими 24 года назад и сегодня абсолютно архаичны.
Действительно не отличается от вашего другого вопроса. В этой книге говорится о передислоцированном бит? это будет машинный код. для других наборов инструкций в целом, был ли адрес загружен в регистр, а затем разветвлен, потому что он был внешним адресом или просто потому, что это так сделал автор или компилятор? (vs с использованием относительного смещения pc) –
Я думаю, что вы должны прекратить читать эту книгу. Получите gnu toolchain (желательно что-либо, кроме x86, arm, mips, являются хорошим выбором) и просто компилируйте, дизассемблируйте ссылку и дизассемблируйте, а также задумайтесь или даже напишите свои собственные инструменты (ассемблер, а затем компоновщик), чтобы увидеть, как проблемы или могут быть решена. –