How to program an Arduino Uno in assembly

February 20, 2023

This tutorial shows you how to program an Arduino Uno R3 in AVR Assembly. The assembly program that you flash onto the Uno just blinks the built-in LED (pin 13) on and off.

Kudos to mhitza for documenting a workflow that actually works.


If you don't have the following equipment or experience, you may have a tough time completing this tutorial.




Create the repository directory

mkdir ~/uno
touch ~/uno/blink.asm
touch ~/uno/Makefile

Install avra

sudo apt install avra

avra (AVR Assembler) will be your assembler.

Install avrdude

sudo apt install avrdude

avrdude (AVR Downloader Uploder) will be your tool for flashing your assembled program onto your Uno.

Create the assembly program

Copy-paste the following code into each respective file.


# Modified from
# which is copyrighted by Marius Ghita and licensed under Apache-2.0.

.device ATmega328P
.equ PORTB = 0x05
.equ DDRB  = 0x04

.org 0x0000
    jmp setup

    sbi DDRB, 5
    clr r16
    jmp main

    tst r16
    brne off
    rjmp on

    sbi PORTB, 5
    ldi r16, 1
    rjmp delay

    cbi PORTB, 5
    clr r16
    rjmp delay

    ldi  r18, 41
    ldi  r19, 150
    ldi  r20, 128
    dec  r20
    brne loop
    dec  r19
    brne loop
    dec  r18
    brne loop
    rjmp main

I'm an assembly n00b. I can only verify that this program is correct in the sense that I can see the LED on my Uno blinking on and off. Also when I left the Uno running overnight nothing blew up.

See Resources to figure out how this code works.


# Modified from
# which is copyrighted by Marius Ghita and licensed under Apache-2.0.

%.hex: %.asm
	~/uno/avra -fI $<
	if [ -f "*.eep.hex" ]; then rm *.eep.hex; fi
	if [ -f "*.obj" ]; then rm *.obj; fi
	if [ -f "*.cof" ]; then rm *.cof; fi

all: $(patsubst %.asm,%.hex,$(wildcard *.asm))

upload: ${program}.hex
	sudo avrdude -c arduino -p m328p -P /dev/ttyACM0 -b 115200 -U flash:w:$<

.PHONY: all upload

Assemble and flash the program

cd ~/uno
# Assumes that the Uno is connected to your Linux computer via the USB-A
# to USB-B cable and is available at /dev/ttyACM0.
make program=blink upload

You should see the built-in LED labeled L blink on for about 1 second and then off for about 1 second.


The insect overlords are surely watching your (assembly) career with great interest now.


Resources for figuring out how the blink.asm code works: