Что означает «escape-код операции»? - PullRequest
0 голосов
/ 15 сентября 2018

В руководстве по разработке программного обеспечения Intel Volumen 2A глава 2.1.2 говорится, что

Двухбайтовые форматы кода операции для инструкций общего назначения и SIMD состоят из одного из следующих:

  • Байт escape-кода операции 0FH в качестве основного кода операции и второй байт кода операции.
  • Обязательный префикс (66H, F2H или F3H), байт escape-кода операции и второй байт кода операции (такой же, как в предыдущем пункте).

Что такое «escape-код операции» и какова его цель?

1 Ответ

0 голосов
/ 15 сентября 2018

Код «escape» в общем случае - это код, который изменяет значение следующего байта / символа, а не означает что-то само по себе.

Например, при вводе с клавиатуры ASCII (например, в терминале Linux) alt + letter часто отправляется как escape + letter. (Где символ ASCII ESC равен 0x1b, поэтому, если я запускаю hd (hexdump) и набираю alt + x , я получаю 1b 78 от этого одного измененного нажатия клавиши.

Или внутри строки C в двойных кавычках, n - просто обычная буква. Но \n означает что-то другое: это новая строка, все еще один символ (после того, как компилятор обработает escape-последовательности). Обратная косая черта выходит за пределы n, поэтому это означает что-то еще.


Машинный код x86 имеет много однобайтовых кодов операций (например, 00 ADD r/m8, r8), но некоторые байтовые значения (например, 0F) являются первым байтом многобайтового кода операции, вместо быть целым кодом операции самостоятельно.

Расширение расширяет пространство кодирования с 256 возможных кодов операций (плюс перегрузки в поле / r байта ModRM) путем использования одного однобайтового кода операции (0f) для предоставления еще 256 2-байтовых кодов операций.

Например, 0F AF равно IMUL r32, r/m32, а 0F B6 равно movzx r32, r/m8. Эти общие инструкции были введены после оригинального 8086, и не осталось места для кодирования, чтобы дать им однобайтовые коды операций. (Или Intel сохраняла его для будущих escape-последовательностей.)


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

Эти байты являются префиксами размера операнда, REP / REPE и REPNE при использовании с кодами операций, в которых эти префиксы имеют смысл. Но для некоторых инструкций эти префиксы имеют смысл , а не : код операции уже подразумевает один размер операнда, и это не строковая инструкция. (Обратите внимание, что префикс размера адреса и префикса переопределения сегмента могут применяться к любой инструкции с явным операндом памяти, поэтому не используются в качестве обязательных префиксов. Также не является lock.)

Инструкция типа MMX 0F FC paddb mm0, mm1/m64 уже имеет фиксированный размер операнда SIMD. Ни один из этих префиксов не будет иметь для этого значения. Intel решила (для SSE2) сделать версию XMM 66 0F FC PADDB xmm1, xmm2/m128, добавив префикс размера операнда к кодировке MMX.

Аналогично, F3 0F 59 MULSS xmm1,xmm2/m32 - это mulps + префикс REP.

Intel использовала rep в качестве обязательного префикса для некоторых не-SIMD инструкций. например pause - это rep nop, tzcnt - это rep bsf (что интересно, потому что они делают то же самое на процессорах с / без BMI1, если вход не равен нулю). Это позволяет выполнять обратное сжатие, поскольку обычно процессоры игнорируют префиксы REP, которые они не понимают как применяемые.

(Преднамеренное использование неприменимых префиксов REP в качестве отступов не является будущим доказательством, однако, потому что кодировка может обрести некоторый смысл в будущих процессорах. Но когда известно как старое, так и новое значение, Intel часто гарантирует, что все старые процессоры декодируют rep nop как просто nop, что делает безопасным использование pause в спин-циклах без проверки битов функций CPUID.)

...