web-dev-qa-db-ja.com

エラー:「asm」が宣言されていません(この関数での最初の使用)

コンパイル中に次のエラーが発生します。

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")
10
Black_Zero

オプション_-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")を削除または変更します。

11
undur_gongor

__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=c99ansiなどのフラグと一緒に使用することはできません。

詳細については https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html#C-Extensions

3
dlmeetei