Листинг 15.1
.def dataL = r4 ;multiplicand low byte
.def dataH = r5 ;multiplicand high byte
.def KoeffL = r2 ;multiplier low byte
.def koeffH = r3 ;multiplier high byte
.def temp = r16 ;result byte 0 (LSB — младший разряд)
.def temp2 = r17 ;result byte 1
.def temp3 = r18 ;result byte 2 (MSB — старший разряд)
…
;**********
;умножение двух 16-разрядных величин, только для Меда
;исходные величины dataH: dataL и KoeffH: KoeffL
;результат 3 байта temp2:temp1:temp;
;**********
Mu1616:
clr temp2 ;очистить старший
mul dataL,KoeffL ;умножаем младшие
mov temp,r0 ;в r0 младший результата операции mu1
mov tempi,r1 ;в r01 старший результата операции mu1
mul dataH,KoeffL ;умножаем старший на младший
add temp1,r1 ;в r0 младший результата операции mu1
adc temp2,r1 ;в r01 старший результата операции mu1
mul dataL,KoeffH ;умножаем младший на старший
add temp1,r0 ;в r0 младший результата операции mu1
adc temp2,r01 ;в r01 старший результата операции mu1
mul dataH,KoeffH ;умножаем старший на старший
add temp2,r0 ;4-й разряд нам тут не требуется, но он — в r01
ret
;**********
Как видите, эта процедура легко модифицируется под любую разрядность результата, если нужно получить полный 32-разрядный диапазон, просто добавьте еще один регистр для старшего разряда (temp3, к примеру) и одну строку кода перед командой ret:
adc temp3,r01
Естественно, можно просто обозначить r01 через temp3, тогда и добавлять ничего не придется.
Деление — значительно более громоздкая процедура, чем умножение, требует больше регистров и занимает больше времени (MPY16U из «аппноты» занимает 153 такта, по уверению разработчиков, а аналогичная операция деления двух 16-разрядных чисел — от 235 до 251 тактов). Операции деления двух чисел (и для 8-, и для 16-разрядных) приведены в той же «аппноте» 200, и на этот раз без ошибок, но они не всегда удобны на практике: часто нам приходится делить результат какой-то ранее проведенной операции умножения или сложения, а он нередко выходит за пределы двух байтов.
Потому пришлось разрабатывать свои операции. Например, часто встречается необходимость вычислить среднее значение для уточнения результата по сумме отдельных измерений. Если даже само измерение укладывается в 16 разрядов, то сумма нескольких таких результатов уже должна занимать 3 байта. В то же время делитель — число измерений — может быть и относительно небольшим, и укладываться в один байт. В листинге 15.2 я привожу процедуру деления 32-разрядных чисел (на всякий случай) на однобайтное число, которая представляет собой модификацию оригинальной процедуры из Application notes 200. Как и ранее, названия переменных отражают назначение процедуры — деление состояния некоего 4-байтового счетчика на число циклов счета (определения регистров-переменных не приводятся, комментарии сохранены из оригинального текста «аппноты», они соответствуют блок-схеме алгоритма, размещенной в pdf-файле).