PAYATHON 2026

16 位模式下的 VCVTSD2USI 能否写入 16 位寄存器?

数据阿明

在题目所指的 16 位保护模式代码段中,62 F1 7F 08 79 C0 的目标寄存器是 EAX。VCVTSD2USI 没有写入 AX 的 16 位目标形式,CS.D=0 不会让这条指令的目标操作数缩小为 16 位。

为什么目标仍然是 EAX?

Intel 为 VCVTSD2USI 定义了 r32 和 r64 两种目标形式,没有 r16 形式。其操作伪代码也只区分两种情况:在 64 位模式且选择 64 位操作数时写入 DEST[63:0],其余情况写入 DEST[31:0]。普通整数指令可以依据代码段的默认操作数大小选择 AX 或 EAX,这条指令不能直接套用该规则。Intel 指令参考:VCVTSD2USI

这条指令的宽度规则如下:

执行环境EVEX.W=0EVEX.W=1
16 位保护模式代码段r32r32,W 位被忽略
32 位非 64 位执行环境r32r32,W 位被忽略
64 位模式r32r64

Intel 明确说明,这条指令在非 64 位模式下会忽略 EVEX.W=1,按 W0 形式处理。只有在 64 位模式下,EVEX.W 才能选择 64 位目标。Intel 指令集扩展参考

16 位保护模式与实模式要分开处理

Intel 的系统编程说明指出,使用 EVEX 编码的指令通常支持 16 位保护模式。指令表中只有“64/32 bit Mode Support”两列,并不能说明这些指令在 CS.D=0 的保护模式代码段中不可用。

实模式和 Virtual-8086 模式不支持这类 AVX-512 指令。即使在受支持的保护模式下,实际执行也要求处理器支持相应指令集,且系统已启用所需的扩展状态管理。反汇编器能够识别出助记符,并不代表当前环境能够执行。Intel SDM:AVX-512 系统编程说明

反汇编器应如何实现?

先完整匹配 EVEX 编码和具体指令,再应用该指令的操作数宽度规则。针对 VCVTSD2USI,可以采用以下伪代码:

# 前提:已经确认是有效的 VCVTSD2USI 编码
if mode_is_64_bit and EVEX.W == 1:
    destination_width = 64
else:
    destination_width = 32

对于题目第一组字节,EVEX.W=0,ModR/M=C0 指定目标寄存器编号 0、源寄存器编号 0,所以结果是:

; 字节:62 F1 7F 08 79 C0
vcvtsd2usi eax, xmm0

这段规则只处理目标寄存器宽度。内存源操作数的寻址方式、前缀合法性和执行模式限制仍须分别检查。其他带 GPR 操作数的 AVX-512 指令也应逐条依据编码表实现,不宜全部套用同一个宽度规则。

两组示例字节不能混用

问题中的两组字节有一处差异:

62 F1 7F 08 79 C0
62 F4 7F 08 79 C0
   ^^

这个字节包含 EVEX 的 opcode map 选择字段。F1 对应这里所需的 0F map,改成 F4 后 map 也随之改变,不能继续按相同的 VCVTSD2USI 编码解释。Intel SDM Volume 2A:EVEX 编码规则

应先确认 NDISASM 测试时输入的是哪组字节。如果输入的是含 F4 的字节,即使工具输出相同助记符,也不能据此证明编码有效。验证寄存器宽度时应统一使用 62 F1 7F 08 79 C0;上述结论依据指令定义,没有经过硬件实测。

备注:内容仅供参考。