4

When I disassemble this instruction using pad on Radare I get an LEA with rip

[0x00000000]> pad 8d 15 c8 90 04 08
lea edx, [rip + 0x80490c8]

I got this instruction from this post here I'm confused though why the disassembly shows rip + 0x80490c8, when the original post claims it's the equivalent of mov? Is this the right disassembled output? Why would the instruction pointer be in the LEA? Is that an implicit base, or did the original poster make a mistake?

7

It is simply a matter of bits. In the example shown, the hexpairs are disassembled using 64bit assembly, and you probably want to change it to a 32bit assembly. Just tell radare that you are working with 32bits and it will do the job for you:

[0x00000000]> pad 8d 15 c8 90 04 08
lea edx, [rip + 0x80490c8]

[0x00000000]> e asm.bits =32

[0x00000000]> pad 8d 15 c8 90 04 08
lea edx, [0x80490c8]

Unlike 32bits modes instructions that were taken as absolute addresses (use 32-bit immediate offset addressing), the 64bits modes (a.k.a long-mode) are usually using 32-bit offset from the current RIP, not from 0x00000000 like before. That means that you don't have to know the absolute address of something you want to reference, you only need to know how far away it is from the currently executing instruction.

There are very few addressing modes which use a full 64bit absolute address. Most addressing modes are 32bit offsets relative to one of the 64bit registers (usually RIP).

  • that's interesting. I could see it happening the other way around, but I wonder how the 32 bit opcode got translated into the same 64bit opcode with the RIP operand (for free). – Evan Carroll Apr 16 '18 at 5:03
  • Added explanation for the reason behind. Again, simply the shift from 32bit to 64bit – Megabeets Apr 16 '18 at 5:21
  • 1
    @EvanCarroll - if you've been doing this for long enough to be familiar with it, it's similar to the way going from 16-bit code to 32-bit changed all your 'ax' (etc) references to 'eax': in each mode there are default settings that are designed to be sensible for that mode, which cause slight changes in the interpretation of each instruction. – Jules Apr 16 '18 at 8:09
  • @EvanCarroll: 32-bit x86 has 2 redundant ways to encode [disp32] (with no registers): with and without a SIB. x86-64 repurposed the without-SIB version to mean [RIP + rel32], leaving the longer with-SIB version to still mean [sign_extended_disp32] like when you use a disp32 with GP registers. In NASM syntax, [rel foo] vs. [abs foo], or use default rel. – Peter Cordes Apr 17 '18 at 4:57
  • @Megabeets: Only the special mov al/ax/eax/rax, moffs form of mov (and the store form) use a full 64-bit / 8-byte absolute address. There are no ModR/M addressing modes that can be used with other instructions that accept more than an absolute disp32. So your last sentence could say that there aren't any normal addressing modes. Actually that's a little weird. normally, you just use small offsets relative to an address in registers, like [rdi + 8], or RIP-relative. But yeah in position-dependent code you can index a static array with [array + rdi]. – Peter Cordes Apr 17 '18 at 5:04
2

32-bit x86 has 2 redundant ways to encode [disp32] (with no registers): with and without a SIB byte. Assemblers will of course always use the shorter form, and that's what the link in your question is showing.

You're disassembling as 64-bit machine code.

x86-64 repurposed the without-SIB version to mean [RIP + rel32], leaving the longer with-SIB version to still mean [sign_extended_disp32] like when you use a disp32 with GP registers. (RIP-relative is not available combined with any GP registers; only this one specific ModR/M encoding.)

In NASM syntax, [rel foo] vs. [abs foo], or use default rel.


AFAIK, lea r32, [disp32] instead of mov r32, imm32 is never useful for performance on any CPU I'm aware of, except to make an instruction longer on purpose instead of padding with NOP.

The only use-case for lea for static addresses is in 64-bit code with RIP-relative LEA.

See this canonical answer for more about LEA, but really this question has nothing to do with LEA specifically, and would have happened with any instruction that used a disp32 ModR/M addressing mode decoded in the wrong mode. You only ran into this because you found an example that compared using an inefficient lea with an efficient mov-immediate in 32-bit mode.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.