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 может пригодиться в вашей борьбе по нескольким причинам:
- Он может использоваться в качестве кодера / декодера для проверки других инструментов.
- Это файлы данных - хороший источник информации ISA, читаемой человеком (и машиной). Вы можете найти технические заметки, которые объясняют структуру файлов данных.
В Go asm есть объект x86.csv, в котором перечислены инструкции x86 в стиле Intel SDM, но иногда с дополнительной информацией.
Если вы наберете "FSTENV", вы увидите связанный с ним "псевдо" тег.
Обратите внимание, что x86.v0.2.csv может пропустить некоторые инструкции, особенно из более новых расширений (хотя это будет исправлено в v0.3).