2024-08-05

「低レイヤを知りたい人のためのCコンパイラ作成入門」第一回勉強会まとめ

この振り返りの内容の目的としては、この振り返りをみたら勉強会の内容を思い出せるように、思い返しの手掛かりになるような振り返りを書くことです。

振り返りの形式について

勉強会の振り返りを書くにあたって記述の形式を非常に迷いました。
例えばただコピペするならほとんど価値はないし、メモの内容だけでは何をしたのかがわかりづらいからです。
価値のある振り返りにするために、自分の書き方でははじめにいくつか方針を決めておいて、その方針に従って書いていこうと思います。
以下の条件で書きはじめますが、何回か書いていくうちにアップデートされるのではないかと思います。

以下「低レイヤを知りたい人のためのCコンパイラ作成入門」を「本書」、この振り返り記事のことを「振り返り」と呼びます。

  • 本書の目的「C言語で書かれたソースコードをアセンブリ言語に変換するプログラム、つまりCコンパイラを作成」のために必要な振り返りのみをする。コラムや著者には言及しない。
  • 長々と振り返りをしてしまっては思い返すための手掛かりにならず、本書を読み返した方がよい。振り返りは手短に2000文字前後に収める。
  • 実際に手を動かして実行したコマンドが毎回あるはずなので、その振り返りを中心にする。理由としてはエピソード記憶の方が「付箋のような役割」になりやすいため。それ以外のまとめは先に箇条書きでかくので、それを見て思い出せなければ本書を読み返す。

勉強した範囲

はじめに(全て)〜機械語とアセンブラ(CPUとメモリ)

今回まとめ

  • 本書の目標はC言語で書かれたソースコードをアセンブリ言語に変換するプログラム(Cコンパイラ)を作成すること。そのために当面は、自作コンパイラでコンパイルできることを目標とする。最初の方は「独自言語」を実装して、その言語に機能を追加していってCと一致するものを作成していく。

  • 本書では細かいコミットをつくってコンパイラを作成していくが、どのコミットにおいてもコンパイラはある意味常に「完成形」になる。どの段階でも、その時点の完成度に合わせたリーズナブルな仕様の言語を目指す。

  • 「CPUとメモリ」の項コンピュータを構成するコンポーネントであるCPUとメモリについての説明している。下記の言語について説明があるので、わからない言葉があれば読み返す。

    • CPU,アドレス,プログラムカウンタ(PC),機械語,分岐命令,レジスタ,命令アーキテクチャ
  • 機械語は人間にとって扱いやすいものではないため、より読みやすいアセンブリ言語を開発した。アセンブリは機械語と1対1で対応している。アセンブルするとはアセンブリを機械語に変換することである。

所感&メモ

  • 「コンパイル」「アセンブル」が何を何に変換するものなのか、正確にわかっていた方がよさそう。ソースコード→アセンブリ言語に変換するのが「コンパイル」、アセンブリ言語→機械語に変換するのが「アセンブル」という(コンパイルと呼ぶときもあるらしい)
  • 「CPUとメモリ」の項は「CPU」や「プログラムカウンタ」などこれから繰り返し出てくる単語の説明があるので、わからなくなったらすぐ戻って読み直したほうが良さそう。井原さんの例えで言うと、メモリは食材を入れる冷蔵庫、レジスタはまな板、CPUは調理することに該当するらしい。
  • ある言語のコンパイルをするために、最初は別の言語でコンパイルする必要がある?らしい。コンパイルしている言語をコンパイルしていた言語・・・というふうに辿っていくと始祖言語にたどり着くという話が興味深かった。

実行したコマンド

objdump -d -M intel /bin/ls

何のコマンドか?

/bin/lsの内容をIntel形式のアセンブリ言語で表示するコマンド

コマンドの解説

objdump:指定したオブジェクトファイルの中身を表示するコマンド
-d:逆アセンブル(機械語をアセンブリに変換)して表示するオプション
-M intel:Intel形式のアセンブリ言語での出力を指定する

出力結果

$ objdump -d -M intel /bin/ls
/bin/ls:     file format elf64-x86-64

Disassembly of section .init:

0000000000003d58 <_init@@Base>:
  3d58:  48 83 ec 08           sub    rsp,0x8
  3d5c:  48 8b 05 7d b9 21 00  mov    rax,QWORD PTR [rip+0x21b97d]
  3d63:  48 85 c0              test   rax,rax
  3d66:  74 02                 je     366a <_init@@Base+0x12>
  3d68:  ff d0                 call   rax
  3d6a:  48 83 c4 08           add    rsp,0x8
  3d6e:  c3                    ret
...

3d58: 48 83 ec 08 sub rsp,0x8

3d58が機械語の入っているメモリのアドレス、その次に続いている4つの16進数の数値は実際の機械語、sub rsp,0x8というのは、その機械語命令に対応するアセンブリ。この命令は、RSPというレジスタから8を引く(subtract = 引く)という命令になる。