error: ‘asm’ undeclared (first use in this function)

You are compiling with option -std=c99.

This disables some non-standard GCC extensions like the asm feature.

See https://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html#index-std-112 for some (not very precise) documentation.

Remove or change the line set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99") from your cmakefile if you need inline assembly.


Either use __asm__ instead of asm with -std=c99, or use -std=gnu99

From the GCC docs https://gcc.gnu.org/onlinedocs/gcc-7.2.0/gcc/Extended-Asm.html

The asm keyword is a GNU extension. When writing code that can be compiled with -ansi and the various -std options, use __asm__ instead of asm (see Alternate Keywords).

and https://gcc.gnu.org/onlinedocs/gcc-7.2.0/gcc/Alternate-Keywords.html#Alternate-Keywords:

-ansi and the various -std options disable certain keywords. This causes trouble when you want to use GNU C extensions, or a general-purpose header file that should be usable by all programs, including ISO C programs. The keywords asm, typeof and inline are not available in programs compiled with -ansi or -std (although inline can be used in a program compiled with -std=c99 or -std=c11). The ISO C99 keyword restrict is only available when -std=gnu99 (which will eventually be the default) or -std=c99 (or the equivalent -std=iso9899:1999), or an option for a later standard version, is used.

The way to solve these problems is to put __ at the beginning and end of each problematical keyword. For example, use __asm__ instead of asm, and __inline__ instead of inline.

Other C compilers won’t accept these alternative keywords; if you want to compile with another compiler, you can define the alternate keywords as macros to replace them with the customary keywords. It looks like this:

#ifndef __GNUC__
#define __asm__ asm
#endif

-pedantic and other options cause warnings for many GNU C extensions. You can prevent such warnings within one expression by writing __extension__ before the expression. __extension__ has no effect aside from this.

-std=gnu99 enables GNU extensions such as asm, while still keeping the language C99-like.

C99 standard

GCC works like this to comply with the C99 standard, which marks double underscore symbols as reserved.

From the C99 N1256 standard draft 7.1.3 "Reserved identifiers" 1:

Each header declares or defines all identifiers listed in its associated subclause, and optionally declares or defines identifiers listed in its associated future library directions subclause and identifiers which are always reserved either for any use or for use as file scope identifiers.

  • All identifiers that begin with an underscore and either an uppercase letter or another underscore are always reserved for any use.

Otherwise, if asm were predefined, a legal program like:

int asm = 0;

would become illegal.

Test program

#include <assert.h>
#include <stdint.h>

int main(void) {
    uint32_t io = 0;
    __asm__ volatile (
        "movl %0, %%eax;"
        "inc %%eax;"
        "movl %%eax, %0;"
        : "+m" (io)
        :
        : "%eax"
    );
    assert(io == 1);
}

Tested on Ubuntu 17.10, GCC 7.2.


asm is a gcc extension, Hence you can not used with flags like std=c99 or ansi

More details at https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html#C-Extensions