CMP和2的补码

时间:2015-02-02 21:45:25

标签: assembly x86 masm

我开始学习CMP指令,它比较了两个整数 使用无符号整数时,我读到了:

  • ZF=1表示目的地和来源相等。
  • ZF=0 && CF = 0表示destination > source
  • ZF=0 && CF = 1表示destination < source

据我所知,CMP指令使用隐含的减法而不改变操作数的值 减法没有意义!

假设我执行以下指令:

 CMP 1, 4
     1 - 4 = 1 + (-4)
    ...001
    .+.100
     =  101

我看到这里没有随身携带,我的意思是,执行位是0,不是吗?所以我上面所说的,我读的是正确的,是错的 我只是不明白为什么这个减法设置进位标志。 我没有携带一个位!如果进位位只是(在这种情况下)数字的第4位,则为零。
我花了好几个小时试图搞清楚。

2 个答案:

答案 0 :(得分:3)

所以让我们尝试3位系统中的所有3位数字

000 - 000 = 0000 :  +0  -  +0  =  + 0      Z
000 - 001 = 1111 :  +0  -  +1  =  +15 [-1] C
000 - 010 = 1110 :  +0  -  +2  =  +14 [-2] C
000 - 011 = 1101 :  +0  -  +3  =  +13 [-3] C
000 - 100 = 1100 :  +0  -  +4  =  +12 [-4] C
000 - 101 = 1011 :  +0  -  +5  =  +11 [-5] C
000 - 110 = 1010 :  +0  -  +6  =  +10 [-6] C
000 - 111 = 1001 :  +0  -  +7  =  + 9 [-7] C
001 - 000 = 0001 :  +1  -  +0  =  + 1      
001 - 001 = 0000 :  +1  -  +1  =  + 0      Z
001 - 010 = 1111 :  +1  -  +2  =  +15 [-1] C
001 - 011 = 1110 :  +1  -  +3  =  +14 [-2] C
001 - 100 = 1101 :  +1  -  +4  =  +13 [-3] C
001 - 101 = 1100 :  +1  -  +5  =  +12 [-4] C
001 - 110 = 1011 :  +1  -  +6  =  +11 [-5] C
001 - 111 = 1010 :  +1  -  +7  =  +10 [-6] C
010 - 000 = 0010 :  +2  -  +0  =  + 2      
010 - 001 = 0001 :  +2  -  +1  =  + 1      
010 - 010 = 0000 :  +2  -  +2  =  + 0      Z
010 - 011 = 1111 :  +2  -  +3  =  +15 [-1] C
010 - 100 = 1110 :  +2  -  +4  =  +14 [-2] C
010 - 101 = 1101 :  +2  -  +5  =  +13 [-3] C
010 - 110 = 1100 :  +2  -  +6  =  +12 [-4] C
010 - 111 = 1011 :  +2  -  +7  =  +11 [-5] C
011 - 000 = 0011 :  +3  -  +0  =  + 3      
011 - 001 = 0010 :  +3  -  +1  =  + 2      
011 - 010 = 0001 :  +3  -  +2  =  + 1      
011 - 011 = 0000 :  +3  -  +3  =  + 0      Z
011 - 100 = 1111 :  +3  -  +4  =  +15 [-1] C
011 - 101 = 1110 :  +3  -  +5  =  +14 [-2] C
011 - 110 = 1101 :  +3  -  +6  =  +13 [-3] C
011 - 111 = 1100 :  +3  -  +7  =  +12 [-4] C
100 - 000 = 0100 :  +4  -  +0  =  + 4 [-4] 
100 - 001 = 0011 :  +4  -  +1  =  + 3      
100 - 010 = 0010 :  +4  -  +2  =  + 2      
100 - 011 = 0001 :  +4  -  +3  =  + 1      
100 - 100 = 0000 :  +4  -  +4  =  + 0      Z
100 - 101 = 1111 :  +4  -  +5  =  +15 [-1] C
100 - 110 = 1110 :  +4  -  +6  =  +14 [-2] C
100 - 111 = 1101 :  +4  -  +7  =  +13 [-3] C
101 - 000 = 0101 :  +5  -  +0  =  + 5 [-3] 
101 - 001 = 0100 :  +5  -  +1  =  + 4 [-4] 
101 - 010 = 0011 :  +5  -  +2  =  + 3      
101 - 011 = 0010 :  +5  -  +3  =  + 2      
101 - 100 = 0001 :  +5  -  +4  =  + 1      
101 - 101 = 0000 :  +5  -  +5  =  + 0      Z
101 - 110 = 1111 :  +5  -  +6  =  +15 [-1] C
101 - 111 = 1110 :  +5  -  +7  =  +14 [-2] C
110 - 000 = 0110 :  +6  -  +0  =  + 6 [-2] 
110 - 001 = 0101 :  +6  -  +1  =  + 5 [-3] 
110 - 010 = 0100 :  +6  -  +2  =  + 4 [-4] 
110 - 011 = 0011 :  +6  -  +3  =  + 3      
110 - 100 = 0010 :  +6  -  +4  =  + 2      
110 - 101 = 0001 :  +6  -  +5  =  + 1      
110 - 110 = 0000 :  +6  -  +6  =  + 0      Z
110 - 111 = 1111 :  +6  -  +7  =  +15 [-1] C
111 - 000 = 0111 :  +7  -  +0  =  + 7 [-1] 
111 - 001 = 0110 :  +7  -  +1  =  + 6 [-2] 
111 - 010 = 0101 :  +7  -  +2  =  + 5 [-3] 
111 - 011 = 0100 :  +7  -  +3  =  + 4 [-4] 
111 - 100 = 0011 :  +7  -  +4  =  + 3      
111 - 101 = 0010 :  +7  -  +5  =  + 2      
111 - 110 = 0001 :  +7  -  +6  =  + 1      
111 - 111 = 0000 :  +7  -  +7  =  + 0      Z

