FSTENV? Едва ли можно найти какую-либо информацию об этой инструкции

У меня есть эта инструкция в программе:

FSTENV (28-BYTE) PTR SS:[ESP-1C]

Что оно делает?

Какие регистры он использует и обновляет?

Спасибо!

4 ответа

Решение

Джерри Гробинс Ответ правильный.
В случае, если вы задаетесь вопросом о (28-BYTE) PTR SS:[ESP-1C]:
Это эффективный адрес, где должна храниться среда FP, он обозначает 28-байтовую версию команды и указывает на 28 (0x1c) байтов ниже указателя стека в сегменте стека.
Я просто добавляю официальное описание от Intel, которое я нашел с помощью поисковой системы.

Описание

Сохраняет текущую операционную среду FPU в месте памяти, указанном с операндом-адресатом, а затем маскирует все исключения с плавающей точкой. Операционная среда FPU состоит из управляющего слова FPU, слова состояния, слова тега, указателя команд, указателя данных и последнего кода операции. На рисунках с 7-13 по 7-16 в томе 1 Руководства разработчика программного обеспечения Intel® для архитектуры IA-32 показано расположение в памяти хранимой среды в зависимости от режима работы процессора (защищенного или действительного) и текущего операнда. атрибут -size (16-битный или 32-битный). В режиме virtual-8086 используются раскладки реального режима.

Инструкция FSTENV проверяет и обрабатывает любые ожидающие немаскированные исключения с плавающей запятой перед сохранением среды FPU; инструкция FNSTENV - нет. Сохраненное изображение отражает состояние FPU после того, как все инструкции с плавающей запятой, предшествующие команде FSTENV/FNSTENV в потоке команд, были выполнены.

Эти инструкции часто используются обработчиками исключений, поскольку они обеспечивают доступ к инструкциям FPU и указателям данных. Среда обычно сохраняется в стеке. Маскировка всех исключений после сохранения среды предотвращает прерывание обработчиком исключений исключений с плавающей точкой. Совместимость с архитектурой Intel®

При работе процессора Pentium® или Intel486™ в режиме совместимости с операционной системой MS-DOS* возможно (при необычных обстоятельствах), чтобы инструкция FNSTENV была прервана перед выполнением для обработки ожидающего исключения FPU. Описание этих обстоятельств см. В разделе "Инструкции FPU без ожидания могут получить прерывание FPU в окне" в Приложении D к Руководству разработчика программного обеспечения по архитектуре архитектуры Intel®, том 1, IA-32. Инструкция FNSTENV не может быть прервана таким образом на процессоре Pentium Pro.

операция

DEST [FPUControlWord) <- FPUControlWord;

DEST [FPUStatusWord) <- FPUStatusWord;

DEST [FPUTagWord) <- FPUTagWord;

DEST [FPUDataPointer) <- FPUDataPointer;

DEST [FPUInstructionPointer) <- FPUInstructionPointer;

DEST [FPULastInstructionOpcode) <- FPULastInstructionOpcode;

Флаги FPU затронуты

C0, C1, C2 и C3 не определены.

Исключения с плавающей точкой

Никто.

Исключения защищенного режима

GP(0) - если место назначения находится в недоступном для записи сегменте. Если эффективный адрес операнда памяти выходит за пределы сегмента CS, DS, ES, FS или GS. Если регистр DS, ES, FS или GS используется для доступа к памяти и содержит селектор нулевого сегмента.

SS (0) - если эффективный адрес операнда памяти выходит за пределы сегмента SS.

NM - EM или TS в CR0 установлены.

PF (код ошибки) - если происходит сбой страницы.

AC (0) - если проверка выравнивания включена и выполняется ссылка на невыровненную память, в то время как текущий уровень привилегий равен 3. Исключения режима реального адреса

GP - если эффективный адрес операнда памяти выходит за пределы сегмента CS, DS, ES, FS или GS.

SS - если эффективный адрес операнда памяти выходит за пределы сегмента SS.

NM - EM или TS в CR0 установлены. Исключения режима Virtual-8086

