[TUT][ASM] Moron's guide to starting in AVR assembler

Go To Last Post
21 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

A MORON'S GUIDE TO STARTING IN AVR ASSEMBLER v1.1

by RetroDan@GMail.com

CONTENTS:

INTRODUCTION
BASIC AVR ARCHITECTURE
THE REGISTERS
REGISTER DEFINITIONS
CONSTANTS
THE INCLUDE FILE DIRECTIVE
INSTALLING THE ASSEMBLER
BEEP: OUR FIRST PROGRAM
A BUTTERFLY BEEP
ADAPTATIONS FOR OTHER AVR CHIPS
THE ORIGIN DIRECTIVE
LABELS
THE LOW & HIGH EXPRESSIONS
THE STACK POINTER
THE DATA DIRECTION REGISTERS
THE CLR & SER COMMANDS
ACTIVATING THE SPEAKER
SUBROUTINES AND THE RCALL & RET COMMANDS
THE ADD & SUBTRACT COMMANDS
JUMPING & BRANCHING
THE PAUSE ROUTINE
THE NOP INSTRUCTION
THE AND INSTRUCTION
THE OR INSTRUCTION
THE EOR INSTRUCTION
AN INVERSE OR "NOT" OPERATION
THE SBI & CBI INSTRUCTIONS
THE STACK
THE PUSH & POP INSTRUCTIONS

INTRODUCTION

Conceptually Assembly Language Programming is very simple, you typically move a byte of data into a register, you do something to it, then you write it out. Practically all languages convert their programs to assembly because assembly is close to what the hardware understands, so there is almost a one-to-one relationship between assembly instructions and hardware binary code (machine language).

Assembly may appear difficult to the novice because of the initial steep learning curve, however because of the limited number of instructions, once over-the-hump it is very simple. Before you can start you need a good understanding of the architecture of the machine, the instruction set, the assembler's syntax and a basic understanding of programming principles such as looping and subroutines before you can create your first program.

One of the benefits of learning Assembly is that they are all very similar, so once you learn one, the rest can be picked up easily since most processors do the exact same thing at the hardware level, basically moving bytes around.

Assembly allows you to create the smallest and fastest code possible, however it can be long and tedious for large projects.

BASIC AVR ARCHITECTURE

In its simplest form the AVRs are made of Registers, Ports and RAM:

[REGISTERS]
[PORTS]
[RAM]

There are 32 registers which can be though of as fast RAM so it is where most of the work is done. As I mention previously, most of Assembly is moving data into these registers and doing something with them.

RAM is where we store our programs and data.

The ports are how we communicate with the outside world but they appear to the MCU as additional registers.

THE REGISTERS

The registers are one byte each (eight bits) and are internal to the MCU so they operate quickly. We can think of them as a work space to get things done before they are sent off somewhere. So before we can write assembly programs for the AVR, a good understanding of the registers is important.

There are 32 internal registers in the AVRs typically referred to as R0-R31. The most often used is R16-R31 because they are easier to use. They can be loaded directly with a constant. For example, if you want to load 100 into register R16 with 100 you would use:

LDI R16,100   ;LDI = LoaD Immediate 100 into Register 16

LDI means LoaD Immediate, R16 is the register and 100 is our constant. Anything after the semi-colon ";" is a comment which is ignored by the Assembler.

If you want to move the value of 100 into one of the Registers R0-R15 you CANNOT do this:

LDI R1,100  ;This is an ERROR!!!

To move 100 to one of the registers R0-R15 you would do something like:

LDI R16,100    ;Load 100 into Register 16  
MOV R1,R16     ;Move the contents of Register 16 to Register 1

This moves the 100 into Register R16 first, then we move it from R16 then into R0. Note that the operands are read right-to-left. The MOV is from R16 to R1 and not the reverse, even though it may appear to read that way.

So we can see that Registers R16-R31 are easier to use because they are half the work to load. Out of these, Registers R26-R31 are used as two-byte pointers by more advanced commands, so we should stick to the ten Registers R16-R25 as our main workspace to start.

REGISTER DEFINITIONS

We can use the .DEF command to give our registers meaningful names.

.DEF A = R16
.DEF B = R18 
.DEF N = R20
.DEF STUDENT_SCORE = R25

Now we can load the R16 Register with 100 using the command:

LDI A,100

CONSTANTS

Constants are values that do not change value while the program is running. They are defined at the time your program is assembled into machine language (binary code) and do not change when your program is executed.

Constants can be given a name with the .SET (or .EQU) command. In our last example we loaded the R16 register with the value of 100. Instead of using the constant 100 we could give it a name like PERFECT_SCORE with the statements:

