[assembly] What's the purpose of the LEA instruction?

The 8086 has a large family of instructions that accept a register operand and an effective address, perform some computations to compute the offset part of that effective address, and perform some operation involving the register and the memory referred to by the computed address. It was fairly simple to have one of the instructions in that family behave as above except for skipping that actual memory operation. Thus, the instructions:

mov ax,[bx+si+5]
lea ax,[bx+si+5]

were implemented almost identically internally. The difference is a skipped step. Both instructions work something like:

temp = fetched immediate operand (5)
temp += bx
temp += si
address_out = temp  (skipped for LEA)
trigger 16-bit read  (skipped for LEA)
temp = data_in  (skipped for LEA)
ax = temp

As for why Intel thought this instruction was worth including, I'm not exactly sure, but the fact that it was cheap to implement would have been a big factor. Another factor would have been the fact that Intel's assembler allowed symbols to be defined relative to the BP register. If fnord was defined as a BP-relative symbol (e.g. BP+8), one could say:

mov ax,fnord  ; Equivalent to "mov ax,[BP+8]"

If one wanted to use something like stosw to store data to a BP-relative address, being able to say

mov ax,0 ; Data to store
mov cx,16 ; Number of words
lea di,fnord
rep movs fnord  ; Address is ignored EXCEPT to note that it's an SS-relative word ptr

was more convenient than:

mov ax,0 ; Data to store
mov cx,16 ; Number of words
mov di,bp
add di,offset fnord (i.e. 8)
rep movs fnord  ; Address is ignored EXCEPT to note that it's an SS-relative word ptr

Note that forgetting the world "offset" would cause the contents of location [BP+8], rather than the value 8, to be added to DI. Oops.

Examples related to assembly

Why does C++ code for testing the Collatz conjecture run faster than hand-written assembly? While, Do While, For loops in Assembly Language (emu8086) Replacing a 32-bit loop counter with 64-bit introduces crazy performance deviations with _mm_popcnt_u64 on Intel CPUs How to run a program without an operating system? Difference between "move" and "li" in MIPS assembly language Carry Flag, Auxiliary Flag and Overflow Flag in Assembly How do AX, AH, AL map onto EAX? JNZ & CMP Assembly Instructions Difference between JE/JNE and JZ/JNZ The point of test %eax %eax

Examples related to x86

How to compile Tensorflow with SSE4.2 and AVX instructions? Why does C++ code for testing the Collatz conjecture run faster than hand-written assembly? Replacing a 32-bit loop counter with 64-bit introduces crazy performance deviations with _mm_popcnt_u64 on Intel CPUs How to install ia32-libs in Ubuntu 14.04 LTS (Trusty Tahr) How to run a program without an operating system? Carry Flag, Auxiliary Flag and Overflow Flag in Assembly How do AX, AH, AL map onto EAX? JNZ & CMP Assembly Instructions How does the ARM architecture differ from x86? Difference between JE/JNE and JZ/JNZ

Examples related to x86-64

How to build x86 and/or x64 on Windows from command line with CMAKE? How to include static library in makefile Difference between x86, x32, and x64 architectures? Floating point vs integer calculations on modern hardware What are the calling conventions for UNIX & Linux system calls (and user-space functions) on i386 and x86-64 What's the purpose of the LEA instruction? How to find if a native DLL file is compiled as x64 or x86? System.BadImageFormatException: Could not load file or assembly (from installutil.exe) How can I determine if a .NET assembly was built for x86 or x64? Targeting both 32bit and 64bit with Visual Studio in same solution/project

Examples related to x86-16

While, Do While, For loops in Assembly Language (emu8086) What's the purpose of the LEA instruction?