📄 avr_200_b.asm
字号:
;**** A P P L I C A T I O N N O T E A V R 2 0 0 ************************
;*
;* Title: Multiply and Divide Routines
;* Version: 1.1
;* Last updated: 97.07.04
;* Target: AT90Sxxxx (All AVR Devices)
;*
;* Support E-mail: avr@atmel.com
;*
;* DESCRIPTION
;* This Application Note lists subroutines for the following
;* Muliply/Divide applications. Routines are straight-line implementations
;* optimized for speed:
;*
;* 8 x 8 = 16 bit unsigned
;* 16 x 16 = 32 bit unsigned
;* 8 / 8 = 8 + 8 bit unsigned
;* 16 / 16 = 16 + 16 bit unsigned
;*
;***************************************************************************
.include "1200def.inc"
rjmp RESET ;reset handle
;***************************************************************************
;*
;* "mpy8u" - 8x8 Bit Unsigned Multiplication
;*
;* This subroutine multiplies the two register variables mp8u and mc8u.
;* The result is placed in registers m8uH, m8uL
;*
;* Number of words :34 + return
;* Number of cycles :34 + return
;* Low registers used :None
;* High registers used :3 (mc8u,mp8u/m8uL,m8uH)
;*
;* Note: Result Low byte and the multiplier share the same register.
;* This causes the multiplier to be overwritten by the result.
;*
;***************************************************************************
;***** Subroutine Register Variables
.def mc8u =r16 ;multiplicand
.def mp8u =r17 ;multiplier
.def m8uL =r17 ;result Low byte
.def m8uH =r18 ;result High byte
;***** Code
mpy8u: clr m8uH ;clear result High byte
lsr mp8u ;shift multiplier
brcc noad80 ;if carry set
add m8uH,mc8u ; add multiplicand to result High byte
noad80: ror m8uH ;shift right result High byte
ror m8uL ;rotate right result L byte and multiplier
brcc noad81 ;if carry set
add m8uH,mc8u ; add multiplicand to result High byte
noad81: ror m8uH ;shift right result High byte
ror m8uL ;rotate right result L byte and multiplier
brcc noad82 ;if carry set
add m8uH,mc8u ; add multiplicand to result High byte
noad82: ror m8uH ;shift right result High byte
ror m8uL ;rotate right result L byte and multiplier
brcc noad83 ;if carry set
add m8uH,mc8u ; add multiplicand to result High byte
noad83: ror m8uH ;shift right result High byte
ror m8uL ;rotate right result L byte and multiplier
brcc noad84 ;if carry set
add m8uH,mc8u ; add multiplicand to result High byte
noad84: ror m8uH ;shift right result High byte
ror m8uL ;rotate right result L byte and multiplier
brcc noad85 ;if carry set
add m8uH,mc8u ; add multiplicand to result High byte
noad85: ror m8uH ;shift right result High byte
ror m8uL ;rotate right result L byte and multiplier
brcc noad86 ;if carry set
add m8uH,mc8u ; add multiplicand to result High byte
noad86: ror m8uH ;shift right result High byte
ror m8uL ;rotate right result L byte and multiplier
brcc noad87 ;if carry set
add m8uH,mc8u ; add multiplicand to result High byte
noad87: ror m8uH ;shift right result High byte
ror m8uL ;rotate right result L byte and multiplier
ret
;***************************************************************************
;*
;* "mpy16u" - 16x16 Bit Unsigned Multiplication
;*
;* This subroutine multiplies the two 16-bit register variables
;* mp16uH:mp16uL and mc16uH:mc16uL.
;* The result is placed in m16u3:m16u2:m16u1:m16u0.
;*
;* Number of words :105 + return
;* Number of cycles :105 + return
;* Low registers used :None
;* High registers used :6 (mp16uL,mp16uH,mc16uL/m16u0,mc16uH/m16u1,m16u2,
;* m16u3)
;*
;***************************************************************************
;***** Subroutine Register Variables
.def mc16uL =r16 ;multiplicand low byte
.def mc16uH =r17 ;multiplicand high byte
.def mp16uL =r18 ;multiplier low byte
.def mp16uH =r19 ;multiplier high byte
.def m16u0 =r18 ;result byte 0 (LSB)
.def m16u1 =r19 ;result byte 1
.def m16u2 =r20 ;result byte 2
.def m16u3 =r21 ;result byte 3 (MSB)
;***** Code
mpy16u: clr m16u3 ;clear 2 highest bytes of result
clr m16u2
lsr mp16uH ;rotate multiplier Low
ror mp16uL ;rotate multiplier High
brcc noadd0 ;if carry set
add m16u2,mc16uL ; add multiplicand Low to byte 2 of res
adc m16u3,mc16uH ; add multiplicand high to byte 3 of res
noadd0: 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
brcc noadd1 ;if carry set
add m16u2,mc16uL ; add multiplicand Low to byte 2 of res
adc m16u3,mc16uH ; add multiplicand high to byte 3 of res
noadd1: 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
brcc noadd2 ;if carry set
add m16u2,mc16uL ; add multiplicand Low to byte 2 of res
adc m16u3,mc16uH ; add multiplicand high to byte 3 of res
noadd2: 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
brcc noadd3 ;if carry set
add m16u2,mc16uL ; add multiplicand Low to byte 2 of res
adc m16u3,mc16uH ; add multiplicand high to byte 3 of res
noadd3: 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
brcc noadd4 ;if carry set
add m16u2,mc16uL ; add multiplicand Low to byte 2 of res
adc m16u3,mc16uH ; add multiplicand high to byte 3 of res
noadd4: 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
brcc noadd5 ;if carry set
add m16u2,mc16uL ; add multiplicand Low to byte 2 of res
adc m16u3,mc16uH ; add multiplicand high to byte 3 of res
noadd5: 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
brcc noadd6 ;if carry set
add m16u2,mc16uL ; add multiplicand Low to byte 2 of res
adc m16u3,mc16uH ; add multiplicand high to byte 3 of res
noadd6: 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
brcc noadd7 ;if carry sett
add m16u2,mc16uL ; add multiplicand Low to byte 2 of res
adc m16u3,mc16uH ; add multiplicand high to byte 3 of res
noadd7: 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
brcc noadd8 ;if carry set
add m16u2,mc16uL ; add multiplicand Low to byte 2 of res
adc m16u3,mc16uH ; add multiplicand high to byte 3 of res
noadd8: 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
brcc noadd9 ;if carry set
add m16u2,mc16uL ; add multiplicand Low to byte 2 of res
adc m16u3,mc16uH ; add multiplicand high to byte 3 of res
noadd9: 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
brcc noad10 ;if carry set
add m16u2,mc16uL ; add multiplicand Low to byte 2 of res
adc m16u3,mc16uH ; add multiplicand high to byte 3 of res
noad10: 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
brcc noad11 ;if carry set
add m16u2,mc16uL ; add multiplicand Low to byte 2 of res
adc m16u3,mc16uH ; add multiplicand high to byte 3 of res
noad11: 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
brcc noad12 ;if carry set
add m16u2,mc16uL ; add multiplicand Low to byte 2 of res
adc m16u3,mc16uH ; add multiplicand high to byte 3 of res
noad12: 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
brcc noad13 ;if carry set
add m16u2,mc16uL ; add multiplicand Low to byte 2 of res
adc m16u3,mc16uH ; add multiplicand high to byte 3 of res
noad13: 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
brcc noad14 ;if carry set
add m16u2,mc16uL ; add multiplicand Low to byte 2 of res
adc m16u3,mc16uH ; add multiplicand high to byte 3 of res
noad14: 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
brcc noad15 ;if carry set
add m16u2,mc16uL ; add multiplicand Low to byte 2 of res
adc m16u3,mc16uH ; add multiplicand high to byte 3 of res
noad15: 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
ret
;***************************************************************************
;*
;* "div8u" - 8/8 Bit Unsigned Division
;*
;* This subroutine divides the two register variables "dd8u" (dividend) and
;* "dv8u" (divisor). The result is placed in "dres8u" and the remainder in
;* "drem8u".
;*
;* Number of words :66 + return
;* Number of cycles :50/58/66 (Min/Avg/Max) + return
;* Low registers used :1 (drem8u)
;* High registers used :2 (dres8u/dd8u,dv8u)
;*
;***************************************************************************
;***** Subroutine Register Variables
.def drem8u =r15 ;remainder
.def dres8u =r16 ;result
.def dd8u =r16 ;dividend
.def dv8u =r17 ;divisor
;***** Code
div8u: sub drem8u,drem8u ;clear remainder and carry
rol dd8u ;shift left dividend
rol drem8u ;shift dividend into remainder
sub drem8u,dv8u ;remainder = remainder - divisor
brcc d8u_1 ;if result negative
add drem8u,dv8u ; restore remainder
clc ; clear carry to be shifted into result
rjmp d8u_2 ;else
d8u_1: sec ; set carry to be shifted into result
d8u_2: rol dd8u ;shift left dividend
rol drem8u ;shift dividend into remainder
sub drem8u,dv8u ;remainder = remainder - divisor
brcc d8u_3 ;if result negative
add drem8u,dv8u ; restore remainder
clc ; clear carry to be shifted into result
rjmp d8u_4 ;else
d8u_3: sec ; set carry to be shifted into result
d8u_4: rol dd8u ;shift left dividend
rol drem8u ;shift dividend into remainder
sub drem8u,dv8u ;remainder = remainder - divisor
brcc d8u_5 ;if result negative
add drem8u,dv8u ; restore remainder
clc ; clear carry to be shifted into result
rjmp d8u_6 ;else
d8u_5: sec ; set carry to be shifted into result
d8u_6: rol dd8u ;shift left dividend
rol drem8u ;shift dividend into remainder
sub drem8u,dv8u ;remainder = remainder - divisor
brcc d8u_7 ;if result negative
add drem8u,dv8u ; restore remainder
clc ; clear carry to be shifted into result
rjmp d8u_8 ;else
d8u_7: sec ; set carry to be shifted into result
d8u_8: rol dd8u ;shift left dividend
rol drem8u ;shift dividend into remainder
sub drem8u,dv8u ;remainder = remainder - divisor
brcc d8u_9 ;if result negative
add drem8u,dv8u ; restore remainder
clc ; clear carry to be shifted into result
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -