gccのみでOS自作入門

2014-02-11

haribote

OSを作りたくて「OS自作入門」本を以前試してたんだけど、WindowsじゃなくてMacでやろうとしたところ、3章のC言語を導入するところで躓いてしまい、放置していた。

これはMacで使われているgccでコンパイルしたオブジェクトファイルからバイナリを取り出す方法がわからなかったのが原因だった。

それならと、Linux系OS上のgccならばリンカスクリプトも受け付けて直のバイナリを取り出すことができるのでやってみた。アセンブラもgccのもの(gas)を使うようにした。

VirtualBoxでLinux系OSを動かす

普段Macを使っていて手元にLinux系のマシンを持ってないんだけど、OS開発にエミュレータを使うこともあり、ついでにとエミュレータ上でLinux系OSを走らせて、その上で自作OSの開発を行うことにした。

使っているエミュレータはVirtualBoxで、使ったゲストOSはUbuntu。動かし方はいろいろググればできるはず。

しかし実際のところ、キーボード操作がMacに慣れてしまっていてCommandキーがないと死んじゃう派で、Ubuntuのデスクトップ画面とか使いたくない。なのでゲストOSのウィンドウからは操作せずに、sshでつないで操作するようにした。そうするとゲストOSのウィンドウは開いても最小化しっぱなしとかになって、無駄である。VirtualBoxにはウィンドウを開かずにコマンドラインからVMを起動する方法があるので、それを利用する:

$ VBoxManage startvm <VM名> --type=headless

停止させるには

$ VBoxManage controlvm <VM名> poweroff

VirtualBox上のゲストOSとホストOSで通信するにはネットワーク設定で、NAT+ホストオンリーアダプタを使う方法と、ブリッジ接続を使う方法がある。ブリッジ接続にすればホストOSのネットワーク接続と同じ設定を使うので外部のネットワークにつなげるのも簡単なんだけど、ネットワークを使えない環境だとホスト−ゲスト間も通信できなくなってしまうという問題がある。まあお好みで。

gas

OS自作本ではnaskという、著者が作ったアセンブラを使用している。しかしできればそういう独自ツールに依存したくないので、GCCのアセンブラ(gas)を利用することにした。gasはnaskとはアセンブラの文法が違っている。nask(nasm)はインテルシンタックス、gasはAT&Tシンタックスとのこと。

文法の違いで一番大きいのはオペランドの順番で、インテルシンタックスでは

MOV DST, SRC  ; DST ← SRC

に対して、AT&Tシンタックスでは逆に

MOV SRC, DST  # SRC → DST

となる。またレジスタには%を前につける。直値には$を前につける。 他にもいろいろ、間接インデックスを丸括弧にするとか、コメントが#で始まるとか、擬似命令が違うとか。

オペランドの順番はまあどちらでも慣れでいいんだけど、%とか$が頻発してとにかく入力しづらいので面倒くさいという欠点がある。まあしかたがない。

c言語導入(gccのリンカスクリプトを使う)

オブジェクトファイルからバイナリファイルを作る際に、OS自作本では著者の方が作ったいろいろなツール(tolset: cc1.exe, gas2nask.exe, nask.exe, obj2bim.exe, bim2hrb.exe)を通す必要があった。それらの操作が煩雑ということと、実際にそれぞれがどういうことをしているのかよくわからないのがちょっと不満だった。

今回はGCCのリンカにリンカスクリプトを指定して、hrbファイルと同様のバイナリを生成するようにした。参考にしたのは『30日でできる!OS自作入門』のメモ

OS作成に使うCのソースを、gccを使ってオブジェクトファイルを作成する:

$ gcc -c <Cファイル名>

アセンブラのソースも同様にオブジェクトファイルを作成する:

$ as <アセンブラソース名>

生成されたすべてのオブジェクトファイルを、リンカとリンカスクリプトを使ってバイナリを生成する:

$ ld -T <リンカスクリプト> --oformat binary <オブジェクトファイル…>

ブートローダとブートされるOSとの連結は、単にcatを使ってやればできる。ファイルの配置情報を設定する場合にはちゃんとFATの内容を書き込む必要があるだろうが、OS自作本の前半ではディスクからごそっとデータを読み込んで固定のアドレスにジャンプするだけなので、今のところはこれでOK。

生成されたディスクイメージを走らせる

理論的にはゲストOSのUbuntu上でさらにエミュレータを動かして、その上で自作OSを走らせることもできないことはないとは思うんだけど、やってみたところうまく動かなかった。

しかたがないので、scpでホストOS(Mac)に持ってきて、ホストOS上のVirtualBoxで動かしている。面倒くさい。もっといい方法はないものだろうか…。

総括

一応これでMac上でも自作OSを開発できる環境は整ったので、本の通りに進められるはず。 著者的にはtolsetなどの開発環境はすべて自作のものなので、なにがどう動いているか全て把握していると思うのでいいんだろうけども、第三者の私としてはどういうことをしているのかよくわからないので不安が残っていた。とはいっても、gccはgccで中身を知っているわけでもないけど、使うツールが少ないのはその不安が減ってよろしい。