为什么在循环中使用跳转时不需要'cmp'?

时间:2017-01-03 15:30:53

标签: assembly x86

我将ecx填入我想要循环的次数,dececxjump if not zero放到back:

现在的问题是,为什么不是:

cmp ecx, 0 jnz back之前必要的。 jnz如何在跳转时自动知道要比较哪个寄存器? (在这种情况下为ecx)。

int _tmain(int argc, _TCHAR* argv[])
{
    int a = 0;

    __asm 
    {
        mov eax, 0
        mov ecx, 4
back:
        inc eax
        sub ecx, 1
        jnz back
        mov a, eax
    }

    cout << a << endl; //outputs '4' properly

    return 0;
}

1 个答案:

答案 0 :(得分:4)

在汇编中,有多个指令可用于执行“比较”。

通常(只有极少数例外),条件分支指令根本不比较任何寄存器。他们在EFLAGS寄存器中测试所谓的“状态标志”(零标志,进位标志等),并根据这些标志的状态确定是否执行跳转。 p>

正如您所见in this list,某些说明甚至有多个名称。例如,je J ump,如果 E qual)只是jz的别名( J ump if设置 Z ero标志。)

对于cmp指令,它只是一个减法。它将标志设置为好像已执行减法,但不保存值或修改其任何操作数。例如,如果从12减去10(通过cmpsub),则清零零标志(因为结果不为零)并且进位标志被清除(没有必要借)。在这种情况下,根据零标志的状态,jnz(aka jne)将采用分支,而jz(aka je)则不会。

几乎所有算术和按位指令都会影响这些标志以及其他一些标志。官方文档清楚地说明了哪些标志受每条指令的影响。例如,dec cx也设置标志。如果cx中的值在递减后为​​零,则将设置零标志。因此,jnz不会跳跃,你将失去循环。