[assembly] What's the purpose of the LEA instruction?

The LEA (Load Effective Address) instruction is a way of obtaining the address which arises from any of the Intel processor's memory addressing modes.

That is to say, if we have a data move like this:

MOV EAX, <MEM-OPERAND>

it moves the contents of the designated memory location into the target register.

If we replace the MOV by LEA, then the address of the memory location is calculated in exactly the same way by the <MEM-OPERAND> addressing expression. But instead of the contents of the memory location, we get the location itself into the destination.

LEA is not a specific arithmetic instruction; it is a way of intercepting the effective address arising from any one of the processor's memory addressing modes.

For instance, we can use LEA on just a simple direct address. No arithmetic is involved at all:

MOV EAX, GLOBALVAR   ; fetch the value of GLOBALVAR into EAX
LEA EAX, GLOBALVAR   ; fetch the address of GLOBALVAR into EAX.

This is valid; we can test it at the Linux prompt:

$ as
LEA 0, %eax
$ objdump -d a.out

a.out:     file format elf64-x86-64

Disassembly of section .text:

0000000000000000 <.text>:
   0:   8d 04 25 00 00 00 00    lea    0x0,%eax

Here, there is no addition of a scaled value, and no offset. Zero is moved into EAX. We could do that using MOV with an immediate operand also.

This is the reason why people who think that the brackets in LEA are superfluous are severely mistaken; the brackets are not LEA syntax but are part of the addressing mode.

LEA is real at the hardware level. The generated instruction encodes the actual addressing mode and the processor carries it out to the point of calculating the address. Then it moves that address to the destination instead of generating a memory reference. (Since the address calculation of an addressing mode in any other instruction has no effect on CPU flags, LEA has no effect on CPU flags.)

Contrast with loading the value from address zero:

$ as
movl 0, %eax
$ objdump -d a.out | grep mov
   0:   8b 04 25 00 00 00 00    mov    0x0,%eax

It's a very similar encoding, see? Just the 8d of LEA has changed to 8b.

Of course, this LEA encoding is longer than moving an immediate zero into EAX:

$ as
movl $0, %eax
$ objdump -d a.out | grep mov
   0:   b8 00 00 00 00          mov    $0x0,%eax

There is no reason for LEA to exclude this possibility though just because there is a shorter alternative; it's just combining in an orthogonal way with the available addressing modes.

Examples related to assembly

Why does C++ code for testing the Collatz conjecture run faster than hand-written assembly? While, Do While, For loops in Assembly Language (emu8086) Replacing a 32-bit loop counter with 64-bit introduces crazy performance deviations with _mm_popcnt_u64 on Intel CPUs How to run a program without an operating system? Difference between "move" and "li" in MIPS assembly language Carry Flag, Auxiliary Flag and Overflow Flag in Assembly How do AX, AH, AL map onto EAX? JNZ & CMP Assembly Instructions Difference between JE/JNE and JZ/JNZ The point of test %eax %eax

Examples related to x86

How to compile Tensorflow with SSE4.2 and AVX instructions? Why does C++ code for testing the Collatz conjecture run faster than hand-written assembly? Replacing a 32-bit loop counter with 64-bit introduces crazy performance deviations with _mm_popcnt_u64 on Intel CPUs How to install ia32-libs in Ubuntu 14.04 LTS (Trusty Tahr) How to run a program without an operating system? Carry Flag, Auxiliary Flag and Overflow Flag in Assembly How do AX, AH, AL map onto EAX? JNZ & CMP Assembly Instructions How does the ARM architecture differ from x86? Difference between JE/JNE and JZ/JNZ

Examples related to x86-64

How to build x86 and/or x64 on Windows from command line with CMAKE? How to include static library in makefile Difference between x86, x32, and x64 architectures? Floating point vs integer calculations on modern hardware What are the calling conventions for UNIX & Linux system calls (and user-space functions) on i386 and x86-64 What's the purpose of the LEA instruction? How to find if a native DLL file is compiled as x64 or x86? System.BadImageFormatException: Could not load file or assembly (from installutil.exe) How can I determine if a .NET assembly was built for x86 or x64? Targeting both 32bit and 64bit with Visual Studio in same solution/project

Examples related to x86-16

While, Do While, For loops in Assembly Language (emu8086) What's the purpose of the LEA instruction?