shomikc
Member level 4
Hi. I am trying to learn Atmel AVR microcontroller assembly programming.
I am trying to do the division of two signed 16 bit numbers and I have used the code from the AVR200 webpage but when I rum the program it does not go the quotient registers at all. I have no idea what is going on. Please can anyone help. The code I have used is here. And also when the program returns it does not go to the forever loop but instead it goes to start.
I am trying to do the division of two signed 16 bit numbers and I have used the code from the AVR200 webpage but when I rum the program it does not go the quotient registers at all. I have no idea what is going on. Please can anyone help. The code I have used is here. And also when the program returns it does not go to the forever loop but instead it goes to start.
Code:
.def d16s = r13 ; sign register
.def drem16sL = r22 ; remainder low byte
.def drem16sH = r23 ; remainder high byte
.def dquo16sL = r24 ; quotient low byte
.def dquo16sH = r25 ; quotient high byte
.def dd16sL = r26 ; dividend low byte
.def dd16sH = r27 ; dividend high byte
.def dv16sL = r18 ; divisor low byte
.def dv16sH = r19 ; divisor high byte
.def dcnt16s = r20 ; loop counter
start:
ldi dd16sL,low(00)
ldi dd16sH,high(10)
ldi dv16sL,low(00)
ldi dv16sH,high(10)
rcall div16s ; result: $f752 (-2222)
; remainder: $0002 (2)
forever: rjmp forever
;***** Code
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 dquo16sH ; change sign of result
com dquo16sL
subi dquo16sL,low(-1)
sbci dquo16sH,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