# Advanced Arduino Assembly – Programming Problems

## AVR Assembly Programming Problems

## Programming Problems

- The following programming problems are designed for the Arduino Uno (ATmega328P) with the CSULB Shield. Programs may be written in AVR Studio 4 or Atmel Studio 6.
- To display code, open in Chrome browser or download (Firefox).

**1)** In this programing problem you will write the assembly code needed to display a number between 0 and 9 as defined by the least significant 4 switches on your proto-shield (PINC). If the number is greater than 9 turn ON the discrete LED wired to PORTB bit 0, otherwise turn OFF the LED.

I have written much of the code, including calls to subroutines **InitShield,** **WriteDisplay** and **BCD_to_7SEG**. You should be familiar with the first two from your Lab work. The BCD_to_7SEG subroutine takes as input a number between 0 and 9 in **register r0**. The subroutine then converts the decimal number into its corresponding 7 segments and displays answer.

As you write your program remember that:

- The least significant 4 switches are wired to
**PINC**. - The error LED is wired to
**PORTB bit 0** - BCD_to_7SEG’s calling argument is in
**register r0** **Do not modify r16**when you check to see if it is less than 10

.INCLUDE RST_VECT: rjmp reset .ORG 0x0100 .INCLUDE "spi_shield.inc" reset: ldi r16,low(RAMEND) out SPL,r16 ldi r16,high(RAMEND) out SPH,r16 ; Initialize Proto-shield call InitShield loop: _____ r16, _____ // Read Switches from GPIO Registers _____ r16, 0x___ // clear most significant nibble _____ r16, 0x___ // Is r16 less than 10_{10}? (see notes) _____ ___________ // unsigned conditional branch _____ ______, ___ // error - turn on the LED rjmp ___________ // see the flowchart no_error: _____ ______, ___ // not an error - turn off the LED display: _____ ____, _____ // send argument to subroutine call BCD_to_7SEG // (see notes) call WriteDisplay rjmp ____________

**2)** Write a subroutine named BlinkIt to complement a variable named blink and to then send the least significant bit (b0)of blink, in SREG bit T, to a subroutine named TestIt. For the purpose of this exam you do not need to save registers on the stack for this question.

.DSEG Blink: .BYTE 1 .CSEG BlinkIt: ______ _________ // load variable to register 16 ______ _________ // do something ______ _________ // store register 16 back to variable ______ _________ // store bit 0 to SREG T bit ______ _________ // call TestIt usingrelativeaddressing mode ret

#### Solution

**Code**

; ---------------------------------------- ; BlinkIt - TestIt ; Version 1.0 ; Date: 10/24/2014 ; Written By : Khoi Vu ; ---------------------------------------- .INCLUDE .DSEG blink: .BYTE 1 .CSEG .ORG 0x0000 RST_VECT: rjmp reset .ORG 0x0100 .INCLUDE "spi_shield.inc" reset: call InitShield clr spiLEDS // clear discrete LEDs test: rcall BlinkIt rjmp test BlinkIt: lds r16,blink com r16 // complement r16, since blink=0x00, output= 0xFF sts blink,r16 // store back to blink bst r16,0 // store bit 0 of r16 to T rcall TestIt // call TestIt ret TestIt: mov r16,spiLEDS // move LEDs to register 16 sbr r16,0b10000000 // guessing LED is on brts done // since bit 0 of r16 was 1 T=1 so brts is set. it will branch to done cbr r16,0b10000000 // clear r16 if not on done: mov spiLEDS,r16 // move r16 back to LED rcall WriteDisplay // output to display ret

**Simulation**

**Solution Package**

**3)** The following flowchart defines a subroutine named TestIt which is called by BlinkIt. TestIt therefore accepts the T bit as an argument. We are working with the Arduino Proto-shield (see Proto-shield Schematic). Translate the following flowchart into its equivalent AVR code. Your code must implement the flowchart on the right. For the purpose of this exam you do not need to save any registers on the stack for this question.

