为什么INC和DEC指令*不影响进位标志(CF)?

时间:2012-11-17 21:53:40

标签: assembly x86 increment flags decrement

为什么x86指令INC(递增)和DEC(递减)不会影响FLAGSREGISTER中的CF(进位标志)?

4 个答案:

答案 0 :(得分:29)

要理解为什么你可能需要记住当前的“x86”具有32位和64位值的CPU开始使用更多有限的8位机器,返回到英特尔8008.(我在1973年的世界编码,我还记得(呃)它!)。

在那个世界里,登记册很珍贵。出于各种目的,您需要INC / DEC,最常见的是循环控制。许多循环涉及进行“多精度算术”(例如,16位或更多!)通过让INC / DEC设置零标志(Z),您可以使用它们来控制循环很好;通过坚持循环控制指令不改变进位标志(CF),进位在循环迭代中保留,并且您可以实现多精度操作而无需编写大量代码来记住进位状态。

一旦你习惯了丑陋的指令集,这个效果非常好。

在字体较大的更现代的机器上,您不需要这么多,因此INCDEC在语义上等同于ADD ...,1等。事实上,这就是我在需要随身携带时使用的内容: - }

大多数情况下,我现在远离INCDEC,因为他们会进行部分条件代码更新,这会导致管道中出现有趣的停顿,ADD / {{1 }} 别。因此,无关紧要(大多数地方),我使用SUB / ADD来避免失速。我只在保持代码较小的情况下才使用SUB / INC,例如,适合缓存行,其中一条或两条指令的大小会产生足够的差异。这可能是毫无意义的纳米[字面意思!] - 优化,但我在编码习惯上相当老派。

我的解释告诉我们为什么DEC / INC设置了零标志(DEC)。我没有特别引人注目的解释为什么Z / INC设置了标志(以及奇偶校验标志)。

编辑2016年4月:似乎在现代x86上处理失速问题更好。见INC instruction vs ADD 1: Does it matter?

答案 1 :(得分:5)

当你有一个由inc / dec设置的标志时,为什么签名的问题最好用问题解决:你宁愿没有选项 a

a) for (n=7;n>=0;n--)   // translates to   `dec + jns`
b) for (n=8;n>0;n--)    // translates to   `dec + jnz`

正如Ira Baxter已经阐明的那样,Carry标志用于许多算法 - 不仅是多精度算术,而且还用于单色/ cga / EGA时代的位图处理: 这会将80像素宽的行一个像素右移......

        mov cx, 10
begin:  lodsb
        rcr al,1   // this is rotate though carry:
        stosb      // for the algorithm to work, carry must not be destroyed
        LOOP begin //

但是:为什么平价?

我相信答案就是为什么不。这个指令集是从70年代后期开始的,当时晶体管很稀缺。拒绝为某些特定指令计算奇偶校验标志是没有任何意义的,但只是增加了CPU的复杂性。

答案 2 :(得分:1)

  1. inc dec 指令通常用于维护迭代或循环计数。使用32位,迭代次数可以高达4,294,967,295。对于大多数应用而言,此数字足够大。如果我们需要一个大于此的计数怎么办?我们必须使用add代替inc吗?这是第二个也是最主要的原因。

  2. 由进位标志检测的条件也可以由零标志检测。为什么?因为inc和dec仅将数字更改1。例如,假设ECX寄存器已达到最大值4,294,967,295(FFFFFFFFH)。如果然后执行

                     inc ECX
    

    我们通常希望将进位标志设置为1。但是,我们可以通过注意到ECX = 0(将零标志设置为零)来检测这种情况。因此,对于这些指令,设置进位标志确实是多余的。

答案 3 :(得分:-1)

因为没有必要影响。检查Zero标志就足够了。 因此,在inc和dec指令之后,进位标志保持不变,在某些情况下这是有用的。