PowerUpを使ってC#のアセンブラを見る
PowerUpを使うとC#のコンパイル結果であるILやJITアセンブラを見る事が出来ます。SharpLabのオフライン版のようなイメージです。
PowerUpはもともとLevelUP++というサイトの画像を作成するために作られており、アセンブラを見やすく出力する機能がついています。SharpLabよりもかなり見やすくなるのでおすすめです。
また、C#だけでなくGo言語でも使えるようですがこの記事では説明しません。
使ってみる
まずPowerUpはexe形式では配布されていないので自分でビルドする必要があります。GitHubからソースコードをダウンロードします。slnファイルが入っているのでVisualStudioで開いてPowerUp.Watcherプロジェクトをビルドします。「PowerUp.Watcher.exe」というファイルが生成されていればOKです。
とりあえず簡単なcsファイルを用意します。次のコードを「PowerUp.Watcher.exe」とおなじフォルダにcode.csという名前で保存しておきます
int Add(int a, int b)
{
return a + b;
}
そしてコマンドラインでそのフォルダをで開いて次のコマンドを実行します。
PowerUp.Watcher.exe -cs code.cs out.asm out.il
これでcode.csのアセンブラがout.asm、ILがout.ilというファイルに出力されます。
もし「Cannot find the libs under Path: C:\Program Files\dotnet\shared\Microsoft.NETCore.App\5.0.10」のようなエラーが出力される場合は対応するSDKがインストールされていません。この場合は.NET 5.0.10のSDKをインストールすれば動きます。
PowerUp.Watcher.exeが実行されている間、code.csが更新されれば自動的にout.asmとout.ilも更新されます。なので実際に使うときはまずPowerUp.Watcher.exeを実行しておき、VSCodeなどでcode.csとout.asmとout.ilを横に表示しておきます。これでcode.csを書き換えるたびに横にコンパイル結果が自動的に表示される環境がつくれます。
このcode.csではMainメソッドやそのクラスは省略してAddメソッドを直接書いています。PowerUpではそれらは自動的に用意されるので自分で書く必要はありません。
out.ilでは自分で書いたメソッドの中身だけ出力されていましたが、out.ilの方では自動生成されたコードのILも含まれるので少し見づらいです。メソッド名などで検索して該当の箇所を探して見る必要があります。
アセンブラ出力を見やすくする
PowerUpでは属性を付けることでアセンブラを見やすく出力できます。
ShowASMDocs属性
ShowASMDocs属性を付けるとアセンブラの横に対応する擬似コードを出力してくれます。
ShowASMDocs属性ではoffsetで擬似コードのオフセットを指定できます。少し読みやすくなります。
ShowGuides属性
ShowGuides属性を付けるとジャンプする箇所が分かりやすいようにガイドを付けてくれます。
ジャンプが増えてもかなり追いやすくなります。
ShortAddr属性
ShortAddr属性でアドレスとして表示される文字数を減らせます。byで省略する文字数を指定します。
[ShortAddr(by=8)]によってアドレスの上位8文字が省略されて4文字だけで表示されるようになりました。
Hide属性
PowerUpでは複数のメソッドを書けます。
Hide属性を付けるとそのメソッドの中身が省略されなくなります。
実行する
Run属性
Run属性を付けるとそのメソッドを実行できます。また、Printメソッドに変数を渡すとその変数を出力できます。
Inline, NoInline属性
先ほどのコードはAddの呼び出しがインライン化されてアセンブラ上ではAddメソッドが呼ばれていません。
NoInline属性は[MethodImpl(MethodImplOptions.NoInlining)]の省略表記です。これによってインライン化されないように指定できます。
Inline属性は[MethodImpl(MethodImplOptions.AggressiveInlining)]の省略表記です。こちらは必ずインライン化される保証はありませんがインライン化されやすくなります。
Bench属性
Bench属性を付けると簡易的に実行速度を測れます。
WarmUpCountとRunCountでそれぞれウォームアップで実行する回数と計測で実行する回数も指定できます。省略するとどちらも1000になります。
メモリレイアウトを出力する
classやstructを書くとそのメモリレイアウトを出力してくれます。
まとめ
PowerUpでは特にアセンブラを整形して出力する機能が強力です。複雑でよく分からないアセンブラも読めるようになるかもしれません。本来の用途であるブログに載せる画像を作るのにも便利そうなので活用していきたいです。