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.

Prints 6.
MOV BX, 2
MOV SI, 3
LEA AX, [BX+SI+1] ; AX = 2 + 3 + 1; memory is not touched
ADD AL, '0' ; digit -> character
MOV DL, AL
MOV AH, 02h ; DOS: print DL
INT 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.

Prints "this part".
MOV SI, 4
LEA DX, [MSG1+SI] ; DX = address of the 5th byte of MSG1
MOV AH, 09h ; DOS: print the string at DS:DX
INT 21h
MSG1 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.