MMX指令和x87 FPU标记字

Bit*_*tes 3 x86 assembly fpu x87 mmx

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
Run Code Online (Sandbox Code Playgroud)

这一刻ax0101 0101 0101 0110

但是从英特尔手册,第9.5.1MMX指令和x87 FPU标签字,我引用:

在每个MMX指令之后,整个x87 FPU标记字被设置为有效(00B).

那么为什么ax不是全零呢?

Mar*_*oom 5

你引用的部分继续说:

英特尔®64和IA-32架构软件开发人员手册第3A卷中的第12章"英特尔®MMX™技术系统编程"提供了有关x87 FPU和MMX指令对x87 FPU标记字的影响的其他信息.

实际上,第三手册的第12.2节澄清了:

当MMX指令将值写入MMX寄存器时,同时将相应浮点寄存器的第64位至第79位设置为全1.

movq mm0, [qVar1]然后该指令将寄存器设置R0为0xffff_00000000_00000000,这是从80387开始的无效双扩展精度浮点值(之前是正无穷大).
这在以后很重要.

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

效果fstenv使用x87 FPU标记字是:

标签和寄存器值被读取和解释; 然后所有标签都设置为11B.

存储在内存中的x87 FPU标记字的图像是:

根据浮点寄存器中的实际值设置标签; 也就是说,空寄存器标记为11B,有效寄存器标记为00B(非零),01B(零)或10B(特殊).

MMX和x87指令对x87 FPU标记字的影响

如果您emms在任何XMM代码之前使用过,那么标签将全部为11b(空).
一旦movq mm0, [qVar1]执行,所有标签都设置为00b(有效).
fstenv被执行时,寄存器被标记为不空,并且它们的内容进行分析:R1-R7似乎是零,而R0,如先前看到的,含有特殊的值和其存储在存储器中的图像中的标签是这样10b中的所有寄存器(特别).

fstenv第二本手册中的条目无疑是伪写的伪代码

操作
DEST [FPUControlWord]←FPUControlWord;
DEST [FPUStatusWord]←FPUStatusWord;
DEST [FPUTAGWord]←FPUTagWord;
DEST [FPUDataPointer]←FPUDataPointer;
DEST [FPUInstructionPointer]←FPUInstructionPointer;
DEST [FPULastInstructionOpcode]←FPULastInstructionOpcode;

这根本不是真的.