I have been assigned a university project to make sound/audio responsive LED using assembly language. I have already made a C++ code in arduino which uses Fastled library. How do I write a working code for this project in assembly (not restricted to arduino IDE, but preferable). I've already tried converting my code to assembly using an online converter, but it is useless.
3 Answers
The Arduino IDE is quite idiosyncratic. It won't let you work on a
project that doesn't have a file with the extension “.ino”. On the other
hand, it doesn't care about how much code is in that file, and you can
keep it happy by creating an empty .ino file. I recommend however that
you put at least a comment block in that file, in order to make things
less confusing for other people who could see your project. Then you can
put your assembly code alongside this empty file, in files of their own
ending with the “.S” extension. These files will be preprocessed before
being assembled, so you can #include <avr/io.h>
and use the macros
defined therein for the IO ports, bits, etc.
The project would look like this:
my_project/ # containing directory
├── my_project.ino # comments only, to keep the IDE happy
├── my_project.S # main assembly file
└── some_extras.S # possibly more assembly files...
If the whole project is pure assembly, one of your assembly files should
define a symbol called main
, which is the entry point of the program:
.global main
main:
; code starts here
If you are going to mix assembly and C++, then you can define main()
in the .ino file, and call from there your assembly routines, which
should be declared as extern "C"
:
extern "C" void my_assembly_routine();
int main()
{
my_assembly_routine();
}
Mind the calling conventions when mixing asm and C++ though.
If you are going to use the Arduino core library, then you should define
setup()
and loop()
instead of main()
. The Arduino core will then
provide it's own main()
, which takes care of its initialization.
If you are going to write mostly C++, with only some assembly sprinkled here and there, inline assembly could be a better option. C.f. Michel Keijzers' answer.
You have to use the asm
keyword, like:
asm("sei \n")
In your case it is advised to use defines, e.g.
#define CLI() asm("cli \n")
#define noInterrupts() cli()
#define SEI() asm("sei \n")
#define interrupts() sei()
See more info at arduino-inline-assembly-tutorial-1.
-
Which IDE do we have to use for this? Also, are these definitions for inline assembly? We are restricted to have the main working code of our program in assembly language.– COALNov 20, 2019 at 10:14
-
Afaik the default Arduino IDE can be used for this. You probably have to put the code inside the setup and loop functions. Note however, the Arduino IDE creates some code around the setup and loop (like interrupt handling). Nov 20, 2019 at 10:49
Sorry.
The main learning effect of this exercise is "Don't do it". You won't beat the c++ compiler regarding performance (speed). But you will run into more errors than you can imagine.
The only purpose of manual assembler language inside c/c++ is to add nanosecond timing by adding some asm("nop");
statements to wait a controlled small number of cpu clock cycles.
@Michel Keijzers' examples are already implemented. Even in Arduino's convenience environment.
IMO it's more challenging to get beyond Arduino programming by going directly to the MCU's hardware level, dealing with Timers, other MCU components, Registers etc. directly. In C/C++ of course. There you learn that there's much more that can be done beyond the Arduino environment.
Or: Look at compiled results via avr-objdump
to learn how C++ is compiled to machine code by experts. Very eventually, you might notice how you could help the compiler optimizing.
-
11. By learning assembly, you learn a lot more than “don't do it”: you get an intimate understanding of what the compiler and the hardware do, and you learn what kind C/C++ constructs compile to efficient machine code. Also, you must have written at least a little bit of assembly to really appreciate the compiler's job (the output of
avr-objdump
). 2. It is not rare that avr-gcc produces sub-optimal code, easily beaten by hand-crafted assembly. I guess this flavor of gcc has not been fine-tuned as much as the ARM or x86_64... Nov 20, 2019 at 19:34 -
@Edgar Bonet : Sure, you learn a lot more. And only after you've learnt that you can 1. appreciate what the compiler is doing for you 2. interpret its results 3. decide whether you'll continue with assembly programming. BTW: I came from assembly programming, because FORTRAN was not really optimal for small machines, and I'm happy since someone invented C and others built cross-compilers. Nov 21, 2019 at 9:41