Какие процессоры вы настраиваете?Вы действительно имеете в виду 8086?Они по-прежнему существуют в виде микроконтроллеров, но подавляющее большинство кода x86 в наши дни работает на современных x86.
Современные процессоры x86 имеют очень быстрые множители, поэтому обычно стоит только использовать shift / add или LEA, когда вы можетеполучить работу за 2 моп или меньше.div
/ idiv
все еще медленны, но умножение не в современных процессорах, которые бросают достаточное количество транзисторов в проблему.
imul eax, ebx, 41
имеет задержку 3 цикла, 1 на тактовую пропускную способность, вклсовременные процессоры Intel и Ryzen (https://agner.org/optimize/), и поддерживается в 286 и более поздних версиях. (16-разрядная форма imul ax, bx, 41
составляет 2 моп вместо 1, с задержкой в 4 цикла на ЦП семейства Sandybridge.)
Если вы можете использовать 32-битные режимы адресации (386 и более поздние), вы можете сделать это в 2 инструкциях LEA (таким образом, всего 2 мопа, задержка 2 цикла на современных процессорах).
Посмотрите, как gcc / clang компилирует эту функцию ( в проводнике компилятора Godbolt ):
int times41(int x) { return x*41; }
# compiled for 32-bit with gcc -O3 -m32 -mregparm=1
times41(int): # first arg in EAX
lea edx, [eax+eax*4] # edx = eax*5
lea eax, [eax+edx*8] # eax = eax + edx*8 = x + x*40
ret
Это лучший выбор для старых процессоров, где imul
или mul
требуют больше мопов, и если задержка важнее, чем количество мопов на современных процессорах.
В вашем 16-битном коде вы можете использовать
lea eax, [ebx+ebx*4] # ax = bx*5
lea ax, [ebx+eax*8] # ax = bx + ax*8 = x + x*40
Использование 32-битный размер операнда для первого LEA позволяет избежать ложной зависимости от старого значения EAX и избежать остановки частичного регистрав Nehalem и более ранних версиях (из 2-го LEA, считывающего EAX после записи AX).
Это стоит всего 1 дополнительный байт размера кода для префикса размера операнда (а также префикса размера адреса), ине имеет значения для правильности.(Младшие 16 битов результатов сдвига влево и сложения не зависят от старших битов ввода.)
Или, возможно, вы захотите xor eax,eax
перед записью AX, позволяя процессорам Intel избежать частичнойзарегистрировать слияние для будущего использования AX.( Почему GCC не использует частичные регистры? ).