TestIt: ______ _________ ______ _________ ______ _________ ; guess bit is set ;execute next line only if t = 0 ______ _________ ; guess is wrong

done: ______ _________ ______ _________ ret

#### Solution

**Code**

; ---------------------------------------- ; BlinkIt - TestIt ; Version 1.0 ; Date: 10/24/2014 ; Written By : Khoi Vu ; ---------------------------------------- .INCLUDE .DSEG blink: .BYTE 1 .CSEG .ORG 0x0000 RST_VECT: rjmp reset .ORG 0x0100 .INCLUDE "spi_shield.inc" reset: call InitShield clr spiLEDS // clear discrete LEDs test: rcall BlinkIt rjmp test BlinkIt: lds r16,blink com r16 // complement r16, since blink=0x00, output= 0xFF sts blink,r16 // store back to blink bst r16,0 // store bit 0 of r16 to T rcall TestIt // call TestIt ret TestIt: mov r16,spiLEDS // move LEDs to register 16 sbr r16,0b10000000 // guessing LED is on brts done // since bit 0 of r16 was 1 T=1 so brts is set. it will branch to done cbr r16,0b10000000 // clear r16 if not on done: mov spiLEDS,r16 // move r16 back to LED rcall WriteDisplay // output to display ret

**Simulation**

**Solution Package**

**4) **Given variables A and B, each holding an 8-bit signed 2’s complement number. Write a program to find the maximum value and put into variable C. Example if A > B then C = A.

Option A: Basic implementation of if-then-else statement using load -> do something -> store structure

#### Solution

**Code**

/* Given variables A and B, each holding an 8-bit signed 2's complement number, * write a program to find the maximum value and put into variable C. For * example if A > B then C = A. * * Solution A: Basic implementation of if-then-else statement * using load -> do something -> store structure */ .INCLUDE .DSEG A: .BYTE 1 B: .BYTE 1 C: .BYTE 1 .CSEG Max1: lds r16,A ; load lds r17,B cp r16,r17 brlt elseMax1 ; if (A >= B) note: if A < B branch to else block mov r18,r16 ; then C = A rjmp endMax1 elseMax1: mov r18,r17 sts C,r18 ; store endMax1: rjmp Max1

**Simulation**

**Solution Package**

Option B: Basic implementation of if-then-else statement. Structure modified to immediately

#### Solution

**Code**

/* Given variables A and B, each holding an 8-bit signed 2's complement number, * write a program to find the maximum value and put into variable C. For * example if A > B then C = A. * * Solution B: Basic implementation of if-then-else statement. * Structure modified to immediately store result. */ .INCLUDE .DSEG A: .BYTE 1 B: .BYTE 1 C: .BYTE 1 .CSEG Max2: lds r16,A ; load lds r17,B cp r16,r17 brlt elseMax2 ; if (A >= B) sts C,r16 ; then C = A rjmp endMax2 elseMax2: sts C, r17 endMax2:

**Simulation**

**Solution Package**

Option C: If-then-else statement restructured to if-then with guess. Result immediately stored in SRAM.

#### Solution

**Code**

/* Given variables A and B, each holding an 8-bit signed 2's complement number, * write a program to find the maximum value and put into variable C. * For example if A > B then C = A. * * Solution C: if-then-else statement restructured to if-then with guess * Result immediately stored in SRAM. */ .INCLUDE .DSEG A: .BYTE 1 B: .BYTE 1 C: .BYTE 1 .CSEG Max3: lds r16, A ; load lds r17, B sts C, r16 ; guess A > B cp r16, r17 brge endMax3 sts C, r17 endMax3: rjmp Max3

**Simulation**

**Solution Package**

**5)** Given variable A holds an 8-bit signed 2’s complement number. Write a program to find the absolute value A. Save result back into variable A.

A = |A|

#### Solution

**Code**

/* Program 2 Given variable A holds an 8-bit signed 2's complement number, * write a program to find the absolute value A. * Save result back into variable A. * A = |A| */ .INCLUDE .DSEG A: .BYTE 1 .CSEG Absolute: lds r16, A ; load tst r16 ; if (A < 0) brpl endAbs neg r16 ; then convert to a positive number endAbs: sts A, r16 ; store rjmp Absolute

