LEA reg16, mem works out the offset that the memory operand would use, from its base register, index register and displacement, and stores that offset in the register. It does not read memory at all: only the address arithmetic happens. The destination is a 16-bit general register; the source must be written as a memory operand. The segment is not part of the result, so a segment override on the source has no effect. No flags change.
MOV BX, 2MOV SI, 3LEA AX, [BX+SI+1] ; AX = 2 + 3 + 1; memory is not touchedADD AL, '0' ; digit -> characterMOV DL, ALMOV AH, 02h ; DOS: print DLINT 21h
LEA or MOV OFFSET
For a plain label, LEA DX, MSG1 and MOV DX, OFFSET MSG1 give the same value. The MOV form is a byte shorter, because the address is a constant the assembler already knows. LEA is needed when the address depends on registers at run time, such as the address of element SI of a table.
MOV SI, 4LEA DX, [MSG1+SI] ; DX = address of the 5th byte of MSG1MOV AH, 09h ; DOS: print the string at DS:DXINT 21hMSG1 DB 'skip this part', 13, 10, '$'
LEA as arithmetic
Since it only adds, LEA is also an addition that keeps the flags and can write to a third register: LEA DI, [BX+SI+2] sets DI to BX + SI + 2 and leaves BX, SI and the flags alone. On the 8086 the registers you can combine are those of the addressing modes: BX or BP, plus SI or DI, plus a constant.
Not allowed
LEA AX, BX is rejected because BX is a register, not a memory operand; write MOV AX, BX. LEA cannot load a segment register, and it cannot add AX, CX or DX, which are not address registers on the 8086.
Later CPUs
From the 80386 on, any 32-bit register can be a base or index and the index can be scaled by 2, 4 or 8. LEA EAX, [EAX+EAX*4] multiplies by 5 in one instruction, an idiom compilers still use.