3
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 Instructions 和 x87 FPU Tag Word部分,我引用:

在每个 MMX 指令之后,整个 x87 FPU 标签字都设置为有效 (00B)。

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

4

1 回答 1

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;

这根本不是真的。

于 2017-06-24T19:12:10.593 回答