読者です 読者をやめる 読者になる 読者になる

たにしきんぐダム

プログラミングやったりアニメやゲーム見たり京都に住んだりしてます

OS自作入門記(1~2日目)

OS自作入門

「30日でできる! OS自作入門」を読んでいく、やったことをメモすれば自分の勉強にもなるしこれを見た誰かの役に立つかもしれない...?

モチベーション

自分でオリジナルのOSを作りたいというよりは、コンピュータのことをもっとよく知りたい、恥ずかしながらコンピュータのこと全然知らないし。
一応大学でOSの授業を受けて勉強はしたのですが、いまいち実感がわかないしとりあえず作りながら勉強していこう!

開発環境

この本ではWIndowsでの開発を行っているのですが本を読み始めた時、手近にWIndows機が無かったのもあって仮想マシン上のUbuntuでやることに

1日目

バイナリでhelloos.imgを作るのは途中までやるものの飽きてコピペで済ませる
作者自作ツールの使い方がよく分からない...参考記事などを読んで何とかしよう

  • sudo apt-get install qemu
  • qemu-system-x86_64 helloos.img
  • qemu-system-i386 helloos.img

でなんか動いた。 x86_64をエミュレートしたわけですが、エミュレートするシステムは何でもいいのかな?

※8/18追記: OS自作入門はx86で動く32bitのOSを作るみたいなのでi386とか指定しておけば良さそう?

もうちょっと書きなおしてみる

naskがうまく動かない、UbuntuGNU Assembly でやってる先人たちのブログを参考にして僕もGASでやってみよっと
参考記事を見ながらnaskのコードをgasに変換する

gist2fef672c3a0a73cb2eba48981f9c8149

  • as -o helloos.o helloos.s
  • ld --oformat binary -o helloos.img helloos.o
  • qemu-system-i386 helloos.img

これで良いのかな

https://gyazo.com/1ac73f028b8152ba18e93a88369d3716

動いたっぽい

  • このOSもどきはフロッピーディスクに書き込むもので、フロッピーディスクの1セクタは512バイ
  • BIOSは起動ディスクの先頭1セクタをメモリに読み込む(今回の場合は先頭512バイト)(起動ディスクの優先順位ってBIOS割り込みルーチンの番地の順番のこと?)
  • この先頭1セクタをブートセクタと呼び、通常このブートセクタにはOSを呼び出す読み込むプログラムが格納されているため、それをIPL(Initial program loader)と呼ぶ

FAT12

FAT12とはMS-DOSファイルシステムで容量の少ないフロッピーディスクなどによく使われてたらしい。 今回書いたプログラムはFATの4つの領域のうちブートセクタ部分でブートセクタに記入すべきBPB(BIOS Parameter Block)は仕様で定められているようですね。これを眺めていると

  • .word が1語(2バイト)の宣言
  • .byte が1バイトの宣言
  • .int が4バイトの宣言

なのでなんか納得

参考

一日目の感想

一日目をやるだけで3日くらいかかってしまった、こんなことも知らないかと思われるかもしれないけど自分がどれだけもの知らずか分かってよかった。どんどん読み進めていくぞい


2日目

2.1 まずはテキストエディタの紹介

本書ではTeraPadを紹介してますが僕は普段vimを使ってるのでそのままvim

2.2 さて開発再開

ORG命令これはnask独自の命令?実行時にメモリのどこに読み込まれるかを教える命令らしいがGASには無さそう?なのでリンカスクリプトで指定してあげることにしよう(リンカスクリプト初体験)

GASについてちょっとお勉強

X86アセンブラ/GASでの文法 - Wikibooks

BIOSサービス割り込み

BIOS(Basic input output system)はその名の通り基本的な処理をサービスルーチンとして提供していて、INT命令で割り込み番号を指定してやることでBIOSのサービス割り込みが利用できる。INT命令はinterruptの略!

