正如您所写,x86TEST
操作执行按位AND
操作。您应该再次检查 AND 的真值表:
INPUT OUTPUT
A B A AND B
0 0 0
0 1 0
1 0 0
1 1 1
TEST
将对 src 和 dst 操作数中的每 2 个对应位执行此操作,因此只有1
两者中的位才会成为1
结果:00001111b & 00000010b
将简单地给出00000010b
.
对标志的影响现在很容易看到 - ZF=0 因为结果非零,SF=0 因为结果 MSB 关闭,CF=0 因为 TEST 不会设置它(这是一个逻辑操作,不是算术的)。
顺便说一句,TEST
随着操作的进行,它非常便宜,所以你可能会注意到它经常被用作简单的零检查 -TEST RAX, RAX
会和 RAX 对自身进行注册(当然会产生相同的值),所以你有一个很好的方法来检查是否RAX 为零(例如,je
紧随其后的分支使用)或负数(通过将 SF 与js
分支一起使用)
现在,其他 2 个问题处理另一个操作 -CMP
进行实际减法(它与 做相同的事情SUB
,但也丢弃结果,仅更新标志)。
第一个将计算00000110b - 00000101b = 00000001b
ZF=SF=0(出于与上述相同的原因)和 CF=0,因为我们不需要进位/借位。
第二个将计算00000101b - 00000111b = 11111110
(对于 的二进制补码表示5 - 7 = -2
),如上所述,ZF 仍然为 0,但这次你会看到 SF=1,因为我们得到了一个否定的结果,所以 MSB 开启,CF=1,因为计算做了一个“借”给MSB。
这里有一点关于 CF 及其对应的 OF(溢出标志)的要点 - 数字只是数字,它们并不意味着有符号或无符号值,直到您决定使用它们。然而 x86 必须为任何可能性维护正确的标志,所以它基本上使用 CF 进行无符号操作,实际上意味着最后一个操作5 - 7 = 254
就像你“借”了一个额外的位到 MSB(这就是 CF=1 标记在这里)。OF 不会被设置,因为如果您将这些完全相同的操作视为有符号算术,那么您确实已经完成了5 - 7 = -2
完全合法的操作并且没有上溢/下溢。
另一方面,像这样的操作127 + 127 = 254
会做相反的事情,它不会切换 CF(因为如果您将其视为无符号算术,则不会发生任何坏事),但 OF 将被设置,因为如果这些是有符号值,您我刚刚说过127 + 127 = -2
这显然是错误的,因为溢出超过了一个字节可以存储的最大有符号值 (127)