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

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

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

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

C

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

GCC

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

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

Q&A

解決済

2回答

964閲覧

インラインアセンブリ "\ n->"#sym "%0" #val とは何なんですか?

kazuyakazuya

総合スコア193

アセンブリ言語

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

C

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

GCC

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

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

0グッド

0クリップ

投稿2020/04/11 18:31

編集2020/04/12 09:21

リンク内容

c

1 #define DEFINE(sym, val) \ 2 asm volatile("\n->" #sym " %0 " #val : : "i" (val))

上記のインラインアセンブリは一体なんですか?

①"\n->" #sym " %0 " #val
②: : "i" (val)

「1」
関連ありそう質問
コメントを見ると

"\n->" #sym " %0 " #val

上記自体が1つの文字列として要約されると書かれています。

リンク内容
"\n->" #sym " %0 " #val

"\n->""sym" "%0" "val"

だと思っていましたがやっぱ違いますよね?

「2」
関連ありそうな内容のリンクを貼りました。
すべて拝見しましたがよくわかりませんでした・・・。

: : "i" (val)

:"=i"(val)
:"i"(val)

にでもなるのかなと思っていましたが
PTXがなんちゃらとか書かれているので
やっぱ違うのでしょうか?

リンク内容
リンク内容
リンク内容

検索にかけて調べていたのですが結局成果は1つもなしで分からずじ終いに終わりました。
分からないので教えてください。

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

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

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

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

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

ikadzuchi

2020/04/12 05:28

コードは打ち直すのではなくコピー&ペーストしてください。 転記ミスがあると回答者が間違った問題を考えてしまい時間の無駄です。
kazuyakazuya

2020/04/12 08:37

>コードは打ち直すのではなくコピー&ペーストしてください。 どっかミスっていましたか? (すべてコピペのはずだけど・・・)
thkana

2020/04/12 08:52

少なくともCのプログラムで'、'とか'#'とかありえない。
ikadzuchi

2020/04/12 09:18

すべてコピペというのは質問内での話でしょうか。 そうではなく「リンク内容」のページからコピペしてほしいのです。 軽く見て全角文字になっている箇所とスペースの有無が異なる箇所が以下のようにあります。(あと2行目のインデントも無い) #define DEFINE全角(sym、val全角)\スペース asm volatile全角(スペース"\スペースn->"全角#sym "スペース無し全角%0スペース無し" #val全角:全角: "i"全角(val全角)全角)スペース×2 > これですか? それはコピペしたものですね。質問文もそのようにしていただきたいのです。
guest

回答2

0

ベストアンサー

Kbuildとセットで読む必要があります。

というのも、asm-offsets.cは通常の.cファイルと目的が違い
最終的に作りたいのはasm-offsets.hなのです。

そのために、インラインアセンブラの.s生成機能を文書生成機として用い
sedによって置換を行っています。


c

1DEFINE(TI_TASK, offsetof(struct thread_info, task)); 2DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));

s

1-> TI_TASK $0 offsetof(struct thread_info, task) 2-> TI_FLAGS $16 offsetof(struct thread_info, flags)

c

1#define TI_TASK 0 /* offsetof(struct thread_info, task) */ 2#define TI_FLAGS 16 /* offsetof(struct thread_info, flags) */

投稿2020/04/11 22:59

編集2020/04/15 10:31
asm

総合スコア15149

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

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

kazuyakazuya

2020/04/12 08:47

回答ありがとうございます。 正直今のところ言っている意味が分かりませんが まずそもそもKbuildとは何ですか? (今回の話とどう関係してくるのでしょうか?) 条件コンパイルみたいなものですか?
asm

2020/04/12 09:06

Kbuildはビルドスクリプトです。 Makefileのファイル名だけ変わったやつですね。
kazuyakazuya

2020/04/12 09:15

asm-offsets.h とは結局何をするためのものなんですか?
asm

2020/04/12 10:02

OSを作った場合 自作OSをコンパイルするホストと、自作OS上で動くターゲット 2つのコンパイラがあります。 sizeof(構造体)などの結果はホストのコンパイラに依存し場合によってはターゲットでのsizeof(構造体)とは別になることがあります。 というわけで、ホストコンパイラでそういった数値を計算させヘッダに定数としてまとめてるわけですね
kazuyakazuya

