装配命令LEA/LDS/LES

Rox*_*anu 9 x86 assembly command

什么是下面的命令的区别是:LEA,LDS,LES?我搜索了答案,但我不是很清楚.从我的理解block1应该相当于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
Run Code Online (Sandbox Code Playgroud)

...但是当我打印str1str1使用以下宏时,第二个块不会返回预期的结果.

print MACRO param
    lea DX, param
    mov AH, 9
    int 21h
ENDM
Run Code Online (Sandbox Code Playgroud)

nrz*_*nrz 13

lea意味着加载有效地址.所以lea SI, str1设置si为偏移量str1.正确的内存寻址语法lea和其他指令取决于所使用的汇编程序,一些汇编程序需要lea si,[str1].

ldsles做一些完全不同的事情lea.lds表示使用DS加载指针,同样les表示使用ES加载指针.在实践中,lds SI, ptr_str1设置dssi基于存储在存储器地址中的值ds:ptr_str1(语法[ds:ptr_str1]在某些汇编器中).

那么,这些指令在您的代码中执行的操作:

  1. lea SI, str1设置si指向的地址str1.这似乎完全没问题.

  2. lds SI, ptr_str1设置si'My'(十六进制的0x794d)并设置ds' f'(十六进制的0x6620).请注意,x86是一个小端架构.ds是使用lds和读取指针值的默认段les.因此,不是加载字符串地址ds:si,而是将字符串的前4个字节用作加载的地址ds:si.我认为这不是你想要做的.

  3. les DI, ptr_str2di根据存储在0x6620的值:ptr_str2(ds是大多数x86指令缺省段,和目前ds的值为0x6620),并且还设置es根据存储在0x6620的值:ptr_str2 + 2.可能这不是你想要做的.

  • 我个人从不写`lea si,str1`(或者类似的,对于'mov`,`push`等),但总是`lea si,[str1]`(可能是'dword ptr`和朋友,如果它不是clear)或`mov si,offset str`,也就是说,我总是添加括号或`offset`运算符来消除歧义.这是因为当你不这样做时,汇编程序彼此不同:有些人添加了括号,有些是`offset`(特别是对'mov`和朋友的烦恼).但很好的解释,+ 1. (2认同)
  • @mirabilos `dword ptr` 和朋友与 `lea` 无关,也不影响编码,因为只有内存地址对 `lea` 重要。不同 x86/x86-64 汇编器的内存寻址语法的差异非常令人烦恼,因为完全相同的语法在不同的 x86/x86-64 汇编器中可能具有不同的含义,因此如果使用不同的汇编器进行汇编,可能会导致错误。http://stackoverflow.com/questions/14984788/assemble-i386-code-on-x86-64/14984887#14984887 (2认同)