4

I dont fully understand the meaning of first two lines, and the difference of last two lines..

LDS SI,[BX]
LES DI,[BX]
LEA DI,5000h 
MOV DI,5000h

I think LEA loads 5000h in DI and MOV loads content of 5000h in DI. Am I right??

Michael Petch
  • 46,082
  • 8
  • 107
  • 198
Wahid Masud
  • 67
  • 1
  • 6

2 Answers2

7

The first two load the contents of 32 bits pointed to by bx into ds and si (or es and di).

The second two are the same because the values are literals. If, however they were:

lea di,[bx]
mov di,[bx]

then your expectation would be right: the former putting the address bx into di and the latter putting the 16 bits pointed to by bx into di.

For more information on both, see this question for les/lds and this question for mov/lea.

Community
  • 1
  • 1
DocMax
  • 12,094
  • 7
  • 44
  • 44
4

The lea instruction doesn't actually load anything from memory.

In 8086, the capabilities of lea were limited, comparing to what we have now. lea just can make a sum of up to two address registers and an immediate (constant) value, and put this sum to a destination register. For example, lea bp, [bx+si+3] sets to the bp register the sum of bx plus si plus 3.

The 80386 processor introduced a series of scaling modes, in which the index register value can be multiplied by a valid scaling factor to obtain the displacement. The valid scale factors are 1, 2, 4, and 8. Therefore, you can use instructions like lea ebp, [ebx+esi*8+3].

The instructions lds and les, on the contrary, load values from memory to a pair of registers: one segment register (ds or es) and one general register. There are also versions of this load instruction for the other segment registers: lfs, lgs and lss for fs, gs and ss segment registers respectively (introduced in 80386). So these instructions load "far" pointer - a pointer consisting of a 16-bit segment selector and a 16-bit (or a 32-bit, depending on mode) offset, so the total far pointer size was 32-bit in 16-bit mode and 48-bit in 32-bit mode.

These are handy instructions for 16-bit mode, be it 16-bit real mode or 16-bit protected mode.

Under 32-bit mode, there is no need for these instructions since OSes set all segment bases to zero (flat memory model), so there is no need to load segment registers. We just use 32-bit pointers, not 48.

Under 64-bit modes, these instructions are not implemented. Their opcodes give access violation interrupt (exception). Since Intel's implementation of VEX - "vector extensions - (AVX), Intel reclaimed the opcodes of lds and les and started using them for VEX prefixes. That is why only x/ymm0..7 are accessible in 32-bit mode. The VEX prefixes overlap with invalid encodings of lds and les in 32-bit mode, where R̅, X̅, and B̅ bits are all 1.

Maxim Masiutin
  • 3,991
  • 4
  • 55
  • 72
  • @SepRoland - why do you think that the following information is misleading: "It just sets a sum of up to two source registers (one may be multiplied) and an immediate value to a destination register. For example lea bp, [bx*2+si+3] sets to the bp register the sum of bx multiplied by two plus si plus 3."??? – Maxim Masiutin Oct 23 '21 at 02:42
  • @SepRoland - howerver, you have correctly spotted that this information is duplicated later, so your edit was great, thank you! – Maxim Masiutin Oct 23 '21 at 02:44
  • In the paragraph that I removed, the example 'lea bp, [bx*2+si+3]` is invalid. There can not be a multiplier __*2__ when working with 16 bit base (`si`) and index (`bx`) registers. A valid example could have been `lea bp, [esi + ebx * 2 + 3]` – Sep Roland Oct 24 '21 at 19:22