Setting/Unsetting MASM 标志如何工作

How Does Setting/Unsetting MASM Flags Work

设置表示 flag value = 1,未设置表示 flag value = 0

现在我明白了在MASM中有几种设置和取消设置标志的方法,如下:

test al,0 ; set Zero flag
and al,0 ; set Zero flag
or al,1 ; clear Zero flag

Sign flag也是如此:

or al,80h ; set Sign flag
and al,7Fh ; clear Sign flag

要设置Carry flag,我们使用STC指令;要清除进位标志,我们使用 CLC:

stc ; set Carry flag
clc ; clear Carry flag

为了设置 Overflow flag,我们添加两个产生负和的正值。要清除 Overflow flag,我们用 0:

或操作数
mov al,7Fh ; AL = +127
inc al ; AL = 80h (-128), OF=1
or eax,0 ; clear Overflow flag

OverflowCarry 标志操作是自我理解且易于掌握的,但我发现很难理解设置 Zero/Sign 标志背后的数学原理。感谢您的帮助!

谢谢!

SF 和 ZF 仅基于结果而不是输入设置。

SF 是结果的最高位,因此(对于位模式的 2 的补码解释),这意味着结果为负。

SF = ((signed)result < 0);

ZF = (result == 0);

你也可以说 ZF 是所有位的水平或,取反。 (如果只有一个设置位,则清除)。

当然result是8位、16位、32位或64位,具体取决于操作数的大小。对于像 neg al.

这样的指令,标志是根据实际输出的高位和零来设置的,而不是它所属的完整寄存器。

当然不是所有指令都设置所有标志,例如inc/dec famously保持CF不变,同时设置其他通常的方式,使其在 adc 循环中可用。

Rotates only set CF, and (for the implicit shift-by-1 opcode) also OF. SF/ZF/PF remain unmodified, unlike with regular non-circular shifts. Unless the shift count was zero, in which case all the flags are unmodified. This is 的移位和旋转(标志是变量计数 shifts/rotates 的额外依赖项),这就是 BMI2 shlx/shrx 在 Intel 上更快的原因. rol/ror 是额外的微指令。


BSF / BSR 根据 输入(不是结果)设置 ZF,如果输入为零,则保持输出寄存器不变。

Intel 的文档在那种情况下说 "undefined",但 AMD 记录了所有硬件实际实现的未修改行为。我认为英特尔不太可能构建不实现未修改行为的硬件,尤其是现在 BMI1 lzcnt/tzcnt 为我们提供了一个没有错误依赖的替代方案。 IDK 为什么他们不只是记录 bsf/bsr 如何在他们的硬件上工作。

使用标志的全部意义在于它们是其他操作的副作用 - 您可以在操作发生后测试结果。

因此,例如,您可以从 10 倒数到 0 而无需显式测试零:

       mov cx, 10
Again:
       ; Do some stuff, not changing cx
       dec cx
       jnz Again ; Go back to Again if not zero

"Do some stuff" 发生了十次,因为 dec 影响了 Z 标志。

stcclc存在的原因是为了帮助进行多位数运算。 C 标志用于跟踪先前算法中的 "Carries",以便您可以将它们纳入未来的操作:

op1 dd  0x12345678 ; 32-bit value
op2 dd  0x9abcdef0 ; 32-bit value

    mov ax,[op1+0] ; Get low word of op1
    mov dx,[op1+2] ; Get high word of op1

    add ax,[op2+0] ; Add in low word of op2
    adc dx,[op2+2] ; Add in high word of op2 - WITH CARRY!

由于这些类型的操作,您可能需要在开始算法之前使用 01 预加载 C。因此 clcstc - 以及为什么没有其他(算术)标志具有 "set" 或 "clear" 操作码。

请注意还有其他非算术标志:

  • D(方向)标志控制字符串指令的方向,例如STOSMOVS。 因此有 cldstd 指令。
  • I(中断)标志控制是否启用中断。 因此有 clisti 指令。