**Simulation**

**Solution Package**

**6) **Write a program to add 8 bit variables A and B together. Store the sum into 8 bit variable C. For this programming problem you may assume that the sum is less than 255 if A and B are unsigned and between -128 and 127 if signed.

C = A + B

#### Solution

**Code**

/* Write a program to add 8 bit variables A and B together, * and storing the sum into 8 bit variable C. * For this programming problem you may assume that the sum is less * than 255 if A and B are unsigned and between -128 and 127 if signed. * C = A + B */ .INCLUDE .DSEG A: .BYTE 1 B: .BYTE 1 C: .BYTE 1 .CSEG Adder88: lds r0,A ; load lds r2,B add r0,r2 ; add sts C,r0 ; store rjmp Adder88

**Simulation**

**Solution Package**

**7) **Write a program to find the sum of unsigned 8 bit variables A and B. For this programming problem the sum may be greater than 255 if A and B. Store the sum into 16 bit variable C using little endian byte ordering.

C = A + B

#### Solution

**Code**

/* Write a program to find the sum of 8 bit variables A and B. * For this programming problem the sum may be greater than 255 if A and B * are unsigned or less than -128 and greater than 127 if signed. * Store the sum into 16 bit variable C using little endian byte ordering. * C = A + B */ .INCLUDE .DSEG A: .BYTE 1 B: .BYTE 1 C: .BYTE 2 .CSEG Adder816: ; load clr r1 ; r1:r0 = 0:A lds r0,A clr r3 ; r3:r2 = 0:B lds r2,B ; add add r0,r2 ; add least significant bytes adc r1,r3 ; add with carry most significant bytes ; store sts C,r0 ; store least significant byte first sts C+1,r1 rjmp Adder816

**Simulation**

**Solution Package**

**8) **Write a program to find the sum of **signed **8 bit variables A and B. For this programming problem the sum may be less than -128 and greater than 127. Store the sum into 16 bit variable C using little endian byte ordering.

C = A + B

#### Solution

**Code**

/* Write a program to find the sum of 8 bit variables A and B. * For this programming problem the sum may be less than -128 and greater than 127 * Store the sum into 16 bit variable C using little endian byte ordering. * C = A + B */ .INCLUDE .DSEG A: .BYTE 1 B: .BYTE 1 C: .BYTE 2 .CSEG Adder816s: ; load clr r17 ; 0:A lds r16,A ; First 8 bits are A clr r19 ; 0:B lds r18,B ; First 8 bits are B ; make variables 16-bit sbrc r16,7 ser r17 sbrc r18,7 ser r19 ;add add r16,r18 adc r17,r19 ;store sts C,r16 ; store the least significant byte sts C+1,r17 ; store most significant bytes rjmp Adder816s

**Simulation**

**Solution Package**

**9) **Multiply 8-bit unsigned variables A and B placing the product into 16-bit variable C. Save the 16-bit product using little endian byte ordering.

C = A x B

#### Solution

**Code**

/* Multiply 8-bit unsigned variables A and B placing * the product into 16-bit variable C. * Save the 16-bit product using little endian byte ordering. * C = A x B */ .INCLUDE .DSEG A: .BYTE 1 B: .BYTE 1 C: .BYTE 2 .CSEG Mul8x8_16: lds r16,A ; load lds r17,B mul r16,r17 sts C,r0 ; least significant byte (little end) sts C+1,r1 ; most significant byte (big end) rjmp Mul8x8_16

**Simulation**

**Solution Package**

**10) **Given 8-bit variables A and B, each holding an 8-bit **unsigned** Write a program to find the average of A and B. Place the result into variable C.

Hint: Shifting (or rotating) a binary number to the left divides the number by 2.

#### Solution

**Code**

