2
votes

I am new to assembly language. I am currently going through this Assembly Guide. I have doubt in LEA instruction. My understanding of LEA instruction is LEA loads the destination operand with the effective address of source operand

Below example is from the same link.

lea edi, [ebx+4*esi] — the quantity EBX+4*ESI is placed in EDI.
lea eax, [var] — the value in var is placed in EAX.
lea eax, [val] — the value val is placed in EAX.

In the above 2nd and 3rd example comment says the value is loaded in the EAX. This is my confusion. Kindly let me know if LEA instruction can be used to load the effective address as well as value in the destination operand.

Introduction to assembly language


The above image is from Introduction to assembly language from youtube's Open SecurityTraining channel.

Thank You.

2
2nd and 3rd are wrong. The address is placed into eax. When in doubt, consult the official reference (google for Intel Manual 2)Margaret Bloom
The 2nd part of the question, added in an update, is an exact duplicate of stackoverflow.com/questions/46597055/…: yes, LEA can be used to shift/add any values, even if the value isn't an address. The first part: resolving confusion caused by a wording error in an example in a guide / tutorial, is a valid question. Confusion caused by wrong guides / tutorials makes an otherwise-too-trivial question valid, IMO.Peter Cordes

2 Answers

5
votes

LEA is an ALU shift+add instruction that uses addressing-mode syntax and machine-code encoding to take advantage of hardware support for decoding this kind of operation. (It doesn't care if the inputs are addresses or not, so the 2nd part of your question is answered there: lea eax, [ecx + eax*2] implements x*2 + y efficiently.)

Under no circumstances does lea ever load or store from memory. See Intel's instruction-manual entry for it.

Fun fact: the only exception it can take is if the ModR/M byte encodes a register source instead of memory. e.g. lea eax, eax would fault with #UD (UnDefined instruction) if your assembler didn't refuse to assemble it, or if you manually encoded it with a db pseudo-instruction. This is not something to worry about in practice if you're writing in asm, not in hex machine code. But there are no data-dependent exceptions it can take; it doesn't care at all what values it's operating on.


In the 3rd one, I think they're talking about something like val equ 4 or val = 4, so "the value of val" is an assemble-time constant, not stored in memory.

Yes you can use LEA for that (or any 32-bit constant), but mov eax, val is shorter and more efficient. Using an LEA with an absolute disp32 addressing mode is pointless.

Fun fact: MASM ignores [] around assemble-time constants: mov eax, [val] is a mov eax, imm32, the same as mov eax, val. Ross Ridge wrote a nice answer on Confusing brackets in MASM32.


lea eax, [var] — the value in var is placed in EAX.

The comment is wrong. The address of var is placed in EAX. In normal asm terminology, the value in a symbol name means the value stored in memory at that address.

mov eax, OFFSET var is more efficient and shorter than lea eax, [var]. Some people like to write lea because of the "semantic" meaning for human readers: taking the address. But if you're writing in assembly, human readability should come after efficiency, and only win as a tie-breaker, e.g. choosing esi for a source pointer when the choice makes no other difference. (Format / indent your code nicely, and comment it well.)

lea eax, [var + edi] would make sense, you can't do that with mov. But you can do mov eax, OFFSET var + 1234, because assemblers + linkers have to be able to support filling in a 32-bit symbol+offset values for addressing modes like [var + 1234].

In 64-bit mode, lea rax, [rel var] makes sense in position-independent code: you can't get a RIP-relative address with mov.

2
votes

LEA is literally "Load Effective Address." It computes an address first - called "effective" because it may be composed from several parts and the results is what effectively ends up in the destination - and loads that address somewhere.
While [var] uses an addressing mode, lea merely computes the address and stores it in the destined location, it doesn't use it to load something from main memory. "the value in var" is wrong, "the value var" is more on point, if "var" refers to the address of a label, not a stored value.

Since the source explicitly says that "[...] the contents of the memory location are not loaded, only the effective address is computed and placed into the register," I think this is just a misleading typo, not misinformation.