Ревич, Ю.В. Программирование микроконтроллеров AVR: от Arduino к ассемблеру

Глава 8. Арифметические операции и операции в двоично-десятичном формате 207 тель соответствующей двоичной дроби (у которой знаменатель равен 65 536) - он будет равен 3 1 834,76736, или, с округлением до целого, 3 1 83 5 . Такой точности хватит, если исходные числа не выходят, как у нас, за пределы трех-четырех деся­ тичных разрядов . Теперь мы в контроллере должны умножить исходную величину 976 на 3 1 835 (как это делается, мы уже знаем) и полученное число 3 1 070 960 (оно оказывается 4-байтовым - $ 0 1 DA1AFO ) сдвинуть на 1 6 разрядов вправо (лис­ тинг 8.7) . ; в ddHH : ddН : ddМ : ddL число $ 0 1 DA1AFO , ; его надо сдвинуть на 1 6 разрядов cl r cnt div1 6L : ; деление на 6553 6 ls r ddНH ; сдвинули старший ror ddН ; сдвинули 3-й ror ddМ ; сдвинули 2-й ror ddL ; сдвинули мrr адший inc cnt cpi cnt , 1 6 brne div1 6L ; сдвинули-поделили на 2 л 1 6 В результате, как вы можете легко проверить, старшие байты обнулятся, а в ddМ: ddL окажется число 474 - тот же самый результат. Но и это еще не все - такая про­ цедура приведена, скорее, для иллюстрации общего принципа. Ее можно еще больше упростить, если обратить внимание на то, что сдвиг на восемь разрядов есть просто перенос значения одного байта в соседний (в старший, если сдвиг вле­ во, и в младший - если вправо) . Итого получится, что для сдвига на 1 6 разрядов вправо нам нужно всего-навсего отбросить два младших байта и взять из исходно­ го числа два старших ddНH : ddН - это и будет результат. Проверьте - $ 0 1 DA и есть 474. Никаких других действий вообще не требуется ! Пример использования этого метода вы можете увидеть в программе ультразвукового дальномера, приве­ денной в главе 16. Если степень знаменателя дроби, как в рассмотренном случае, кратна 8-ми, то, Д ей­ ствительно, не нужно никакого деления, даже в виде сдвига, но чаще всего это не так. Однако и тут приведенный принцип может помочь : например, при делении на l 1 5 вместо пятнадцатикратного сдвига вправо результат можно сдвинуть на один разряд влево (фактически, умножив число на два), а потом уже выделить из него старшие два байта. Итого процедура будет состоять из четырех операций и займет четыре такта. А в виде циклического сдвига на 1 5 , как ранее, нам необходимо в каж­ дом цикле выполнить четыре операции сдвига и одну увеличения счетчика, итого 1 5 · 5 = 75 простых однотактных операций и еще 1 5 сравнений, из которых 1 4 мут зай­ два такта, - всего 1 04 такта. А рt:: шение «в лоб» - на основе целочисленного деления - еще в несколько раз превышало бы и эту величину. Существенная раз­ ница, правда? Вот такая специальная арифметика в МК.

RkJQdWJsaXNoZXIy MTExODQxMg==