[Solved]Problems using assembler.

I have in the past used assembler files in arduino this way (this is a working example):

  • Created a library called "asmSMDiv" this contained two files:
  • asmSMDiv.h with this content
extern "C" {
	unsigned int aSMDiv(unsigned int, unsigned int);
}
  • asmSMDiv.S
#include <avr/io.h>

.global aSMDiv
aSMDiv:
//code follows here
  • The sketch contains the normal include statement
    #include <asmSMDiv.h>

This both compiles and run fine. The call

res=aSMDiv(i, 40329)

did exactly was it was supposed to do.

Now to the problem. I created a new new library: "asmAlign32" with two files:
"asmAlign32.h" and "asmAlign32.s"

extern "C" {
	unsigned long align32(unsigned long, unsigned long);
}
#include <avr/io.h>

.global align32
align32:

The sketch contains this (apologies for the snippet but it on this that is important)

#include <asmAlign32.h>
...
y=align32(Data[m], Data[d]>>shift+1);

This doesn't compile, get the message

C:\Program\Arduino/DivisionBenchmark.ino:48: undefined reference to `align32'

I have been staring myself blind on this for hours now. Can anybody spot what i am missing? As i can see both projects have a identical structure, one works, the other doesn't

you know you can actually write a function purely in assembly in the arduino IDE right?

// function prototype
char myfunc();

// function - implemented in assembly
asm volatile(".global myfunc");
asm volatile("myfunc:");
asm volatile("    clr  r25");
asm volatile("    ldi  r24,1");
asm volatile("    ret");

void setup()
{
  Serial.begin(9600);
  while (!Serial) delay(250);

  Serial.print(myfunc());
  Serial.println();
}

void loop()
{
}

I didn't want to use a library structure and messing around with the standard inline asm code wasn't working as I wanted. I didn't find anyone had documented this was possible, but it works perfectly for what I do - maybe it can assist you as well.

Yes, I know that, but there are reasons i want to use a .S file. And the thing that is odd that it works in one case and not the other

is it actually compiling the assembler file in the first place? (ie: verbose on with compilation)
it could be that it finds the file with the extension .S (uppercase) but not the one with .s (lowercase).

the error message says "yes, we know the function exists... but going through all the files we compiled, we cannot find it"

Changing to uppercase .S solved the problem

Thank you very much

Yep you need uppercase S, and a good reason for using an S file it that the ASM code is more readable if there is a lot of it, not that many people have a need for a lot of ASM code these days.


Rob

There IS one area where assembler code is needed in the arduino and that is division.
From one of my programs benchmarking 16 bit division by a constant (13 in this case) all numerators from 1 to 65535:

  • compiler generated division: 895 us
  • assembler shift/multiply with pre computed constants 263us
  • shift multiply in C with pre-computed constants: 384us
  • multiplication with (double) reciprocal 650us

on arduino (specifically 8bit Atmel CPU's) - the only way to really get speed is to use assembly.

the issue is that in C, all int's are upcast to 16bit (as thats the minimum size of an int) so anything with bitwise operations is expensive. i rewrote my BigInt code for RSA 2048 - the original speed was 65 seconds, after removing the C and replacing with assembler - it was 32 seconds. assembler is definitely a must for some projects, especially when gcc cannot optimise C code sufficiently.

http://www.ardiri.com/blog/long_live_assembly_cannot_beat_it_for_performance

you can do some amazing stuff at such a low level, reminds me of programming z80 and 8502 CPU's back in the day :stuck_out_tongue: programmers are expecting so much RAM and power and expect to run over-bloated, clunky apps.

I certainly miss ASM, when I started that's pretty much all their was and I did many commercial applications in Z8/80/8000 and 65/68xx assembly language and just 2k of EPROM in some cases.

I remember doing things like tokenising strings to save space so

"Open the gate"
"Close the gate"

Would be

"Open",1,2
"Close",1,3

where the 1, 2 and 3 indexed into a table of common words and the spaces were implied.

And no bytes or ints for flags, they where all packed into bits. Ahhh those where the days :slight_smile:

You guys are right in that it is faster, but I think few people actually need that, although I did get close recently when I was going to do some networking stuff and needed to detect a bit clash the "instant" it happened.


Rob