Load Effective Address for Mere Mortals
An attempt to explain the x64 LEA Instruction
Among the learners of x86-x64 assembly, lea (load effective address) instruction seems to cause some confusion. People struggle to understand its purpose, its relation to the mov instruction, its name and its syntax.
Short Explanation
In spite of its name lea is not a data transfer instruction, but the address computation instruction. According to Intel® 64 and IA-32 Architectures Software Developer’s Manual, it computes the effective address in memory (offset within a segment) of a source operand and places it in a general-purpose register.
Let’s look at an example:
lea rax, [rdi+8]The instruction takes the value of the register rdi, adds eight to it and loads the result into the rax register. Basically, the equivalent of:
mov rax, rdi
add rax, 8, except that it takes only one instruction and no flags are affected.
Longer Explanation
To understand the purpose and syntax of the lea instruction, let’s start with the more familiar and arguably less confusing mov.
mov destination, sourcemov copies (doesn’t move!) the source operand to the destination operand. Source and destination can be different things, but the case we are interested in here is when source is a memory location and destination a general-purpose register. For example:
mov rax, QWORD PTR [rdi+8]performs the following two steps:
Calculates the address of the memory location that contains the value for the source. The address is called effective address, and, in our case, it is calculated by adding 8 to the value contained in
rdiregister.Fetches the value that is stored in memory at the address we calculated in step 1 and copies it to
raxregister.
A lea function that takes the same two arguments (ignoring the size directive QWORD PTR) looks like:
lea rax, [rdi+8]and does only the step 1. above. It calculates the effective address, but it does not use it to access a memory location; instead, the address is copied directly to the destination.
One way to think of it is:
mov rax, rdi+8 ; Invalid syntaxSome people feel that lea should not exist and mov should be expanded to cover that case as well. Things are not that simple. The syntax above does not make it clear that rdi+8 is an effective address; it would be way too easy to specify a source destination for which there is no built-in mechanism of calculating in a single instruction. The square brackets in lea instruction make clear that we have an effective address as an operand; unfortunately, they also suggest that the effective address is used to fetch the value from the memory, which is not the case.
If you want to learn more about the concept of effective address, I highly suggest reading the following article by William Woodruff: How x86_64 addresses memory

