Trying to run assembly language with string literals stored in flash


I've been messing around with asm volatile () to run some assembly language in a library (ArdOS), and I'd like to store all the string literals in flash to free up some ram. I've tried using the F() macro to no avail (works fine without the F() macro):

void portSAVE_CONTEXT(){
  asm volatile (F(
  "push r0 \n\t"
  "in r0, __SREG__ \n\t"
  " etc. "));

It gives me the error:
C:\Program Files\Arduino\libraries\ArdOS\kernel.cpp: In function 'void portSAVE_CONTEXT()':
C:\Program Files\Arduino\libraries\ArdOS\kernel.cpp:479: error: expected string-literal before '(' token

I've also tried using PROGMEM, loading the strings into a buffer, and trying asm volatile(buffer); with the same results. Is there any way to make this happen?

As far as I understand, this cannot be done.

While "asm()" looks like a functions, walks like a function and smells like a function, it's not. The asm string literal you pass in is actually evaluated at compile time and not at run-time. Thus the only valid argument for asm() is a string, not anything that requires memory access.

Since the AVR architecture is a modified Harvard architecture, program memory and data memory are separate. You cannot inject code at runtime.

I'd like to store all the string literals in flash to free up some ram

I think you're trying to solve a problem which doesn't exist. The asm source code is entered as strings as a way to bodge it into the 'C' language syntax but it does not end up in your code as string literals - it is compiled and the compiled assembler will be stored in flash, along with the rest of your code.

I've been messing around with asm volatile () to run some assembly language in a library (ArdOS), ...

As a general rule the C++ compiler does an excellent job of generating fast, efficient code. It keeps track of registers, for example, in a way that you will probably have trouble emulating unless you are extremely organized.

Rather than writing the whole thing in assembly, it often times is better just to write the parts that need to be, and use the extended asm syntax, specifying inputs and outputs. This way, you let the compiler keep track of register assignments. However, if you use extended asm, be sure to make sure you list all of the inputs, outputs, and clobbers. If you lie to the compiler, it will get its revenge.

Here is the man page for extended asm. Note, it is NOT user friendly, and the syntax in the strings, is based on what the compiler uses for normal instructions, and can be hard for people to come up to speed on: Extended Asm - Using the GNU Compiler Collection (GCC)

My fingers must have typed the original on the own without input from the brain. I meant to say that it is not user friendly, but instead I wrote especially instead of not. After working on GCC since 1980, reading the asm strings are second nature to me, but I know there is a high learning curve for most people. I did not mean to imply that those strings are user friendly. :roll_eyes: :cold_sweat:

One other thing about writing in asm. You are locking your code to only running on the same processor (or at least processor in the same family). If you move up to a different processor, such as a Due, you will need to throw out all of your asm, and begin again. Sometimes you need to do this, sometimes you don’t.

Hey, thanks for the help! I guess when the problem your trying to solve doesn't exist it'll either make it much easier or much more difficult, depending on how you look at it. XD