Mastering Reverse Engineering
上QQ阅读APP看书,第一时间看更新

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.