06 - More AVR Assembly Language

Updated 4 Oct 2026

Operators with Immediate Values

  • AVR allows direct arithmetic (math) operations on immediate values.

Arithmetic operators


Example: Basic computation by using arithmetic operators.

  • LDI R16, ((50-40)*2)-5 ;R16 = 0x0F
  • LDI R20, (0x1F-10)*2 ;R20 = 0x2A (อันนี้คือเอาไป Mix กันก็ได้— 10 คือ Decimal, 0x1F คือ Hex อย่างเจ๋ง)

We can also use mixed numeral systems (Decimal & Hex), which is quite useful!

Logic operators


Example: Basic computation using logic operators.

.EQU C1 = 0x50
.EQU C2 = 0x10
.EQU C3 = 0x04
LDI R21, (C1&C2)|C3 ; R21=(0x50&0x10)|0x04 = 0x10|0x04 = 0x14

Shift operators

  • Left shift (<<): Moves bits left (towards the MSB), filling in zeros at the LSB.
    • Example: Shift to the left, two times:
    LDI R16, 0b10000101<<2 ;R16 = 0b00010100
    
  • Right shift (>>): Moves bits right (towards the LSB), filling in zeros at the MSB.
    • Example: Shift to the right, three times:
    LDI R16, 0b11100011>>3 ;R16 = 0b00011100
    

HIGH() and LOW() Functions

  • HIGH() returns the high byte of a 16-bit value.
  • LOW() returns the low byte of a 16-bit value.

Example:

LDI R16, LOW(0x4455) ; R16 = 0x55
LDI R17, HIGH(0x4455) ; R17 = 0x44

⚠️ Be careful! Writing 0x34 is actually 0x0034 in 16-bit representation.


Data Addressing Modes

The data addressing mode is about the way that an instruction will access the data.  There are two types:

  • Direct-addressing-mode instructions – the address of the data (to be read or write) must be specified in these instructions.
  • Indirect-addressing-mode instructions – the address of the data (to be read or write) will be specified via a pointer.

Direct Address

Single-Register Addressing Mode

  • The instructions in this mode will use one register to hold and store data.
  • Examples:
NEG R18 ; negate the contents of R18
COM R19 ; complement the contents of R19
INC R20 ; increment R20
DEC R21 ; decrement R21
ROR R22 ; rotate right R22

Single-Register Addressing Mode with Immediate value

  • The instructions in this mode will use a register to store immediate data.
  • Examples:
LDI R19, 0x25 ; load 0x25 into R19
SUBI R19, 0x6 ; subtract 0x6 from R19
ANDI R19, 0b01000000 ; AND R19 with 0x40

Two-Register Addressing Mode

  • The instructions in this mode use two registers to hold the data and store to a register.
  • Examples:
ADD R20, R23 ; add R23 to R20
SUB R29, R20 ; subtract R20 from R29
AND R16, R17 ; AND R16 with 0x40
MOV R23, R19 ; copy the contents of R19 to R23

Data Addressing Mode

  • The instructions in this mode will store data into or retrieve data from a RAM address.
  • Example:
STS 0x520, R19 ; store R19 into data location 0x520

I/O Addressing Mode

  • The instructions in this mode will store data into or retrieve data from an I/O address.
  • Examples:
IN R18, 0x16 ; R18 = contents of location $16 (PINB)
OUT 0x15, R18 ; PORTC (location $15) = R18

Indirect Address

Register Indirect Addressing Mode

  • The instructions in this mode will use a pointer register to point to a data address to load data from or store data to this address.
  • Three pointer registers are available: X, Y, Z, created from two general-purpose registers:
    • X: R27 (XH) & R26 (XL)
    • Y: R29 (YH) & R28 (YL)
    • Z: R31 (ZH) & R30 (ZL)

  • Common instructions in this mode:
    • LD (Load Data): Reads the value in a pointer register (X, Y, Z) and stores it into another register.
    LDI XL, 0x30 
    LDI XH, 0x01
    LD R18, X ; X now points to 0x0130
    
    • ST (Store Data): Writes a value to a location pointed to by a pointer register.
    LDI ZL, 0x9F
    LDI ZH, 0x13
    ST Z, R23 ; Z now points to 0x139F and stores R23 there
    
  • The AVR allows auto-increment and auto-decrement for pointer registers, simplifying data movement.

Program Memory Addressing Mode

Storing Data in the Program Memory

  • The program memory is primarily for storing programs, but we can also store data.
  • To store data, we use the .DB directive (Define Byte), which supports:
    • Decimal, binary, hexadecimal, and ASCII formats.
    • ASCII characters ('A') and strings ("Hello"). ต่างกันนะ Single quote, double quote
    • 8-bit data storage.
  • For data larger than 8 bits, we use .DW (Define Word).
  • Example usage of .DB to store 8-bit data:

Padding Effect

  • If the data stored is an odd number of bytes, an extra 00 byte is added for alignment (stored as even-numbered bytes).

Loading Data from the Program Memory

  • Data retrieval uses register indirect flash addressing mode, meaning:
    • A Z register pointer is used to access the program memory.
    • X and Y registers can also be used similarly.

Instructions Used:

Z Register Breakdown:

  • The Z register is 16-bit:
    • Bits 15-1 → Address in program memory.
    • Bit 0 (LSB) → Controls whether the low byte (0) or high byte (1) is loaded.

For example, to load data from the high byte of address 02∗∗,the∗∗Zregistervalue=02**, the **Z register value = 0005.