2020/04/12 10:37

今私はgccを使っていますがそれはホストコンパイラですよね? 逆にターゲットコンパイラとは具体的になんでしょうか? 仮に自作OSを作ったとして ホストコンパイラを使わずわざわざターゲットコンパイラを作って利用する理由がよく わからないです・・・。
asm

2020/04/12 11:47

セルフホスティングは機能のアピールとして有用だと思いますが。 失礼しました読み違えていたようです。 > Generate definitions needed by assembly language modules. ですので、この場合アセンブリ用の定義でした。
kazuyakazuya

2020/04/12 13:10

つまり、Kbuild以降の話は間違いで これらはただのプログラム実行用のマクロ定義ということですか?
asm

2020/04/12 14:22

ターゲットコンパイラの話は今回関係なかったということです。 Kbuildによってasm-offsets.cからasm-offsets.hが生成されているのは間違いありません。 ただのマクロ定義というのはあっているような間違っているような微妙な感じです。 確かに生成された.hファイル自体は単なる定数のマクロ定義といっていいですが .cファイルを主に見ていくと、コンパイラによる処理のあとに#define命令を生成しています。
kazuyakazuya

2020/04/13 02:27

追記された内容を見ると マクロ名DEFINE 引数は(要約) 1:定義したいマクロ名 2: 処理内容 構造体の要素のオフセット という感じで新たにプログラム内でマクロを定義できるもの(?)のように見えるのですが この理解は合っていますか?
asm

2020/04/13 02:46

プログラム内とは少し違うように思います。 あくまでも、「コンパイル」(と少しの後処理)することで「ヘッダ」を生成するための命令です。 DEFINE(TI_TASK, offsetof(struct thread_info, task)) ↓ (CPPによる置換) ↓ asm volatile("\n->TI_TASK %0 offsetof(struct thread_info, task)" : : "i" (offsetof(struct thread_info, task))) ↓ (gccによる.sへのコンパイル) ↓ -> TI_TASK 0 offsetof(struct thread_info, task) ↓ (sedによる文字列処理によって.hファイルを生成) ↓ #define TI_TASK 0 /* offsetof(struct thread_info, task) */ です。
kazuyakazuya

2020/04/13 02:57

では最後に・・・ DEFINE(TI_TASK, offsetof(struct thread_info, task)); ↓ #define TI_FLAGS 16 /* offsetof(struct thread_info, flags) */ 上記のようになるようですが https://elixir.bootlin.com/linux/v2.6.17.8/source/Kbuild これをどのように見れば上記のように置き換えられるのですか?
asm

2020/04/13 05:01

まず、 arch/$(ARCH)/kernel/asm-offsets.s: arch/$(ARCH)/kernel/asm-offsets.c FORCE この行の意味は、asm-offsets.cからasm-offsets.sを作る という意味です。 次に $(obj)/$(offsets-file): arch/$(ARCH)/kernel/asm-offsets.s Kbuild とあるので同様に offsets-file := include/asm-$(ARCH)/asm-offsets.h がasm-offsets.sから作られています。 .c→.sについては、/scripts/Kbuild.includeや/scripts/Makefile.buildを読んだりと大変な割に $(call if_changed_dep,cc_s_c)から想像できる「.cが変化してたら$(CC)を用いて.sへコンパイル」と大差ないので省略します。 .s→.hは$(call cmd,offsets)によってcmd_offsetsが呼び出され cmd_offsetsで、sed -ne $(sed-y) $<; によって依存ファイル(.s)から "/^->/{s:^->([^ ]*) [$$#]*([^ ]*) (.*):#define \1 \2 /* \3 */:; s:->::; p;}" で正規表現による置換を行った結果として #define ~ になっています。
kazuyakazuya

2020/04/13 06:59 編集

(書き方悪かったので再度) Kbuildというカーネルをビルドするためのコマンド集(・・・?)があり -> TI_TASK 0 offsetof(struct thread_info, task) ここまで展開された式がそのsedコマンドによってさらに以下のように展開されるということですよね? #define TI_TASK 0 最初から#define TI_TASK 0 このように定義していればsedコマンドを使わずに済む気がするのですが どうしてもsedコマンドを使わなければいけない理由でもあるのでしょうか?
asm

