Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

lea is also used frequently to actually load addresses. When passing the address of a stack buffer, for example, the compiler will usually generate code like "lea eax, [ebp-0x80]; push eax". Or, when loading the address of a struct member, you might have "lea ecx, [eax+8]".


Yup, the original intention behind lea is the & operator. Compute the address but instead of accessing the memory immediately (like mov does) just keep it for later use. Just what & does.


Loading an address is just adding a fixed number to the value in a register. Your two examples are mathematically equivalent to "eax = ebp - 0x80" and "ecx = eax + 8."


Yes, but those would be two assembly instructions each. The basic idea of using lea over 'movl $ebp, $eax; addl 0x80,$eax'ist that we can shave off a cycle because lea can be executed in a single cycle.

However I wonder how much any of this still matters in a time where CPUs have developed to include all sorts of complex optimizations.


Modify the backend, or do a binary translation from one to the other and test. If `lea` is the predominate instruction, there might be microcode optimizations that favor `lea` over `movl`. My hunch is that is will be mostly the same barring overflowing the instruction cache. The microps should compile to the same instruction stream.


No, LEA issues as a single micro-op on modern Intel CPUs, but no x86 CPU will merge a sequence of shift and add into a single micro op.


How would one find this out? Sounds like it would be fun to figure out how to develop all possible reasonably compact instruction combinations to achieve the same basic block and then compare timings.



lea also doesn't modify the flags register. At one point this meant there was a wider choice of execution units it could be scheduled on than arithmetic instructions that required a full ALU.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: