First off, you have to recall that assembly language is not the same as the machine code; rather, it is a human-readable representation of the machine code, which is actually a series of electrical impulses inside the CPU. Assembly language is almost a one to one analog to the machine code, but still isn't an exact representation (especially on the x86 processors, as the Intel assembly instruction set often maps a single mnemonic to more than one machine instruction). The assembler converts the instructions into a series of numeric representations of the machine codes, which when loaded into memory make up the executable program (actually, even this isn't quite true, as the 'executable' file is usually in a format that is patched by the loader with the specific memory locations it is loaded to and other details of the binary executable, but for now this is close enough).
Just how it works is going to depend on the details of the hardware implementation inside the chip. I don't know if the current generation of x86 processors uses microcode or not, but most likely they do, in which case some of the machine codes are themselves broken down into a series of simpler steps. In general, though, the operations are performed directly by the hardware, in the form of a series of circuits that alter one set of register and memory valuues to another.
Assembly language cretainly does hide the internal operation of the processor.
The cmp instruction is probably implemented as a microcode program which subtracts one number from the other, without storing the result, and then sets bits in the flags register depending upon whether the result is less than zeo, equal to zero, or greater than zero.
Ultimately it will come down to the hardware, with logic gates switching.