The LEA (Load Effective Address) instruction allows us to copy the address of a memory location (in the memory addressing format you would find in ModR/M encoding) into a register. This instruction is also often used as a multiplication math hack used in place of MUL when LEA can be used instead. With the memory (pointer) encoding of the ModR/M byte (and the SIB) bytes, we are able to add 3 different numbers (two of them registers, one of them an immediate), and one of those numbers (one of the registers) can be multiplied by 2,4, or 8. For example, we could use LEA to compute (30 * 8) + 5 + 10. It would look like this:
The answer in hex is 0xff, which is 255 in decimal; the expected value.
Those are some ‘effective’ ways to use LEA, but let’s explore an impossible way to do it (there will be errors). Even though the Instruction format in the manual shows ‘LEA r32,m‘ (assuming the 32 bit version), it still shows the /r for the Opcode section. This implicitly means that we can encode for ‘LEA r32, r32/m‘; both operands can be encoded as a register. For this LEA instruction to work how it’s supposed to, the source operand (2nd one) needs to be a memory address (not a register).
As you probably can guess by the theme of any of these “Assembly is Too High Level” posts, we probably can’t do this in assembly…
Not that it will be useful (unless you like having errors thrown in obscure ways), but we will encode the above instruction directly in machine code. Running this instruction will cause an error. The edb debugger shows the 2nd operand as invalid (astute observation) and then you get an illegal instruction fault (true).
objdump shows a more interesting output, it splits the operand byte off and interprets it as its own instruction (rolb).
Either way you cut it, as advertised, it’s not very effective.