当零是减数时,为什么在减法期间设置进位标志?

时间:2016-07-03 03:53:34

标签: assembly x86 flags

目前,我为非常大的无符号整数编写了我自己的小库,用于算术和逻辑运算。为了提高性能,我决定在汇编中实现一些功能。所以这是我的问题。 当减去两个无符号整数时,当我从0中减去任何数字时,将设置进位标志。

但为什么Carry Flag会在这种情况下设定?进位标志仅在发生溢出时设置,但如果我从零中减去任何数字,则不会出现溢出。 或者我错了?

2 个答案:

答案 0 :(得分:12)

进位标志是从最高有效位(MSb)进位或借出:

  

CF(位0)进位标志 - 设置算术运算是否从结果的最重要位产生进位或借位;否则清除。该标志表示溢出条件   无符号整数运算。它也用于多精度算术。

不要将CF与符号位相关联,在减法CF中,只要被视为无符号的减值小于减数,则将其设置为无符号。 这相当于溢出条件,对于带符号的数字,等效标志为OF。

对于(不必要的?)视觉线索,在这个4-5操作中,它是第二个借用,红色的,设置CF

Borrow and CF

如果你从零减去,那么自然而然地,对于任何数字,但本身为零,你总是会设置CF,因为减数至少有一个位设置。

最后,一些指令允许您在不影响CF的情况下更改符号位(例如,参见逻辑运算或neg的行为)。

答案 1 :(得分:2)

我们从小学就知道a - b = a +( - b)。这就是逻辑如何我们不减去我们添加负面。我们也从初学者编程课程中了解到,通过二进制补码来获得负数,您可以反转并添加一个。 a - b = a +(~b)+ 1.我们也从小学就知道了携带的概念。 9 + 3 = 2携带一个。二进制相同,有两个操作数,1 + 1 = 0可以携带一个操作数。所以逻辑中的每一列都需要一个进位。每个都是三位,两位输出,两位操作数加上进位并执行,结果输出。由于这些逻辑blob中的每一个都有一个输入位,进位,第一个进位的正常加法是零,但是对于减法我们可以使得进位1并反转第二个操作数得到a + b = a +(〜 b)+ 1

所以减法是另外的,如果你通过一些简单的例子,或者更好地尝试每三位操作数组合。你会看到没有签名或无符号加法(或减法)这样的东西,二进制补码编码之美。

知道所有这一切,减法是加法,加上我们得到一个关于UNSIGNED溢出的进位,有符号溢出位是当进位和进位的msbit不匹配时,通常表示为V标志。现在有些架构,因为它们已经在路上反转b操作数并且在路上进入,它们会在出路时反转执行。有点不对劲。因此,您必须查看您的特定体系结构,以了解执行是否被视为无符号加法溢出或是否为借用。或不借用或其他什么。

零减去某些东西并不总是会有一个执行添加。

0b000 - 0b111

 0001
  000
+ 000
=====
  001

添加的执行为零。您的架构可能选择将其保留,或者可以选择将其反转并将其称为借用。

在一个架构系列中。所有的x86或所有ARM很可能会继续以同样的方式继续这样做。但是没有理由期望ARM和MIPS以及x86和XYZ都以同样的方式做到这一点。

从术语的角度来看,颠倒它并将其定义为借用是有意义的。

请注意,所有(有符号/无符号)大于,小于,大于或等于,小于或等于定义都基于该体系结构的进位/借位选择,您不能跨体系结构转换这些标志比较,除非他们有相同的定义。