by Richard Russell, July 2007
Beginners in x86 (or IA-32) assembly language programming often fail to appreciate the value of the lea (Load Effective Address) instruction and use it rarely, if at all. lea takes advantage of the CPU's address generator(s) in being able to perform some simple calculations on 32-bit values which do not tie-up the resources of the CPU's Arithmetic Logic Unit(s). In so doing the resulting code can be shorter and faster.
This is particularly so on modern processors, because the address generators are likely to be relatively underused and may be available to perform a calculation in parallel with other operations taking place on the ALUs. Also, because the lea instruction doesn't affect the condition flags it doesn't stall other instructions which may be dependent on the state of those flags, hence they can be executed simultaneously rather than sequentially.
To take an extreme example, suppose you want to perform the following register arithmetic:
eax = ebx*4 + ecx + constant
That is, add four-times ebx to ecx, add a constant, then put the result into eax.
A simplistic approach, using the ALU, would require code like the following:
00100000 8B C3 mov eax,ebx 00100002 C1 E0 02 shl eax,2 00100005 03 C1 add eax,ecx 00100007 05 40 E2 01 00 add eax,constant
However using lea we can do it in just one instruction:
00100000 8D 84 99 40 E2 01 00 lea eax,[ecx+ebx*4+constant]
Not only is this five bytes shorter, it is likely to execute considerably more quickly.
Of course the limitation of lea is that only certain arithmetic operations - those required for address generation - are available. Basically it can add any 32-bit register (or none) to 1, 2, 4 or 8 times any other 32-bit register, and optionally add a constant to the result. Since it can add a register to 2, 4, or 8 times the same register, it can also multiply a register by 3, 5 or 9:
00100000 8D 04 5B lea eax,[ebx*3] 00100003 8D 04 9B lea eax,[ebx*5] 00100006 8D 04 DB lea eax,[ebx*9]