Example: Sending Stored Characters to PORTB

  • Assume program memory at 0x500 contains "WORLD PEACE."
  • The program sends each character to PORTB.


  • Program memory addresses are word-addressed, so the actual address is $A00 (500 * 2 = 1000).
  • Instead of MYDATA << 1, you can directly use 0xA00.
  • LDI R16, 12 acts as a counter.
  • LDI R20, 0xFF + OUT DDRB, R20 → Sets PORTB as output.

Look-up Table

  • A look-up table stores precomputed values, avoiding real-time computation.
  • Example: A program maps values from PORTB to PORTC.
  • We define look-up tables using .DB and .DW just like before.

Bit Manipulation Instructions

Manipulating the Bits of General Purpose Registers

The AVR microcontroller provides a set of bit/flag-manipulating instructions, categorized into:

Manipulating a Bit in an I/O Register

The AVR provides instructions to manipulate a single bit in an I/O register:

  • SBI → Set bit to 1
  • CBI → Clear bit to 0

SBIC and SBIS:

  • SBIC (Skip if Bit in I/O Register is Cleared): Skips the next instruction if the specified bit is 0.
  • SBIS (Skip if Bit in I/O Register is Set): Skips the next instruction if the specified bit is 1.

Manipulating a Flag in the Status Register (SREG)

  • AVR provides instructions to set or clear flags in the status register (SREG):

Conditional Branch Instructions

  • Instructions that check a bit (flag) in SREG and conditionally branch (jump) to a specific address:

Manipulating the Bits of General Purpose Registers (GPRs)

We can set, clear, copy, and check bits in GPRs.

1. Setting Bits (SBR)

  • Syntax:
    SBR Rd, K ; Sets bits in register Rd based on K
    • Rd → Register (R16 - R31)
    • K → 8-bit value (0x00 - 0xFF)
  • Example:
    LDI R17, 0b01011001 ; R17 = 0x59
    SBR R17, 0b01100100 ; Set bits 2, 5, and 6 in R17
    • After execution: R17 = 0x7D (0b01111101)

2. Clearing Bits (CBR)

  • Syntax:
    CBR Rd, K ; Clears bits in register Rd based on K
  • Example:
    LDI R17, 0b01011001 ; R17 = 0x59
    CBR R17, 0b01100100 ; Clear bits 2, 5, and 6 in R17
    • After execution: R17 = 0x19 (0b00011001)

3. Copying a Bit (BST & BLD)

To copy a bit from one register to another:

  • BST stores a bit from a register into the T flag (Temporary flag).

  • BLD loads the T flag into another register.

  • Syntax:

    BST Rd, b  ; Store bit b from Rd into T flag
    BLD Rr, k  ; Load T flag into bit k of Rr
  • Example: Copy bit 3 of R17 to bit 5 of R19:

    BST R17, 3 ; Store bit 3 of R17 in T flag
    BLD R19, 5 ; Copy T flag to bit 5 of R19

BST = Copy, BLD = Paste (Single Bit Clipboard)

Bit positions:  7  6  5  4  3  2  1  0
Binary value:   0  1  0  1  1  0  0  1

4. Checking a Bit (SBRS & SBRC)

  • SBRS (Skip if Bit in Register is Set): Skips the next instruction if bit is 1.

  • SBRC (Skip if Bit in Register is Cleared): Skips the next instruction if bit is 0.

  • Syntax:

    SBRS Rd, b  ; Skip next instruction if bit b in Rd is set
    SBRC Rd, b  ; Skip next instruction if bit b in Rd is cleared
  • Example:

    LDI R17, 0b0001010
    SBRS R17, 3  ; Skip next instruction if Bit 3 in R17 is set
    LDI R20, 0x55 ; This will be skipped if Bit 3 in R17 is 1
    LDI R30, 0x33

Macros

What is a Macro?

  • A macro groups a set of instructions under a name for reuse.
  • Useful when a task (like moving data to RAM) is repeated.
  • Defined using:
    .MACRO name  
    .........  
    .ENDMACRO  
  • Macros accept up to 10 input parameters (@0 to @9).
  • Example:
    .MACRO LOADIO  
        LDI R20, @1  
        OUT @0, R20  
    .ENDMACRO  

Example Program

This program toggles PORTB using macros:

.MACRO LOADIO  
    LDI   R20, @1  
    OUT   @0, R20  
.ENDMACRO  
 
;---------------------------- time delay macro ----------------------------  
 
.MACRO DELAY  
    LDI   @0, @1  
BACK:  
    NOP  
    NOP  
    NOP  
    NOP  
    DEC   @0  
    BRNE  BACK  
.ENDMACRO  
 
;---------------------------- program starts ----------------------------  
 
.ORG 0  
    LOADIO DDRB, 0xFF      ; Make PORTB output  
L1:  
    LOADIO PORTB, 0x55     ; PORTB = 0x55  
    DELAY  R18, 0x70       ; Delay  
    LOADIO PORTB, 0xAA     ; PORTB = 0xAA  
    DELAY  R18, 0x70       ; Delay  
    RJMP   L1  

Explanation:

  • LOADIO macro sets PORTB values.
  • DELAY macro introduces a time delay using NOP and DEC.
  • The loop alternates PORTB between 0x55 (0101 0101) and 0xAA (1010 1010).

Why is there no RET?

The program runs in an infinite loop (RJMP L1).

  • RET (Return from Subroutine) is only used in subroutines, but this is the main execution flow, so RET is unnecessary.