29-Aug-03 19:03 Oleksandr Redchuk wrote to "Harry Zhurov " snipped-for-privacy@online.nsk.su>:
HZ>> push r11 HZ>> clr IRACL ; CLEAR RESULT HZ>> mov #17,IRBT ; INITIALIZE LOOP COUNTER
OR> Смотрел на этот код, смотрел.... Далеко не сразу въехал - что же он OR> делает :-))) OR> Тут специфика одна вылезла - я пару раз в жизни писал себе деление OR> неравных по разрядности чисел и оба раза мне нужно было частное OR> в разрядности _делимого_. Т.е. OR> u16/u8 -> u16, остаток u8 OR> u32/u16 -> u32, остаток u16 [...] OR> Так что если вопрошавшему надо u20/u10 -> u10, то OR> деление можно переписать под такой вариант и выйдет OR> ещё быстрее :-) OR> Только в начале надо будет сдвигать влево не на 4 бита, а на 2, И не делимое, а делитель :-)
Вход: (dvd_h,dvd_m,dvd_l) - 20-битное делимое (divs_h,divs_l) - 10-битный делитель Выход: при переполнении возвращается C=1, иначе C=0 и (dvd_m,dvd_l) - 10-битное частное (divs_h,divs_l) - 10-битный остаток
.macro shift_acc add dvd_l,dvd_l rol dvd_m rol dvd_h .endm .macro sub_divs sub dvd_m,divs_l sbc dvd_h,divs_h .endm .macro add_divs add dvd_m,divs_l adc dvd_h,divs_h .endm
ff20_10: ; 43w, 121cy ; align MSB of 10 bit divisor to MSB of 20 bit divident .rept 2 add divs_l,divs_l rol divs_h .endr
cp dvd_m,divs_l cpc dvd_h,divs_h brcc overflow
ldi cnt,10 lminus: shift_acc sub_divs brmi toplus tominus: inc dvd_l dec cnt brne lminus rjmp makeresult
lplus: shift_acc add_divs brmi toplus inc dvd_l dec cnt brne lminus rjmp makeresult
toplus: dec cnt brne lplus add_divs
makeresult: mov divs_l,dvd_m mov divs_h,dvd_h andi dvd_m,0x03 ; (dvd_m,dvd_l) = 10 bits of quotient .rept 2 asr divs_h ror divs_l .endr clc ret
overflow: sec ret
Итого 121 цикл на деление. Даже на 8-мегагерцовом AVR будет 15.125 мкс.
wbr,