.SET PERFECT_SCORE = 100
.EQU PERFECT_SCORE = 100

Then later in the program we can load R16 with 100 using the command:

LDI R16,PERFECT_SCORE

Constants can be represented in a number of ways. They can be defined as hexadecimal, octal, binary, etc. All of the following define PERFECT_SCORE as 100:

.SET PERFECT_SCORE = 100              ;Decimal notation
.SET PERFECT_SCORE = (2000+500)/25    ;2500 divided by 25 = 100
.SET PERFECT_SCORE = 0x0064           ;Hexadecimal notation
.EQU PERFECT_SCORE = $64              ;Hexadecimal notation
.EQU PERFECT_SCORE = 0b0110_0100      ;Binary notation
.EQU PERFECT_SCORE = 0144             ;Octal Notation
.EQU PERFECT_SCORE = 'd'              ;ASCII Notation

As we have seen before, a constant can be loaded directly into the Registers from R16 to 31. All of the following will load R16 with 100:

LDI R16,100
LDI R16,PERFECT_SCORE
LDI R16,(2000+500)/25
LDI R16,$64
LDI R16,0b0110_0100
LDI R16,'d'
LDI A,PERFECT_SCORE  ;if you have defined A = R16

THE INCLUDE FILE DIRECTIVE

The AVRs include a large family of chips. To help us produce code for the various processors, ATMEL provides a file for each one that contains a series of standard .DEF and .EQU definitions tailored to that specific chip. For example here is a small clip from the M69DEF.INC file for the ATmega169 processor that is used in the AVR Butterflys that defines the R26-R31 Registers as two-byte pointers called X, Y and Z:

; ***** CPU REGISTER DEFINITIONS *************
.def	XH	= r27
.def	XL	= r26
.def	YH	= r29
.def	YL	= r28
.def	ZH	= r31
.def	ZL	= r30

The .INCLUDE directive tells the assembler to read in a file as part of our program. For example at the top of a program for the Butterfly you will typically see:

.INCLUDE "M169DEF.INC"    ;BUTTERFLY DEFS

Or for a program for the ATtiny13:

.INCLUDE "TN13DEF.INC" 

You could even create your own libraries of commonly used routine or constants and include them yourself.

.INCLUDE "MYFILE.ASM"

INSTALLING THE ASSEMBLER

The best way to learn Assembler is by doing Assembler, so if you have not done it yet, we simply download the Studio 4 Software from Atmel.com and install it in Windows. Last time I downloaded it, I had to register first, which is a simple and quick process. If you are using another operating system, I assume you have already figured out how to install the assembler and programmer. We run a cable from a COM port on your PC to either your programmer or chip, and you are ready to go.

We are going to enter an assembly program called BEEP for the Butterfly. If you are not using the Butterfly, keep reading along we'll get into how to adapt the program for other chips soon enough.

If this is the first time you run the software, select "Atmel AVR Assembler." Select "Assembler 2" if asked. Enter a file name of BEEP or something similar, then you will be presented with a list of chips for which to assemble for, if using the Butterfly choose ATmega169.

FOR THE REMAINING CHAPTERS I INVITE YOU TO DOWNLOAD THE PDF FILE BELOW
(You must login to see the Files)

Attachment(s): 

Visit AVR Assembler site http://avr-asm.tripod.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thanks for the tutorial :D
hope it will usefull for very beginers in AVR asm, like me

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I,m moron also.....

.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hai

After reading in one night..very good toturial.
hopefully I didn't forget.

Keep moron.

Jeckson

.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Cheers to Moronic ! Great Job !

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks Moronic, just what I need to get started

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks Moronic

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Clean up on page 13...

Quote:
LDI A,0b1010_1111 ;A = 1111_1111

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Great Job ! Thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thx so much... =]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Anyone know of a similar tutorial for programming in C? Im trying to use an ATmega8...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Anyone know of a similar tutorial for programming in C? Im trying to use an ATmega8...

Kerninghan & Ritchie

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

C for dummies ???
or countless sites that do it.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Awsome Tutorial!
This has helped me learn much about Assembly for AVR.
I look forward to more in the future.
Keep up the good work.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This is really cool stuff.
Thanks for sharing.

When you do ask questions, you may look stupid.
When you do NOT ask questions, you will STAY stupid.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

very helpfull for me..
thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I found this on the last day of the microcontroller section in the electronics course I took. We only scratched the surface, but it was a much needed assist that I will use after the course. Kudos

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm Moronic too, hehe

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thanks, this would be helpful for me.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for this tutorial. You are the man.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

On page 25 the Logical Shift Right should be LSR and the diagram for ROR is mislabeled.

Other than that thanks for a great tutorial