2 ms·
"lea" is a fun instruction. Going piece by piece: on x86, each register has several sizes. For instance, rax is a 64-bit register, with its lower 32-bit half b
by cesarb 8y ago
"lea" is a fun instruction.
Going piece by piece: on x86, each register has several sizes. For instance, rax is a 64-bit register, with its lower 32-bit half being eax, its lower 16-bit half being ax, and its lower 8-bit half being al (for historical reasons). So when a register name starts with "r", it's the 64-bit variant. Therefore, "rip" is the 64-bit address of the next instruction.
The instruction "mov rsi, str[rip]" would get the 64-bit address of the next instruction, add to it a fixed offset (which the assembler and linker compute for you, as the exact offset you need to get to the data at the "str" label), load 64 bits from that address, and put the result in the "rsi" register. And that's not even the most complex addressing mode; you can get a register, add to it another register multiplied by 2, 4, or 8, add to it a constant, and use it as the memory address to load, store, or even modify in-place.
The "lea" instruction (load effective address) is a way to get directly at the power of that complex address calculation logic for your own uses. Instead of using the computed memory address to get at the memory, it's the memory address that's put in the register. Therefore, where "mov rsi, str[rip]" would read from memory, "lea rsi, str[rip]" would put in rsi the memory address the "mov" would have read from.
This also allows for a few tricks. For instance, you can use "lea" to multiply a number by five, without using the multiplier: just use a register and the same register scaled by 4 (and you can also add a constant to the result, still in a single complex instruction).