AVR Assembler Tutorial 1




About: I am interested in a wide range of things as shown in my list of interests. Almost anything creative is fun and worth trying.

I have decided to write a series of tutorials on how to write assembly language programs for the Atmega328p which is the microcontroller used in the Arduino. If people remain interested I will continue to put out one a week or so until I run out of free time or else people stop reading them.

I am running Arch linux and I am working on an atmega328p-pu set up on a breadboard. You can do it the same way as me or you can simply plug an arduino into your computer and work on the microcontroller that way.

We will be writing programs for the 328p like the one that is in most arduino's but you should note that these same programs and techniques will also work for any of the Atmel microcontrollers and later on (if there is interest) we will work with some of the other ones as well. The details of the microcontroller can be found in the Atmel data sheets and the Instruction Set Manual and so you may want to keep a copy of them for reference. You can find them here (I am also attaching them to this instructable in case they change the links at some point in the future):



Here is what you will need:

1. A breadboard

2. An Arduino, or just the microcontroller

3. A computer running Linux

4. The avra assembler http://sourceforge.net/projects/avra/files/

5. avrdude http://www.nongnu.org/avrdude/

The complete set of my AVR assembler tutorials can be found here: https://www.instructables.com/id/Command-Line-AVR-T...

Teacher Notes

Teachers! Did you use this instructable in your classroom?
Add a Teacher Note to share how you incorporated it into your lesson.

Step 1: Construct a Testing Board

You can simply use your arduino and do everything in these tutorials on that if you like. However, since we are talking about coding in assembly language our philosophy is inherently to strip away all the periferals and interact directly with the microcontroller itself. So don't you think it would be more fun to do it that way?

For those of you who agree, you can pull the microcontroller out of your arduino and then start by constructing a "Breadboard Arduino" by following the instructions here: http://arduino.cc/en/Main/Standalone

In the picture I show my set up which consists of two standalone Atmega328p's on a large breadboard (I want to be able to keep the previous tutorial wired and loaded on one microcontroller while working on the next one). I have the power supply set up so that the very top rail is 9V and all of the others are 5V from the voltage regulator. I also use an FT232R breakout board to program the chips. I bought them and put bootloaders on them myself, but if you just pulled one out of an Arduino then it is fine already.

Step 2: Install the Assembler and Avrdude

You can now download and install the assembler and avrdude from the links given on the first step of this tutorial. It is likely that if you have already been working with Arduino's then you already have avrdude installed.

After you have avra installed you will notice that there is a subdirectory that comes with it called "sources" and inside that directory are a bunch of include files. These are all of the microcontrollers that you can program with avra. You will notice right away that there is no file for the 328p that we are using here. I have attached one. The file is called m328Pdef.inc which you should put inside the includes directory or anywhere else you like. We will be including it in our assembly language programs. All this does is give each of the registers in the microcontroller names from the data sheet so that we don't have to use their hexidecimal names. The above include file contains "pragma directives" since it was designed for C and C++ programming. If you get tired of seeing the assembler spit out "ignoring pragma directive" complaints just go into the file and delete or comment out all the lines beginning with #pragma

Okay, now that you have your microcontroller ready, your assembler ready, and your programmer ready, we can write our first program.

Step 3: Hello World

The goal of this first tutorial is to build the standard first program one writes when learning any new language or exploring any new electronics platform. "Hello World!." In our case we simply want to write an assembly language program, assemble it, and upload it to our microcontroller. The program will cause an LED to turn on. Causing an LED to "blink" like they do for the normal Arduino hello world program is actually a much more complicated program in assembly language and so we won't do that just yet. We are going to write the simplest "bare bones" code with minimal unnecessary fluff.

First connect an LED from PB5 (see the pinout diagram) which is also called Digital Out 13 on an arduino, to a 220 ohm resistor, then to GND. I.e.

PB5 ----> LED ----> R(220 ohm) ----> GND

Now to write the program. Open up your favorite text editor and create a file called "hello.asm"

;  turns on an LED which is connected to PB5 (digital out 13)

.include "./m328Pdef.inc"

	ldi r16,0b00100000
	out DDRB,r16
	out PortB,r16
	rjmp Start

The above is the code. We will go through it line-by-line in a minute, but first lets make sure we can get it working on your device.

After you have created the file, then in a terminal you assemble it as follows:

avra hello.asm

this will assemble your code and create a file called hello.hex which we can upload it as follows:

avrdude -p m328p -c stk500v1 -b 57600 -P /dev/ttyUSB0 -U flash:w:hello.hex

