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

Vin*_*rta 2 x86 assembly

我填ecx与我想循环中,倍量decrease ecxjump if not zeroback:

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

cmp ecx, 0 之前必需的jnz backjnz跳转时如何自动知道要比较哪个寄存器?(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;
}
Run Code Online (Sandbox Code Playgroud)

Tom*_*e2k 5

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

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

如您在此列表中看到的,某些指令甚至具有多个名称。例如,jeĴ UMP如果Ë QUAL)只是一个别名jzĴ如果UMP Ž ERO标志被设置)。

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

几乎所有的算术和按位指令都会影响这些标志以及其他标志。官方文档非常清楚每个指令会影响哪些标志。例如,dec cx还设置标志。如果in的值cx递减后为零,则将置零标志。因此,jnz不会跳,您会掉入循环。