/Fa"アセンブリファイル名"
と /Fm"マップファイル名"
をちょっとしたプログラムのコンパイル時に付けてみた。■アセンブリファイルは .obj と内容的に一致するものかな。ファイル名とか行数とか関数名がコメントとして付加されてるので、まずは関数のサイズが行数として把握できる。処理の内容はまあだいたいがスタックの上げ下げ、比較、ジャンプ、call, ret. こういう目立つ定型部分が高級言語の構成要素になるのでしょう。■マップファイルは .dll に対応するものだと思う。オプションを何もつけずにコンパイルしていたら一切の最適化がオフで(これをアセンブリファイル内のコメントで知った)、inline 指定していた関数の名前がすべてマップファイルの中に現れていてぎょっとした。そういうことがわかる。関数を単位とした .obj やアセンブリ(リスティング)ファイルの中身から、何が関数としてそのまま抜き出されたか、何がインライン化され無名のコードとして埋め込まれたかがわかる。インライン化はリンカの標準的な仕事とは違う気もするけどリンク時コード生成が有効だったのかも。並びとアドレスの差から関数のサイズもだいたいわかる。サイズ優先の最適化フラグを付けると、小さい関数間に最低限確保されていた間隔が短く詰められたんだけど、配置の間隔とその他の都合にどういう関係があるのか。■サイズ優先でコンパイルすると POD構造体のゼロ初期化(= {};
)に memset が使われるようになって、/NODEFAULTLIB を指定していたもんだからリンクエラーになる。自分が Cランタイムライブラリを使わないように気をつけていても、コンパイラが使ってしまう(ことがある)。どないせーと? 初期化しないでメンバのひとつひとつに代入したら memset を使わせないで済んだけど、なんだかなあ。memset だけ自作してリンクしたらよかったんか。自作せずにコンパイラの実装から memset だけ抜き出したりはできないのか。■@2018-10-29 GCC のドキュメントからそのものズバリ「The compiler may generate calls to memcmp, memset, memcpy and memmove. These entries are usually resolved by entries in libc. These entry points should be supplied through some other mechanism when this option is specified.」