2016-07-08 7 views
3

私はGCCを使ってLinux環境でOS開発を学んでいます。 Branのカーネル開発では、コンパイルされたCの関数と変数名は、対応するアセンブリソースファイルの "_"(アンダースコア)に先行することが分かりました。 しかし、コンパイルされたCプログラムのアセンブリソースを調べると、 "_main"関数を見つけることさえできません。 私は次のことをしました。gccを使用してコンパイルすると、関数と変数の前に "_"が付きますか?

CPP SAMPLE.C sample.i

gccが初期の頃にそうでしたsample.I

+1

にあなたはユーザー空間のプログラムをコンパイル。どのように "カーネル"タグがその問題に関連していますか? – Tsyvarev

+0

最近のツール/ソフトウェアの最新のリソースを使用 – Olaf

答えて

5

を-S。与えられたC関数fooはアセンブラに_fooと表示されます。これは手で生成されたファイル.sとの衝突を避けるために行われました。

合計8文字に制限されます(リンカー制限)。

これは何十年も真実ではありません。今や、記号の先頭には_がなくなり、8文字をはるかに超えることがあります。


UPDATE:

だから、今日ではGCCは関数や変数の前に_を生成しないのですか?

ほとんどの場合、この時点であなたが引用している参考資料であるIMOは、少し古いと思われます。

ほとんどのPOSIXシステム(linux、* BSDなど)はgcc [またはclang]を使用し、_をそのまま使用します。

C [1981年]でプログラミングを始めたとき、まだ_が使用されていました。これはAT & T Unix v7、System III、およびSystem V.

IIRCであり、新しいシステム(Linuxなど)では1990年代初頭に廃止されました。個人的には、それ以来_という接頭辞がありませんでしたが、linux [と時にはcygwin]を使用しました。

いくつかのAT & T Unixから派生したシステムは、下位互換性のために残しているかもしれませんが、最終的には、 "foo is foo"で標準化されたほとんどの人がいます。私はOSXにアクセスできないので、それに関するJohnathanのコメントを除外することはできません。

_は、UNIX(1970年頃)の初期から周りを回っていました。これは私の時間の前であったが、IIRC、Unixはもともとアセンブラで書かれていた。それはCに変換されました。_は、C言語で書かれた関数、またはC言語関数から呼び出せる関数を定義することでした。

接頭辞を持たないものは[asmのみ] [非標準呼び出し規約を使用している可能性があります]でした。 RAM、CPUサイクルなど

したがって、asm関数はリソースを節約するために "トリック"を使うことができます。いくつかのasm関数は、お互いを知っていたのでグループとして機能することができました。

Cから特定のasm関数を呼び出すことができた場合、_というプレフィックス記号はCの「ラッパー」となっていました[prolog/epilogで余分なセーブ/リストアを行った]。

私はCプログラムのmain関数を "call_main"の代わりに "call main"と呼ぶことができますか?

これは合理的に安全な賭けです。

Cから特定の関数を呼び出す場合、自動的に正しいことが行われます(接頭辞を追加するかどうかなど)。

問題がかもしれないという手作りのアセンブラからC関数を呼び出そうとしているときだけです。

したがって、asmの場合、私は単純なことをしてcall mainを実行します。ほとんどの[すべてではないにしても]システム上で動作します。あなたは「証拠弾丸は」あなたのコードは、あなたが.Sファイルを経由して)Cプリプロセッサを通して、あなたのASMを実行して行うことができますしたい場合

(例):

#ifdef C_USES_UNDERSCORE 
#define CF(_x)   _##_x 
#else 
#define CF(_x)   _x 
#endif 

    call CF(main) 

はしかし、私はそれがだと思います過剰な

また、_という接頭辞の問題の全体を示しています。現代のシステム(メモリとCPUサイクルがたくさんある)では、アセンブラ関数は、呼び出し元のABI互換関数がCか手書きアセンブラから生成されたものかどうかを知る必要がありますか?

+2

プラットフォームによって異なります。 Mac OS Xでは、Cのソースファイル 'any_function 'をコンパイルします。オブジェクトファイルは、 'nm -g any_function.o'に従ったシンボル' _any_function'を含んでいます。 –

+0

今、GCCは関数と変数ri8の前に_を生成しませんか? –

+0

私はCプログラムのmain関数を "call_main" ri8ではなく "call main"と呼ぶことができますか? –

1

Craigによって詳述されているように、COFFやELFのような現代のフォーマットやABIはもはや追随しないという慣習です。

異なるABIを使用するターゲットによっては、まだ使用中です。 例としては、NeXT/OS XのMach-Oまたは16ビットおよび32ビットのWindowsがあります。 64ビットWindowsではアンダースコアが使用されなくなりました(ただし、GCCは4.5.1まではこれを続けていましたが)。

さらに、アンダースコアはより大きな接頭辞の一部として表示されることがあります。たとえば、(__declspec(dllimport)シンボル)または_Z(Itanium ABI)。

何らかの理由でマングリングに影響を与える必要がある場合、GCCは-f[no]leading-underscoreフラグを提供します。これにより、ABIとの互換性が損なわれます。


いくつかのリンク:レイモンド・チェン

  • x86 Calling Conventionsことで

  • 関連する問題