Основная причина следующая.Как вы можете заметить, если вы внимательно посмотрите на x86, этот ISA является двухадресным.Каждая инструкция принимает не более двух аргументов.Таким образом, семантика операций следующая:
DST = DST <operation> SRC
LEA является своего рода инструкцией взлома, потому что это инструкция SINGLE в ISA x86, которая на самом деле является трехадресной:
DST = SRC1 <operation> SRC2
Это своего рода хакерская инструкция, потому что она использует схему диспетчера аргументов процессора x86 для выполнения сложения и сдвига.
Компиляторы используют LEA, потому что это вмешательство позволяет им заменять несколько вторжений одной инструкцией вслучаи, когда содержимое регистров слагаемых выгодно сохранить без изменений.Обратите внимание, что во всех случаях, когда компилятор использует регистр LEA DST, отличается от регистра SRC или аргумент SRC использует логику вычисления сложных адресов.
Например, в сгенерированном коде практически невозможно найти такой вариант использования:
LEA EAX, [EAX ] // equivalent of NOP
LEA EAX, [ECX ] // equivalent of MOV EAX, ECX
LEA EAX, [EAX+12] // equivalent of ADD EAX, 12
, но распространены следующие варианты использования:
LEA EAX, [ECX +12] // there is no single-instruction equivalent
LEA EAX, [ECX+EDX*4+12] // there is no single-instruction equivalent
LEA EDX, [ECX+EDX*4+12] // there is no single-instruction equivalent
Действительно, представьте себе следующий сценарий с предположением, что значение EBP должно быть сохранено для будущего использования:
LEA EAX, [EBP+12]
LEA EDX, [EBP+48]
Всего две инструкции!Но в случае отсутствия LEA код будет следующим
MOV EAX, EBP
MOV EDX, EBP
ADD EAX, 12
ADD EDX, 48
Я считаю, что выгода от использования LEA должна быть очевидной сейчас.Вы можете попробовать заменить эту инструкцию
LEA EDX, [ECX+EDX*4+12] // there is no single-instruction equivalent
на ADD-код.