To expand on Brendan's point:
Most ASM opcodes only do one tiny thing at a time. Example:
OR EAX, 0x4000
That's pitiful, isn't it? One entire opcode, and one entire machine cycle, just to set one bit in a register?
Now, as Brendan said, take a look at what I call an "addressing SIB mode".
MOV ECX, [EBX + EAX*8 + 0x12345678]
In order to do this one instruction, the CPU had to calculate an address. It took a register, shifted it by 3 bits, added it to another register, and added a constant -- all in one opcode! Isn't that amazing that it can do all that in one opcode, with dedicated circuitry, so quickly? Wouldn't it be neat if you actually had access to that math operation -- all that dedicated address calculation circuitry -- to do high-speed MATH (not just calculating addresses) in your code?
That is what the LEA address is for. Sadly, there are many times when I wish I could do:
LEA ECX, [EBX - EAX*8]
but the x86 doesn't support subtraction at all.
One point that I don't think Brendan emphasized enough: the other nice thing about LEA is that you can do some useful multiplications on ALL registers IN PLACE.
LEA EDI, [EDI + EDI*4]
Now, please think about how many registers you would normally have to trash, in order to multiply EDI by 5, using MUL. This works for multiplications by 3, 5, and 9. So those (surprisingly) are very efficient numbers to multiply by, in Assembly language.
Another (semi-)important note: LEA does not set or trash any EFLAGS bits. So, if you want to (say) fix your stack pointer at the end of a function, but your EFLAGS bits are already set, you can do:
LEA ESP, [ESP + 16]
Which gets rid of 4 dwords off your stack, without messing up your Carry flag (for instance).