/* Given 8-bit unsigned variables A and B, each holding an 8-bit signed 2's complement number, * write a program to find the average of A and B and put the result into variable C. * Hint: Shifting (or rotating) a binary number to the left is equivalent to dividing by 2. */ .INCLUDE .DSEG A: .BYTE 1 B: .BYTE 1 C: .BYTE 1 .CSEG Avg: lds r16, A ; load lds r17, B add r16, r17 ; add ror r16 ; divide by 2 (include carry) sts C, r16 ; store rjmp Avg

**Simulation**

**Solution Package**

**11) **Given 8-bit variables A and B, each holding an 8-bit **signed** 2’s complement number. Write a program to find the average of A and B. Place the result into variable C.

Hint: Shifting (or rotating) a binary number to the left divides the number by 2.

#### Solution

**Code**

/* Given 8-bit variables A and B, each holding * an 8-bit signed 2's complement number. Write * a program to find the average of A and B. * Place the result into variable C. */ .INCLUDE .DSEG A: .BYTE 1 B: .BYTE 1 C: .BYTE 2 .CSEG ; inputs: 8-bit variables A and B ; output: 16-bit register C Avg8s: ; load registers A and B lds r24,A lds r26,B ; find average C = A+B/2 rcall Adder816s ; C=A+B ; divide by 2 asr r25 ; least significant bit moved to carry bit C ror r24 ; carry moves into most significant bit of r24 ; store the 8 bit result sts C,r24 clr r25 sts C+1,r25 rjmp Avg8s ; Add two 8-bit signed 2's complement numbers, ; where sum of A and B may be 9 bits ; input: r24 and r26 are two 8-bit numbers ; output: register pair r25:r24 equals sum of r24 and r25 Adder816s: ; make variables 16-bit clr r25 ; guess r25 is positive 0x00:A sbrc r24,7 ; if number is positive guess is correct so skip next instruction ser r25 ; guess incorrect, number is negative 0xFF:A clr r27 sbrc r26,7 ser r27 ;add add r24,r26 adc r25,r27 ;store sts C,r24 ; store the least significant byte sts C+1,r25 ; store most significant bytes ret

**Simulation**

**Solution Package**

**12) **Write a function named Div8_8 to divide an unsigned 8 bit number by an unsigned 8 bit number. You can find this program in your textbook (Mazidi). Test your function by writing a program named Div8_8test to test the subroutine Div8_8 by dividing the 8-bit-number: 0xAA by the 8-bit-number 0x55.

#### Solution

**Code**

; Div8_8 ; Version 1.0 ; Date: November 11, 2014 ; Written By : Yoseph Yegezu ; From text book 'The AVR Microcontroller and Embedded systems'Chapter 5 Page 167 .INCLUDE .CSEG .DEF Num=R20 .DEF Denominator=R21 .DEF Quotient=R22 .ORG 0x0000 ldi Num, 0xAA ldi Denominator, 0x55 //call the 8 bit division rcall Div8 ret /************************************ * subroutine divides unside 8bit by 8bit * Quotient = Numerator/Denominator * * r22 = r20 / r21 * with remainder in r20 * ************************************/ Div8: clr Quotient // r22 // quotient is going to increment by 1 everytime L1 loops // loop L1 stops when the numerator-denominator = less than the demoninator L1: inc Quotient sub Num,Denominator // r20,r21 brcc L1 //since the quotient is incremented by 1 when the loop began, after the loop quotient is dec dec Quotient //notice L1 is going to branch off when the numerator is no lnger divisiable by the denominator //which means L1 is branching off when numerator-denominator results in a negative value. //therefore, the denominator is going to be added to the numerator after the loop. add Num,Denominator // r20,r21 ret

**Simulation**

**Solution Package**

**13) **Write a function named Div16_8 to divide an unsigned 16 bit number by an unsigned 8 bit number. Test your function by writing a program named Div8_test to test the subroutine Div16_8 by dividing the 16-bit-number: 0xAAAA by the 8-bit-number 0x55.

Option A

#### Solution

**Code**

