assembly記事は、WebAssemblyを“概念機械の命令”として理解する入口になる

Mozilla Hacks記事紹介シリーズのアイキャッチ画像

執筆者:

カテゴリ:

Mozilla Hacksの「A crash course in assembly」を読みました。Lin Clark氏によるWebAssembly解説シリーズの第3回で、WebAssemblyそのものに入る前に、assemblyとは何か、コンパイラが高水準言語をどのように機械に近い表現へ落としていくのかを整理する記事です。

前回のJITコンパイラの記事では、JavaScriptエンジンが実行中の情報を使って最適化する仕組みが扱われていました。今回の記事は、その「最終的に機械が理解する形」とは何かに踏み込みます。

記事の要点

  • CPUの中には、計算を担うALU、短期的な値を置くレジスタ、長期的な値を置くRAMのような役割分担があります。
  • 機械語の命令は、opcodeのような「何をするか」を示す部分と、どのレジスタを使うかを示す部分などに分かれます。
  • assemblyは、機械語を人間が読みやすくするためのsymbolic machine codeです。
  • ただし「機械語」は1種類ではなく、x86やARMなどアーキテクチャごとに異なります。
  • そのため、C、C++、Rustなどの高水準言語から各CPU向けassemblyへ直接すべて変換しようとすると組み合わせが増えすぎます。
  • そこで多くのコンパイラは、中間表現(IR)を挟みます。フロントエンドが高水準言語をIRへ変換し、バックエンドがIRを対象アーキテクチャ向けのassemblyへ変換します。

リンク先も見てわかったこと

シリーズ冒頭の「A cartoon intro to WebAssembly」では、WebAssemblyはJavaScriptの置き換えではなく、JavaScriptと併用される実行形式として説明されていました。今回のassembly記事を挟むと、その説明がより具体的になります。WebAssemblyは「別の言語をブラウザで動かす」だけでなく、「CPUごとの違いを直接ユーザーへ配布しないための中間的な実行形式」として見えてきます。

さらに次の「Creating and working with WebAssembly modules」を読むと、WebAssemblyはx86やARMのような特定の物理CPU向けassemblyではなく、概念上の機械に向けた形式として説明されています。assembly記事でIRとバックエンドの役割を理解しておくと、WebAssemblyがどの位置に差し込まれるのかがかなり見えやすくなります。

記事中のRustWebAssemblyへのMozilla Researchリンクは、現在のページ取得では内容を確認しきれませんでしたが、文脈としてはC/C++/Rustのような言語を対象アーキテクチャへ翻訳する話に接続されています。

気づき

今回の気づきは、WebAssemblyを理解するには「JavaScriptより速い形式」と見るだけでは足りず、「配布時点では特定CPUに固定しない命令形式」と見る必要があるという点です。assemblyは物理的な機械の都合に近い表現ですが、Webでは実行先のCPUを事前に決められません。だからこそ、WebAssemblyは特定CPUのassemblyではなく、ブラウザが各環境の機械語へ短く橋渡しできる形式として設計されている。

この見方をすると、IRの話も単なるコンパイラ内部の実装詳細ではなくなります。高水準言語、IR、WebAssembly、実機の機械語という段階を分けることで、開発者、配布形式、ブラウザ、CPUそれぞれの責務が分離されます。WebAssemblyの実用性は、この責務分離のうまさにも支えられているのだと思いました。

読むとよさそうな人

  • WebAssemblyの前提としてassemblyや機械語の位置づけをつかみたい人
  • opcode、レジスタ、ALU、IRといった用語をざっくり整理したい人
  • なぜWebAssemblyが特定CPU向けのバイナリではないのかを理解したい人

参照した記事

コメント

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です