フラミナル

考え方や調べたことを書き殴ります。IT技術系記事多め

【2日目】OS自作入門を読んで振り返りと注意点

30日でできる! OS自作入門

30日でできる! OS自作入門

今回の内容

一日目に引き続き、アセンブラで書かれた「Hello World」とだけ表示されるOSのソースコードを読む回。

CPUのレジスタ(記憶するところ)とメモリーの概念が登場し、アセンブラのコードを通じてどのように画面に文字を出力したのかが書かれていた。

変数の代入、メモリの番地指定、条件分岐、goto命令などプログラミングを知っていると理解しやすい雰囲気。

コードの解説・理解

; プログラム本体

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            ; SIに1を足す
        CMP      AL,0
        JE       fin
        MOV      AH,0x0e         ; 一文字表示ファンクション
        MOV      BX,15           ; カラーコード
        INT      0x10           ; ビデオBIOS呼び出し
        JMP      putloop
fin:
        HLT                      ; 何かあるまでCPUを停止させる
        JMP      fin              ; 無限ループ

msg:
        DB       0x0a, 0x0a        ; 改行を2つ
        DB       "hello, world"
        DB       0x0a           ; 改行
        DB       0

        RESB 0x7dfe-$       ; 0x7dfeまでを0x00で埋める命令

        DB       0x55, 0xaa

コードはentry/putloop/fin/msgの4種類の要素から成り立っている。

  • entryは初期変数の定義
  • putloopはmsgでメモリに書き込まれた内容を1文字づつ出力
  • finはCPUの停止
  • msgは表示する文字情報をメモリに書き込む処理

ブートセクタ

OSイメージはブートセクタと呼ばれる領域が存在する。0x7c00から始まる512バイトのこの領域にOSイメージを作成することでBIOSはOSが存在することが確認でき起動ができる。(より正確には1日目に書かれていたが最後のバイト文字を見ているらしい)

Makefile

すげえ便利。

疑問点

     1 00000000                                 ; hello-os
     2 00000000                                 ; TAB=4
     3 00000000                                 
     4                                                 ORG      0x7c00         ; このプログラムがどこに読み込まれるのか
     5 00007C00                                 
     6 00007C00                                 ; 以下は標準的なFAT12フォーマットフロッピーディスクのための記述
     7 00007C00                                 
     8 00007C00 EB 4E                                   JMP      entry
     9 00007C02 90                                    DB       0x90
    10 00007C03 48 45 4C 4C 4F 49 50 4C                DB       "HELLOIPL"     ; ブートセクタの名前を自由に書いてよい(8バイト)
    11 00007C0B 0200                                  DW       512                ; 1セクタの大きさ(512にしなければいけない)
    12 00007C0D 01                                    DB       1              ; クラスタの大きさ(1セクタにしなければいけない)
    13 00007C0E 0001                                  DW       1              ; FATがどこから始まるか(普通は1セクタ目からにする)
    14 00007C10 02                                    DB       2              ; FATの個数(2にしなければいけない)
    15 00007C11 00E0                                    DW       224                ; ルートディレクトリ領域の大きさ(普通は224エントリにする)
    16 00007C13 0B40                                  DW       2880           ; このドライブの大きさ(2880セクタにしなければいけない)
    17 00007C15 F0                                      DB       0xf0           ; メディアのタイプ(0xf0にしなければいけない)
    18 00007C16 0009                                  DW       9              ; FAT領域の長さ(9セクタにしなければいけない)
    19 00007C18 0012                                  DW       18             ; 1トラックにいくつのセクタがあるか(18にしなければいけない)
    20 00007C1A 0002                                  DW       2              ; ヘッドの数(2にしなければいけない)
    21 00007C1C 00000000                              DD       0          ; パーティションを使ってないのでここは必ず0
    22 00007C20 00000B40                               DD       2880           ; このドライブ大きさをもう一度書く
    23 00007C24 00 00 29                              DB       0,0,0x29       ; よくわからないけどこの値にしておくといいらしい
    24 00007C27 FFFFFFFF                                DD       0xffffffff     ; たぶんボリュームシリアル番号
    25 00007C2B 48 45 4C 4C 4F 2D 4F 53 20 20         DB       "HELLO-OS   "   ; ディスクの名前(11バイト)
       00007C35 20 
    26 00007C36 46 41 54 31 32 20 20 20                DB       "FAT12   "     ; フォーマットの名前(8バイト)
    27 00007C3E 00 00 00 00 00 00 00 00 00 00         RESB 18             ; とりあえず18バイトあけておく
       00007C48 00 00 00 00 00 00 00 00 
    28 00007C50                                 
    29 00007C50                                 ; プログラム本体
    30 00007C50                                 
    31 00007C50                                 entry:
    32 00007C50 B8 0000                                MOV      AX,0        ; レジスタ初期化
    33 00007C53 8E D0                                   MOV      SS,AX
    34 00007C55 BC 7C00                                 MOV      SP,0x7c00
    35 00007C58 8E D8                                   MOV      DS,AX
    36 00007C5A 8E C0                                   MOV      ES,AX
    37 00007C5C                                 
    38 00007C5C BE 7C74                                 MOV      SI,msg
    39 00007C5F                                 putloop:
    40 00007C5F 8A 04                                 MOV      AL,[SI]
    41 00007C61 83 C6 01                              ADD      SI,1            ; SIに1を足す
    42 00007C64 3C 00                                 CMP      AL,0
    43 00007C66 74 09                                JE       fin
    44 00007C68 B4 0E                                MOV      AH,0x0e         ; 一文字表示ファンクション
    45 00007C6A BB 000F                                 MOV      BX,15           ; カラーコード
    46 00007C6D CD 10                                  INT      0x10           ; ビデオBIOS呼び出し
    47 00007C6F EB EE                                JMP      putloop
    48 00007C71                                 fin:
    49 00007C71 F4                                      HLT                      ; 何かあるまでCPUを停止させる
    50 00007C72 EB FD                                JMP      fin              ; 無限ループ
    51 00007C74                                 
    52 00007C74                                 msg:
    53 00007C74 0A 0A                                DB       0x0a, 0x0a        ; 改行を2つ
    54 00007C76 68 65 6C 6C 6F 2C 20 77 6F 72         DB       "hello, world"
       00007C80 6C 64 
    55 00007C82 0A                                      DB       0x0a           ; 改行
    56 00007C83 00                                    DB       0
    57 00007C84                                 
    58 00007C84 00 00 00 00 00 00 00 00 00 00         RESB 0x7dfe-$       ; 0x7dfeまでを0x00で埋める命令

わかりやすさのためにアセンブラのコードとバイナリを一覧化できるリストファイルが登場した。ここのMOV命令行が複数あるけれど、どこもバイナリコードは別々になっている。MOVを使っている列は全部同じバイナリ始まりになると思ったけどどうやらアセンブラの命令はバイナリ化されず、結果がバイナリとして示されるっぽい。ここの変換方法はどういうロジックなんだろうか?

注意点