Assembler for Arduino

I've been building Arduino projects for awhile now (18 months or so) with much joy. On monday, I'm starting a class on compilers, threading, and language design that's using the Arduino as a test subject. I was wondering if anyone knows of any resources or tutorials for writing and running assembler on the Arduino. I've got a bunch of AVR documentation and books, but what would be really awesome would be a "hello world" guide that's specifically focused on the Arduino. And of course any other good introductory texts on ASM programming would be great as well (this is my first voyage into that world).


Are you willing to put up with gnu assembler syntax, or will you want Atmel-style syntax for the assembler files? The latter will take you into the realm of needing different tools for different platforms, I think...

@westfw: For now, at least, I'm willing to put up with whatever has the lowest barrier to entry, so if that's gnu, so be it. Any tips on actually running some gnu assembler on my Arduino? Or writing some in the first place?


Hey - I just started with Atmel Assembly last night, and thought I'd post my experiences in case it helps anyone else (and to cement the info in my own mind) (thanks go to eadthem for help).

For my IDE, I used AVR Studio 3.5 (Smart | Connected | Secure | Microchip Technology)

As I run linux, I needed to use wine... wasn't a problem doing so. Wine decompresses to a folder in the fake 'windows/temp' directory.... you simply need to navigate and open '~/.wine/drive_c/windows/temp/cdrom/SETUP.EXE' which completes installation process. After installation, Atmel Studio was available in application menu (Applications -> Wine -> Programs->Atmel AVR Tools->AVR Studio 3.56).

I'm using Atmega8, so I made sure I had the relevant datasheet at hand and the AVR 8-bit Instruction Set docs.

[*1] (Smart | Connected | Secure | Microchip Technology)

[*2] (Smart | Connected | Secure | Microchip Technology) <- pages 10 to 14 are especially relevant.

Okay, first task was to set-up a new project in AVR Studio.

Project -> new -> [give it a name] / [pick AVR assembler].

This creates a blank project. Next we need a new text file to put our assembly code.

File -> new text file -> [give it the name 'main.asm']

As far as I know, the name isn't important - what is important, is that when you right click the file, 'assembler entry file' is ticked. You also need to drag this file into the Assembler Files folder.

Next, right click the route node of the project, and select the 'project settings'. Change the output file format to 'intel hex'. This defines the format that will eventually be used by the programmer software / board to upload the code to the microprocessor.

Okay - now it's on with the actual code. Open up the text file created a few steps ago.

First stage is to set the start point in your program memory, to hex address 3A.

.ORG $3A


START:      LDI      r16,high(ramend)      ;ramend=$025F p7-9
      OUT      sph,r16
      LDI      r16,low(ramend)
      OUT      spl,r16

It's worth running through some of the conventions here.

The word preceding the colon, defines a point in the program code which can be called or jumped to later on. It's used to allow us to call subroutines and create loops.

The semicolon defines a comment.

LDI and OUT are instructions ... (a full list of the AVR instruction set can be found in the guide linked above [*2], pages 10-14)

r16 is a register. Registers can be though of as internal variables, which are able to be accessed very quickly by the processor; some are specific and can only be used in certain circumstances, while others are general purpose.

sph and spl refer to the AVR stack pointer (which is implemented as two 8-bit registers). The stack is a stack of data - you can add (push) data to the stack, or take (pop) data from the stack. Find out more about the stack on page 13 of [*1].

As far as I can tell ramend, is a device specific constant, which refers to the end of the available data RAM.

For this first program, I simply wanted to make an LED flash. To do this, I need to output a HIGH signal followed by a LOW signal to one of the ports on the ATmega.

I was a bit confused here, thinking that port is another word for pin... it isn't. The Atmega8 has three ports labelled BCD which are responsible for looking after 23 IO general purpose IO lines/pins.

Port B

looks after 8 I/O lines (PB7-0)

Port C

looks after 7 I/O lines (PC6-0) ... but note that PC6 is special case and is different to others, it's used as an IO pin or reset see page 5 of [*1] for more info.

Port D

looks after 8 I/O lines (PD7-0)

Each port pin consists of three register bits ( DDxn, PORTxn, PINxn).

DDxn bits are accessed at the DDRx I/O address, the PORTxn bits at the PORTx I/O address, and the PINxn bits at the PINx I/O address.

(N/B Page 65 of [*1] is a useful overview of how data is output (PORTxn), how pin direction is defined (DDRxn) and where input data is stored/accessed (PINxn), in relation to the available ports and pins.)

Because the ports and IO lines/pins are general purpose, we need to be able to define which are used for input and which are used for output. This is done by setting the port direction.

      LDI r18,0b10000000
      OUT ddrb,r18

LDI is the instruction for 'load immediate', OUT is the instruction for 'out to i/o location'.

Next, we preload registers r18 and r19 with info that we'll use to make our LED flash... because we use these values many times, the assignment happens before the main loop.

      LDI r18,0b10000000; set register to pin 7 high
      LDI r19,0b00000000; set register to all pins low

Then the main loop ...

      out portb,r18 
      out portb,r19
      jmp MAINLOOP

Now, the great thing about AVR Studio - is that you can use it to run your code in a simulator, which allows you to debug the code, while monitoring the status of registers, i/o ports etc..

Before we can do this we need to include a file (giving device dependant info) at the beginning of the code. (inc files can be found in the 'Appnotes' subdirectory of yr AVR Studio install)

.include ""

Then select; Project -> Build and run... You'll need to select the chip you're working with. Select View -> 'registers' & 'new io view'... then step through yr code with F10 and examine it's effect.