Строя моего ассемблера для x86 я столкнулся с некоторыми проблемами с кодирующей JMP
инструкции:Как относительный JMP (x86) реализован в ассемблере?
OPCODE INSTRUCTION SIZE
EB cb JMP rel8 2
E9 cw JMP rel16 4 (because of 0x66 16-bit prefix)
E9 cd JMP rel32 5
...
(из моих любимого сайта инструкций x86, http://siyobik.info/index.php?module=x86&id=147)
Все являются относительными скачков, где размер каждой кодировки (операция + операнд) находится в третьем столбце.
Теперь моя оригинальная (и, следовательно, ошибка из-за этого) конструкция зарезервировала максимальное (5 байтов) пространство для каждой команды. Операнд еще не известен, потому что это переход в неизвестное место. Поэтому я реализовал механизм «переписать», который перезаписывает операнды в правильном месте в памяти, если местоположение прыжка известно, и заполняет остальные NOP
с. Это несколько серьезная проблема в жестких петлях.
Теперь моя проблема заключается в следующей ситуации:
b: XXX
c: JMP a
e: XXX
...
XXX
d: JMP b
a: XXX (where XXX is any instruction, depending
on the to-be assembled program)
Проблема заключается в том, что я хочу наименьшее возможное кодирование для JMP
инструкции (и не NOP
наполнения).
Я должен знать размер инструкции на c
, прежде чем я могу вычислить относительное расстояние между a
и b
для операнда в d
. То же самое относится к JMP
по адресу c
: ему необходимо знать размер d
, прежде чем он сможет рассчитать относительное расстояние между e
и a
.
Как существующие ассемблеры решают эту проблему или как вы это сделаете?
Это то, что я имею в виду, что решает проблему:
Первый закодировать все инструкции опкодами между
JMP
и его цели, если эта область содержит переменную величину опкод, используйте максимальный размер , например5
дляJMP
. Затем закодируйте относительныйJMP
на свою цель, выбирая минимально возможный размер кодирования (3, 4 или 5) и вычисляя расстояние. Если какой-либо код операции с переменным размером закодирован, измените все абсолютные операнды раньше и все относительные инструкции, которые проскакивают по этой закодированной инструкции: они перекодируются, когда их операнд изменяется, чтобы выбрать наименьший возможный размер. Этот метод гарантированно заканчивается, поскольку коды операций с переменным размером могут сокращаться (поскольку он использует максимальный размер).
Интересно, возможно, это избыточно решение, вот почему я задаю этот вопрос.
+1 за ссылку хорошей документации ASM –