GP(0) - если эффективный адрес операнда памяти выходит за пределы сегмента CS, DS, ES, FS или GS.

SS (0) - если эффективный адрес операнда памяти выходит за пределы сегмента SS.

NM - EM или TS в CR0 установлены.

PF (код ошибки) - если происходит сбой страницы.

AC (0) - если проверка выравнивания включена и выполняется ссылка на невыровненную память.

Просто для полноты, вот схема памяти, которая FSTENV/FNSTENV инструкции производят. То же самое в x86-64 "Long 64-bit Mode"и в х86 "32 bit compatibility mode" (если вы не добавите его с префиксом 66h в x86-64.)

Цитируя этот громоздкий документ Intel, это макет:

(Кстати, изображение выше также должно было называться "длинный режим".)

Итак, если мы запустим реальный тест в длинном 64-битном режиме:

и сломаться сразу после FNSTENV инструкция со следующим контекстным состоянием:

расположение памяти, которое он возвращает, выглядит следующим образом:

Что, я не собираюсь скрывать, очень странно. (Что-нибудь от отрубленного регистра RIP до странно выглядящего кода операции.) Но это все еще поддерживается, я думаю, по старым причинам.

Хорошей новостью является то, что сегодня не так много вариантов использования этих архаичных инструкций x87 FPU при кодировании современного кода x64. В этом случае вы должны обязательно придерживаться XMM0 через XMM15 регистры и соответствующие инструкции для ваших потребностей с плавающей запятой.

Он хранит среду с плавающей запятой. Это включает в себя: текущее управляющее слово, слово состояния, слово тега, указатель команды и указатель операнда. Они хранятся в структуре в памяти. В 16-битном режиме эта структура составляет 14 байтов. В 32-битном режиме это 28 байтов. Я совсем не уверен, что он доступен в 64-битном режиме (в 64-битном режиме в основном вместо этого используется SSE) [Правка: очевидно, работает одинаково в 32-битном и 64-битном режиме.]

Я не верю, что это меняет текущее состояние сопроцессора [Редактировать: упс - да, он маскирует исключения FP, но большинство людей никогда не снимает их с нуля, поэтому...] - но когда вы используете fldenv, это восстановит состояние до того, что было, когда вы использовали fstenv хранить его.

Я хочу ответить на вопрос с другим подходом.

FSTENV не является "настоящей" инструкцией.
Возможно, вам больше повезет при поиске кода операции "FNSTENV".

Внимательно изучите кодировку (из Intel SDM):

FSTENV   9B D9 /6  
FNSTENV  D9 /6

Видишь эту ведущую "9В"?
Это действительно "FWAIT", добавленный к "FNSTENV".

Итак, "FSTENV", как и многие другие инструкции, является просто соглашением, которое понимают большинство ассемблеров и дизассемблеров.

Руководство Intel действительно упоминает эту особенность, но вы не должны ожидать, что она будет точной в 100% случаев, иногда в ней могут отсутствовать такие детали:

FSTENV / FNSTENV - сохранение среды x87 FPU (том 2A 3-393)

Ассемблер выдает две инструкции для инструкции FSTENV (за инструкцией FWAIT следует инструкция FNSTENV), и процессор выполняет каждую из этих инструкций отдельно. Если для какой-либо из этих инструкций генерируется исключение, EIP сохранения указывает на инструкцию, вызвавшую исключение.

Есть много таких "специальных" инструкций.
Например, вы можете быть удивлены, сколько NOP есть в x86, они обычно псевдонимы других инструкций.

Бонус - полезные ресурсы

Intel XED может пригодиться в вашей борьбе по нескольким причинам:

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

В Go asm есть объект x86.csv, в котором перечислены инструкции x86 в стиле Intel SDM, но иногда с дополнительной информацией.
Если вы наберете "FSTENV", вы увидите связанный с ним "псевдо" тег.
Обратите внимание, что x86.v0.2.csv может пропустить некоторые инструкции, особенно из более новых расширений (хотя это будет исправлено в v0.3).

Другие вопросы по тегам