Pfad: Home => AVR-Assembler gavrasm => Introduction
Logo

Introduction to Gerd's AVR Assembler

Here I introduce some special features of the gavrasm Assembler. These examples do not compile on other assemblers. The features discussed:
  1. Calling the assembler on a command line
  2. Calling the assembler within a batch or a shell
  3. Window caller as assembling tool
  4. Using the IF-ELSE-ENDIF directive
  5. Use of the EXIT directive
  6. Using macro labels
  7. Using special literal constants
  8. Using a separator in constants

Calling the assembler on the command line

Two hints for the Linux-user: Assembling with gavrasm on the command line is as follows.
  1. Open a command line (Win: select start/programs/addons/MSDOS window) or a shell (Linux-KDE) and change the directory, typing cd [path], to the one that has the source code file.
  2. Assembling starts with typing [gavrasm-path]gavrasm [-options] sourcefile[.asm].
If you start gavrasm without the option -x, the included header files (such as "8515def.inc", are not read. Instead the internally stored symbols are used, the include file just serves for the recognition of the target AVR type.
If you use the option -x on the command line, all included files must be physically available and accessable. If you have all used INCLUDE-files in the same directory where the source code file resides, you can just add the name of these files (e.g. .INCLUDE "8515def.inc"). Otherwise add the whole path to the included files (e.g. under Windows with the Studio installed .INCLUDE "C:\Programs (X86)\Atmel\assembler2\appnotes\8515def.inc" or under Linux "/home/gerd/avrasm/def/8515def.inc"). In case you use def.inc files from advanced Studio installations, the C-stylish lines in these files are ignored and a warning is displayed.

The parameter options are completely listed in the file ReadMe.Txt. Here are some additional explanations:

To the top of that page

Calling the assembler in a batch or a shell

If you're tired of typing in the path of the assembler, you can place that call in a batch file. If win is used: create a new textfile in the same directory, where your source resides, and add the following lines:

REM Batch calling assembler
[drive]:
CD [Path-to-your-sourcefile]
[gavrasm-path]\gavrasm [-options] sourcefile[.asm]
PAUSE
Rename this text file with the extension ".bat". If you like, you can place a reference to that batch file on your desktop. Assembling is just started by clicking on that file or its reference. PAUSE leaves the window open, until you type in a character.

In Linux we use the follwing shell script:

#!/bin/bash
cd [Path-to-your-sourcefile]
[Path-to-gavrasm]/gavrasm [-options] sourcefile[.asm]
read key
and place it somewhere with the extension .sh. Those who like it: place a reference to that shell on the KDE desktop (Create new, reference to program, execute in a terminal program). The line with "read key" leaves the shell open.

To the top of that page

Window caller - a tool for assembling

Tired of writing batch files for the command line assembler, if you work in a window-orientated environment? Here's something for you!
By request I designed a windows program that creates batch files, calls the assembler, and allows views/editing for the different textfiles that play a role in assembling. Some new features are: The Read-Me file has more informations on its features and how to work with that small helper.
This executable is only available for windows operating systems (sorry linuxers). The zipped executable and the ReadMe-file is available for downloaded here.

Use of IF-ELSE-ENDIF

The additional directives .IF, .ELSE and .ENDIF add the opportunity to compile or not compile certain code depending on conditions. During compilation the IF condition is checked. If it is true, the following source code is compiled. If not, the compilation is restarted behind the .ELSE or the .ENDIF directive. Be careful: If those two directives are missing, the whole remaining source code might not be compiled!

As application example the following source code:

.EQU clock=40000000
.IF clock>4000000
.EQU divider=4
.ELSE
.EQU divider=2
.ENDIF
A short look to the symbol list in the list file shows, that divider has been set to 2. If you change the value of clock e.g. to 10,000,000, divider will be set to 4. Generally speaking: you can avoid further changes in the source code, if you anticipate these changes under certain conditions.

A typical application is, if you like to write and use the same code for different processor types. With other types, interrupt vectors are different. Using .IF, the vector area of the processor is compiled specifically for each AVR type.

;
; Define processor type on top of the source code
;
.EQU aType=2313 ; Processor is a 2313
;.EQU aType=2323 ; Processor would be a 2323
;.EQU aType=8515 ; Processor would be a 8515
;
; Int-Vector area
;
.CSEG
.ORG $0000
	rjmp Main ; for all types
	rjmp IntVecInt0 ; External Int Vector, is used
.IF aType == 2313
; Int-Vector area for 2313
	reti ; IntVecInt1 ; External Int Vector, not used
	reti ; Timer1Capt, not used
	reti ; Timer1/Comp, not used
	reti ; Timer1/Ovf, not used
	rjmp IntVecTC0Ovf ; TC0-Overflow, used
	reti ; UartRX, not used
	reti ; UartUdre, not used
	reti ; UartTx, not used
.ENDIF
.IF aType == 2323
; Int-Vector area for 2323
	rjmp IntVecTC0Ovf ; TC0-Overflow, used
.ENDIF
.IF aType == 8515
; Int-Vector area for 8515
	reti ; IntVecInt1 ; External Int Vector, not used
	reti ; Timer1Capt, not used
	reti ; Timer1/CompA, not used
	reti ; Timer1/CompB, not used
	reti ; Timer1/Ovf, not used
	rjmp IntVecTC0Ovf ; TC0-Overflow, used
	reti ; SpiStc, not used
	reti ; UartRX, not used
	reti ; UartUdre, not used
	reti ; UartTx, not used
	reti ; AnaComp, not used
.ENDIF
;
; Interrupt-Service-Routine INT0
;
IntVecInt0:
	[...]
	reti
;
; Interrupt-Service-Routine TC0-Overflow
;
IntVecTC0Ovf:
	[...]
	reti
;
; Main program start
;
Main:
	[...]
You see, that just changing the processor type is easy, if you have once designed the vector area for this type. Otherwise you'd have to go through your whole source code and redesign. If you forget the difference in the int vector area, you run into a real nice design bug.

The conditions of the .IF directive can be more complex, if you like, e.g.:

.IF (aType == 2313) || (aType == 8515)
Nested .IF directives are implemented in every depth.

To the top of that page

Use of the EXIT directive

If a certain number exceeds its defined value range, one likes to stop assembling and issuing an error message. So, if you missed this opportunity for extended range check in other assemblers, you'll be a friend of gavrasm. .EXIT checks the following condition and stops assembling, if it's true:

.EQU clock=4000000
.EQU divider=64
.EXIT (clock/divider)>65535
With this range check you make sure that no overflow of your 16-bit timer/counter will occur, before you run into a debugger problem. gavrasm notifies you of such a condition and refuses compilation of the buggy code.

To the top of that page

Use of macros

Macros are code sequences stored by the assembler, which are only added to the code, if the macro is called. E.g.:

.MACRO mtest
	.nop
.ENDM
;
; Here we place the macro's code
;
	mtest
The code within the macro can be changed by calling the macro with paqrameters. Parameters can be numbers, but can also be register names or any other symbol. The parameters are referenced within the macro as @0 bis @9. E.g. like this:

;
; Register global definition
;
.DEF rmp,R16
; Here's the macro
.MACRO mtest
	ldi @0,@1 ; Expects a register as first param, a constant as second
	clr @0
.ENDM
;
; Macro call with parameters
;
	mtest rmp,50
The use of macros in gavrasm is enhanced, because you can call macros within a macro whenever you need it. Nesting of macros is only limited by memory storage space.
Labels in macros are in gavrasm clearly protected. Labels can only be used within the macro, using them outside the macro yields an error message. This prevents bugs, if you call a macro more than one time in your source code. Globally defined symbols are accessible within the macro, so don't try to use a symbol name in a macro, that is already defined outside. If you'd like to export a local label within a macro to the outside, use the special directive

.SETGLOBAL label1[, label2, ...]

to export its value. Whenever you call such a macro, the value of label1 is redefined to its current value. This works exact, even if the label is used before it is defined.

With this instrument I added the opportunity to write extensive code for different purposes in macros, and place these code sequences into the source whenever it is required. As the code is only placed there if the macro is called, you can include all your favoured macros, without wasting place if you don't need some of them.

To the top of that page

Use of special literal constants

gavrasm allows the use of ASCII control codes within a literal constant, e.g.

.DB "This is the first line.\m\jThis is the second line."
A '\'-char is inserted by two backspaces, e.g. "path is C:\\dos". Contrary to other assemblers, a ';' in a string is recognized and treated correct.

To the top of that page

Separators in binary- and hex-constants

gavrasm allows the use of the dot as separator in constants, e.g.

.EQU abc = 0b0001.0010
.EQU def = 0x0FFF.FFFF
Don't ever try to assemble this code with another assembler!

To the top of that page

©2003-2011 by http://www.avr-asm-tutorial.net