/* Given variables A, B and C, each holding an 8-bit signed 2's complement number, * write a program to find the average of A to C, placing the result into variable D. * D = A + B + C / 3 * Allow for a 16-bit interim sum and result. * Tip: Copy and paste Div8 subroutine into the AvgABC.asm program. */ .INCLUDE .DSEG A: .BYTE 1 B: .BYTE 1 C: .BYTE 1 D: .BYTE 2 .CSEG Setup: ldi r16, 0x34 ; 52 variable default values sts A, r16 ldi r16, 0x78 ; 120 sts B, r16 ldi r16, 0xBC ; 188 sts C, r16 ; sum = 0x168 (360), average = 0x78 (120) AvgABC: ; load clr r1 ; r1:r0 = 0:C lds r0,A clr r3 ; r3:r2 = 0:B lds r2,B clr r5 ; r5:r4 = 0:A lds r4,C add r0,r2 ; A = A + B adc r1,r3 add r0,r4 ; A = A + C adc r1,r5 ; numerator r1:r0 = A + B + C ldi r16,3 ; divisor /r2 = /3 mov r3,r16 rcall Div8 ; quotient r4:r3 = r1:r0 / r2 sts D,r4 rjmp AvgABC /* Div8 * Q = N/D Divide a 16-bit-number NH:NL by an 8-bit-number Q * input * N = Numerator (dividend) * D = Denominator (divisor) * output * Q = Quotient */ .DEF NL = r0 ; LSB 16-bit-number to be divided .DEF NH = r1 ; MSB 16-bit-number to be divided .DEF DIV = r3 ; 8-bit-number to divide with .DEF QL = r4 ; LSB result .DEF QH = r5 ; MSB result Div8: push r0 push r1 push r2 clr r2 ; clear interim register clr QH ; QH:QL = 0b0000 0000 0000 0001 clr QL inc QL div8a: ; start of the division loop clc ; clear carry-bit rol NL ; rotate the next-upper bit of the numerator rol NH ; to the interim register (multiply by 2) rol r2 brcs div8b ; a one has rolled left, so subtract cp r2,DIV ; Division result 1 or 0? brcs div8c ; jump over subtraction, if smaller div8b: sub r2,DIV ; subtract number to divide with sec ; set carry-bit, result is a 1 rjmp div8d ; jump to shift of the result bit div8c: clc ; clear carry-bit, resulting bit is a 0 div8d: rol QL ; rotate carry-bit into result registers rol QH brcc div8a ; as long as zero rotate out of the result ; registers QH:QL go on with the division loop pop r2 pop r1 pop r0 ret ; End of the division reached