Path: 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

1 Calling the assembler on the command line

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 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. .INCLUDE "C:\avrtools\appnotes\8515def.inc" or "/home/gerd/avrasm/def/8515def.inc").

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

To the top of that page

2 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 or shell file. Doing this is different in Windows batch files and Linux shell scripts.

2.1 A windows batch file

If win is used: create a new textfile in the same directory, where your source resides, rename it to Assemble_en.bat (and yes: the type of the file changes indeed), right-click on that file and select edit.

2.1.1 A simple windows batch file

Add the following lines to the empty file:

REM Batch calling assembler
[drive]:\
CD [Path-to-your-sourcefile]
[gavrasm-path]\gavrasm [-options] sourcefile[.asm]
PAUSE

Batch script

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.

To the top of that page

2.1.2 Checking assembling errors in the batch file

In gavrasm versions from 3.4 on, the assembler returns errorlevel after execution. You can use these information to execute different pathes.


REM
REM Tests return value of the assembler
REM
[path-to-gavrasm/]gavrasm.exe -options Sourcecode[.asm]
If errorlevel 1 Goto err
REM No error, add additional commands her
goto final
:err
REM Errors occurred during assembly
echo Error handling!
notepad.exe ATestReturn.err
:final
pause

The batch should look like this example.

Batch with error handling

If you execute this by clicking on the batch file, and if your source code has errors the following happens:

Batch file on error

Now the batch file has detected that gavrasm returned an error and opened a notepad with the .err file, generated by gavrasm.

Batch opened notepad on error

Of course you can use every other editor you like.

To the top of that page

2.2 A linux shell

In Linux just right-click into a folders free space, select new file from the context menue and name it Assemble_en.sh. If you right-click on that empty file you can open it with your favoured editor.

2.2.1 A simple linux shell

For a simple script calling the assembler in Linux we use the follwing shell script:

cd [Full-path-to-your-sourcefile]
[Full-path-to-gavrasm/]gavrasm [-options] sourcefile[.asm]
read key

Shell script Save the shell script. Those who like it: place a reference to that shell on whatever desktop you use (Create new, reference to program, execute in a terminal program). The line with "read key" leaves the shell open after it finished execution of gavrasm, so we can inspect its output.

To the top of that page

2.2.2 A linux shell with error handling

With gavrasm versions from 3.4 the result of assembling is returned back. This result can be used to react appropriately on errors. For such a script type:

#!/bin/bash
cd [Full-path-to-your-source-code-directory]
[Full-path-to-gavrasm/]gavrasm -seb Source[.asm]
if [ "$?" = "0" ]; then
  echo "Shell: No error during assembling"
else
  echo "Shell: Error during assembly"
  kwrite "Source.err"
fi

Linux error handling

The example shows how to do that branching in practice. Here is what happens if executed and an error occurred during assembling.

Linux error executed gavrasm's output says there is an error. The following branching causes the shell to report that error. And an editor is opened by the shell with the file error.err, in which gavrasm reports all errors.

Linux editor

Of course you can call your favourite editor.

To the top of that page

3 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.

4 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
; Int-Vector area for 2313
.IF aType == 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
; Int-Vector area for 2323
.IF aType == 2323
	rjmp IntVecTC0Ovf ; TC0-Overflow, used
.ENDIF
; Int-Vector area for 8515
.IF aType == 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 currently not implemented in order to keep the thing simple.

To the top of that page

5 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

6 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 parameters. 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

7 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

8 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 - 2014 by http://www.avr-asm-tutorial.net