hello,worldと表示するためには文字コード書き込みのためにBIOSのビデオサービス割り込みを利用するっぽい、そのために各種レジスタに値を入れてINT命令でBIOS割り込みを呼び出せば良いよう

  • ah: 0x0e
  • al: 書き込む文字コード
  • bh: カラーコード
  • bl: ビデオモード(?)

Tips BIOSサービス割り込み ビデオサービス 文字コード書き込み(テレタイプモード)

msgラベルのアドレスに表示したい文字列を置いておき、ラベルアドレスをADD命令でずらしながら表示していってるのか〜

最終的にコードは以下のような感じ? (.data セクションとかちゃんと使ったほうが良いのかな...)

.stringディレクティブ は最後に\0が入ってくれる

リンカスクリプト

初めてのC言語 - 第9回 リンカスクリプト

プログラムが 0x7c00 番地に配置されるように指定
ブートセクタをメモリに配置するわけですが好き勝手な場所に配置できるわけではなくて 0x7c00 に配置することが決まっているらしい、決まり事なら仕方ないね

0xaa55 というのはブートシグニチャというもので、MBRの末尾2バイト(0x7dfe = 0x7c00 + 510)に記入するマジックナンバーで、ブートシグニチャが正しくないとMBRが正しいと認識されずにブートストラップローダーに制御が移らないらしい。実際にこの値を変更してやるとうまくブート出来なかった

こんな感じでしょうか??

2.3 ブートセクタだけを作るように整理

ディスクイメージ全体をアセンブリで作るのではなく、とりあえずブートセクタ512バイトだけ作ってあとはディスクイメージ管理ツールで作ってもらったほうが良いよとのこと 1440KBまで埋めたりもしてないしね

ディスクイメージの作成にはmformatコマンドを使えば良さそう

  • ldコマンドは -T でリンカスクリプトを指定
  • mformatは
    • -f: サイズ
    • -C: ディスク作るぞ!
    • -B: ブートセクタを指定
    • -i: イメージファイル名を指定らしい
      • man mformat を見てもiオプションの説明は無かったがいろんなブログを見てるとどうやらそうらしい、一次ソース求む!!!

動かしていくぞ!

  • as -o ipl.o ipl.s
  • ld -o ipl.bin -T lnk.ld ipl.o
  • mformat -f 1440 -C -B ipl.bin -i ipl.img
  • qemu-system-x86_64 ipl.img
  • qemu-system-i386 ipl.img

動いた!めでたい :tada: https://gyazo.com/e13aa1c907128e481f97e83bd45e1782

疑問

適当に qemu-system-x86_64ipl.img を動かしたが、エミュレートするアーキテクチャはなんでもいいのか?命令セットとか違そうだし特定のアーキテクチャを指定してあげなくちゃいけないんじゃないの????そもそもディスクイメージって何者なの?????

※ 追記8/18: この本はx86の32bitOSを作ってるがx86_64が互換性を持ってたから動いたみたい? i386で十分っぽい

どうやら qemu-img info hoge.img でディスクフォーマトについて調べられるらしい

$ qemu-img info ipl.img
image: ipl.img
file format: raw
virtual size: 1.4M (1474560bytes)
disk size: 24K

Raw ディスクイメージフォーマット(デフォルト)。このフォーマットは単純で、全ての 他のエミュレータに簡単にエキスポートできます。

28.3. qemu-img の使用

rawフォーマットのディスクイメージはいろんなアーキテクチャで認識できるってことだろうか??とにかくディスクイメージが何者なのかいまいち分かってないけど...これはまた今度で...

今後のためにMakefile導入

Makefileを書きます

雑ですがこんな感じで?

2日目の感想

色々と知らないことが出てきて面白い、qemuとかディスクイメージのあたりは後でちゃんと調べないといけないなー
リンカスクリプトとか初めてだしqemuもasもldも使うの初めてで色々調べてたらだいぶ時間かかってしまう、う〜ん30日じゃ絶対無理そう、ゆっくり勉強しながら1年くらいかけてやっていければ良い

参考