Собранная вами сборка не является обобщенным множителем - компилятор выполнил некоторый алгоритм в автономном режиме и жестко запрограммировал константы и арифметические операции, необходимые для фиксированного вычисления f(X) = X * 0xaaa
.
mov r2, r3 // r2 = X, r3 = X
lsl r2, r2, #1 // r2 = 2 * X
add r2, r2, r3 // r2 = 2X + X = 3X
lsl r3, r2, #3 // r3 = 8 * 3X = 24X
sub r3, r3, r2 // r3 = 24X - 3X = 21X
lsl r2, r3, #6 // r2 = 64 * 21X = 1344X
add r3, r3, r2 // r3 = 21X + 1344X = 1365X
lsl r3, r3, #1 // r3 = 2 * 1365 = 2730X = 0xAAA * X
В этомв сценарии компилятору не нужно использовать алгоритм умножения общего назначения, как у Бута;он знает значение, к которому стремится, поэтому он просто предопределяет наилучший способ генерации постоянного масштабирования с помощью 0xAAA
, используя сдвиги, сложения и вычитания.
Общая проблема - «Умножение одной константы»проблема - в Интернете есть статьи (оптимальные решения для произвольного числа битов - это "трудная" проблема, поэтому есть много статей для исследований).