¿Cuál es la diferencia entre MOV y LEA?

Me gustaría saber cuál es la diferencia entre estas instrucciones:

MOV AX, [TABLE-ADDR] 

y

 LEA AX, [TABLE-ADDR] 

  • LEA significa Dirección Efectiva de Carga
  • MOV significa valor de carga

En resumen, LEA carga un puntero al elemento al que se dirige, mientras que MOV carga el valor real en esa dirección.

El propósito de LEA es permitir que uno realice un cálculo de dirección no trivial y almacene el resultado [para uso posterior]

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

Cuando solo hay constantes involucradas, MOV (a través de los cálculos constantes del ensamblador) a veces puede superponerse con los casos más simples de uso de LEA . Es útil si tiene un cálculo de varias partes con múltiples direcciones base, etc.

En syntax 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 

En la syntax de MASM, use OFFSET var para obtener un mov-immediate en lugar de una carga.

La instrucción MOV reg, addr significa leer una variable almacenada en dirección addr en registro reg. La instrucción LEA reg, addr significa leer la dirección (no la variable almacenada en la dirección) en register reg.

Otra forma de la instrucción MOV es MOV reg, immdata que significa leer los datos inmediatos (es decir, constantes) immdata en registro reg. Tenga en cuenta que si el addr en LEA reg, addr es solo una constante (es decir, un desplazamiento fijo) entonces esa instrucción LEA es esencialmente exactamente igual a una instrucción MOV reg, immdata equivalente que carga la misma constante que los datos inmediatos.

Si solo especifica un literal, no hay diferencia. LEA tiene más habilidades, sin embargo, y puedes leer sobre ellas aquí:

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

Depende del ensamblador utilizado, porque

 mov ax,table_addr 

en MASM funciona como

 mov ax,word ptr[table_addr] 

Entonces carga los primeros bytes de table_addr y NO el desplazamiento a table_addr . Deberías usar en su lugar

 mov ax,offset table_addr 

o

 lea ax,table_addr 

que funciona igual.

lea versión de lea también funciona bien si table_addr es una variable local, por ejemplo

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

Básicamente … “Muévete a REG … después de calcularlo …” parece ser bueno para otros propósitos también 🙂

si simplemente olvida que el valor es un puntero, puede usarlo para optimizar / minimizar el código … lo que sea …

 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 sería:

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

La diferencia es sutil pero importante. La instrucción MOV es un ‘MOVe’ efectivamente una copia de la dirección que representa la etiqueta TABLE-ADDR. La instrucción LEA es una ‘Dirección efectiva de carga’ que es una instrucción indirecta, lo que significa que TABLE-ADDR apunta a una ubicación de memoria en la que se encuentra la dirección a cargar.

Usar LEA de manera efectiva es equivalente a usar punteros en idiomas como C, ya que es una instrucción poderosa.