Skip to content

Files

Latest commit

 

History

History

04-more-asm

Файлики с кодом:

На самом деле переменной это называть не совсем корректно, так как это просто метка, которая будет заменена на адрес. Но здесь используется слово переменная, из-за того, что работа с метками похожа работу с привычными переменными

Lea (load effective address)

lea offset(base, index, mult), reg -> offset + base + index * mult -> reg

mult может быть только 2 4 8 16 для 32 битной системы.

Пример использования lea

lea в отличие от mov не будет пытаться взять значение по получившемуся адресу, поэтому нет требования, чтобы адрес в итоге получится корректным. Поэтому его можно использовать для арифметических операций.

Например, если в %ecx лежит 5, а в %edx 6, то в результате работы следующего кода в %eax будет лежать 4 + (5 + 6 * 2)

  lea     4(%ecx, %edx, 2), %eax

Если несколько операций сложения/умножения можно заменить одной операцией lea, то лучше так делать, потому что lea не сохраняет промежуточные результаты в регистры. Но lea не выставляет флаги.

Использование lea для арифметических операций

Lea в реальной жизни

Есть простой код, приведенный в файлике multiply_by_three. Код считывает число и умножает на 3.

-O0

Если мы скомпилируем с флагом -S(чтобы получить код ассемблера) и флагом -O0(чтобы выключить оптимизации). Получившийся файл с комментариями multiply_by_three_O0.

	movl	%edx, %eax
	addl	%eax, %eax
	addl	%edx, %eax

Обратим внимаение, что не используется инструкция умножения, а используется несколько раз сложение. Это происходит из-за того, что инструкции mul являются трудозатратными и честного умножения числе выгоднее избегать.

Так, например, можно попробовать поменять 3 на 7 в коде. Можно увидеть, что в результате получится тоже что-то отличное от умножения (у меня вышло умножение на 8 с помощью сдвига с последующим вычитанием).

	sall	$3, %eax
	subl	%edx, %eax

-O3

Если скомпилировать код с флагами -S, -O3 (третий уровень оптимизации кода), то получится файл multiply_by_three_O3.

В нем можно увидеть, что больше нет операций сложения, вместо них испоользуется конструкция

	leal	(%eax,%eax,2), %eax

Так как для lea в отличие от mov не требуется, чтобы в результаате выполонения инструкции получился валидный адрес, то можно использовать эту инструкцию для того, чтобы быстро выполнять арифметические операции.

В данном случае происходит следующее: в %eax будет лежать значение равное %eax + %eax * 2, что как раз и будет умножением на 3.

Умножение на 7 заменилось на следующие инструкции:

	leal	0(, %edx, 8), %eax
	subl	%edx, %eax