Arduino Inline Assembly Tutorial #2 (Extending asm)

extended

The Extended asm Statement

The first tutorial in this series can be found here and covers a great amount of necessary background material.

The general form of an extended inline assembler statement is:

asm(“code” : output operand list : input operand list : clobber list);

This statement is divided by colons into (up to) four parts. While the code part is required, the others are optional:

  • Code: the assembler instructions, defined as a single string constant.
  • A list of output operands, separated by commas.
  • A list of input operands, separated by commas.
  • A list of “clobbered” or “accessed” registers.

For now, we are going to ignore parts 2 through 4 and concentrate on the code part of the statement.

Our First Inline Assembly Program

This is a basic example of storing a value in memory.

volatile byte a=0;

void setup() {
  Serial.begin(9600);

  asm (
    "ldi r26, 42  \n" //load register r26 with 42
    "sts (a), r26 \n" //store r26 into memory location of variable a
  );

  Serial.print("a = "); Serial.println(a);
}

void loop() { }

To fully understand what we are doing here first we need to cover some background.

Memory

The arduino has 3 basic types of memory, flash, SRAM and EEPROM. Flash is the memory where our program is stored. Arduino flash is non-volatile storage where data can be retrieved even after power has been cycled (turned off and then back on). When you upload an arduino program, it gets loaded into flash memory.

EEPROM is a form of non-volatile storage used for variable data that we want to maintain between operations of our program.

SRAM is the memory used to store variable information and data. SRAM is volatile storage, and anything placed here is immediately lost when power is removed. In our program above, variable a is stored in SRAM. For now, we are not concerned about EEPROM or Flash memory, and will concentrate on SRAM.

Registers Are Memory Too

Registers are special SRAM memory locations. The arduino has 32 general purpose registers (labeled r0 to r31). Each register is 8-bits, or 1-byte in size. r0 occupies SRAM position 0, with each register following incrementally through SRAM position 31. These 32 general purpose registers are important because the arduino cannot operate (change, do math, compare values, etc.) directly upon memory. Values stored in memory must first be loaded into a register(s).

As you can imagine, the arduino has more than 32 registers. Registers also have lots more specific details about them, but for now, these first 32 are more than enough.

Assembly Instructions

Our inline assembly consisted of just two instructions, LDI and STS:

  "ldi r26, 42  \n"
  "sts (a), r26 \n"

The LDI instruction is a mnemonic for “LoaD Immediate”. This instruction simply loads an 8 bit constant value directly into a register. The register must be between 16 and 31. For example, thrying to use register #1, r1 with the LDI instruction would cause an error.

In our program, we load the value “42” into register #26, r26 (pedantically we take note, r26 is actually the 27th register, since numbering starts at zero). We could have chosen r18, r19 or even r24 for that matter. Later, our register selection will become crucial, but for now #26 seems like a good choice.

The LDI instruction is followed by an STS instruction. STS is a mnemonic for “STore direct to data Space”. STS stores one byte from a Register into SRAM, the data space. In our inline code, we place the contents of register #26, r26 into the memory location of variable a. Quietly, behind the scenes, the assembler replaces “a” with the memory location of a. Neat.

Our program finishes by printing the contents of variable location a through the Serial Terminal. Hopefully this produces the output: “a = 42”.

A Few Caveats About Our Program

The variable must be global in scope. This causes the compiler to locate the variable inside SRAM. If we declared the variable a inside of the setup() function, it may have been stored temporarily on the stack or inside a register. If that was the case, the STS instruction would have caused an error because it only works when storing to SRAM. The stack is a subject of a different tutorial.

Furthermore, since the default arduino compilation uses the –Os optimization level, we must declare it “volatile”, so the optimizer doesn’t eliminate it. The optimizer is very good at what it does, like when it sees code that’s not necessary, it will artfully remove it. In our case here, we don’t want this code to be removed.

More To Come

With these two beginning tutorials we have covered the fundamentals of the inline assembler, basic syntax and a few assembler instructions. We will continue looking at the extended inline assembler, introducing new instructions as we go. Next, we’ll look at the “clobber list” then dive into the bizarre world of input and output operands.

Reference

AVR 8-bit Instruction Set
AVR-GCC Inline Assembler Cookbook
Basic Asm — Assembler Instructions Without Operands
Extended Asm – Assembler Instructions with C Expression Operands

[updated: 4/8/16]

Also available as a book, with expanded coverage!

Book

Advertisements

About Jim Eli

µC experimenter
This entry was posted in Uncategorized and tagged , , , , , . Bookmark the permalink.

2 Responses to Arduino Inline Assembly Tutorial #2 (Extending asm)

  1. Markus says:

    In “Our First Inline Assembly Program” shouldn’t it be “int” instead of “char” as data type else you get no number but the ASCII representation of the register?

    • Jim Eli says:

      Markus,

      You are absolutely correct, when using a “char”, it will print the character representation of 42, or ‘*’. However an arduino integer is two bytes in size, and for this demonstration, I really want a 1-byte wide variable. I have updated the example to correct it (a byte, “unsigned char” or uint8_t would have been appropriate). I actually prefer to use the standard C99 typedefs rather than the sometimes ambiguous arduino char, int and long.

      It now works just as I desired. “Le bon Dieu est dans le détail”

      Thanks.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s