/* * Write a subroutine named Div8 to divide a 16-bit number by an 8-bit number. * Next, write a program named Div8_test to test the subroutine Div8 * by dividing the 16-bit-number: 0xAAAA by the 8-bit-number 0x55 * * Q = N/D Divide a 16-bit-number NH:NL by an 8-bit-number Q * * Source: * 1. Binary division in AVR Assembler * http://www.avr-asm-tutorial.net/avr_en/calc/DIVISION.html * 2. Integer division (unsigned) with remainder * http://en.wikipedia.org/wiki/Division_algorithm */ .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_test: ldi r16,0xAA ; 0xAAAA to be divided mov NH,r16 mov NL,r16 ldi r16,0x55 ; 0x55 to be divided with mov DIV,r16 rcall Div8 rjmp Div8_test /* 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 */ 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 program8:

**Simulation**

**Solution Package**

Option B

This solution is an extension of Div8_8

#### Solution

**Code**

; Div16_8B ; Version 1.0 ; Date: November 11, 2014 ; Written By : Yoseph Yegezu .INCLUDE .CSEG .DEF Denominator=R19 .DEF NL=r24 .DEF NH=r25 .DEF QL=r21 .DEF QH=r22 .ORG 0x0000 ldi r16,0xAA mov NH,r16 mov NL,r16 ldi Denominator, 0x55 //Call the 16 bit by 8 bit division rcall Div16_8 ret /************************************ * subroutine divides unside 16bit by 8bit * Quotient = Numerator/Denominator * * r22:r21 = r25:r24 / r19 * ***************************************/ Div16_8: clr r22 clr r21 // loop L1 stops when the numerator - denominator = less than the demoninator L1: //QL is going to increment by 1, everytime L1 loops inc QL //r22 //When QL reaches 255 or 0XFF and then goes back to 0, QH is going to increment by 1 cpi r21,0 brne No_Inc inc QH //r22 No_Inc: sub r24,Denominator // r19 sbc r25,r2 brcc L1 //Since r21 is incremented by 1 when the loop began, after the loop r21 is decremented dec QL //r21 //Notice L1 is going to branch off when the numerator is no lnger divisiable by the denominator //Which means L1 is branching off when r24-denominator results in a negative value. //Therefore, the denominator is going to be added to the r24 after the loop. add r24,Denominator //r24,r19 adc r25,r2 ret

**Simulation**

**Solution Package**

**14) **Write a subroutine that convert a temperature reading in Fahrenheit (variable F)to Celsius (variable C).

#### Solution

**Code**

; ConvertCtoF ; Version 1.0 ; Date: November 11, 2014 ; Written By : Yoseph Yegezu .INCLUDE .DSEG C: .BYTE 1 F: .BYTE 1 .CSEG .DEF Denominator=R19 .DEF Quotient=R22 .ORG 0x0000 //Input a celsius value into r17 TestConvertCtoF: ldi r17,74 sts C, R17 //call subroutine ConvertCtoF rcall ConvertCtoF rjmp TestConvertCtoF /**************************** * subroutine converts a temperature reading in Celsius (variable C) to Fahrenheit (variable F). * F=(C × 9/5) + 32 ==(C × 18/10) + 32 * Range for C input is from (0 to 124), since F max is 255 ****************************/ ConvertCtoF: //Load the C value into r18 lds r18, C //Input the constant value 18 in reg. 16 ldi r16,18 //This part calculates (C*18) mul r18, r16 //Move the products into r25H and r24L movw r25:r24, r1:r0 //Input the denominator into r19 ldi Denominator, 10 //r19,10 //Call the 16 bit by 8 bit division rcall Div16_8 // add 32 to the quotient (18*C)/10 + 32 ldi r26,32 add Quotient,r26 //r22,r26 adc r23,r2 //Store the answer into F sts F, r22 ret /************************************ * Quotient = Numerator/Denominator * * r23:r22 = r25:r24 / r19 * r24 = remainder * ************************************/ Div16_8: clr r2 clr r23 clr Quotient // r22 // quotient is going to increment by 1 every time L1 loops // loop L1 stops when the numerator-denominator is less than the demoninator(10) //(18*C)/10 L1: inc Quotient adc r23,r2 sub r24,Denominator // r24,r19 sbc r25,r2 brcc L1 //since the quotient is incremented by 1 when the loop began, after the loop quotient is dec dec Quotient sbc r23,r2 //notice L1 is going to branch off when the numerator is no lnger divisiable by the denominator. //which means L1 is branching off when r24-denominator results in a negative value. //therefore, the denominator is going to be added to the r24 after the loop. add r24,Denominator adc r25,r2 ret

