1 Write an assembly code for a subroutine implementing signe
1. Write an assembly code for a subroutine implementing signed multiplication with Booth\'s algorithm. Make sure it works as expected. Compare it with your implementation of sign/magnitude multiplication from the second homework. Which one is better? From what aspects?
Solution
include \"1200def.inc\"
rjmp RESET ;reset handle
.def mc8u =r16 ;multiplicand
.def mp8u =r17 ;multiplier
.def m8uL =r17 ;result Low byte
.def m8uH =r18 ;result High byte
.def mcnt8u =r19 ;loop counter
mpy8u: clr m8uH ;clear result High byte
ldi mcnt8u,8 ;init loop counter
lsr mp8u ;rotate multiplier
m8u_1: brcc m8u_2 ;carry set
add m8uH,mc8u ; add multiplicand to result High byte
m8u_2: ror m8uH ;rotate right result High byte
ror m8uL ;rotate right result L byte and multiplier
dec mcnt8u ;decrement loop counter
brne m8u_1 ;if not done, loop more
ret
.def mc8s =r16 ;multiplicand
.def mp8s =r17 ;multiplier
.def m8sL =r17 ;result Low byte
.def m8sH =r18 ;result High byte
.def mcnt8s =r19 ;loop counter
mpy8s: sub m8sH,m8sH ;clear result High byte and carry
ldi mcnt8s,8 ;init loop counter
m8s_1: brcc m8s_2 ;if carry (previous bit) set
add m8sH,mc8s ; add multiplicand to result High byte
m8s_2: sbrc mp8s,0 ;if current bit set
sub m8sH,mc8s ; subtract multiplicand from result High
asr m8sH ;shift right result High byte
ror m8sL ;shift right result L byte and multiplier
dec mcnt8s ;decrement loop counter
brne m8s_1 ;if not done, loop more
ret
.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)
.def mcnt16u =r22 ;loop counter
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
.def mc16sL =r16 ;multiplicand low byte
.def mc16sH =r17 ;multiplicand high byte
.def mp16sL =r18 ;multiplier low byte
.def mp16sH =r19 ;multiplier high byte
.def m16s0 =r18 ;result byte 0 (LSB)
.def m16s1 =r19 ;result byte 1
.def m16s2 =r20 ;result byte 2
.def m16s3 =r21 ;result byte 3 (MSB)
.def mcnt16s =r22 ;loop counter
mpy16s: clr m16s3 ;clear result byte 3
sub m16s2,m16s2 ;clear result byte 2 and carry
ldi mcnt16s,16 ;init loop counter
m16s_1: brcc m16s_2 ;if carry (previous bit) set
add m16s2,mc16sL ; add multiplicand Low to result byte 2
adc m16s3,mc16sH ; add multiplicand High to result byte 3
m16s_2: sbrc mp16sL,0 ;if current bit set
sub m16s2,mc16sL ; sub multiplicand Low from result byte 2
sbrc mp16sL,0 ;if current bit set
sbc m16s3,mc16sH ; sub multiplicand High from result byte 3
asr m16s3 ;shift right result and multiplier
ror m16s2
ror m16s1
ror m16s0
dec mcnt16s ;decrement counter
brne m16s_1 ;if not done, loop more
ret
.def drem8u =r15 ;remainder
.def dres8u =r16 ;result
.def dd8u =r16 ;dividend
.def dv8u =r17 ;divisor
.def dcnt8u =r18 ;loop counter
div8u: sub drem8u,drem8u ;clear remainder and carry
ldi dcnt8u,9 ;init loop counter
d8u_1: rol dd8u ;shift left dividend
dec dcnt8u ;decrement counter
brne d8u_2 ;if done
ret ; return
d8u_2: 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_1 ;else
d8u_3: sec ; set carry to be shifted into result
rjmp d8u_1
.def d8s =r14 ;sign register
.def drem8s =r15 ;remainder
.def dres8s =r16 ;result
.def dd8s =r16 ;dividend
.def dv8s =r17 ;divisor
.def dcnt8s =r18 ;loop counter
div8s: mov d8s,dd8s ;move dividend to sign register
eor d8s,dv8s ;xor sign with divisor
sbrc dv8s,7 ;if MSB of divisor set
neg dv8s ; change sign of divisor
sbrc dd8s,7 ;if MSB of dividend set
neg dd8s ; change sign of divisor
sub drem8s,drem8s ;clear remainder and carry
ldi dcnt8s,9 ;init loop counter
d8s_1: rol dd8s ;shift left dividend
dec dcnt8s ;decrement counter
brne d8s_2 ;if done
sbrc d8s,7 ; if MSB of sign register set
neg dres8s ; change sign of result
ret ; return
d8s_2: rol drem8s ;shift dividend into remainder
sub drem8s,dv8s ;remainder = remainder - divisor
brcc d8s_3 ;if result negative
add drem8s,dv8s ; restore remainder
clc ; clear carry to be shifted into result
rjmp d8s_1 ;else
d8s_3: sec ; set carry to be shifted into result
rjmp d8s_1
.def drem16uL=r14
.def drem16uH=r15
.def dres16uL=r16
.def dres16uH=r17
.def dd16uL =r16
.def dd16uH =r17
.def dv16uL =r18
.def dv16uH =r19
.def dcnt16u =r20
div16u: clr drem16uL ;clear remainder Low byte
sub drem16uH,drem16uH;clear remainder High byte and carry
ldi dcnt16u,17 ;init loop counter
d16u_1: rol dd16uL ;shift left dividend
rol dd16uH
dec dcnt16u ;decrement counter
brne d16u_2 ;if done
ret ; return
d16u_2: rol drem16uL ;shift dividend into remainder
rol drem16uH
sub drem16uL,dv16uL ;remainder = remainder - divisor
sbc drem16uH,dv16uH ;
brcc d16u_3 ;if result negative
add drem16uL,dv16uL ; restore remainder
adc drem16uH,dv16uH
clc ; clear carry to be shifted into result
rjmp d16u_1 ;else
d16u_3: sec ; set carry to be shifted into result
rjmp d16u_1
.def d16s =r13 ;sign register
.def drem16sL=r14 ;remainder low byte
.def drem16sH=r15 ;remainder high byte
.def dres16sL=r16 ;result low byte
.def dres16sH=r17 ;result high byte
.def dd16sL =r16 ;dividend low byte
.def dd16sH =r17 ;dividend high byte
.def dv16sL =r18 ;divisor low byte
.def dv16sH =r19 ;divisor high byte
.def dcnt16s =r20 ;loop counter
div16s: mov d16s,dd16sH ;move dividend High to sign register
eor d16s,dv16sH ;xor divisor High with sign register
sbrs dd16sH,7 ;if MSB in dividend set
rjmp d16s_1
com dd16sH ; change sign of dividend
com dd16sL
subi dd16sL,low(-1)
sbci dd16sL,high(-1)
d16s_1: sbrs dv16sH,7 ;if MSB in divisor set
rjmp d16s_2
com dv16sH ; change sign of divisor
com dv16sL
subi dv16sL,low(-1)
sbci dv16sH,high(-1)
d16s_2: clr drem16sL ;clear remainder Low byte
sub drem16sH,drem16sH;clear remainder High byte and carry
ldi dcnt16s,17 ;init loop counter
d16s_3: rol dd16sL ;shift left dividend
rol dd16sH
dec dcnt16s ;decrement counter
brne d16s_5 ;if done
sbrs d16s,7 ; if MSB in sign register set
rjmp d16s_4
com dres16sH ; change sign of result
com dres16sL
subi dres16sL,low(-1)
sbci dres16sH,high(-1)
d16s_4: ret ; return
d16s_5: rol drem16sL ;shift dividend into remainder
rol drem16sH
sub drem16sL,dv16sL ;remainder = remainder - divisor
sbc drem16sH,dv16sH ;
brcc d16s_6 ;if result negative
add drem16sL,dv16sL ; restore remainder
adc drem16sH,dv16sH
clc ; clear carry to be shifted into result
rjmp d16s_3 ;else
d16s_6: sec ; set carry to be shifted into result
rjmp d16s_3
.def temp =r16 ;temporary storage variable
RESET:
ldi mc8u,250
ldi mp8u,4
rcall mpy8u ;result: m8uH:m8uL = $03e8 (1000)
ldi mc8s,-99
ldi mp8s,88
rcall mpy8s ;result: m8sH:m8sL = $ddf8 (-8712)
ldi mc16uL,low(5050)
ldi mc16uH,high(5050)
ldi mp16uL,low(10000)
ldi mp16uH,high(10000)
rcall mpy16u ;result: m16u3:m16u2:m16u1:m16u0
;=030291a0 (50,500,000)
ldi mc16sL,low(-12345)
ldi mc16sH,high(-12345)
ldi mp16sL,low(-4321)
ldi mp16sH,high(-4321)
rcall mpy16s ;result: m16s3:m16s2:m16s1:m16s0
;=$032df219 (53,342,745)
ldi dd8u,100
ldi dv8u,3
rcall div8u ;result: $21 (33)
;remainder: $01 (1)
ldi dd8s,-110
ldi dv8s,-11
rcall div8s ;result: $0a (10)
;remainder $00 (0)
ldi dd16uL,low(50000)
ldi dd16uH,high(50000)
ldi dv16uL,low(60000)
ldi dv16uH,high(60000)
rcall div16u ;result: $0000 (0)
;remainder: $c350 (50,000)
ldi dd16sL,low(-22222)
ldi dd16sH,high(-22222)
ldi dv16sL,low(10)
ldi dv16sH,high(10)
rcall div16s ;result: $f752 (-2222)
;remainder: $0002 (2)
forever:rjmp forever








