标志注册

当 x86 算术逻辑单元(ALU)执行 NOTADD 等操作时,它会在特殊的 16 位 FLAGS 寄存器中标记这些操作的结果(变为零溢出变为负)。32 位处理器将其升级为 32 位并将其称为 EFLAGS,而 64 位处理器将其升级为 64 位并将其称为 RFLAGS

条件代码

但无论名称如何,寄存器都不能直接访问(除了几条指令 - 见下文)。相反,在某些指令中引用了单个标志,例如条件跳转或条件集,称为 JccSETcc,其中 cc 表示条件代码并引用下表:

条件代码 名称 定义
EZ 相等,零 ZF == 1
NENZ 不等于,不是零 ZF == 0
O 溢出 OF == 1
NO 没有溢出 OF == 0
S SF == 1
NS 没有签名 SF == 0
P 平价 PF == 1
NP 没有奇偶性 PF == 0
-————- -— -———
CBNAE 携带,下方,不高于或等于 CF == 1
NCNBAE 不携带,不低于,高于或等于 CF == 0
ANBE 以上,不低于或等于 CF == 0 和 ZF == 0
NABE 不高于,低于或等于 CF == 1 或 ZF == 1
-————– -— -———
GENL 更大或更相等,而不是更少 SF == OF
NGEL 不大于或等于,小于 SF != OF
GNLE 更大,更小或相等 ZF == 0 和 SF == OF
NGLE 不大于,小于或等于 ZF == 1 或 SF != OF

在 16 位中,从 0 中减去 165,535-1,具体取决于是使用无符号算法还是带符号算法 - 但目标在任何一种情况下都保持 0xFFFF。只有通过解释条件代码才能明确含义。更有说服力是从 0x8000 中减去 1:在无符号算术中,只是将 32,768 变为 32,767; 在签名算术中,它将 -32,768 改为 32,767 - 一个更值得注意的溢出!

条件代码分为表中的三个块:符号无关,无符号和有符号。后两个块中的命名使用 AboveBelow 表示无符号,GreaterLess 表示签名。所以 JB 将是如果下面跳跃(未签名),而 JL 将是 Jump if less(签名)。

直接访问 FLAGS

上述条件代码对于解释预定义概念很有用,但实际标志位也可直接使用以下两条指令:

  • LAHF 使用 Flags 加载 AH 寄存器
  • SAHFAH 存储到 Flags 中

使用这些指令仅复制某些标志。整个 FLAGS / EFLAGS / RFLAGS 寄存器可以在堆栈中保存或恢复:

  • PUSHF / POPF 将 16 位 FLAGS 推入/弹出堆栈
  • PUSHFD / POPFD 将 32 位 EFLAGS 推入/弹出堆栈
  • PUSHFQ / POPFQ 将 64 位 RFLAGS 推入/弹出堆栈

请注意,中断会自动保存并恢复当前的 [R/E]FLAGS 寄存器。

其他标志

除了上面描述的 ALU 标志之外,FLAGS 寄存器还定义了其他系统状态标志:

  • IF 中断标志。
    这是通过 STI 指令设置为全局启用中断,并使用 CLI 指令清除以全局禁用中断。
  • DF 方向标志。
    内存到内存操作(如 CMPSMOVS)(在内存位置之间进行比较和移动)会自动递增或递减索引寄存器作为指令的一部分。DF 标志指示哪一个发生:如果用 CLD 指令清除,它们会增加; 如果使用 STD 指令设置,它们会递减。
  • TF 陷阱标志。这是一个调试标志。设置它将使处理器进入单步模式:执行每条指令后,它将调用单步中断处理程序,预计将由调试器处理。没有设置或清除此标志的指令:你需要在内存中操作该位。

80286 标志

为了支持 80286 中的新多任务设施,英特尔为 FLAGS 寄存器添加了额外的标志:

  • IOPL I / O 权限级别。
    为了保护多任务代码,某些任务需要访问 I / O 端口的权限,而其他任务必须停止访问它们。英特尔推出了四级权限级别,其中 00 2 享有最高权限,而 11 2 则最少。如果 IOPL 小于当前的权限级别,则任何访问 I / O 端口或启用或禁用中断的尝试都将导致一般性保护错误。
  • NT 嵌套任务标志。
    如果一个任务提示另一个任务导致上下文切换,则设置此标志。设置标志告诉处理器在执行 RET 时执行上下文切换。

80386 标志

‘386 需要额外的标志来支持处理器中设计的额外功能。

  • RF 简历标志。
    `386 添加了调试寄存器,它可以在各种硬件访问上调用调试器,如读,写或执行某个存储位置。但是,当调试处理程序返回执行指令时*,访问将立即重新调用调试处理程序!* 或者至少它不会用于 Resume Flag,它会在进入调试处理程序时自动设置,并在每条指令后自动清除。如果设置了 Resume Flag,则不会调用 Debug 处理程序。
  • VM 虚拟 8086 标志。
    为了支持较旧的 16 位代码以及较新的 32 位代码,80386 可以在“虚拟 8086”模式下运行 16 位任务,借助 Virtual 8086 执行程序。VM 标志表明此任务是虚拟 8086 任务。

80486 标志

随着英特尔架构的改进,它通过缓存和超标量执行等技术得到了更快的发展。这必须通过做出假设来优化对系统的访问。为了控制这些假设,需要更多的标志:

  • AC 对齐检查标志 x86 架构总是可以在任何字节边界上访问多字节内存值,这与一些需要它们进行大小对齐的架构(4 字节值需要在 4 字节边界上)不同。但是,这样做的效率较低,因为访问未对齐数据需要多次内存访问。如果设置了 AC 标志,那么未对齐的访问将引发异常而不是执行代码。这样,在使用 AC 设置开发期间可以改进代码,但是关闭生产代码。

奔腾标志

Pentium 为虚拟化增加了更多支持,并支持 CPUID 指令:

  • VIF 虚拟中断标志。
    这是此任务的 IF 的虚拟副本 - 此任务是否要禁用中断,而不会实际影响全局中断。
  • VIP 虚拟中断挂起标志。
    这表明 VIF 实际上阻止了一个中断,所以当 Task 执行一个 STI 时,可以为它提出一个虚拟中断。
  • ID CPUID 允许的标志。
    是否允许此任务执行 CPUID 指令。虚拟监视器可以禁止它,并且如果它执行指令则撒谎到请求任务。