error: ‘asm’ undeclared (first use in this function)
error: ‘asm’ undeclared (first use in this function)
我在编译过程中遇到以下错误:
error: ‘asm’ undeclared (first use in this function)
EXCHANGE( s, *(a) );
^
在调用宏的头文件中,如下所示:
EXCHANGE( s, *(a) );
而宏的实际定义如下:
#define EXCHANGE(R,M) asm volatile ( "xchg %1, %0" : "+m" (M), "+r" (R) )
宏调用和定义存在于同一个头文件中。
怎么了?
我正在使用CMAKE构建项目,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")
您正在使用选项 -std=c99
进行编译。
这会禁用一些非标准的 GCC 扩展,例如 asm
功能。
请参阅 https://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html#index-std-112 了解一些(不是很精确的)文档。
如果您需要内联汇编,请从您的 cmakefile 中删除或更改行 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")
。
asm
是 gcc 扩展,因此您不能使用 std=c99
或 ansi
等标志
更多详细信息,请访问
https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html#C-Extensions
要么使用 __asm__
而不是 asm
和 -std=c99
,或者使用 -std=gnu99
来自 GCC 文档 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).
和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
启用 GNU 扩展,例如 asm
,同时仍保持类似 C99 的语言。
C99 标准
GCC 这样工作以符合 C99 标准,该标准将双下划线符号标记为保留。
来自C99 N1256 standard draft 7.1.3“保留标识符”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.
否则,如果预定义了 asm
,则合法程序如:
int asm = 0;
会变成非法的。
测试程序
#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);
}
在 Ubuntu 17.10,GCC 7.2 上测试。
我在编译过程中遇到以下错误:
error: ‘asm’ undeclared (first use in this function)
EXCHANGE( s, *(a) );
^
在调用宏的头文件中,如下所示:
EXCHANGE( s, *(a) );
而宏的实际定义如下:
#define EXCHANGE(R,M) asm volatile ( "xchg %1, %0" : "+m" (M), "+r" (R) )
宏调用和定义存在于同一个头文件中。 怎么了?
我正在使用CMAKE构建项目,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")
您正在使用选项 -std=c99
进行编译。
这会禁用一些非标准的 GCC 扩展,例如 asm
功能。
请参阅 https://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html#index-std-112 了解一些(不是很精确的)文档。
如果您需要内联汇编,请从您的 cmakefile 中删除或更改行 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")
。
asm
是 gcc 扩展,因此您不能使用 std=c99
或 ansi
更多详细信息,请访问 https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html#C-Extensions
要么使用 __asm__
而不是 asm
和 -std=c99
,或者使用 -std=gnu99
来自 GCC 文档 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).
和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
启用 GNU 扩展,例如 asm
,同时仍保持类似 C99 的语言。
C99 标准
GCC 这样工作以符合 C99 标准,该标准将双下划线符号标记为保留。
来自C99 N1256 standard draft 7.1.3“保留标识符”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.
否则,如果预定义了 asm
,则合法程序如:
int asm = 0;
会变成非法的。
测试程序
#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);
}
在 Ubuntu 17.10,GCC 7.2 上测试。