30日でできる! OS自作入門 を読むために nasm_of_nask というコンパイラを作った話

この記事は はてなエンジニア Advent Calendar 2020の22日目の記事です。 昨日はid:motemen さんの PCを離れたらマイク音量を下げるmacOSアプリを作った - 詩と創作・思索のひろば でした!

qiita.com

経緯

とこぼしたところ、著者の 川合秀実 (@hkawai3) | Twitter さん*1 を始めとした各種大先生に目をつけられて*2しまい、やらなければ肉体が低レイヤから順に消されると思い読み始めました。

30日でできる! OS自作入門

30日でできる! OS自作入門

しかし、この本の初版は2006年であり時代はフロッピィ〜〜〜〜〜〜から†SSD†なわけで、macOS上で動かすための環境構築はqemuを使ったり、本の中で使われているツールのmacOS版を用意する必要があります。

github.com

このように、以前までは有志が用意をしてくれていたので何とかなっていました。あのOSが出るまでは。

macOS Catalina

macOS Catalinaからついに32ビットアップリが使えなくなりました。これの影響で上記のリポジトリで提供されているnaskを使おうとするとbad CPU type in executableするわけです。

代替手段としてのNASM

naskの代替手段としてはNASMを使ったりすると良いらしいです。しかし、naskとNASMはコンパチではないのでいくつかサンプルコードを修正する必要があります。

『30日でできる!OS自作入門』を macOS Catalina で実行する - Qiita から修正する表を引用したものがこちらです。

nask NASM
RESB 18 TIMES 18 DB 0
RESB 0x7dfe-$ TIMES 0x1fe-(−−$) DB 0
ALIGNB 16 ALIGN 16, DB 0
[FORMAT "WCOFF"] この行削除
[INSTRSET "i486p"] この行削除
[FILE "naskfunc.nas"] この行削除
[FORMAT "WCOFF"] この行削除
JMP entry JMP SHORT entry
_io_hlt( _ の付くもの) io_hlt( _ を削除)

な〜〜〜んだこれだけなんだ!簡単ですね!!!

しかし

この表を一々頭に覚えるのはめんどくさい、めんどくさいですよね?*3いっそのことnaskを作り直すのもいい*4が、多分その時間でこの本読み切れるな、という葛藤がありました。そこで僕なりのアプローチとして 「「「nask のコンパイリ*5を受け取って NASM にコンパイルするだけのめちゃくちゃ簡単なコンパイラ」」」を書けばいいんじゃないか?と思って用意したものがこちらになります。

nasm_of_nask

github.com

最近は趣味でocamllexとmenhirばっか書いてたし、OCamlと仲良くなりたかったので実装言語に選びました。本質っぽいところはここでそれ以外はまんまを吐き出す本当にやるだけのコンパイラです。命名規則OCaml の型変換関数 *6 をリスペクト*7しました!ℒℴѵℯ...

対応状況

対応してる共通部

  • DB
  • DW
  • DD
  • RESB
  • 16進数
  • 10進数
  • 文字列(エスケープ無し)
  • セミコロンを使ったコメント

naskとNASMの差分

nask NASM 対応してる?
RESB 18 TIMES 18 DB 0
RESB 0x7dfe-$ TIMES 0x1fe-(−−$) DB 0
ALIGNB 16 ALIGN 16, DB 0 ×
[FORMAT "WCOFF"] この行削除 ×
[INSTRSET "i486p"] この行削除 ×
[FILE "naskfunc.nas"] この行削除 ×
[FORMAT "WCOFF"] この行削除 ×
JMP entry JMP SHORT entry ×
_io_hlt( _ の付くもの) io_hlt( _ を削除) ×

Future work

  • 対応増やす
  • CIとかでいい感じにバイナリをビルドする
    • これから始める全人類がnaskの代わりにこれとnasmを使うコバンザメ戦法したい

締め

気づいた方は5000人ぐらいいらっしゃるとは思いますが、id:Krouton は1日目で出てくる差分しかやっていません。何故かと言えばまだ1日目しか読んでない*8からです!ガハハ!

オチもついたところで解散とします!明日の担当はid:pokutunaさんです!!

*1: 川合さんへ: 1年以上関わりがあるのにずっと読む読む詐欺しててすみません!!!!!

*2: ふぁぼられただけです、所でふぁぼって死語ですか?

*3: この記事書いてから気づいたんですけど、そんなに多くないな...

*4: DB命令だけ使えるnaskなら書けそう

*5: この人生が裏目りやすい!2021 on Twitter: "caller-callee-callの関係を考えればコンパイラ-コンパイリ-コンパイルの関係も自明"

*6:OCamlプリミティブな型変換関数は to_of_from といった命名規則が多い。例えば int から char だったら char_of_int みたいな

*7: 世の中にはOCaml から JSを吐く処理系もある GitHub - ocsigen/js_of_ocaml: Compiler from OCaml to Javascript.

*8: 参加してる読書会が2つあるのに気づいてそっちをやらないと本当にまずい