Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Микроконтроллеры (MCU) и микропроцессоры (MPU) > Умножение двухбайтовых чисел для AtTiny2313


Автор: Arcanum 6.11.2011, 07:09
Нашёл на одном http://elm-chan.org/docs/avrlib/mul08.txt функцию умножения байтовых чисел с двухбайтовым результатом.
содрал и переделал под себя. макрос выполняет вспомогательную функцию
Код

.MACRO MULD
   MOV R16,@1
   MOV R17,@0
   MOV R18,@2
   RCALL mul08s
   MOV @0,R17
   MOV @1,R16
   MOV @2,R18
.ENDMACRO

/*
; Register variables:
;  Call:  var10 r16 = 8bit multiplicand
;         var11 r17 = <don't care>
;         var20 r18 = 8bit multiplier
;         lc r19    = <don't care> (high register must be allocated)
;
;  Result:var1[r17:r16 ] = 16bit result of var10 r16 * var20 r18
;         var20 r18      = <not changed>
;         lc    r19      = 0
;
; Size  = 9 words
; Clock = 64 cycles (+ret)
; Stack = 0 byte

*/

mul08u:      sub   r17,r17   ;initialize variables
      ldi   r19,9      ; r19 = 9;
      brcc   PC+2      ;---- car19urating loop
      add   r17,r18   ;
      ror   r17      ;
      ror   r16      ;
      dec   r19      ;if (--r19 > 0)
      brne   PC-5      ; continue loop;
      ret



mul08s:      clr   r19      ; Optional fast signed helper
      tst   r16      ;  process with fast unsinged routine
      brpl   PC+3
      inc   r19
      neg   r16
      tst   r18
      brpl   PC+3
      inc   r19
      neg   r18
      bst   r19,0
      rcall   mul08u
      brtc   PC+5
      com   r16
      com   r17
      adc   r16,r19
      adc   r17,r19
      ret



так вот эта процедура вызывается из моего кода два раза:

Код

.def minsH = r20 ; старщий регистр переменной суперминут
.def minsL = r21 ; младший регистр переменной суперминут

.def stepsH = r22 ; старщий регистр переменной супершагов
.def stepsL = r23 ; младший регистр переменной супершагов

.def TmpVar = r24 ; регистр переменной часов

SetTimeMinute:
; загрузка минут и константы
LDS MinsL, RamMinute ; загрузили из ОЗУ минуты
LDI TmpVar, StepsToMin
; теперь умножение
MULD MinsH, MinsL, TmpVar ; младший, страший, константа
;тут плохо считает
; загрузка шагов и константы
LDS StepsL, RamSteps ; загрузили из ОЗУ пройденые шаги
LDI TmpVar, MinPerHour
; теперь умножение
MULD StepsH, StepsL, TmpVar ; младший, страший, константа
; тут считает отлично.


вот MULD MinsH, MinsL, TmpVar выдаёт порнографию
при умножении 02 * A4 = FF48 а не 0148
а MULD StepsH, StepsL, TmpVar считает правильно
раз 10 проверял
вроде всё аналогично но что за на фиг?! всю ночь с этим мучался

Автор: UniBomb 6.11.2011, 17:59
Цитата(Arcanum @  6.11.2011,  08:09 Найти цитируемый пост)
при умножении 02 * A4 = FF48 а не 0148

Эта функция для знакового умножения двух чисел. При этом старший бит определяет знак числа. A4 можно представить как 164 беззнаковое или как -92. Соответсвенно и результат получается знаковым.

Посему либо приводи результат к беззнаковому представлению, либо ищи функцию беззнакового умножения.

Для второго пути поищи книги "Микроконтроллеры? Это же просто!" за авторством товарища Фрунзе А.В. Там в том числе в третьем и четвёртом томе разбираются вопросы арифметических операций над знаковыми и беззнаковыми числами. Единственное что - все примеры на асме для ПИКовый мк, но переделать их под АВР ассемблер не составит труда.

Автор: Arcanum 7.11.2011, 06:45
Спасибо! всё понял и нашёл функцию для без знаковых вычислений. переделал. работает.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)