FSTENV?几乎找不到有关此指令的任何信息

时间:2012-04-26 16:43:01

标签: assembly x86 x87

我在程序中得到了这条指令:

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

它做了什么?

它使用和更新了哪些寄存器?

谢谢!

4 个答案:

答案 0 :(得分:4)

存储浮点环境。这包括:当前控制字,状态字,标记字,指令指针和操作数指针。它们存储在内存中的结构中。在16位模式下,该结构为14个字节。在32位模式下,它是28个字节。我完全不确定它是否可用于64位模式(64位模式主要使用SSE)[编辑:显然在32位和64位模式下运行相同。]

我不相信它会改变协处理器的任何当前状态[编辑:oops - 确实如此,它掩盖了FP异常,但大多数人从不揭露它们开始,所以...] - 但是当您使用fldenv时,会将状态恢复为使用fstenv存储时的状态。

答案 1 :(得分:2)

Jerry Coffins答案是正确的。
如果您想知道(28-BYTE) PTR SS:[ESP-1C]:这是FP环境存储的有效地址,它指定28字节该命令的版本并指向堆栈段中堆栈指针下方的28(0x1c)字节 我只是添加了英特尔的官方说明,我发现这是使用搜索引擎。

  

<强>描述

     

将当前FPU操作环境保存在内存位置   使用目标操作数指定,然后屏蔽全部   浮点异常。 FPU操作环境包括   FPU控制字,状态字,标记字,指令指针,数据   指针和最后一个操作码。 IA-32中的图7-13至7-16   英特尔®架构软件开发人员手册第1卷显示了   存储环境的内存布局,取决于操作   处理器的模式(受保护或实际)和当前操作数大小   属性(16位或32位)。在virtual-8086模式下,实模式   使用布局。

     

FSTENV指令检查并处理任何未处理的未屏蔽的   存储FPU环境之前的浮点异常;该   FNSTENV指令没有。保存的图像反映了状态   在前面的所有浮点指令之后的FPU   指令流中的FSTENV / FNSTENV指令已经完成   执行。

     

这些指令通常由异常处理程序使用,因为它们   提供对FPU指令和数据指针的访问。该   环境通常保存在堆栈中。掩盖所有异常   保存环境后会阻止浮点异常   中断异常处理程序。英特尔®架构兼容性

     

在MS-DOS *操作中操作Pentium®或Intel486™处理器时   系统兼容模式,有可能(不寻常   情况)FNSTENV指令在之前被中断   被执行以处理待处理的FPU异常。见部分   标题为“无等待FPU指令可以在窗口中获得FPU中断”   IA-32英特尔®架构软件开发人员的附录D.   手册,第1卷,描述这些情况。一个FNSTENV   在Pentium Pro上不能以这种方式中断指令   处理器。

     

<强>操作

     

DEST [FPUControlWord]&lt; - FPUControlWord;

     

DEST [FPUStatusWord]&lt; - FPUStatusWord;

     

DEST [FPUTagWord]&lt; - FPUTagWord;

     

DEST [FPUDataPointer]&lt; - FPUDataPointer;

     

DEST [FPUInstructionPointer]&lt; - FPUInstructionPointer;

     

DEST [FPULastInstructionOpcode]&lt; - FPULastInstructionOpcode;

     

受影响的FPU标志

     

C0,C1,C2和C3未定义。

     

浮点异常

     

无。

     

受保护模式例外

     

GP(0) - 如果目的地位于不可写的段中。如果内存操作数有效地址在CS,DS,ES,FS或GS之外   分段限制。如果使用DS,ES,FS或GS寄存器进行访问   内存,它包含一个空段选择器。

     

SS(0) - 如果内存操作数有效地址超出SS段限制。

     

NM - 设置CR0中的EM或TS。

     

PF(故障代码) - 如果发生页面错误。

     

AC(0) - 如果启用了对齐检查,并且在当前权限级别为3时进行了未对齐的内存引用。实地址   模式例外

     

GP - 如果内存操作数有效地址超出CS,DS,ES,FS或GS段限制。

     

SS - 如果内存操作数有效地址超出SS段限制。

     

NM - 设置CR0中的EM或TS。 Virtual-8086模式异常

     

GP(0) - 如果内存操作数有效地址超出CS,DS,ES,FS或GS段限制。

     

SS(0) - 如果内存操作数有效地址超出SS段限制。

     

NM - 设置CR0中的EM或TS。

     

PF(故障代码) - 如果发生页面错误。

     

AC(0) - 如果启用了对齐检查并且未进行未对齐的内存引用。

答案 2 :(得分:2)

我想用不同的方法回答这个问题。

FSTENV不是真实的&#34;指令。
在搜索&#34; FNSTENV&#34;时,您可能会更幸运。操作码。

仔细研究编码(来自Intel SDM):

FSTENV   9B D9 /6  
FNSTENV  D9 /6

看到领先&#34; 9B&#34;? 它真的是一个&#34; FWAIT&#34;先于&#34; FNSTENV&#34;。

所以,&#34; FSTENV&#34;就像许多其他指令一样,它只是大多数汇编程序和反汇编程序都能理解的约定。

英特尔手册确实提到了这种特性,但你不应该指望它在100%的情况下都是精确的,有时它可能会省略这些细节:

  

FSTENV / FNSTENV-Store x87 FPU环境(第2A卷3-393)

     

汇编程序为FSTENV指令发出两条指令 FWAIT 指令后跟FNSTENV   指令),处理器分别执行这些指令中的每一个。如果生成异常   这些指令中的任何一个,保存EIP指向导致异常的指令。

有很多这样的&#34;特别&#34;说明。
例如,您可能会感到惊讶much NOP's there are in x86, 他们通常会将其他说明作为别名。

奖金 - 有用的资源

Intel XED可能会在您的斗争中得心应手,原因如下:

  1. 它可以用作编码器/解码器来验证其他工具。
  2. datafiles是人类(和机器)可读ISA信息的良好来源。您可能会找到解释数据文件结构的engineering notes
  3. Go asm有一个名为x86.csv的内容列出了x86指令 采用英特尔SDM方式,但有时还有其他信息 如果你为#34; FSTENV&#34; grep它,你会看到&#34;伪&#34;与之相关的标签 请注意,x86.v0.2.csv可能会遗漏一些指令,尤其是来自较新的扩展(虽然这将在v0.3中修复)。

答案 3 :(得分:1)

为了完整起见,这里是FSTENV / FNSTENV指令产生的内存布局。它在x86-64 "Long 64-bit Mode"和x86 "32 bit compatibility mode"中是相同的(除非您在x86-64中使用前缀66h作为前缀。)

引用this unwieldy英特尔文档,这是布局:

enter image description here

(顺便说一下,上面的图片应该被命名为#34;长模式&#34;以及

因此,如果我们在长64位模式下运行实际测试:

enter image description here

并在具有以下上下文状态的FNSTENV指令后立即中断:

enter image description here

它返回的内存布局如下:

enter image description here

我不会躲起来,这是非常奇怪的。 (从切断的RIP寄存器到看起来很奇怪的操作码的任何东西。)但是由于遗留原因,我仍然支持它。

好消息是,在编写现代x64代码时,目前没有太多用于这些古老的x87 FPU指令的用法。在这种情况下,您应该坚持使用XMM0XMM15寄存器及其相关指令来满足您的浮点需求。