コンパイル中に次のエラーが発生します。
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
_を使用してコンパイルしています。
これにより、asm
機能などの一部の非標準GCC拡張機能が無効になります。
一部の(あまり正確ではない)ドキュメントについては、 https://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html#index-std-112 を参照してください。
インラインアセンブリが必要な場合は、cmakefileから行set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")
を削除または変更します。
__asm__
でasm
の代わりに-std=c99
を使用するか、-std=gnu99
を使用します
GCCドキュメントから https://gcc.gnu.org/onlinedocs/gcc-7.2.0/gcc/Extended-Asm.html
AsmキーワードはGNU拡張子です。-ansiおよびさまざまな-stdオプションを使用してコンパイルできるコードを作成する場合は、asmの代わりに
__asm__
を使用してください(代替キーワードを参照)。
および https://gcc.gnu.org/onlinedocs/gcc-7.2.0/gcc/Alternate-Keywords.html#Alternate-Keywords :
-ansiおよびさまざまな-stdオプションは、特定のキーワードを無効にします。これにより、GNU C拡張子、またはISO Cプログラムを含むすべてのプログラムで使用できる汎用ヘッダーファイルを使用する場合に問題が発生します。キーワードasm、typeof、およびinlineは使用できません。 -ansiまたは-stdでコンパイルされたプログラムで使用可能(ただし、インラインは-std = c99または-std = c11でコンパイルされたプログラムで使用できます)。ISOC99キーワードrestrictは、-std = gnu99(最終的にはデフォルト)または-std = c99(または同等の-std = iso9899:1999)、またはそれ以降の標準バージョンのオプションが使用されます。
これらの問題を解決する方法は、問題のある各キーワードの最初と最後に
__
を配置することです。たとえば、asmの代わりに__asm__
を使用し、インラインの代わりに__inline__
を使用します。他のCコンパイラは、これらの代替キーワードを受け入れません。別のコンパイラでコンパイルする場合は、代替キーワードをマクロとして定義して、通常のキーワードに置き換えることができます。次のようになります。
#ifndef __GNUC__ #define __asm__ asm #endif
-衒学者やその他のオプションにより、多くのGNU C拡張機能に対して警告が発生します。式の前に
__extension__
を書き込むことで、1つの式内でこのような警告を防ぐことができます。__extension__
は効果がありません。これから。
-std=gnu99
は、言語C99のようなものを維持しながら、GNU asm
などの拡張機能を有効にします。
C99標準
GCCは、C99標準に準拠するためにこのように機能します。 C99 N1256標準ドラフト 7.1.3「予約済み識別子」から1:
各ヘッダーは、関連する副節にリストされているすべての識別子を宣言または定義し、オプションで、関連する将来のライブラリ方向の副節にリストされている識別子と、任意の使用またはファイルスコープ識別子としての使用のために常に予約されている識別子を宣言または定義します。
- アンダースコアで始まり、大文字または別のアンダースコアのいずれかで始まるすべての識別子は、常に使用のために予約されています。
それ以外の場合は、次のような法的プログラム:
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、GCC7.2でテスト済み。
asm
はgcc拡張であるため、std=c99
やansi
などのフラグと一緒に使用することはできません。
詳細については https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html#C-Extensions