1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

自分でOSを1から作ってみるAdvent Calendar 2024

Day 3

OSの基礎解説

Last updated at Posted at 2024-12-02

自分でOSを1から作ってみる Advent Calendar 2024の3日目です。

そもそも昨日書いたコードは何をしているのか

昨日書いたコードが何をしているのかが分からなければ、これからのことはさらに分からなくなると思いますので、説明しておきます。
昨日書いたコードはアセンブラ(NASM)で作りましたが、ブートセクタはバイナリです。バイナリというのは2進数のみで書かれているコードで、PCが直接認識できるのはこの形式のみです。実際に、昨日作ったboot.binはバイナリで、バイナリエディタを使えば確認することができると思います。そして、普通のテキストエディタで開いても文字化けして見ることができないと思います。
そして、このコードがなぜ実行されているのかというと、コンピュータの電源が入ると最初にBIOSが実行され、まずシステムの基本的なハードウェアをチェックし、正常に動作するか確認します。そしてその後、BIOSはブートデバイス(HDD、USB、CD-ROMなど)の先頭セクタ(最初の512バイト)を探し、この512バイトのデータがブート可能なものであるかをチェックし、ブートデバイスに有効なブートセクタが見つかると、BIOSはこの512バイトの内容をメモリの0x7C00番地にロードします。そして、CPUの制御を0x7C00番地に移し、このアドレスからプログラムが実行されるように設定されるからです。ちなみに先頭セクタがブート可能かどうかは最後の2バイトが0xAA55であるかどうかで判断しています。

boot.asmのコードの説明

ここでは機能書いたコードを1から解説していますが、アセンブリがわかる人とかにとってはあまり必要ない話だと思いますので、読み飛ばしてもらっても大丈夫です。

boot.asm
org 0x7C00

orgというのはアセンブリの「起点アドレス」を設定する命令で、BIOSはブートローダをメモリのアドレス0x7C00に読み込むため、ここでプログラムの起点を0x7C00に指定します。

boot.asm
mov ax, 0xB800   ; テキストモードのビデオメモリのアドレス
mov es, ax

0xB800は、テキストモードでのビデオメモリのセグメントアドレスです。
mov ax, 0xB800で、ビデオメモリのアドレスをaxレジスタに格納します。
mov es, axで、このアドレスをes(Extra Segment)に設定します。esを使うことで、以降のコードで[es:di]に書き込みを行うと、ビデオメモリにアクセスできます。

boot.asm
mov di, 0

diesと組み合わせてアドレス指定に使われます。ここでは、ビデオメモリの先頭位置(左上)を示す0を設定しています。

boot.asm
mov si, message

si(Source Index)にmessageのアドレスを格納します。これにより、messageで定義された文字列のデータを1文字ずつ読み取ることができます。

boot.asm
print_char:

ここから、message内の各文字を順に読み出し、ビデオメモリに書き込むループが始まります。

boot.asm
lodsb

lodsbは、siが指しているメモリから1バイトをalレジスタにロードし、siを自動的にインクリメントする命令です。
ここでは、messageから1文字ずつalにロードし、alに格納された文字をビデオメモリに表示します。

boot.asm
cmp al, 0        ; 終端をチェック
je hang          ; 終端なら停止

cmp al, 0で、alの内容が0かどうかを確認します。
0は文字列の終端を示す特殊な文字で、もし0ならje hangにより、hangラベル(無限ループ)にジャンプして表示を終了します。

boot.asm
mov [es:di], al
inc di

mov [es:di], alで、alにロードした文字をビデオメモリの現在の位置に書き込みます。
inc diで、ビデオメモリのカーソル位置を1バイト分進めます。

boot.asm
mov byte [es:di], 0x07
inc di

mov byte [es:di], 0x07で、表示する文字の色属性を指定します。0x07は白色を意味します。
inc diで、再度カーソル位置を進めます(1文字分の位置を確保するため、2バイト進める必要があるのでinc diを2回使用しています)。

boot.asm
jmp print_char

print_charラベルに戻り、次の文字を表示するためにループを継続します。

boot.asm
hang:
    jmp $

メッセージの表示が終わった後、無限ループに入ります。このループは、プログラムが終了しないようにするためのものです。
jmp $で現在のアドレスにジャンプすることで、プログラムを停止させています。

boot.asm
message db "hello, world", 0

0は終端文字で、この文字が出てきたらループを終了するようにしています。

boot.asm
times 510-($-$$) db 0

ブートセクタは必ず512バイトである必要があり、残りのバイトを0で埋めて512バイトにしています。
($-$$)は現在の位置からプログラムの開始位置までのバイト数を表し、510-($-$$)で埋めるべきバイト数を計算しています。

boot.asm
dw 0xAA55

ブートセクタの最後の2バイトには必ず0xAA55という署名が必要です。この署名がないと、BIOSはこのコードをブートセクタとして認識しません。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?