質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.51%
アセンブリ言語

アセンブリ言語とは、機械語を人間にわかりやすい形で記述した低水準言語です。

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

GCC

GCCはGNU Compiler Collectionの略です。LinuxのC言語コンパイラのデファクトスタンダードであり、数多くの他言語やプラットフォームサポートもします。

Q&A

解決済

3回答

4689閲覧

インライン展開される関数内でインラインアセンブラを使う方法

d50820dcb8bcb31

総合スコア11

アセンブリ言語

アセンブリ言語とは、機械語を人間にわかりやすい形で記述した低水準言語です。

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

GCC

GCCはGNU Compiler Collectionの略です。LinuxのC言語コンパイラのデファクトスタンダードであり、数多くの他言語やプラットフォームサポートもします。

1グッド

1クリップ

投稿2016/02/17 08:28

編集2016/02/17 08:31

下記のような、最適化によってインライン展開されるような関数内で、ラベルを含むインラインアセンブラを使うと、コンパイル時にラベル重複でエラーとなってしまいます。

c:

1#include <stdio.h> 2 3static int func(){ 4 __asm__("xxx:"); 5 return 0; 6} 7 8int main(){ 9 printf("%d\n", func()); 10 printf("%d\n", func()); 11 return 0; 12}
$ gcc -O1 hoge.c -o hoge # 少しでも最適化するとエラーになる hoge.c: Assembler messages: hoge.c:4: Error: symbol `xxx' is already defined $ gcc -O0 hoge.c -o hoge # -O0だとコンパイルできる $

最適化を-O0にしたり、関数func()を別の翻訳単位に移動してリンクしたりする以外に、これを回避する方法ってあるのでしょうか?
x64のLinuxと、GCC 4.9, 5.2で試しています。

tatsuya6502👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

こんにちは。

noinlineアトリビュートを付けるとインライン展開されなくなるようです。

C

1#include <stdio.h> 2 3__attribute__((noinline)) 4static int func(){ 5 __asm__("xxx:"); 6 return 0; 7} 8 9int main(){ 10 printf("%d\n", func()); 11 printf("%d\n", func()); 12 return 0; 13}

【追記】
インラインのまま通すためには、ラベルをユニークにする方法があれば良さそうですね。
そこで、「インラインアセンブラ ラベル」でググったら、ここがでました。
なんでも、ラベル名の後ろに"%="を付けると連番が追加されるとか。でも、ダメでした。

上記の回答者がリンクしているここをよく見ると、'%='と書かれてます!!
で、下記でうまくいくようです。

C

1static int func(){ 2 __asm__("xxx'%=':"); 3 return 0; 4}

アセンブラ出力をみると、両方ともxxx'%=':と出力されていますが、ビルドに通るのでアセンブルされる段階で連番に置き換わるのではないかと思います。

投稿2016/02/17 08:47

編集2016/02/17 12:30
Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

d50820dcb8bcb31

2016/02/17 08:54

コンパイル通りました~ ありがとうございます。 ただ、もしインライン展開するけど、エラーを出さない方法とかあれば興味がありますので、引き続きご回答を募集いたします。
Chironian

2016/02/17 12:23

なるほど。ちょっと思い立ったのでググッてみたらできました。 回答に追記します。
guest

0

使われているアセンブラがどれかわからないのですが、
気の利いたアセンブラなら、テンポラリラベルとか、特殊ローカルラベルがあったりするのですが
見当たりませんか?

例えば gas 系だと 0: ~ 9: がローカルラベルになってたりすることが多いんですけど・・・

ex)
1: jra 1f ; フォワード方向にある1:
2: jra 1b ; バック方向にある1:
1: jra 2f ; フォワード方向にある2:
2: jra 1b ; バック方向にある1:

こんな感じのありませんでしたか?

投稿2016/02/17 11:25

T.Kanno

総合スコア915

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

cateye

2016/02/17 11:50 編集

この場合は、ラベルそのものをインラインアセンブラとして定義しているので、__asm__("xxx:");を変更するのはまずいかと・・・数字だけのラベル(e.g. 123:)はOKですね。
d50820dcb8bcb31

2016/02/18 03:35

ありがとうございます。 数字だけラベルだと確かにコンパイル通りました。 セマンティクス的に若干気持ち悪いですが、インラインアセンブラはどうしても特定の命令を局所的に使うため以外には使う気は無いので、なんとかなりそうです。
guest

0

面白かったのでアセンブラソースを出してみましたd^^

asm

1~/test/ctst >cat *.s 2 .file "tst02.c" 3 .section .rodata.str1.1,"aMS",@progbits,1 4.LC0: 5 .string "%d\n" 6 .text 7 .globl main 8 .type main, @function 9main: 10.LFB2: 11 .cfi_startproc 12 subq $8, %rsp 13 .cfi_def_cfa_offset 16 14#APP 15# 4 "tst02.c" 1 16 xxx: 17# 0 "" 2 18#NO_APP 19 movl $0, %esi 20 movl $.LC0, %edi 21 movl $0, %eax 22 call printf 23#APP 24# 4 "tst02.c" 1 25 xxx: 26# 0 "" 2 27#NO_APP 28 movl $0, %esi 29 movl $.LC0, %edi 30 movl $0, %eax 31 call printf 32 movl $0, %eax 33 addq $8, %rsp 34 .cfi_def_cfa_offset 8 35 ret 36 .cfi_endproc 37.LFE2: 38 .size main, .-main 39 .ident "GCC: (FreeBSD Ports Collection) 4.9.4 20160203 (prerelease)" 40 .section .note.GNU-stack,"",@progbits 41~/test/ctst >

・・・2回呼ぶ事で同じラベルが出来てしまうようです。

c

1#include <stdio.h> 2 3static int func(){ 4 __asm__("xxx:"); 5 return 0; 6} 7 8int main(){ 9 printf("%d\n", func()); 10/* printf("%d\n", func());*/ 11 return 0; 12} 13

これなら通りますv^^

投稿2016/02/17 09:45

cateye

総合スコア6851

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.51%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問