|
ブートローダその3 はじめてのブートローダとアセンブルと書き込み
|
前回までの内容
これまでで、
- 電源を起動したらBIOSがディスクの最初のセクタ(512バイト)を読み込む
- 読み込んだ最初のセクタ(512バイト)はアドレス0x7C00にコピーされる
- コピーされた後0x7C00から処理が開始される
ということがわかりました。それでは最初のセクタとして読み込まれる
512バイトのブートローダを作ってみましょう
最初のブートローダを作ってみる
テキストエディタを開いて次のアセンブラプログラムを作ってみます
ここではファイル名を”boot.asm”としました
(テキストエディタはメモ帳でもなんでもいいです。
サクラエディタ
とかはどうでしょうか)
;/********************************************************************************
; File:boot.asm
; Description:Bootloader
;
;********************************************************************************/
[BITS 16]
ORG 0x7C00
;/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
;
; BOOT
;
;/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
BOOT:
CLI
HLT
TIMES 510 - ($ - $$) DB 0
DW 0xAA55
ここでソースコードの説明をしたいと思います
[BITS 16]
最初のこの記述はプログラムが16ビットで始まることを意味しています
パソコンのCPUは起動後は16ビットのモードで動きます
なにやら古いOSとかのための互換性を保つためのようです
(もしかしたらDOSも最新のCPUで動くかもしれません)
ですので16ビットの命令をアセンブルする必要があります
この16ビットのモードはリアルモードと呼ばれています
(何がリアルなのかさっぱりわかりませんが。。。)
後" ; "を書くとそれ以降はコメントになります。好きなようにコメントをつけていきましょう
ORG 0x7C00
でてきました。見たことのある数字です
この記述はこのプログラムは0x7C00で始まることを宣言しています
なぜならBIOSが0x7C00にこのプログラムを置いてくれるからですね(復習、復習)
このプログラムがある変数などにアクセスするときにアドレスを指定した場合
アセンブルすると0x7C00をベースとしてアドレスを決めてくれます
BOOT:
:がつくとラベル付けができます。ここではBOOTというラベル名をつけています
ラベルをつけておくとアドレスを直に指定する代わりにBOOTというラベルを使うことができます
CLI
これが初めてのアセンブラ言語の命令となります
この命令は割り込みをすべて受け付けないように(割り込みフラグをクリア)します
とりあえず念のためこの命令を入れただけであまり意味はありません
HLT
次の命令は実行を止めてCPUを停止状態にする命令です
このプログラムはここでこれ以上何もしなくなります
TIMES 510 - ($ - $$) DB 0
これは命令ではなくプリプロセッサで処理される擬似命令となります
少し複雑ですが、TIMES 510 - ($ -$$)の擬似命令とDB 0と分けて見てみます
DBのDは定義(Define)を、Bはバイトを意味しています。DBですので1バイトと言う意味で
0を宣言しているので、値が0の1バイトをこの場所に置くことになります
その前のTIMES以降についてはまず$、$$について説明します
$$は最初の命令(最初の行でここではCLI命令)の場所を意味しています
逆に$は現在の場所を意味しています
ですので($ - $$)は先頭から現在の行まで何バイト使っているかを表しています
(ここでは($ - $$) = (2 - 0)となります。16ビットの命令(CLIが1バイト、HLTが1バイト)が2つなので2バイト引く最初の0
厳密には(0x7C02 - 0x7C00)となります)
510については、1セクタのバイト数が512バイト−最後のデータは0xAA55の2バイトなので
プログラムのサイズとしては510バイトとなります
そしてこのプログラムで使用している命令のバイト数は($ - $$)=2でしたので
命令以外の空きサイズは510-($ - $$) = 508バイトとなります
そしてTIMESはデータ(または命令)をその数だけ繰り返す擬似命令です
この2つを組み合わせると”値が0である1バイトを508バイト配置する”を意味します
DW 0xAA55
最後は簡単です。DWはワードサイズ(16ビットのワードは2バイト)のデータを配置します
ここでは0xAA55というデータを置きます
もちろんこのデータは511バイト目に置かれることに注意してください
これでようやく何もしない最初のブートローダのソースができました
ではアセンブルしていきます
アセンブル
アセンブルするためにまずCygwinを起動して作ったソースがあるフォルダまで
cdコマンドで移動してください。そして
nasm -o boot.img boot.asm
と入力してEnterを押すとアセンブルします
ここでオプションとして-oを指定しました。-oは出力ファイル名を指定します
ここではboot.imgを指定しました(好きなファイル名でOKです)
boot.imgというファイルができたと思います。
試しにバイナリエディタ(例えば
Stirling
など)で開いてどのような
バイナリができているのか眺めて見ることをおすすめいたします
フロッピーディスクの最初のセクタに書き込む
まず、ImDisk Virtual Disk Driverを起動して適当にフロッピーの
イメージファイルをマウントしてAドライブができているか確認をしておきましょう
できていることが確認できたら
dd if=boot.img bs=512 count=1 of=/proc/sys/Device/ImDisk0
とCygwinに入力します。ここでddはファイルをコピーするコマンドです
ifオプションは入力ファイルを指定します。アセンブルしたboot.imgを指定しています
bsはコピーするバイト数で当然512バイトです。countはあまり気にしなくいいですが、
一応コピーするブロック数で1ブロックのみコピーを指定しています(よくわかってないです。。。)
ofは出力ファイルを指定しています。/proc/sys/Device/ImDisk0は
ImDiskがマウントしているはAドライブを意味しています
これでImDiskで例えばfd.imgをAドライブとしてマウントしておくとfd.imgのブートセクタにあたる部分が
boot.imgに書き換わります。試しにImDiskで開いているフロッピーディスクイメージを
バイナリエディタで確認してみてください
ようやく起動してみる
それではVirtual Boxを起動して環境設定でやったようにデバイスとしてAドライブを
指定して仮想マシンを起動してみてください
上手くいけば何も表示されません。起動するとこんな画面になります