Error: 'asm uneclared (use in this function first)

At compile time, I get the following error:

error: 'asm' undeclared (first use in this function) EXCHANGE( s, *(a) ); ^ 

in the header file, where the macro is invoked as follows:

 EXCHANGE( s, *(a) ); 

and the actual macro definition is as follows:

 #define EXCHANGE(R,M) asm volatile ( "xchg %1, %0" : "+m" (M), "+r" (R) ) 

The macro call and definition exist in the same header file. What's wrong?

I use CMAKE to create a project, and CFLAGS:

 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") 
+9
source share
3 answers

You are compiling with the -std=c99 option.

This disables some non-standard GCC extensions, such as the asm function.

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

Delete or modify the set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99") lines of the set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99") from your cmake file, if you need the built-in assembly.

+11
source

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 Alternative 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 problems when you want to use the GNU C extensions or the general-purpose header file that should be used by all programs, including the ISO C programs. The keywords asm, typeof and inline are not available in programs compiled with -ansi or -std (although inline may used in a program compiled with -std = c99 or -std = c11). The ISO C99 keyword restriction is only available if -std = gnu99 (which will eventually be used by default) or -std = c99 (or 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 at the end of each problematic keyword. For example, use __asm__ instead of asm and __inline__ instead of inline.

Other C compilers do not accept these alternative keywords; if you want to compile with another compiler, you can define alternative keywords as macros to replace them with regular keywords. It looks like this:

 #ifndef __GNUC__ #define __asm__ asm #endif 

-pedantic and other options trigger warnings for many GNU C extensions. You can prevent such warnings within a single expression by writing before the __extension__ expression. __extension__ has no influence other than this.

-std=gnu99 includes GNU extensions such as asm , but retains the C99 language.

Standard C99

GCC works to meet the C99 standard. From the draft standard C99 N1256 7.1.3 "Reserved identifiers" 1:

Each heading announces or defines all the identifiers listed in the associated subclause, and, optionally, declares or defines the identifiers listed in the corresponding subclause of the future directions of the library, and identifiers that are always reserved either for any use or for use as area identifiers file.

  • All identifiers that begin with an underscore, as well as a capital letter or other underscore, are always reserved for any use.

Otherwise, a legal program like:

 int asm = 0; 

will 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.

+6
source

asm is a gcc extension, so you cannot use flags like std=c99 or ansi

Read more https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html#C-Extensions

+3
source

Source: https://habr.com/ru/post/1241998/


All Articles