How to use assembler together with Arduino libraries?

I have significant experience with AVR assembler (using AVR Studio 4) and almost zero with C language. I'm working on project that will measure some curves and need to output them on graphic display. I have enough working code pieces to put together measurement completely in assembler but no library for graphic displays. I already modified mcufriend display special to my Mega128 board pinout and his examples are working on my board. I need to decide what will be easiest way - tray to include my asm file in Arduino IDE or tray to transfer graphic library to AVR Studio 4 if it's possible. I will not not if possible go to newer AVR Studio because my programming tools are not supported there.

You can mix inline assembler, assembler and C/C++ in the same sketch.

To include an assembler program, in addition to a (or several) C/C++ Library inside your sketch folder, create a .S file by clicking in the upper right arrow in your IDE window, name it as you like (e.g. foo.S) and inside the .ino sketch, declare all your assembler functions with extern “C”.

Here is a basic sketch :

The .ino sketch

char array[] =" Hello World\n";

extern "C" 
void Print_Hello();

void setup() {}

void loop() {



The .S file

#include   "avr/io.h"

.global Print_Hello

.set size_of_array, 14


; Setting baud rate 9600
    clr r0
    sts   UCSR0A, r0
    ldi   r24, 1<<RXEN0 | 1 << TXEN0  ; enable Rx & Tx
    sts   UCSR0B, r24
    ldi   r24, 1 << UCSZ00 | 1 << UCSZ01  ; asynchronous, no parity, 1 stop, 8 bits
    sts   UBRR0H, r0
    ldi   r24, 103
    sts   UBRR0L, r24

; loading address and size of array
    ldi XL, lo8(array)         ; r26
    ldi XH, hi8(array)         ; r27
    ld r16, X                  ; Load charactere pointed by X registers (r26/r27)
    ldi r24, size_of_array

    lds   r17, UCSR0A
    sbrs  r17, UDRE0   ; test the data buffer if data can be transmitted
    rjmp  Loop
    sts   UDR0, r16     ; send data contained in r16
    dec   r24
    ld r16, X+        ; point to the next charactere
    brne Loop



ldi  R17, 0x53
LOOP0:  ldi  R18, 0xFB
LOOP1:  ldi  R19, 0xFF
LOOP2:  dec  R19
brne LOOP2
dec  R18
brne LOOP1
dec  R17
brne LOOP0


Charlyf: I have significant experience with AVR assembler (using AVR Studio 4) and almost zero with C language.

You'll learn quickly, as you see stuff you do all the time in ASM manifested in the language.

Already find out that assembler in arduino IDE has different syntax from AVR studio, .byte or .string instead db, hi8,lo8 instead HIGH,LOW and need of pm if you refer to program memory, but I can not find out how to multiply address by two:

ldi r31,hi8(pm(array*2))
ldi r31,hi8(pm(array<<1))

are both giving error,

but ldi r31,hi8(pm(array)) loads pointer to 1/2 needed address.

Sorry needed to say that I found a solution myself

ldi r31,hi8(array) ldi r30,lo8(array) ... lpm r16,Z+

works correctly, what I don't understand is what purpose pm has... BTW without pm arithmetic inside braces is working!

pm along with pm_lo8/pm_hi8 are used for addresses located in Flash/Program memory (documentation found here). These are not macros, but rather builtin assembler functions. Note that pm (for program memory) returns a byte address suitable for use by the LPM instruction, whereas lo8/hi8 return word addresses.

Specific to your situation, unlike the Atmel's assembler, the GNU assembler doesn't know the address which is determined at link time, therefore it can’t perform math upon it.

ldi r31,pm_hi8(array) ldi r30,pm_lo8(array) and ldi r31,hi8(pm(array)) ldi r30,lo8(pm(array))

give the same 1/2 value of correct address for LPM command

ldi r31,hi8(array) ldi r30,lo8(array)

give correct address.

Possibly there is some bug in current compiler version , copy/paste from another processor that has two separate commands for low and high half of program memory.