まりものメモ帳

なぐり書き

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

本との変更点を以下に記します。

  1. RESB命令をTIMES DB命令に(アセンブルの時にWarningが出なくなる)
  2. 0x7dfe-$0x7dfe-($-$$)に(何故かは一日目をご参照下さい)

で、nasmでアセンブルして、qemuで実行します。

$ qemu-system-i386 -drive file=helloos3,format=raw,if=floppy

するとエラーを吐きます。
f:id:admarimoin:20180909211939p:plain
これはTIMES 0x7dfe-($-$$) DB 0TIMES 0x7dfe-0x7c00-($-$$) DB 0としてやることによって正常に動作します。説明的な何かは後で。
f:id:admarimoin:20180909213706p:plain

調べたこととか

個人的に?となったとこをピックアップして書いていきます。

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.bintail.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.

ちゃんと正しく実行出来ました。
f:id:admarimoin:20180913024805p:plain
このWarningを消したいという方は②を

qemu-system-i386 -drive file=helloos.img,format=raw,if=floppy

に変更して下さい。
お疲れ様でした。