Why is this instruction here? Isnt it equivalent to mov ax, label?
As long as you dont deference it should label be equivlant to an address?
purpose of lea instruction?
Re: purpose of lea instruction?
It can compute more complex addresses. Likeyemista wrote:Why is this instruction here? Isnt it equivalent to mov ax, label?
As long as you dont deference it should label be equivlant to an address?
Code: Select all
mov eax, index_into_jump_table
lea eax, [offset some_variable + 4*eax]
Code: Select all
lea ecx, [0 + 2*eax + eax] ; multiply by three
lea ecx, [0 + 4*eax + eax] ; multiply by five
Re: purpose of lea instruction?
Hi,
Cheers,
Brendan
Indirect addressing doesn't need to be as simple as "[label]". Consider these instructions (note: the second instruction isn't legal):yemista wrote:Why is this instruction here? Isnt it equivalent to mov ax, label?
As long as you dont deference it should label be equivlant to an address?
- mov eax, [esi+ebx*4+0x12345678]
- mov edi, esi+ebx*4+0x12345678
- lea edi, [esi+ebx*4+0x12345678]
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Re: purpose of lea instruction?
When you think in C terms, then point of LEA is to support the & 'address-of' operator when used in conjunction with local variables and function parameters. These don't have labels pointing to them, so the only way to access them is by using indirect address with the ebp register as base. For example, [ebp-4] is the first local variable, [ebp-8] the second and so on, and similarly for [ebp+8] (first parameter), [ebp+12] (second parameter) etc. This is fine if you only need the values of those variables. But what if you need their addresses? You could do:
to get the address of the first local variable into eax. But with LEA, you need only one instruction to do the same:
This is faster than doing MOV and ADD, and it might even be faster than a single ADD alone! An additional benefit is that the assembly code is clearer, as the notation [ebp-4] makes it instantly clear what you're referring to.
Code: Select all
mov eax, ebp
sub eax, 4
Code: Select all
lea eax, [ebp-4]
Re: purpose of lea instruction?
To expand on Brendan's point:
Most ASM opcodes only do one tiny thing at a time. Example:
OR EAX, 0x4000
That's pitiful, isn't it? One entire opcode, and one entire machine cycle, just to set one bit in a register?
Now, as Brendan said, take a look at what I call an "addressing SIB mode".
MOV ECX, [EBX + EAX*8 + 0x12345678]
In order to do this one instruction, the CPU had to calculate an address. It took a register, shifted it by 3 bits, added it to another register, and added a constant -- all in one opcode! Isn't that amazing that it can do all that in one opcode, with dedicated circuitry, so quickly? Wouldn't it be neat if you actually had access to that math operation -- all that dedicated address calculation circuitry -- to do high-speed MATH (not just calculating addresses) in your code?
That is what the LEA address is for. Sadly, there are many times when I wish I could do:
LEA ECX, [EBX - EAX*8]
but the x86 doesn't support subtraction at all.
One point that I don't think Brendan emphasized enough: the other nice thing about LEA is that you can do some useful multiplications on ALL registers IN PLACE.
LEA EDI, [EDI + EDI*4]
Now, please think about how many registers you would normally have to trash, in order to multiply EDI by 5, using MUL. This works for multiplications by 3, 5, and 9. So those (surprisingly) are very efficient numbers to multiply by, in Assembly language.
Another (semi-)important note: LEA does not set or trash any EFLAGS bits. So, if you want to (say) fix your stack pointer at the end of a function, but your EFLAGS bits are already set, you can do:
LEA ESP, [ESP + 16]
Which gets rid of 4 dwords off your stack, without messing up your Carry flag (for instance).
Most ASM opcodes only do one tiny thing at a time. Example:
OR EAX, 0x4000
That's pitiful, isn't it? One entire opcode, and one entire machine cycle, just to set one bit in a register?
Now, as Brendan said, take a look at what I call an "addressing SIB mode".
MOV ECX, [EBX + EAX*8 + 0x12345678]
In order to do this one instruction, the CPU had to calculate an address. It took a register, shifted it by 3 bits, added it to another register, and added a constant -- all in one opcode! Isn't that amazing that it can do all that in one opcode, with dedicated circuitry, so quickly? Wouldn't it be neat if you actually had access to that math operation -- all that dedicated address calculation circuitry -- to do high-speed MATH (not just calculating addresses) in your code?
That is what the LEA address is for. Sadly, there are many times when I wish I could do:
LEA ECX, [EBX - EAX*8]
but the x86 doesn't support subtraction at all.
One point that I don't think Brendan emphasized enough: the other nice thing about LEA is that you can do some useful multiplications on ALL registers IN PLACE.
LEA EDI, [EDI + EDI*4]
Now, please think about how many registers you would normally have to trash, in order to multiply EDI by 5, using MUL. This works for multiplications by 3, 5, and 9. So those (surprisingly) are very efficient numbers to multiply by, in Assembly language.
Another (semi-)important note: LEA does not set or trash any EFLAGS bits. So, if you want to (say) fix your stack pointer at the end of a function, but your EFLAGS bits are already set, you can do:
LEA ESP, [ESP + 16]
Which gets rid of 4 dwords off your stack, without messing up your Carry flag (for instance).
Re: purpose of lea instruction?
You could negate EAX first, then it'd work.bewing wrote:That is what the LEA address is for. Sadly, there are many times when I wish I could do:
LEA ECX, [EBX - EAX*8]
but the x86 doesn't support subtraction at all.
Re: purpose of lea instruction?
Yes, but then you're up to 2 opcodes anyway (and EFLAGS is trashed), so you might as well just use SHL and SUB for clarity at that point.