Qual é a diferença entre MOV e LEA?

Eu gostaria de saber qual é a diferença entre essas instruções:

MOV AX, [TABLE-ADDR] 

e

 LEA AX, [TABLE-ADDR] 

  • LEA significa Carregar Endereço Efetivo
  • MOV significa valor da carga

Em suma, o LEA carrega um ponteiro para o item que você está endereçando, enquanto o MOV carrega o valor real nesse endereço.

O objective do LEA é permitir que um faça um cálculo de endereço não trivial e armazene o resultado [para uso posterior]

 LEA ax, [BP+SI+5] ; Compute address of value MOV ax, [BP+SI+5] ; Load value at that address 

Onde há apenas constantes envolvidas, os MOV (através dos cálculos constantes do montador) podem às vezes parecer se sobrepor aos casos mais simples de uso do LEA . É útil se você tiver um cálculo de várias partes com vários endereços base, etc.

Na syntax do NASM:

 mov eax, var == lea eax, [var] ; ie mov r32, imm32 lea eax, [var+16] == mov eax, var+16 lea eax, [eax*4] == shl eax, 2 ; but without setting flags 

Na syntax MASM, use OFFSET var para obter um imediato de movimento em vez de um carregamento.

A instrução MOV reg, addr significa ler uma variável armazenada no endereço addr no registro reg. A instrução LEA reg, addr significa ler o endereço (não a variável armazenada no endereço) no registrador reg.

Outra forma da instrução MOV é MOV reg, immdata que significa ler os dados imediatos (ie constante) immdata no registrador reg. Note que se o addr em LEA reg, addr é apenas uma constante (isto é, um offset fixo), então essa instrução LEA é essencialmente exatamente igual a uma instrução MOV reg equivalente, que carrega a mesma constante que os dados imediatos.

Se você especificar apenas um literal, não haverá diferença. O LEA tem mais habilidades, e você pode ler sobre elas aqui:

http://www.oopweb.com/Assembly/Documents/ArtOfAssembly/Volume/Chapter_6/CH06-1.html#HEADING1-136

Depende do montador usado, porque

 mov ax,table_addr 

em MASM funciona como

 mov ax,word ptr[table_addr] 

Portanto, ele carrega os primeiros bytes de table_addr e NÃO o deslocamento para table_addr . Você deveria usar

 mov ax,offset table_addr 

ou

 lea ax,table_addr 

que funciona da mesma

versão lea também funciona bem se table_addr é uma variável local, por exemplo

 some_procedure proc local table_addr[64]:word lea ax,table_addr 

Basicamente … “Mude para o REG … depois de o calcular …” parece ser bom para outros propósitos também 🙂

Se você simplesmente esquecer que o valor é um ponteiro, você pode usá-lo para otimizações de código / minimização … o que nunca ..

 MOV EBX , 1 MOV ECX , 2 ;//with 1 instruction you got result of 2 registers in 3rd one ... LEA EAX , [EBX+ECX+5] 

EAX = 8

originalmente seria:

 MOV EAX, EBX ADD EAX, ECX ADD EAX, 5 

A diferença é sutil, mas importante. A instrução MOV é uma ‘MOVe’ efetivamente uma cópia do endereço que o label TABLE-ADDR representa. A instrução LEA é um ‘Load Effective Address’ que é uma instrução indireta, o que significa que TABLE-ADDR aponta para um local de memory no qual o endereço a carregar é encontrado.

Efetivamente usando LEA é equivalente a usar pointers em linguagens como C, como tal, é uma instrução poderosa.