首页 > 解决方案 > 代码段描述符中的 D 标志对 x86-64 指令有什么作用?

问题描述

我试图了解D flag在 x86-64 代码中使用时代码段描述符中的工作原理。它设置在D/B代码段描述符的第 22 位,如下图所示:

在此处输入图像描述

英特尔文档(来自第3.4.5 节段描述符)声明如下:

在此处输入图像描述

D/B(默认操作大小/默认堆栈指针大小和/或上限)标志

根据段描述符是可执行代码段、向下扩展数据段还是堆栈段执行不同的功能。(对于 32 位代码和数据段,该标志应始终设置为 1,对于 16 位代码和数据段,该标志应始终设置为 0。)

• 可执行代码段。该标志称为 D 标志,它指示段中指令引用的有效地址和操作数的默认长度。如果设置了标志,则假定 32 位地址和 32 位或 8 位操作数;如果清楚,则假定 16 位地址和 16 位或 8 位操作数。指令前缀 66H 可用于选择默认以外的操作数大小,前缀 67H 可用于选择默认以外的地址大小。

所以我试图了解它会影响哪些 x86-64 指令以及如何影响?

PS。当我尝试通过设置该位来运行一些测试(在 Windows 内核中)时,操作系统会立即出现三倍故障。

标签: windowsassemblyx86-64intelmemory-segmentation

解决方案


如果L为代码段描述符设置了(长模式),则D必须清除。L=1 / D=1 组合目前无意义/保留。英特尔在您正在查看的同一文档中记录了这一点。

如果L清除,则D在 16 位和 32 位模式之间进行选择。(即默认操作数/地址大小)。是的,存在 16 位保护模式,但不,没有人使用它。


默认地址/操作数大小只有 3 种可能性:

  • 16 位模式(real、vm86、protected):默认地址和操作数大小 = 16 位
  • 32 位保护模式:默认地址和操作数大小 = 32 位
  • 64 位模式:默认地址大小 = 64 位,默认操作数大小 = 32 位

没有 16 个 64 位寄存器的选项,但默认操作数大小为 16 位或 64 位。或 32 位的默认地址大小可覆盖为 64。


推荐阅读