Неоднозначность в декодировании определенных команд x87 FPU - PullRequest
1 голос
/ 21 ноября 2011

Я сталкиваюсь с неоднозначным случаем в отношении декодирования инструкций x87 FPU. Взгляните на следующую инструкцию, взятую на странице 3-380 тома 2A руководства по набору команд Intel [1].

D9 /0    --> FLD m32fp --> Push m32fp onto the FPU register stack.
D9 C0+i  --> FLD ST(i) --> Push ST(i) onto the FPU register stack.

Обе эти инструкции имеют одинаковый однобайтовый базовый код операции 0xD9. Первая инструкция имеет код операции расширения 0x00. Код операции расширения будет указан в поле 'reg' байта ModR / M. Но вторая инструкция - это 2-байтовый код операции с функцией «Добавить, чтобы получить регистр». Это означает, что:

D9 C0  --> FLD ST0  
D9 C1  --> FLD ST1  
(and so on)

У меня есть небольшая проблема, связанная с разграничением этих двух инструкций. Небольшой пример:

Теперь, предположим, я получил последовательность кода операции "D9 C1". Если мне нужно проверить, является ли это инструкция "FLD m32fp", я должен проверить, является ли поле 'reg' байта ModR / M 0x00 или нет. Если это так, то действительно используется инструкция "FLD m32fp".

Двоичное представление C1 равно "1100 0001". Предполагая, что бит 0 равен LSB, тогда бит 3-бит 5 (включительно) образуют поле 'reg' байта ModR / M "C1". Мы видим, что это действительно 0x00 (3 нуля).

Поэтому я сопоставляю последовательность кода операции "D9 C1" с инструкцией "FLD m32fp". Расшифровывая далее, мы видим, что операнд на самом деле становится "ecx" в этом случае. Но мы видим, что "FLD ST1" также имеет последовательность кода операции "D9 C1", и это фактическая инструкция, используемая для этой последовательности кода операции.

По сути, как я могу быть уверен, что последовательность кода операции "D9 C1" соответствует инструкции "FLD ST1", а не "FLD ecx"?

Очень похожие проблемы возникают и для инструкции "FMUL", так как принимает операнды так же, как здесь "FLD".

[1] http://www.intel.com/design/intarch/manuals/243191.HTM

Спасибо и всего наилучшего,
Хришикеш Мурали

1 Ответ

4 голосов
/ 21 ноября 2011

Это описано в «A.2.6. Инструкции по спасению кода операции», соответствующая часть:

Если байт ModR / M находится в пределах диапазон от 00H до BFH, биты 5, 4 и 3 байта ModR / M используются в качестве расширения кода операции, аналогично методике, используемой для 1- и 2-байтовых кодов операции (см. раздел A.2.5., « Опкод Расширения для одно- и двухбайтовых кодов операций »). Если байт ModR / M находится вне диапазона 00H через BFH весь байт ModR / M используется как расширение кода операции.

На вопрос:

Теперь предположим, что я получаю последовательность кода операции "D9 C1". Если мне нужно проверить, является ли это инструкция "FLD m32fp", то я должен проверить, является ли поле 'reg' байта ModR / M 0x00 или нет. Если это так, то это действительно инструкция "FLD m32fp".

Когда вы сталкиваетесь с инструкцией x87, вы должны проверить, равен ли байт mod / rm> = 0xC0 (соответствует полю mod 0b11 или 3), и в этом случае найдите его в таблице Таблица A-10 (для D9 ). Глядя туда, вы видите, что D9 C1 = FLD ST(0),ST(1).

Когда байт mod / rm равен <0xC0, используемая таблица - A-9. <code>D9 01 (mod = 0b00, расширение кода операции (reg) = 0b000, rm = 0b001) равно "FLD single-real", что в таблице 2-2 выглядит как fld dword [ecx].

Кроме того, нет такой инструкции, как "FLD ecx", поскольку вы не можете напрямую загружать из целочисленного регистра в стек FPU.

...