I am getting the following error during compilation:
error: ‘asm’ undeclared (first use in this function)
EXCHANGE( s, *(a) );
^
in a header file where the macro is invoked as follows:
EXCHANGE( s, *(a) );
and the actual defintion of the macro is as follows:
#define EXCHANGE(R,M) asm volatile ( "xchg %1, %0" : "+m" (M), "+r" (R) )
Macro invocation and definition exists in same header file. What's going wrong?
I am using CMAKE to build the project and CFLAGS are as follows:
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wextra")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-missing-braces")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-missing-field-initializers")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wformat=2")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wswitch-default")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wcast-align")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wpointer-arith")
#-Wno-deprecated-declarations to suppress the deprecation errors with newer version of JSON-C
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated-declarations")
#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wbad-function-cast")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wstrict-overflow=5")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Winline")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wundef")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wnested-externs")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-cast-qual")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wshadow")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wunreachable-code")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wfloat-equal")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wstrict-aliasing=2")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wredundant-decls")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wold-style-definition")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-parameter")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")
#set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} -O0 -g3 -ggdb")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -O3")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -E")
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.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With