Ubuntu 18.04で「30日でできる!OS自作入門」をやりたい[2日目]
Ubuntu 18.04で30日OS自作入門をやりたい[1日目] - まりものメモ帳の続きです。
2日目でも現実の日数的には大きくかけ離れるんですがそれは許して下さい。深夜までみんなとPUBGmをしてたのが敗因です。
使ったツール
・nasm
・qemu
・make
詳しくは一日目を参照して下さい。
9月9日, 9月10日, 9月12日, 9月13日
事件
いろいろやらかしてOSが起動しなくなった(!)んですが
$ fsck -y /dev/sda2
であっさりと直りました。fsckちゃんすき💕。すっげえ焦りました。OSを作ってる間にOSが壊れるというなんとも皮肉な…
ちなみに明日提出(9月9日現在)のレポートは終わってません。よろしくお願いします。こっちの方が大事件な気がする
アセンブリ写経タイム
いつものおまたせってことでアセンブリを(nasmに都合のいいように)写経していきます。
helloos3.asm
;hello-os ;TAB = 4 ORG 0x7c00 ;① ;disk JMP entry DB 0x90 DB "HELLOIPL" DW 512 DB 1 DW 1 DB 2 DW 224 DW 2880 DB 0xf0 DW 9 DW 18 DW 2 DD 0 DD 2880 DB 0, 0, 0x29 DD 0xffffffff DB "HELLO-OS " DB "FAT12 " TIMES 18 DB 0 ;1 ;main entry: MOV AX, 0 MOV SS, AX MOV SP, 0x7c00 MOV DS, AX MOV ES, AX MOV SI, msg putloop: MOV AL, [SI] ADD SI, 1 CMP AL, 0 JE fin MOV AH, 0x0e MOV BX, 15 INT 0x10 ;④ JMP putloop fin: HLT JMP fin msg: DB 0x0a, 0x0a DB "Hello,World" DB 0x0a DB 0 TIMES 0x7dfe-($-$$) DB 0 ;1,2 ;② DB 0x55, 0xaa ;③ ;ブートセクタ以外の記述 DB 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 TIMES 4600 DB 0 ;1 DB 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 TIMES 1469432 DB 0 ;1
本との変更点を以下に記します。
- RESB命令をTIMES DB命令に(アセンブルの時にWarningが出なくなる)
- 0x7dfe-$を0x7dfe-($-$$)に(何故かは一日目をご参照下さい)
$ qemu-system-i386 -drive file=helloos3,format=raw,if=floppy
するとエラーを吐きます。
これはTIMES 0x7dfe-($-$$) DB 0をTIMES 0x7dfe-0x7c00-($-$$) DB 0としてやることによって正常に動作します。説明的な何かは後で。
調べたこととか
個人的に?となったとこをピックアップして書いていきます。
nasmのORG命令(origin)はこのプログラムがどこのメモリに読み込まれるかを指定するみたいです。また、本にある
http://oswiki.osask.jp/?%28AT%29memorymapによると0x7c00から0x7dffまで(512バイト)がブートセクタが読み込まれるアドレスとなっています。つまり、コードの①のORG 0x7c00は「ブートセクタが読み込まれる所にこのプログラムを読み込んでくれ」ということを意味していたとです。
②の0x7dfeについても説明します。②では使っていない領域の最初から0x7dfeまで0x00で埋めろという命令を出しているのですが、これはブートセクタが読み込まれる最初の0x7c00から数えて510バイト目の0x7dfeまで、使ってない領域を0で埋めることを意味しています。
「最後の2バイトはどうなってんねん」というなんですが、それは③の2バイト分です。最後の2バイトの511バイト目と512バイト目は絶対に0x55, 0xaaじゃないといけません。「これが有効なブートセクタである」ということを示すための署名だと考えるといい感じだと思います。
TIMES 0x7dfe-($-$$) DB 0でエラーが出たことについて。このプログラムの始めが0x7c00なのでその"基準"を考えなかったらマズイ。考え方的に510バイト目まで使っていない領域を0で埋めるということなのでちゃんと基準を考慮してあげなきゃマズイでしょう、ということで0x7dfeから0x7c00を引くことによって初めて「使ってない最初の所から510バイト目までを埋める」という意味になり(そうだな〜と勝手に考えてい)ます。当然ですが0x7dfe-0x7c00-($-$$)を510-($-$$)にしても十分動作します。こっちの書き方の方がわかりやすい人もいるかもしれません。説明がヘッタクソでごめんなさい。
④のINT命令ですが、これはソフトウェア割り込み命令と言って、これは別にint型で何かしてるわけではなかったです(intはinterrupt、割り込みという意味です)。まあINT なんちゃらとやることによって割り込むぞオラァン!やってるわけですね。で、そのなんちゃらを0x10にするとビデオ機能が使用出来るようになるというわけです。詳しいことはここを見て下さい…→
http://oswiki.osask.jp/?(AT)BIOS
Makefile
ここはUbuntuにデフォルトで入っているmakeコマンドで頑張ります。といってもMakefileを作るのは全く持って初めてなので少し時間をかけて咀嚼していきます。
Makefileについての記事を読んでると、「いっぱいソースコードがあるときに一部を書き換えただけで全部コンパイル(アセンブル)するのはダルいから自動化しちゃえ」ってことみたいです。Makefileの拡張子ってなんだとか思ってたらファイル名にMakefileが入ってたらOKなんですね。面白い。
そんで出来上がったMakefileがこちらです。本とか他サイトには不要になったファイルを消す動作も入っていましたがこれには入れていません。
なお、ipl.asmはこの記事のhelloos3.asmと同じです。tail.asmは現在内容は必要ないのでファイルだけ作っておきましょう。
$ touch tail.asm
Linuxで書くOS自作入門 2日目 - Tsurugidake's diaryを参考にさせて頂きました。
Makefile(作業ディレクトリと同じ所に!)
default: make img ipl.bin: ipl.asm Makefile nasm ipl.asm -o ipl.bin -l ipl.lst tail.bin: tail.asm Makefile nasm tail.asm -o tail.bin -l tail.lst helloos.img: ipl.bin tail.bin Makefile cat ipl.bin tail.bin > helloos.img #① asm: make -r ipl.bin img: make -r helloos.img run: make img qemu-system-i386 helloos.img #②
makeの文法とかの説明は本に任せて、仕組みの説明ですね。といってもあまり無いですが。
ファイルの結合をcatでやっていますが(①)、これはcatで出力した2つのファイル(ipl.binとtail.bin)を結合させhelloos.imgに書き込んでいます。
実行します。
$ make run
出力結果(ターミナル)
make img make[1]: ディレクトリ '/home/admarimoin/os' に入ります make -r helloos.img make[2]: ディレクトリ '/home/admarimoin/os' に入ります nasm ipl.asm -o ipl.bin -l ipl.lst nasm tail.asm -o tail.bin -l tail.lst cat ipl.bin tail.bin > helloos.img make[2]: ディレクトリ '/home/admarimoin/os' から出ます make[1]: ディレクトリ '/home/admarimoin/os' から出ます qemu-system-i386 helloos.img WARNING: Image format was not specified for 'helloos.img' and probing guessed raw. Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. Specify the 'raw' format explicitly to remove the restrictions.
ちゃんと正しく実行出来ました。
このWarningを消したいという方は②を
qemu-system-i386 -drive file=helloos.img,format=raw,if=floppy
に変更して下さい。
お疲れ様でした。