**Simulation**

**Solution Package**

**15) **Write a subroutine that convert a temperature reading in Celsius (variable C) to Fahrenheit (variable F).

#### Solution

**Code**

; ConvertFtoC ; Version 1.0 ; Date: November 11, 2014 ; Written By : Yoseph Yegezu .INCLUDE .DSEG C: .BYTE 1 F: .BYTE 1 .CSEG .DEF Denominator=R19 .DEF Quotient=R22 .ORG 0x0000 // Input a Fahrenheit value into r17 TestConvertFtoC: ldi r17,124 sts F, R17 // Call subroutine ConvertFtoC rcall ConvertFtoC rjmp TestConvertFtoC /**************************** * Subroutine converts a temperature reading in Fahrenheit (variable F) to Celsius (variable C). * (F - 32) x 5/9 = C * Range of F (32 to 255) therefore Cmax is 123.8 ****************************/ ConvertFtoC: //Load the F value into r18 lds r18, F //Input the constant value 18 in reg. 16 ldi r16, 32 //This part calculates (°F-32) sub r18, r16 ldi r20, 5 //This part calculates (°F-32)*5 mul r18, r20 //Move the products into r25H and r24L movw r25:r24, r1:r0 //Input the denominator into r19 ldi Denominator, 9 //Call the 16 bit by 8 bit division rcall Div16_8 sts C, r22 ret /************************************ * Quotient = Numerator/Denominator * * r23:r22 = r25:r24 / r19 * ************************************/ Div16_8: clr r2 clr r23 clr Quotient // r22 // Quotient is going to increment by 1 everytime L1 loops // Loop L1 stops when the numerator-denominator = less than 10(the demoninator) // This part calculates (°F-32)*5/9 L1: inc Quotient adc r23,r2 sub r24,Denominator // r19 sbc r25,r2 brcc L1 // Since the quotient is incremented by 1 when the loop began, after the loop quotient is dec dec Quotient sbc r23,r2 // Notice L1 is going to branch off when the numerator is no lnger divisiable by the denominator. // Which means L1 is branching off when r24-denominator results in a negative value. // Therefore, the denominator is going to be added to the r24 after the loop. add r24,Denominator adc r25,r2 ret

**Simulation**

**Solution Package**

**16) **Given variables A, B, and C; each holding an 8-bit unsigned 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.

#### Solution

**Code**

/* 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

**Simulation**

**Solution Package**

**More Problems to be added…**

Practice Problems: Interrupts

- Initialize Interrupt 1 (INT1) pin to generate an Interrupt on a rising edge. Set all unused bits to default values.

_____ R16, 0x____

_____ EICRA, R16 - Initialize Interrupt 0 (INT0) pin to generate an Interrupt on a falling edge. Do not change the other bits (ISC11, ISC10) in the External Interrupt Control Register A (EICRA). You should assume the previous code (problem 1) has been written (i.e., bits 1 and 0 cleared)

_____ R16, EICRA

_____ R16, 0x____

_____ EICRA, R16 - Configure Pin 15 PB1 (OC1A/PCINT1) to generate an Interrupt whenever the pin changes state. Do not change any other bits. To make things more interesting, do not use the SBR instruction.

_____ R16, PCMSK0 ; load

_____ R17, PCICR

_____ R18, SREG

_____ R16, 0x ; do something

_____ R17, 0x____

_____ R18, 0x____

_____ PCMSK0, R16 ; store

_____ PCICR, R17

_____ SREG, R18