10

What is the difference between the following commands: LEA, LDS, LES? I searched for the answer but I'm not very clear on it. From what I understood block1 should be equivalent to block2.

.data
  str1 db 'My first string. $'
  str2 db 'My second string. $'
  ptr_str1 dd str1 
  ptr_str2 dd str2
.code
  _block1:
  mov AX, @data
  mov DS, AX
  mov ES, AX
  lea SI, str1
  lea DI, str2

  _block2:
  lds SI, ptr_str1
  les DI, ptr_str2

... but when I print str1 and str1 using the following macro, the second block doesn't return the expected results.

print MACRO param
    lea DX, param
    mov AH, 9
    int 21h
ENDM
nrz
  • 10,435
  • 4
  • 39
  • 71
Roxana Ciobanu
  • 253
  • 2
  • 3
  • 12

1 Answers1

15

lea means Load Effective Address. So lea SI, str1 sets si to the offset of str1. The correct memory addressing syntax used by lea and other instructions depends on the assembler used, some assemblers want lea si,[str1].

lds and les do something completely different compared to lea. lds means Load pointer using DS and likewise les means Load pointer using ES. In practice, lds SI, ptr_str1 sets ds and si based on the values stored in the memory address ds:ptr_str1 (the syntax is [ds:ptr_str1] in some assemblers).

So, what these instructions do in your code:

  1. lea SI, str1 sets si to point to the address of str1. This seems perfectly OK.

  2. lds SI, ptr_str1 sets si to 'My' (0x794d in hexadecimal) and also sets ds to ' f' (0x6620 in hexadecimal). Note that x86 is a little-endian architecture. ds is the default segment from where the pointer value is read using lds and les. So instead of loading the string address to ds:si, the first 4 bytes of the string are used as an address that is loaded into ds:si. I assume this is not what you wanted to do.

  3. les DI, ptr_str2 sets di according to the value stored in 0x6620:ptr_str2 (ds is the default segment for most x86 instructions, and currently ds has the value 0x6620) and also sets es according to the value stored in 0x6620:ptr_str2+2. Probably this is not what you wanted to do.

nrz
  • 10,435
  • 4
  • 39
  • 71
  • 3
    I personally never write `lea si,str1` (or similar, for `mov`, `push`, etc.) but always either `lea si,[str1]` (possibly with `dword ptr` and friends if it is not clear) or `mov si,offset str`, that is, I always add either the brackets or the `offset` operator, to disambiguate. This is because when you do neither, assemblers differ from each other: some add the brackets, some the `offset` (especially irritating with `mov` and friends). But good explanation, +1. – mirabilos Dec 09 '13 at 20:01
  • 2
    @mirabilos `dword ptr` and friends are irrelevant for `lea` and do not affect encoding, as only the memory address matters for `lea`. The difference of memory addressing syntax of different x86/x86-64 assemblers is quite annoying as the exactly same syntax may have different meaning in different x86/x86-64 assemblers and thus may cause bugs if assembled with a different assembler. http://stackoverflow.com/questions/14984788/assembling-i386-code-on-x86-64/14984887#14984887 – nrz Dec 09 '13 at 21:09
  • I know that it's the same for lea, but still, teaching good style in one go may be not unimportant. – mirabilos Dec 09 '13 at 21:26