Witam. Przeszukuję sieć w celu znalezienia skutecznego algorytmu mnożenia 16 bitów (16x16) z wynikiem 32 bitowym. Oto przykład z sieci (jakich wiele):
Takich przykładów jest w sieci mnóstwo, ale o dziwo u mnie nie działają (zawsze wynik zerowy). Nawet dokument AVR200 Figure4-1 zawiera wg mnie błędny algorytm (z resztą zgodny z powyższym kodem). To o dziwo nie działa.
Analizując temat doszedłem do wniosku, iż powrót jest w niewłaściwe miejsce, ponieważ jest to skok do , gdzie sprawdzana jest flaga C, ale skąd ta flaga? Wydaje mi się, że przed sprawdzeniem flagi C trzeba ją "wysunąć", a wg kodu (ostatni rozkaz przed sprawdzeniem C) wysuwane jest cały czas zero (przeanalizujcie kod a się przekonacie).
Wpadłem na pomysł że wystarczy przenieść etykietę "m16u_1:" o dwie pozycje w górę w kodzie, wówczas flaga C będzie wysuwana zgodnie z zasadami mnożenia binarnego. No i tak zrobiłem:
Teraz procedurka działa jak należy (sprawdziłem na wszelkie sposoby). No i mam nie lada zagadkę - czyżby w sieci krążyła błędna procedura (no i brak właściwej)?, czy jej nikt nie testował?, czy dokument Atmela także "kłamie"? Spotkał się juz ktoś z takim przypadkiem?
mpy16u:
clr m16u3 ;clear 2 highest bytes of result
clr m16u2
ldi mcnt16u,16 ;init loop counter
lsr mp16uH
ror mp16uL
m16u_1:
brcc noad8 ;if bit 0 of multiplier set
add m16u2,mc16uL ;add multiplicand Low to byte 2 of res
adc m16u3,mc16uH ;add multiplicand high to byte 3 of res
noad8:
ror m16u3 ;shift right result byte 3
ror m16u2 ;rotate right result byte 2
ror m16u1 ;rotate result byte 1 and multiplier High
ror m16u0 ;rotate result byte 0 and multiplier Low
dec mcnt16u ;decrement loop counter
brne m16u_1 ;if not done, loop more
ret
Takich przykładów jest w sieci mnóstwo, ale o dziwo u mnie nie działają (zawsze wynik zerowy). Nawet dokument AVR200 Figure4-1 zawiera wg mnie błędny algorytm (z resztą zgodny z powyższym kodem). To o dziwo nie działa.
Analizując temat doszedłem do wniosku, iż powrót
brne m16u_1brcc noad8ror m16u0Wpadłem na pomysł że wystarczy przenieść etykietę "m16u_1:" o dwie pozycje w górę w kodzie, wówczas flaga C będzie wysuwana zgodnie z zasadami mnożenia binarnego. No i tak zrobiłem:
mpy16u:
clr m16u3 ;clear 2 highest bytes of result
clr m16u2
ldi mcnt16u,16 ;init loop counter
m16u_1:
lsr mp16uH
ror mp16uL
brcc noad8 ;if bit 0 of multiplier set
add m16u2,mc16uL ;add multiplicand Low to byte 2 of res
adc m16u3,mc16uH ;add multiplicand high to byte 3 of res
noad8:
ror m16u3 ;shift right result byte 3
ror m16u2 ;rotate right result byte 2
ror m16u1 ;rotate result byte 1 and multiplier High
ror m16u0 ;rotate result byte 0 and multiplier Low
dec mcnt16u ;decrement loop counter
brne m16u_1 ;if not done, loop more
ret
Teraz procedurka działa jak należy (sprawdziłem na wszelkie sposoby). No i mam nie lada zagadkę - czyżby w sieci krążyła błędna procedura (no i brak właściwej)?, czy jej nikt nie testował?, czy dokument Atmela także "kłamie"? Spotkał się juz ktoś z takim przypadkiem?