MOV and LEA
MOV is used to read the value at a given address, while LEA (Load Effective Address) is used to get the address instead:
mov eax, dword ptr [00000060] ; stores 63626160h to eax
mov eax, dword ptr [00000060] ; stores 00000060h to eax
So, how is the LEA instruction helpful if you can calculate the address by yourself? Let's take the following C code as an example:
struct Test {
int x;
int y;
} test[10];
int value;
int *p;
// some code here that fills up the test[] array
for (int i=0; i<10, i++) {
value = test[i].y;
p = &test[i].y;
}
The C code starts with defining test[10], an array of struct Test, which contains two integers, x and y. The for-loop statement takes the value of y and the pointer address of y in a struct test element.
Let's say the base of the test array is in EBX, the for-loop counter, i, is in ECX, the integers are DWORD values, and so struct Test will contain two DWORD values. Knowing that a DWORD has 4 bytes, the equivalent of value = test[i].y; in assembly language will look like mov edx, [ebx+ecx*8+4]. Then, the equivalent of p = &test[i].y; in assembly language will look like lea esi, [ebx+ecx*8+4]. Indeed, without using LEA, the address can still be calculated with arithmetic instructions. However, calculating for the address could be done much more easily using LEA:
; using MUL and ADD
mov ecx, 1111h
mov ebx, 2222h
mov eax, 2 ; eax = 2
mul ecx ; eax = 2222h
add eax, ebx ; eax = 4444h
add eax, 1 ; eax = 4445h
; using LEA
mov ecx, 1111h
mov ebx, 2222h
lea eax, [ecx*2+ebx+1] ; eax = 4445h
The preceding code shows that the six lines of code can be optimized to three lines using the LEA instruction.