当我们比较两个数字并且一个数字小于另一个数字时,就会设置标志 CF
:
mov eax,1
cmp eax,2
jb truWay
二进制形式:
1=00000001
2=00000010=11111101+1(add. code)=11111110и
00000001+11111110=11111111(no carry)
为什么指令cmp eax,2
设置CF
标志?没有进位,或者我错了。
最佳答案
您可以引用these slides了解 ALU 中如何执行减法。
虽然 A - B = A + (-B) 是正确的,并且在补码中是 A + ØB + 1,但这种考虑仅考虑了结果。
用半加器实现的减法器采用以下形式
请注意,CarryOut 位已反转。
您可以通过示例(将大小限制为 4 位)来检查这是否必要且正确:
1 - 2 = 1 + (-2) = 0001b + 1110b = 0|1111b 因为 Ø0 = 1 我们有一个借位
而 2 - 1 则有
2 - 1 = 2 + (-1) = 0010b + 1111b = 1|0001b 因为 Ø1 = 0 我们没有借位
因此,在您的示例中,存在借位,因此 CF 被设置,正是因为 0001b + 1110b 不产生进位。
为了更正式地证明反转执行标志的正确性,可以使用位数归纳。
基本案例
n = 1
这可以用真值表来证明
a b a-b (a+¬b+1) ¬carryOut Expected borrow
0 0 0+1+1 = 1|0 0 0
0 1 0+0+1 = 0|1 1 1
1 0 1+1+1 = 1|1 0 0
1 1 1+0+1 = 1|0 0 0
感应案例
两个 n 位数字相减时 A = an an-1 ... a0 且 B = bn bn-1 ... b0 我们可以有 A > B、A < B 或 A = B。
在第一种情况下,有一个 k 使得 ak < bk 且 aj = bj 表示所有 j> k 直至 n。
条件 ak < bk 意味着 ak = 0 且 bk = 1。
因此,A 和 ØB 等于第 k-1 位,因此只有这么多位会影响进位。
但根据归纳假设,执行是正确的,因此在这种情况下也是正确的。
同样的过程适用于案例 A > B。
情况 A = B 更容易,因为整个操作被简化为 A + ØA + 1,从而简化为 111...1 + 1,总是产生进位,因此没有借位。
关于assembly - cmp 时设置 CF,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45631132/