1

I can understand that an LEA instruction passes an address to a destination, but I can't understand how an LEA instruction performs the arithmetic operation.

I'm using ATT language (I guess).

say an arithmetic operation:

x = 3 * y + 5;

can be done:

leal 5(%esi, %esi, 2), %eax

What is the procedure of this LEA operation?

In my understanding, it takes the value stored on %esi and add and mult them, and store the result on a new address in memory, and finally pass this address to %eax. If this is correct, there's a seemingly unnecessary step of storing the value on a new address (why don't just store the value on %eax?)

If my understanding is incorrect, please investigate what the LEA actually do in order to pass an address to %eax

Thanks.

  • 3
    AT&T syntax is, in my opinion, just a mess (because it's one step too low-level). In Intel syntax, you'd write `lea eax, [esi+esi*2+5]` - there is no intermediate step here, it's all done in one instruction, and the value in `eax` is actually `x`'s value and not its address. The reason `lea` is called "load effective _address_" is just because it's using the processor's addressing modes to do a calculation without then actually reading memory from somewhere. `mov eax, [ebx+8]` would do `eax = *(ebx+8)` (in C pseudocode) while `lea eax, [ebx+8]` would do `eax = ebx+8`. – CherryDT Mar 07 '22 at 16:49
  • This is one of the main reasons I do not like Intel syntax. As CherryDT wrote it is `lea eax, [esi + esi * 2 + 5]` in Intel syntax, which I believe is clear enough it can be used to calculate `x = 3 * y + 5`. The difference with `imul eax, esi, 3; add eax, 5` for example, is that `lea` does not affect any flags. And on every `x86` processor a single `lea` is a better choice over an `imul` – xiver77 Mar 07 '22 at 16:55
  • @CherryDT: I generally prefer Intel syntax, but I don't think Intel vs. AT&T has anything to do with understanding LEA, i.e. that C `&*(ebx+8)` is just `ebx+8`. If anything, the more fixed format of AT&T addressing modes are more helpful for learning / remembering [what the machine can actually encode](https://stackoverflow.com/questions/34058101/referencing-the-contents-of-a-memory). (I initially preferred AT&T when first learning, but after seeing its warts like different mnemonics and being backwards from official manuals, not to mention the x87 mnemonic bug, I now prefer Intel syntax.) – Peter Cordes Mar 07 '22 at 19:08
  • @CherryDT, Thanks for your answer. Just to reassure, LEA actually never pass an address to the destination, the use of an address is only related to the source, is that correct? – StoneForest Mar 08 '22 at 01:36
  • The result of the addressing-mode calculation is just a number, and the destination register gets that value; it's not used to access memory. But it is an "effective address" because it was the result of an addressing mode calculation. Of course addresses are just numbers in assembly language, being an address does *not* imply it's dereferenced or checked against segment limits or page tables. That's part of dereferencing. – Peter Cordes Mar 08 '22 at 04:25

2 Answers2

2

and store the result on a new address in memory

It is not a new address in memory, but rather an internal temporary variable.

From a conceptual perspective, it is the same, and costs nothing to introduce an internal temporary variable, as part of the description of operation.

The reason they describe it this way is so they can describe the operation of lea the same way as with other instructions, like mov and add, the ones that use the same addressing modes, so compute and use but don't capture the effective address into any architectural register.


The actual implementation varies across processors and on some is much more efficient than the description.

Erik Eidt
  • 23,049
  • 2
  • 29
  • 53
1

The lea instruction is used to calculate addresses, but as your question asks, it can also be used for a range of (somewhat) simple math calculations as well. Comparing the high-level operation and the assembly, %esi does not point to y but holds the value of y. Correspondingly, when it setting %eax it is not setting the address of x but is storing x itself.

lea has a scaled part which is a power of 2, a "variable" offset, and a constant. If your expression we make 3 * y by treating it as 2 * y + y where 2 * y is the scaled bit and y is the "variable" bit. And then end by adding the constant 5.

DocMax
  • 12,094
  • 7
  • 44
  • 44