if you are using a breadboard arduino you will have to push the reset button on the breadboard arduino just before you execute the above command. Note that you may also have to add a sudo in front or execute it as root. Also note that on some arduino's (like the Arduino UNO) you will probably have to change the bitrate to -b 115200 and the port -P /dev/ttyACM0 (if you get an error from avrdude about an invalid device signature just add a -F to the command)

If everything has worked as it should you will now have an LED lit up..... "Hello World!"

Step 4: Hello.asm Line-by-line

To finish this introductory tutorial we will go through the hello.asm program line-by-line to see how it works.

;  turns on an LED which is connected to PB5 (digital out 13)

Everything after a semicolon is ignored by the assembler and hence these first two lines are simply "comments" explaining what the program does.

.include "./m328Pdef.inc"

This line tells the assembler to include the m328Pdef.inc file which you downloaded. You may want to put this in a directory of similar include files and then change the above line to point to it there.

ldi r16, 0b00100000

ldi stands for "load immediate" and tells the assembler to take a working register, r16 in this case, and load a binary number into it, 0b00100000 in this case. The 0b in front says that our number is in binary. If we wanted we could have chosen another base, such as hexidecimal. In that case our number would have been 0x20 which is hexidecimal for 0b00100000. Or we could have used 32 which is base 10 decimal for the same number.

Exercise 1: Try changing the number in the line above to hexidecimal and then to decimal in your code and verify that it still works in each case.

