18
ar db "Defference $"

What's the difference between

mov dx,offset ar

and

lea dx,ar

I think both are doing same work, but what is the difference between these two

Michael Petch
  • 42,023
  • 8
  • 87
  • 158
userBI
  • 347
  • 1
  • 5
  • 15
  • the only difference between them is that `lea` is an instruction and `offset` is not – phuclv Apr 16 '18 at 06:50
  • Possible duplicate of [What is the difference between MOV and LEA?](https://stackoverflow.com/questions/1699748/what-is-the-difference-between-mov-and-lea) – phuclv Apr 16 '18 at 06:50

3 Answers3

23

In this use-case LEA and MOV do the same thing. LEA is more powerful than MOV if you want to calculate an address in a more complex way.

Lets for example say you want to get the address of the n'th character in your array, and the n is stored in bx. With MOV you have to write the following two instructions:

Mov dx, offset ar
add dx, bx

With lea you can do it with just one instruction:

lea dx, [ar + bx]

Another thing to consider here: the add dx,bx instruction will change the status flags of the CPU. The addition done inside the lea dx, [ar + bx] instruction on the other hand does not change the flags in any way because it is not considered an arithmetic instruction.

This is sometimes helpful if you want to preserve the flags while doing some simple calculations (address calculations are very common). Storing and restoring the flag-register is doable but a slow operation.

Nils Pipenbrinck
  • 77,289
  • 24
  • 142
  • 216
  • 3
    Also `offset ar` - is immediate value which is calculated during translation. And `lea` - is actual processor instruction "Load Effective Address" with second operand which references to memmory. – ony May 09 '10 at 11:42
  • 1
    @ony: `lea` is just a shift-and-add instruction. It never actually loads from memory, it just uses the addressing-mode syntax and binary encoding. In the OP's case, with `lea` on an absolute address, the `disp16` is the same as the `imm16` for the `mov`, both calculated the same way at assemble time (actually at link time when the final address is known). – Peter Cordes Jun 04 '16 at 15:32
  • @PeterCordes, I didn't said that `lea` loads anything (reference is just a reference). I said that it is a real x86 instruction. If you do calculatons that can be done during translation you can use `mov`. – ony Jun 05 '16 at 11:31
  • The thing that puzzles me most about `lea` is the syntax used by compilers and debuggers. `lea ax, [addr]` for me is something like "do something with the **contents** of `addr` and put the result into `ax`, which is not the case. – Trap Feb 06 '18 at 00:32
  • Also, this was an issue in the older days of 16-bit real mode programming. When linking to a small binary .com file where everything was in the same segment, you could use `offset` or `lea` interchangeably most of the time, but working with memory models other than `tiny` would cause a lot of problems since `offset` is relative to the segment base address where the data is defined. – Trap Feb 06 '18 at 00:44
  • Worth mentioning that you should never use `lea dx, [ar]`. It's one byte longer than `mov`, and no faster. For a static address with no register index, you only ever want LEA on x86-64, for RIP-relative (position-independent) 64-bit addressing. Otherwise, always use mov-immediate if you need a plain static address in a register. (On x86-64 in position-*dependent* code, `mov edi, offset mydata` is still optimal, e.g. on Linux where static data is in the low 32 bits of virtual address space, so 32-bit absolute addresses can be used for efficiency.) – Peter Cordes Dec 30 '18 at 03:45
2

Quote from Assembly Language for x86 Processors, 7e, KIP R. IRVINE

It is not possible to use OFFSET to get the address of a stack parameter because OFFSET only works with addresses known at compile time. The following statement would not assemble:

mov esi,OFFSET [ebp-30]        ; error
Eli Zehavi
  • 183
  • 2
  • 5
-1

You can use them to do the same thing but, LEA will always be better if the address is a little complex.

consider that you have the following array of chars:

ASC_TBL DB '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'

if you want to get the 6th element '5' you would do something like this using offset:

mov ax, offset ASC_TBL

add ax, 5h; flags [PF] will be affected 

On the other hand, if you are using the LEA instruction you can simply use one instruction like this:

LEA ax, [ASC_TBL + 5h]; no flags are affected

Notice that:

  • Although using LEA proved that it has an advantage over using offset, it's more efficient to use offset if the address isn't very complex to write or both of them will do the same thing with the same number of instructions. The reason is that offset ASC_TBL is calculated during translation - like being be preprocessed- but, LEA is an actual processor instruction.

  • you can't use the offset instruction to get the addresses that aren't known before the compilation time.

Mostafa Wael
  • 127
  • 3
  • `mov ax, offset ASC_TBL + 5` is legal, and shorter (3 bytes for `mov ax, imm16` vs. 4 bytes for LEA: opcode + modrm + disp16). Either way the absolute address is calculated by the assembler (or linker) and embedded into the machine code. `ASC_TBL+5` is a link-time constant just like `ASC_TBL`; there's no `+5` being done at runtime. Symbols don't really exist at runtime, except as debug metadata in the executable. The CPU isn't searching for them when running instructions that reference them. – Peter Cordes Nov 18 '20 at 22:09
  • I didn't say that `+5` is being done at runtime, I said that the full `LEA` instruction is an actual processor instruction – Mostafa Wael Nov 22 '20 at 14:57
  • Ok, so you just weren't aware you could `mov ax, offset ASC_TBL + 5`. Well, you can. :P The assembler (and linker if you're not making a flat binary) handle it with an identical mechanism to what they use to fill in `[disp16]` field in the `lea` operand. The `mov reg, imm16` encoding also just needs an absolute address in the machine code. LEA is worse for code-size and should never be used for this, except in 64-bit code with RIP-relative addressing to get position-independence or instead of 64-bit absolute addresses. – Peter Cordes Nov 23 '20 at 01:51