MMX 指令和 x87 FPU 标记字

MMX Instructions and the x87 FPU Tag Word

section .data
    qVar1: dq 1


section .bss
    var28: resb  28


section .text
    _main:

        ; Use an MMX instruction

            movq mm0, [qVar1] ; Move quadword from r/m64 to mm.

        ; Read Tag Word

            fstenv [var28]
            mov    ax, [var28 + 8] ; move the Tag Word to ax

此时ax0101 0101 0101 0110

但是从 Intel 手册,第 9.5.1 MMX 指令和 x87 FPU 标记字 部分,我引用:

After each MMX instruction, the entire x87 FPU tag word is set to valid (00B).

那么为什么 ax 不全是零?

您引用的部分继续说:

Chapter 12, “Intel® MMX™ Technology System Programming,” in the Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 3A, provides additional information about the effects of x87 FPU and MMX instructions on the x87 FPU tag word.

实际上第三本手册12.2节阐明:

When an MMX instruction writes a value into an MMX register, at the same time, bits 64 through 79 of the corresponding floating-point register are set to all 1s.

指令movq mm0, [qVar1]然后将寄存器R0设置为0xffff_00000000_00000000这是一个无效的double extended precision从80387开始的浮点值(之前是正无穷大) .
这在以后很重要。

fstenv指令保存实际的标记字,而是解释寄存器和实际的标记字来计算将存储的标记字在记忆中。
然后将所有寄存器的标记字寄存器重置为空。

fstenv对x87 FPU标签字的影响是:

Tags and register values are read and interpreted; then all tags are set to 11B.

而内存中存储的x87 FPU tag word的图像为:

Tags are set according to the actual values in the floating-point registers; that is, empty registers are marked 11B and valid registers are marked 00B (nonzero), 01B (zero), or 10B (special).

如果您在任何 XMM 代码之前使用 emms,则标签将全部为 11b(空)。
一旦 movq mm0, [qVar1] 被执行,所有标签都设置为 00b(有效)。
当执行 fstenv 时,寄存器被标记为非空并分析它们的内容:所有寄存器 R1-R7 似乎为零,而如前所述,R0 包含一个特殊值及其在存储图像中的标记因此在内存中是 10b(特殊)。

第二本手册中 fstenv 的条目确实具有欺骗性,其伪代码写为

Operation
DEST[FPUControlWord] ← FPUControlWord;
DEST[FPUStatusWord] ← FPUStatusWord;
DEST[FPUTagWord] ← FPUTagWord;
DEST[FPUDataPointer] ← FPUDataPointer;
DEST[FPUInstructionPointer] ← FPUInstructionPointer;
DEST[FPULastInstructionOpcode] ← FPULastInstructionOpcode;

这根本不是真的。