Debian GNU/Linuxで自作OS

[自作OS Advent Calendar 2016](http://www.adventar.org/calendars/1666) 10日目の @Hiroyuki-Nagata です．
前の人は 川合さんでした（！），次の人は たぶん自分です．

# LinuxでOS自作入門していくことの位置づけ

まず、30日でできるOS自作入門の本はターゲットがWindows環境のため、それをそのままLinux環境で行うことは難しいです。以下の部分において、ツールをOSSのもので代用するか自作することがネット上ではよく見られます。

* アセンブラ　…　`nasm` か `gas` で代用
* リンカ … `ld` のリンカスクリプトを使う
* イメージファイル書き込みツール … 自作 or `mtools`、 `dd`とかでもできる？

OS自作入門は、OSを一から作るときの定石を用意してくれているという認識です。
この本が無ければそもそもの目標設定から難しかったでしょう。

# LinuxでOS自作入門していくための環境

次に、どのような道具を使ってOS自作していくかという話：

* エディタ
    * `Emacs`を使っています、`Vim`でもいいでしょう、`Atom`とかでもいいんじゃないでしょうか（適当）
* バイナリエディタ
    * `Emacs`の`hexl-mode`を使います
* バイナリをテキストにするコマンド
    * ここは結構重要です、アセンブラでオブジェクトファイルを作ったり、イメージファイルを出した後
    * 生のバイナリだとデバッグがしにくいので、以下のコマンドで16進数およびリトルエンディアンのファイルを出せます。
    * `$ od -t x1 hello.bin > hello.hex`

* Diffツール
    * こればっかりは`Emacs`のdiffが見づらいので、[meld](http://meldmerge.org/)というのを使っています
    * Osaskの本家サイトもしくはCDからバイナリ版のツールを取得して`wine`で実行、出てきたオブジェクトファイルを`od`にかけて自分の作ったバイナリと本家osaskの差分がどこにあるか見ます

* アセンブラ：`nasm` or `gas` 
    * `nask`はインテル記法なので気になるアセンブラの出力は`nasm`で同じものを書いてみて比較してみたりします
* `Qemu`
    * 最終的なイメージファイルを食わせて実行するために必要、Linuxだと `# apt-get install qemu` で入るから楽ですね

これだけ使い方を覚えてしまえば、後は本を読んでガリガリ書いていくだけです。

# わたしのOS自作入門

結局わたしは、「既存の`nask`形式ファイルは使いまわしたいけれど、`nask`は使いたくない」というわがままな希望で、`nask`を機能のみクローンしていくことにしました。やってみると非常につらい（勉強にはなるが）。そのへんの実装でわかった気づきも書きたいところですが。

* そこで作ったのが以下のリポジトリです
  * [HobbyOSs/opennask](https://github.com/HobbyOSs/opennask)


* 特徴
  * `C++`と`CMake`で出来てます
  * `C++`はC++11で設定してます
  * `CMake`のターゲット名を叩くと`osask`のproject以下のファイルを全部ビルドします（現状は５日目まで動作確認済み）
  * `CMake`を導入したのでAutotoolsよりだいぶビルドが早いです
  * 構文解析には[`Parasol`](http://www.awa.tohoku.ac.jp/~sanshiro/kinoko/parasol/) というオープンソースのライブラリを使いました
  * 数値計算は[`tinyexpr`](https://github.com/codeplea/tinyexpr)を使いました
  * Windows版のコマンドライン引数処理には[`takamin/win-c`](https://github.com/takamin/win-c)を使いました
  * 機能はもちろん`nask`を参考にしました、すみません

* 動作環境
    * 基本はLinux環境で動かします、`gcc-4.9`以上が推奨です
        * 開発環境は`Debian`ですが、`Ubuntu`でも普通に動くと思います、詳しくは[Travisの設定ファイル](https://raw.githubusercontent.com/HobbyOSs/opennask/master/.travis.yml)を見てください
    * Windowsビルドは`clang-cl`で回してますが、`mtools`のWindows対応をしてないので自作OSのファイルはビルドできません

* コメント
  * `C++`はクロスコンパイルしにくいので、どこかのタイミングでGO言語に書き換えたいと思ってます。GO言語に書き換えられれば、`Windows`, `Linux`, `Mac` 果ては `Plan9`, `Nacl`でも動くらしいので…
  * `opennask` 本体のファイルサイズは結構でかいと思います、ただし実装は平易なので読んだら機能がわかるんじゃないでしょうか
  * `yacc`や`peg`のような言語作成用ライブラリを使うべきだったと後悔している

## ビルドツールチェイン

以下が、いろいろ検討して作ったビルドの流れ図です。
![build-chain.png](https://qiita-image-store.s3.amazonaws.com/0/20634/321d009d-abb5-9fcf-0b0d-22d36e16902d.png)

* `obj2bim` はもともと`ld`のようなリンカと同じ動き（オブジェクトファイルをまとめる）をしています
    * `.bim`および`.hrb`はそれぞれ緻密な計算でファイルの形式が決まっています
    * `ld`は与えられたオブジェクトファイルをスクリプトで並べかえることができます
    * それを使って一気に`.hrb`形式に変換します

* `boot.bin`と`head.bin`は単純に`cat`でくっつけて`haribote.sys`とします
* `haribote.sys`を`mtool`でフロッピーディスクに書き込みます

## 振り返り

OS自作入門の流れを改めて確認してみます

✌('ω'✌ )三✌('ω')✌三( ✌'ω')✌　画面出るの楽しい！

### **１日目** フロッピーディスク相当のデータを手打ち  
画像ナシ

### **２日目** ブートローダーをアセンブラで書く  
画像ナシ

### **３日目** C言語とアセンブラの連携、リンカを使用する  
![harib00j.png](https://qiita-image-store.s3.amazonaws.com/0/20634/b445aeca-e937-cd4e-a91a-492a1a5a4caf.png)

### **４日目** かんたんな画面描画  
![harib01d.png](https://qiita-image-store.s3.amazonaws.com/0/20634/19b85e5f-f546-8d88-f479-d17bc20dbb46.png)

### **５日目** かんたんな画面描画＋文字描画  
![harib02a.png](https://qiita-image-store.s3.amazonaws.com/0/20634/1d8e0bbb-1465-ce5e-6786-e64f0138dc32.png)

# 今後の展望

* GO言語への移植（`yacc`や`peg`を使う）
* カーネルを書く  
* GUIのフレームワーク導入
* インターネット接続  ...etc.