¿Cuál es el propósito de la instrucción LEA?

Resuelto user200557 asked hace 15 años • 0 respuestas

Para mí, parece un MOV original. ¿Cuál es su propósito y cuándo debo usarlo?

user200557 avatar Nov 02 '09 03:11 user200557
Aceptado

Como otros han señalado, LEA (dirección efectiva de carga) se utiliza a menudo como un "truco" para realizar ciertos cálculos, pero ese no es su propósito principal. El conjunto de instrucciones x86 fue diseñado para admitir lenguajes de alto nivel como Pascal y C, donde las matrices, especialmente matrices de ints o estructuras pequeñas, son comunes. Considere, por ejemplo, una estructura que representa las coordenadas (x, y):

struct Point
{
     int xcoord;
     int ycoord;
};

Ahora imagina una declaración como:

int y = points[i].ycoord;

donde points[]hay una matriz de Point. Suponiendo que la base de la matriz ya está en EBX, y la variable iestá en EAX, y xcoordy ycoordson cada uno de 32 bits (por lo tanto ycoord, hay un desplazamiento de 4 bytes en la estructura), esta declaración se puede compilar para:

MOV EDX, [EBX + 8*EAX + 4]    ; right side is "effective address"

que aterrizará yen EDX. El factor de escala de 8 se debe a que cada uno Pointtiene un tamaño de 8 bytes. Ahora considere la misma expresión utilizada con el operador "dirección de" &:

int *p = &points[i].ycoord;

En este caso, no desea el valor de ycoord, sino su dirección. Ahí es donde LEAentra (cargar dirección efectiva). En lugar de un MOV, el compilador puede generar

LEA ESI, [EBX + 8*EAX + 4]

que cargará la dirección en ESI.

I. J. Kennedy avatar Nov 03 '2009 06:11 I. J. Kennedy

Del "Zen de la Asamblea" de Abrash:

LEA, la única instrucción que realiza cálculos de direccionamiento de memoria pero en realidad no direcciona la memoria. LEAacepta un operando de direccionamiento de memoria estándar, pero no hace más que almacenar el desplazamiento de memoria calculado en el registro especificado, que puede ser cualquier registro de propósito general.

¿Qué nos aporta eso? Dos cosas que ADDno proporciona:

  1. la capacidad de realizar sumas con dos o tres operandos, y
  2. la capacidad de almacenar el resultado en cualquier registro; no solo uno de los operandos fuente.

Y LEAno altera las banderas.

Ejemplos

  • LEA EAX, [ EAX + EBX + 1234567 ]calcula EAX + EBX + 1234567(son tres operandos)
  • LEA EAX, [ EBX + ECX ]calcula EBX + ECXsin anular ninguno de los dos con el resultado.
  • multiplicación por constante (por dos, tres, cinco o nueve), si la usas como LEA EAX, [ EBX + N * EBX ](N puede ser 1,2,4,8).

Otro caso de uso es útil en bucles: la diferencia entre LEA EAX, [ EAX + 1 ]y INC EAXes que el último cambia EFLAGSpero el primero no; esto preserva CMPel estado.

Frank Krueger avatar Nov 01 '2009 21:11 Frank Krueger

Otra característica importante de la LEAinstrucción es que no altera los códigos de condición como CFy ZF, mientras calcula la dirección mediante instrucciones aritméticas como ADDo MULlo hace. Esta característica disminuye el nivel de dependencia entre instrucciones y, por lo tanto, deja espacio para una mayor optimización por parte del compilador o programador de hardware.

Angus Lee avatar Oct 09 '2012 17:10 Angus Lee

A pesar de todas las explicaciones, LEA es una operación aritmética:

LEA Rt, [Rs1+a*Rs2+b] =>  Rt = Rs1 + a*Rs2 + b

Es sólo que su nombre es extremadamente estúpido para una operación shift+sum. El motivo de esto ya se explicó en las respuestas mejor calificadas (es decir, fue diseñado para mapear directamente referencias de memoria de alto nivel).

hdante avatar Aug 15 '2011 21:08 hdante