2020/04/13 09:52

0というのはoffsetof(struct thread_info, task)の結果です。 その結果を得るためにはCコンパイラによる計算が必要です。 そして、Cコンパイラはhファイルへ出力するようにはできていません。
kazuyakazuya

2020/04/15 03:22

つまり・・・ コンパイルのより先にプリプロセッサによりマクロの置き換えが行われるから offsetofの結果に応じてマクロを定義することができない。 から~・・・という感じですか? (sedによる文字列処理によって.hファイルを生成) ↓ #define TI_TASK 0 /* offsetof(struct thread_info, task) */ このsedによる文字の置き換えで具体的に何を置き換えているんですか?
asm

2020/04/15 04:06

> offsetofの結果に応じてマクロを定義することができない。 そうです。 .sファイルに出力された「-> TI_TASK 0 offsetof(struct thread_info, task)」といった文字列を 「#define TI_TASK 0 /* offsetof(struct thread_info, task) */」に置換したものを集めています。
kazuyakazuya

2020/04/15 07:00

DEFINE(TI_TASK, offsetof(struct thread_info, task)) ↓ (CPPによる置換) ↓ asm volatile("\n->TI_TASK %0 offsetof(struct thread_info, task)" : : "i" (offsetof(struct thread_info, task))) ↓ (gccによる.sへのコンパイル) ↓ -> TI_TASK 0 offsetof(struct thread_info, task) ↓ (sedによる文字列処理によって.hファイルを生成) ↓ #define TI_TASK 0 /* offsetof(struct thread_info, task) */ プリプロセッサによる置換は asm volatile("\n->TI_TASK %0 offsetof(struct thread_info, task)" : : "i" (offsetof(struct thread_info, task))) この時点で行われているから 新たに#define TI_TASK 0 を定義しても意味ない気がするのですが どういった手順で置換されるのでしょうか?
asm

2020/04/15 08:26

> 新たに#define TI_TASK 0 を定義しても意味ない気がするのですが いいえ、新たに #define TI_TASK 0 が定義されているasm-offsets.hが生成されます。 それを、別のソースからincludeする事で使うことができます。
kazuyakazuya

2020/04/15 09:22

既にプリプロセッサに置換されたあとに #defineでマクロ定義しても意味ないのではないか?ということです
asm

2020/04/15 10:06

生産したasm-offsets.hを、別のソースから#includeします。 asm-offsets.cとは関係ないのでCPPからやり直しです。(#includeの時点でCPP必要ですが)
kazuyakazuya

2020/04/15 10:39 編集

なんか前提から認識がおかしい部分があると思うのですが・・・ asm-offsets.hに#define TI_TASK 0が定義されると思うのですが プリプロセッサによる置換はいつ行われているんですか? (CPPによる置換) ↓ asm volatile("\n->TI_TASK %0 offsetof(struct thread_info, task)" : : "i" (offsetof(struct thread_info, task))) それとも その後ですか?
asm

2020/04/15 16:28

asm-offsets.cのコンパイルとしては、そのCPPによる置換という部分がプリプロセッサによる置換で正しいです。 asm-offsets.hとしては、それを利用するソースのコンパイル時なのでその後です。
guest

0

c

1// gen.c 2#define DEFINE(sym, val) \ 3 asm volatile("\n->" #sym " %0 " #val : : "i" (val)) 4 5#define BLANK() asm volatile("\n->" : : ) 6 7void foo(void) 8{ 9 DEFINE(SIZE_PTR, sizeof(void*)); 10}

gcc -fverbose-asm -S gen.c -o gen.s

結果

asm