Using binary is simplest though because of the way Ports and Registers work. We will discuss the ports and registers of the atmega328p in more detail in future tutorials but for now I'll just state that we are using r16 as our "working register" meaning that we are just going to use it as a variable that we store numbers in. A "register" is a set of 8 bits. Meaning 8 spots that can either be 0 or 1 (`off' or `on'). When we load the binary number 0b00100000 into the register using the above line we have simply stored that number in the register r16.

out DDRB,r16

This line tells the compiler to copy the contents of the register r16 into the DDRB register. DDRB stands for "Data Direction Register B" and it sets up the "pins" on PortB. On the pinout map for the 328p you can see that there are 8 pins labeled PB0, PB1, ... , PB7. These pins represent the "bits" of "PortB" and when we load the binary number 00100000 into the DDRB register we are saying that we want PB0, PB1, PB2, PB3, PB4, PB6, and PB7 set as INPUT pins since they have 0's in them, and PB5 is set as an OUTPUT pin since we put a 1 in that spot.

out PortB,r16

Now that we have fixed the directions of the pins we can now set the voltages on them. The above line copies the same binary number from our storage register r16 to PortB. This sets all of the pins to 0 volts except pin PB5 to HIGH which is 5 volts.

Exercise 2: Take a digital multimeter, plug the black lead into ground (GND) and then tested each of the pins PB0 through PB7 with the red lead. Are the voltages on each of the pins exactly those corresponding to putting 0b00100000 in PortB? If there are any that aren't, why do you think that is? (see the pin map)
   rjmp Start

Finally, the first line above is a "label" which labels a spot in the code. In this case labelling that spot as "Start". The second line says "relative jump to the label Start." The net result is that the computer is placed into an infinite loop that just keeps cycling back to Start. We need this because we cannot have the program just end, or fall off a cliff, the program has to just keep running in order for the light to stay lit.

Exercise 3: Remove the above two lines from your code so that the program falls off a cliff. What happens? You should see something that looks like the traditional "blink" program used by Arduino as their "hello world!". Why do you think it acts this way? (Think about what must happen when the program falls off a cliff...)

Step 5: Conclusion

If you have gotten this far then congratulations! You are now able write assembly code, assemble it, and load it onto your microcontroller.

In this tutorial you have learned how to use the following commands:

ldi hregister, numberloads a number (0-255) into a upper half register (16-31)

out ioregister, registercopies a number from a working register to an I/O register

rjmp labeljumps to the line of the program labeled by "label" (which cannot be further than 204 instructions away -- i.e. relative jump)

Now that these basics are out of the way, we can continue to write more interesting code and more interesting circuits and devices without having to discuss the mechanics of compiling and uploading.

I hope you have enjoyed this introductory tutorial. In the next tutorial we will add another circuit component (a button) and expand our code to include input ports and decisions.

Tech Contest

Participated in the
Tech Contest

Microcontroller Contest

Participated in the
Microcontroller Contest

1 Person Made This Project!


  • Made with Math Contest

    Made with Math Contest
  • Multi-Discipline Contest

    Multi-Discipline Contest
  • Robotics Contest

    Robotics Contest

32 Discussions


Reply 4 years ago on Introduction

There isn't one that I can find. However, if you have some spare time you should write one! Here is the way to do it. Use my m328Pdef.inc file as a template and change the name to correspond to your chip. Then go to the datasheet summary file for the at90usb162 here:


starting with section 4 on page 8 you will find the Register summary. Now you can go through the various sections in the include file and change the hex addresses for the various register names and bits.

Next you can go to the full data sheet here:


and go through each of the sections and map the names to the bit locations. As an examle of what I mean, say you are on the section of the include file called

; PRR - Power Reduction Register

then you would start on page 43 (section 8.6) in the full data sheet. You will notice that the at90USB162 has two power reduction registers PRR0 and PRR1 whereas the ATmega328p only has one called PRR. So you will have to change that section of the include file accordingly and have two sections instead of one. Essentially you just go through each register and equate the name they give to each bit with the number of the bit. So, for example, I would have a line under the PRR1 section that would read:

.equ PRUSART1 = 0 ; Power reduction USART1

Which comes straight from section 8.6.2 on page 44 of the data sheet. You get the idea? I know it is a bit tedious, but then you can use avra with your chip for these tutorials. Also you will know all the in's and out's of your chip by the time you are done.


Question 3 months ago

Hello! First of all, thank you for this instructable. It's a good start off point and there is none like it anywhere else. I was able to follow along and can now program my ATTiny85. Of course, I used a different include file (I used tn85def.inc, which is specifically for ATTiny85). Everything works, except for the last part where I remove the last two lines. It doesn't blink like you say it would. It just stays on. Any thoughts on this? Thanks!


11 months ago

on exercise 3... I removed "Start... rjmp Start" but my led keeps lit steady, no blinking...
I use a bare Atmega328 @ 8MHZ

1 reply

Question 7 months ago on Step 3

Really great tutorial :)
I had issues when trying to get the code to the processor. The command suggested here gives me an error message and I don't know how to fix it:
avrdude: ser_open(): can't open device "/dev/ttyUSB0": No such file or directory


3 years ago

Hi, thanks for this instructable!

I am having trouble compiling AVRA (in Arch Linux). It seems that there is something wrong with the Makefile, but I am not sure. The whole thing is confusing, as the INSTALL file says to install one way, whereas other websites say to install other ways....

2 replies

Reply 2 years ago

hello, I was wondering if you ever managed to resolve this, I am also having problems compiling Avra, I got 1.2.3 installed fine but then found it used a different way of referencing what board you're using and the m328Pdef.inc file would not work on its own.

1.3.0 just has an error in the when I run ./Build because it seems a directory is not created properly


1 year ago

Thanks for supplying a good tutorial, nice initiative!

I made my first "hello world" using your tutorial with an Atmega328PB Xplained Mini board and Atmel Studio.


Question 1 year ago on Introduction

How do I get the avra assembler working on my ubuntu platform? I tried following the instructions but, something seems to be missing...


1 year ago

Thanks for all your work!

Assembler is my favourite language (Spectrum and PC).

I wanted to try it on Arduino and with your help I will start soon.

I looked at some of your .asm files and like your style - more coments than code.


1 year ago

Marry Chrismas. Thanks, it works fine !


2 years ago


Thanks for this tutorial!

At this moment I have no linux, so I tried it on Windows 10.

The only difference is, you have to take the AVR-Assembler avrasm2.exe + avrdude.exe

avrasm2 needs the option -fI to produce a hex-File

The assemler from the avr-gnu-toolchain (avr-as.exe) does not work, because it supports another assembly syntax.

For all who are interested, this is my Batch-File
rem *** buildhex.bat ***
@echo off
echo Assemblieren
avrasm2 -fI led_on.asm
avrdude -p atmega328p -c arduino -P com3 -b 115200 -D -U flash:w:led_on.hex:i
echo Fertig

1 reply

2 years ago

Hi there, notice that when use avrdude to upload the program, you specified the -c option(programmer type) to be stk500v1, but I can find any description about actually using this stk500 programmer, so why is that? thank you!(I've seen other tutorials use -c arduino instead)


3 years ago

Just what I was looking for; thank you so much! This is all very new to me and I am having trouble with the AVRA compiling step. I get 4 unknown mnemonic/macro errors, one for each #ifndef, #define, #pragma, and #endif, and one unknown device: ATmega328p from the m328pdef.inc file. Any suggestions?

Here is my hello.asm file

.include "C:\Users\Renaud\Documents\Arduino\AVRA\includes\m328Pdef.inc"

ldi r16, 0b0010000

out DDRB,r16

out PortB,r16


rjmp Start

1 reply

Reply 3 years ago

I talked about this in step two.
The inc file is designed so that C compilers can also read it. Either comment out those lines or just delete them. Also make sure your device is spelled correctly. Caps too. Or you will get an unknown device error.


3 years ago

how to install avra on linux? and is it also compatible with os x?