Q:

Why is 'cmp' not necessary when using jumps on a loop?

I fill ecx with the amount of times I want to loop, decrease ecx and jump if not zero to back:. 
Now the question is, why isn't:
cmp ecx, 0
necessary before jnz back.
How does jnz knows automatically which register to compare when doing the jump? (which is ecx in this case).
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;
}

A:

In assembly, there is more than one instruction that can be used to perform a "comparison".
In general (with only a very few exceptions), conditional branching instructions do not compare any registers at all. They test the so-called "status flags" (zero-flag, carry-flag, etc.) in the EFLAGS register, and determine whether or not to perform the jump based on the status of these flags.
As you can see in this list, some instructions even have multiple names. For example, je (Jump if Equal) is just an alias for jz (Jump if Zero flag is set).
As for the cmp instruction, it is simply a subtraction. It sets the flags as if a subtraction had been performed, but does not save the value or modify any of its operands. For example, if you subtract 10 from 12 (either via cmp or sub), the zero flag is cleared (since the result is not zero) and the carry flag is cleared (there was no need to borrow). In this case, based on the status of the zero flag, a jnz (aka jne) will take the branch, while a jz (aka je) will not.
Almost all arithmetic and bitwise instructions influence these flags, as well as some others. The official documentation makes it very clear which flags are affected by each instruction. For example, dec cx also sets the flags. If the value in cx is zero after it has been decremented, then the zero flag will be set. Thus, jnz will not jump and you will fall out of the loop.