1 .file "gen.c" 2 # GNU C17 (GCC) version 9.1.0 (x86_64-pc-msys) 3 # compiled by GNU C version 9.1.0, GMP version 6.1.2, MPFR version 4.0.2, MPC version 1.1.0, isl version isl-0.21-GMP 4 5 # warning: GMP header version 6.1.2 differs from library version 6.2.0. 6 # GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 7 # 渡されたオプション: 8 # -idirafter /usr/lib/gcc/x86_64-pc-msys/9.1.0/../../../../lib/../include/w32api 9 # -idirafter /usr/lib/gcc/x86_64-pc-msys/9.1.0/../../../../x86_64-pc-msys/lib/../lib/../../include/w32api 10 # gen.c -mtune=generic -march=x86-64 -auxbase-strip gen.s -fverbose-asm 11 # 有効オプション: -faggressive-loop-optimizations -fassume-phsa 12 # -fasynchronous-unwind-tables -fauto-inc-dec -fcommon 13 # -fdelete-null-pointer-checks -fdwarf2-cfi-asm -fearly-inlining 14 # -feliminate-unused-debug-types -ffp-int-builtin-inexact -ffunction-cse 15 # -fgcse-lm -fgnu-runtime -fgnu-unique -fident -finline-atomics 16 # -fipa-stack-alignment -fira-hoist-pressure -fira-share-save-slots 17 # -fira-share-spill-slots -fivopts -fkeep-inline-dllexport 18 # -fkeep-static-consts -fleading-underscore -flifetime-dse 19 # -flto-odr-type-merging -fmath-errno -fmerge-debug-strings -fpeephole 20 # -fpic -fplt -fprefetch-loop-arrays -freg-struct-return 21 # -fsched-critical-path-heuristic -fsched-dep-count-heuristic 22 # -fsched-group-heuristic -fsched-interblock -fsched-last-insn-heuristic 23 # -fsched-rank-heuristic -fsched-spec -fsched-spec-insn-heuristic 24 # -fsched-stalled-insns-dep -fschedule-fusion -fsemantic-interposition 25 # -fset-stack-executable -fshow-column -fshrink-wrap-separate 26 # -fsigned-zeros -fsplit-ivs-in-unroller -fssa-backprop -fstdarg-opt 27 # -fstrict-volatile-bitfields -fsync-libcalls -ftrapping-math 28 # -ftree-cselim -ftree-forwprop -ftree-loop-if-convert -ftree-loop-im 29 # -ftree-loop-ivcanon -ftree-loop-optimize -ftree-parallelize-loops= 30 # -ftree-phiprop -ftree-reassoc -ftree-scev-cprop -funit-at-a-time 31 # -funwind-tables -fverbose-asm -fzero-initialized-in-bss 32 # -m128bit-long-double -m64 -m80387 -maccumulate-outgoing-args 33 # -malign-double -malign-stringops -mavx256-split-unaligned-load 34 # -mavx256-split-unaligned-store -mfancy-math-387 -mfentry -mfp-ret-in-387 35 # -mfxsr -mieee-fp -mlong-double-80 -mmmx -mno-sse4 -mpush-args -mred-zone 36 # -msse -msse2 -mstack-arg-probe -mstackrealign -mvzeroupper 37 38 .text 39 .globl foo 40 .def foo; .scl 2; .type 32; .endef 41 .seh_proc foo 42foo: 43 pushq %rbp # 44 .seh_pushreg %rbp 45 movq %rsp, %rbp #, 46 .seh_setframe %rbp, 0 47 .seh_endprologue 48 # gen.c:8: DEFINE(SIZE_PTR, sizeof(void*)); 49/APP 50 # 8 "gen.c" 1 51 52->SIZE_PTR $8 sizeof(void*) # 53 # 0 "" 2 54 # gen.c:9: } 55/NO_APP 56 nop 57 popq %rbp # 58 ret 59 .seh_endproc 60 .ident "GCC: (GNU) 9.1.0"

ここから、行頭の->を目印に抽出して置換し

c

1// gen.h 2#define SIZE_PTR 8 /* sizeof(void*) */

を作り

asm

1# other.S 2#include "gen.h" 3push SIZE_PTR

gcc -c other.S (拡張子が大文字のSな事に注意)

的に使います。

投稿2020/04/15 16:52

asm

総合スコア15149

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

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

kazuyakazuya

2020/04/16 01:26

ということはアセンブルした段階でsizeofの結果が出ているということですか?
asm

2020/04/16 03:38

そうですね。
kazuyakazuya

2020/04/16 09:40

実際にやってみてできました。 詳しく対応していただきありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問