Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 为什么INC和DEC指令*不*影响进位标志(CF)?_Assembly_X86_Increment_Flags_Decrement - Fatal编程技术网

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

Assembly 为什么INC和DEC指令*不*影响进位标志(CF)?,assembly,x86,increment,flags,decrement,Assembly,X86,Increment,Flags,Decrement,为什么x86指令INC(递增)和DEC(递减)不影响FLAGSREGISTER中的CF(进位标志)?要理解为什么您可能需要记住当前具有32位和64位值的“x86”CPU,可以追溯到Intel 8008,它的使用寿命与更有限的8位机器一样长。(我早在1973年就在这个世界上编码了,我还记得它!) 在那个世界上,登记册既珍贵又小。您需要INC/DEC用于各种用途,最常见的是循环控制。许多循环涉及到“多精度算术”(例如,16位或更多!),通过让INC/DEC设置零标志(Z),您可以很好地使用它们来控制

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

要理解为什么您可能需要记住当前具有32位和64位值的“x86”CPU,可以追溯到Intel 8008,它的使用寿命与更有限的8位机器一样长。(我早在1973年就在这个世界上编码了,我还记得它!)

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

一旦你习惯了丑陋的指令集,这就非常有效了

在更大字号的现代机器上,您不需要太多,因此
INC
DEC
可以在语义上等同于
ADD
…,1等。事实上,这就是我需要进位集时使用的:-}

大多数情况下,我现在远离
INC
DEC
,因为他们会更新部分条件代码,这可能会导致管道中出现有趣的暂停,而
ADD
/
SUB
则不会。因此,在不重要的地方(大多数地方),我使用
ADD
/
SUB
来避免停顿。我只在代码很小的情况下使用
INC
/
DEC
,例如,在一条或两条指令的大小足以产生影响的缓存线中安装代码。这可能是毫无意义的nano优化(字面意思是!),但我的编码习惯已经很老套了

我的解释告诉我们为什么
INC
/
DEC
设置零标志(
Z
)。对于为什么
INC
/
DEC
设置符号(和奇偶校验标志),我没有特别令人信服的解释


2016年4月编辑:在现代x86上,失速问题似乎处理得更好。请参见,因为没有必要影响。检查零标志就足够了。 因此,在inc和dec指令之后,进位标志保持不变,并且在某些情况下是有用的。

当inc/dec设置了零标志时,为什么要签名的问题最好通过以下问题来解决:您愿意不选择a

如前所述,进位标志用于许多算法中——不仅是多精度算法,还用于单色/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的复杂性

  • 指令incdec通常用于维护迭代或循环计数。使用32位,迭代次数可高达4294967295。对于大多数应用来说,这个数字足够大。如果我们需要一个大于这个的计数呢?我们必须使用add而不是inc吗?这就引出了第二个也是主要的原因

  • 进位标志检测到的条件也可以由零位标志检测到。为什么?因为inc和dec只能将数字更改1。例如,假设ECX寄存器已达到其最大值4294967295(FFFFFFFFH)。如果我们执行

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


  • @安德烈亚斯布林克:这个问题不是关于“为什么?”的,那里的答案也没有回答设计选择的问题。这不是一个完全重复的问题。另一个问题询问如何使用INC/DEC,并简单地观察到进位未更新。这个问题问为什么它没有更新。我发现事实上,有几个人愿意把这个问题作为一个完全重复的问题来结束,而事实并非如此,这表明“主持人”正在抢先一步。这对SO没有帮助。半相关:显示了一些更新的示例,但没有CF。这就是这个问题在某一点上被错误链接到的非重复项。对于
    inc
    :进位从0xFFFF开始。。。为0,则ZF和CF相等。但是
    dec
    0
    变为
    0xFFFF…
    ,因此ZF设置为进位前的减量。我认为真正的原因是
    sub-reg,1
    在需要CF时可用,通常不需要CF结果。因此,保留CF可以将其与ADC、移位、RCL和其他保持CF的内容混合使用(当然,这一设计决策是针对8086作出的,早在部分寄存器暂停作为未来问题出现在雷达上之前很久。在这一点上,
    loop
    是有效的,因此无标志循环很容易)通过设置SF/OF和ZF,您可以
    dec/jge
    从n向下循环到0,而不是从n向下循环到1。(即当
    dec
    产生
    -1
    而不是
    0
    )这偶尔有用。更新:Skylake甚至更好:它完全独立于其他标志处理CF(SPAZO);需要两个输入的少数指令将它们作为两个单独的输入读取,因此根本不需要合并标志。(但是
    cmova
    cmovbe
    仍然是2个UOP,因为总共有4个输入,而其他cmov指令只需要3个。
                     inc ECX