其中C是进位/借位且Z为零

您的规则严格来说是无符号规则。对于签名我认为如果N!= V然后签名小于,如果N == V然后签名大于。

所以0 - 0是0 Z标志它们是相等的 那么0 - 1和0 - 2等。第二个操作数更大Z未设置和进位设置。

直到我们得到1 - 0不为零并且未设置C时,左数字更大。

然后我们点击等于(1 - 1)

还有一些Z未设置C设置,所以正确的数字更大。

然后2 - 0,2 - 1左边更大(Z未设置C未设置)然后设置2 - 2 Z,然后2 - 3到2 - 7 Z未设置C设置,因此右边更大。< / p>

这种模式重复了。

当然,技巧是源和目标的定义,通常没有在指令集中记录,你必须通过实验确定,至少对我来说,我总是猜错了。

您的具体示例

1比较4 1 - 4 = 1 +( - 4),4 = 0b100,所以-4 = 011 + 1

馈送加法器,减法表示反转进位并反转第二个操作数:

     1
   001
+  011
=======

填写

  0111
   001
+  011
=======
   101

1 - 4 = -3。 Z为0 C为0,因此1 <1。 4

注意从进位位获取一个借位,可以反转进位(借用=〜进位)。执行是0表示借款发生,如果你试图用十进制的铅笔和纸从1中减去4,这是显而易见的。

如果没有借用,则设置执行,例如4-1:

  1001
   100
+  110
========
   011

4 - 1 = 3,没有借款。 Z未设定C设定为4> 1

我认为这里的底线是哪个操作数是源,哪个是目标,为什么它们很少正确记录?无论何时在指令集中使用比较,都必须使用固定数字进行一些实验,以查看哪个操作数是哪个。您还必须非常小心地使用大于或小于它的有符号或无符号。一些指令集不提供一种味道或另一种但是没关系你真的不需要很长的有符号和无符号列表,并且左右切换操作数并理解标志你可以找到一个简单的如果携带或不携带或如果有什么能给你带来几乎所有的东西,有时你会得到额外的奖励,当Z被设定时,Carry是一个零权利,这意味着未设置的进位是&#34;或等于&#34;。

答案 1 :(得分:1)

将进位位视为结果的下一个最高有效位。

考虑在一步中减去“补充,添加1,添加”。在硬件中,这是通过LSB的进位来实现的:0表示加,1表示子,C表示addc。

示例:

1 - 4

  0.001       // 1
  1.011 + 1   // 4 complemented, carry in
+ -----
  1.101       // -3, carry out

-1 - -2

  1.111     // -1
  0.001 + 1 // -2 complemented, carry in
+ -----
  0.001     // 1, no carry out

您显示的CMP条件代码用于无符号算术。对于带符号算术,您必须使用exclusive或者进位和符号位。通常也会对此进行测试。

例如,JG(Jump Greater)是ZF = 0且SF = OF

编辑,感谢来自@Blechdose的刺激,下面是一个例子,说明当补码减数的符号没有传播到CF时会发生什么(导致x86反转CF进行减法):

1 - 4

   .001       //  1
   .011 + 1   //  4 complemented, carry in
+ -----
  0.101       // -3, no carry out

4 - 1

   .100       //  4
   .110 + 1   //  1 complemented, carry in
+ -----
  1.011       //  3, carry out
相关问题