0

设置手段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

和flags 操作是自己理解OverflowCarry容易掌握的,但是我发现很难理解设置Zero/Signflags 背后的数学原理。任何帮助表示赞赏!

谢谢!

4

2 回答 2

5

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

10因此,例如,您可以从to倒数,0而无需明确测试为零:

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

“做一些事情”发生了十次,因为dec影响了Z标志。

stc存在的原因clc是为了帮助进行多位数算术。该C标志用于跟踪先前算术中的“进位”,以便您可以将它们分解到未来的操作中:

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!

由于这些类型的操作,您可能需要在开始算法之前或之前C进行预加载。因此-以及为什么没有其他(算术)标志具有“设置”或“清除”操作码。01clcstc

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

  • ( Ddirection) 标志控制字符串指令的方向,例如STOSMOVS。因此有cldstd指示。
  • I中断)标志控制是否启用中断。因此有clisti指示。
于 2018-07-05T04:25:12.330 回答
4

SF 和 ZF 仅根据结果设置,而不是输入。

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

SF = ((signed)result < 0);

ZF = (result == 0);

您也可以说 ZF 是所有位的水平或,反转。(如果有一个设置位,它会被清除)。

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


当然,并非所有指令都设置了所有标志,例如inc/dec 著名地保持CF 不变,而以通常的方式设置其他指令,使其可在adc循环内使用。

仅旋转集合 CF,并且(对于隐式移位 1 操作码)还旋转 OF。SF/ZF/PF 保持不变,与常规的非循环移位不同。除非移位计数为零,在这种情况下,所有标志都未修改。这对于无序执行移位和旋转是有问题的(标志是变量计数移位/旋转的额外依赖项),这就是为什么 BMI2 shlx/shrx在英特尔上更快的原因。和rol/ror是额外的微指令。


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

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

于 2018-07-05T04:18:04.540 回答