Microcode (in the form of a microprogram) refers to a technique for implementing the functionality needed to control the internal operation of a CPU.
On each microcycle (analogous, internally, to the cycles of the main CPU), a microinstruction is fetched, and used to control the operation of the CPU's internal hardware elements during that microcycle: routing data out of registers (including internal registers not visible to the programmer) and/or main memory, through the ALU (while selecting which operation is to be performed by it), and then storing the results as apropriate. They are thus analagous to the instructions of the main CPU, but at a much lower level.
The earliest generation of CPU's used collections of gates and flip-flops to implement the functionality of controlling the operation of the internal elements. As the instruction sets and overall architecture of early computers became more complex, the design of those combinatorial logic networks became more challenging.
In 1947, the Whirlwind computer introduced the concept of a control store; a wide read-only memory whose outputs directly controlled internal elements of the CPU. (E.g. one bit in a control word might control the latching of an internal register.)
The CPU cycled through the words in the control store, to execute instructions. Viewing (and implementing) the internal operation of the CPU in this way made the design task easier.
In 1951, Maurice Wilkes suggested adding conditional branching, to make microcode more flexible. Over time, more concepts from higher-level languages have been added to microcode, such as subroutines.
Although early microcode was implemented in read-only memory (the Whirlwind ROM was a diode matrix), some later computers included high-speed RAM for part of the control store, so that the instruction set could be dynamically extended to speed up applications.
Recently, microcode has been augmented with programmable logic arrays, which are usually given the job of decoding instructions (something done more efficiently in combinatorial logic).
With much of the control for a microprogrammed machine in the microprogram, bugs in the CPU could often be fixed by replacing the microprogram alone, without required hardware changes. (With the coming of the microprocessor, where the microprogram is often in ROM in the chip, this is usually no longer possible.)
Microprogramming also made it possible to offer a range (in performance and cost terms) of machines which all had the same basic architecture, but different internal implementations; microcode could be used to make the different machines all support the same instruction set. This too is now not common, since it is not usual to offer multiple implementations with differing performance at the same time; however, it can be used to meet an analogous goal, making new generations of microprocessors implement the identical instruction set to previous ones.
For much of the lifetime of computers, the CPU was faster than the main memory; in such an environment, it makes sense to make the instructions of the CPU as high-level as possible, so a single instruction fetch (which is, of course, pure overhead in terms ot the actual computation) does as much as possible. Such complex instructions are more easily implemented with a microcode approach, than with combinatorial logic.