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.