laitimes

30 days of homebrew operating system --- day 3

author:Yoman Fat Boy

One, make a real IPL (Launcher Loader)

Today's purpose is to load the program from yesterday's startup program loader.

(1): The initial 512 bytes of the disk are the boot area. In order to load the next 512-byte program, the previous program was modified to get today's harib00a program;

(2): Buffer address is the memory address. Load the programs on disk into memory

; haribote-ipl
; TAB=4
 
 
        ORG        0x7c00            ; このプログラムがどこに読み込まれるのか
 
 
; 以下は標準的なFAT12フォーマットフロッピーディスクのための記述
 
 
        JMP        entry
        DB        0x90
        DB        "HARIBOTE"        ; ブートセクタの名前を自由に書いてよい(8バイト)
        DW        512                ; 1セクタの大きさ(512にしなければいけない)
        DB        1                ; クラスタの大きさ(1セクタにしなければいけない)
        DW        1                ; FATがどこから始まるか(普通は1セクタ目からにする)
        DB        2                ; FATの個数(2にしなければいけない)
        DW        224                ; ルートディレクトリ領域の大きさ(普通は224エントリにする)
        DW        2880            ; このドライブの大きさ(2880セクタにしなければいけない)
        DB        0xf0            ; メディアのタイプ(0xf0にしなければいけない)
        DW        9                ; FAT領域の長さ(9セクタにしなければいけない)
        DW        18                ; 1トラックにいくつのセクタがあるか(18にしなければいけない)
        DW        2                ; ヘッドの数(2にしなければいけない)
        DD        0                ; パーティションを使ってないのでここは必ず0
        DD        2880            ; このドライブ大きさをもう一度書く
        DB        0,0,0x29        ; よくわからないけどこの値にしておくといいらしい
        DD        0xffffffff        ; たぶんボリュームシリアル番号
        DB        "HARIBOTEOS "    ; ディスクの名前(11バイト)
        DB        "FAT12   "        ; フォーマットの名前(8バイト)
        RESB    18                ; とりあえず18バイトあけておく
 
 
; プログラム本体
 
 
entry:
        MOV        AX,0            ; レジスタ初期化
        MOV        SS,AX
        MOV        SP,0x7c00
        MOV        DS,AX
 
 
; ディスクを読む
; ===============================这次添加的内容START=================================
;这里就开始了读写磁盘的方式,下面就会更具 驱动器  柱面 扇区 磁头 确定最终读取的位置
 
        MOV        AX,0x0820
        MOV        ES,AX
        MOV        CH,0            ; 柱面0  CH表示的是柱面号
        MOV        DH,0            ; 磁头0  磁头号
        MOV        CL,2            ; 扇区2  CL扇区号
 
 
        MOV        AH,0x02         ;AH=0x02 : 读盘(0x03是写磁盘)
        MOV        AL,1            ;1个扇区  AL处理对象的扇区数;(只能同时处理连续的扇区)
        MOV        BX,0
        MOV        DL,0x00         ;A驱动器
        INT        0x13            ;调用磁盘BIOS 注释:调用BIOS磁盘0x13号函数。
        JC        error            ;注释:这次的新指令JC:大意是:如果进位标志是1的话,就跳转。   
        ;这里特别解释一下:通过上面一连串的配置,再执行INT 0x13 我们就会去读磁盘内容(为什么是读,因为我们AH那个地方配置的0x02),如果读磁盘成功了,那么我们就返回0,如果错误就会返回1。
        ;我们这里可以这样理解,从 MOV        AX,0x0820 这里到 MOV        DL,0x00 都是我们传递给INT        0x13函数的参数(C语言式理解),那么JC        error 就是对函数返回值的判断。
        ;那我们传递给函数的参数究竟什么意思呢?主要是告诉这个函数我到底去哪个位置读取我想要的数据呢? 毕竟磁盘大如海,想要知道具体去那一片数据还是不容易的。
        ;下面来看怎么确定读取磁盘想要的位置:①首先加入有多个驱动器,那么我们要指定从哪个驱动器读取,这就是DL干的事;②然后00000
;======================================END===========================================
 
; 読み終わったけどとりあえずやることないので寝る
 
 
fin:
        HLT                        ; 何かあるまでCPUを停止させる
        JMP        fin                ; 無限ループ
 
 
error:
        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
msg:
        DB        0x0a, 0x0a        ; 改行を2つ
        DB        "load error"
        DB        0x0a            ; 改行
        DB        0
 
 
        RESB    0x7dfe-$        ; 0x7dfeまでを0x00で埋める命令
 
 
        DB        0x55, 0xaa           

Two: trial and error

Purpose: In order to prevent the floppy disk from occasionally making an error, the program will not terminate immediately, and still try to read the disk again, there is a second section of the program:

Note: JNC: Jump when the carry flag is 0 when the JAE is greater than or equal to

; haribote-ipl
; TAB=4
ORG 0x7c00 ; このプログラムがどこに読み込まれるのか
; 以下は標準的なFAT12フォーマットフロッピーディスクのための記述
JMP entry
DB 0x90
DB "HARIBOTE" ; ブートセクタの名前を自由に書いてよい(8バイト)
DW 512 ; 1セクタの大きさ(512にしなければいけない)
DB 1 ; クラスタの大きさ(1セクタにしなければいけない)
DW 1 ; FATがどこから始まるか(普通は1セクタ目からにする)
DB 2 ; FATの個数(2にしなければいけない)
DW 224 ; ルートディレクトリ領域の大きさ(普通は224エントリにする)
DW 2880 ; このドライブの大きさ(2880セクタにしなければいけない)
DB 0xf0 ; メディアのタイプ(0xf0にしなければいけない)
DW 9 ; FAT領域の長さ(9セクタにしなければいけない)
DW 18 ; 1トラックにいくつのセクタがあるか(18にしなければいけない)
DW 2 ; ヘッドの数(2にしなければいけない)
DD 0 ; パーティションを使ってないのでここは必ず0
DD 2880 ; このドライブ大きさをもう一度書く
DB 0,0,0x29 ; よくわからないけどこの値にしておくといいらしい
DD 0xffffffff ; たぶんボリュームシリアル番号
DB "HARIBOTEOS " ; ディスクの名前(11バイト)
DB "FAT12 " ; フォーマットの名前(8バイト)
RESB 18 ; とりあえず18バイトあけておく
; プログラム本体
entry:
MOV AX,0 ; レジスタ初期化
MOV SS,AX
MOV SP,0x7c00
MOV DS,AX
; ディスクを読む
MOV AX,0x0820
MOV ES,AX
MOV CH,0 ; 柱面0 CH表示的是柱面号
MOV DH,0 ; 磁头0 磁头号
MOV CL,2 ; 扇区2 CL扇区号
;===============================这次添加的新内容START=================================
MOV SI,0 ; 记录失败次数的寄存器
retry:
MOV AH,0x02 ; 读盘(0x03是写磁盘) 注释: 看来每次读写数据,都要进行AH寄存器的配置,不像上面CL,可以保存,只配置一次
MOV AL,1 ; 1扇区 注释:这里是读写扇区的数目,和上面的CL是不同的
MOV BX,0
MOV DL,0x00 ; A驱动器
INT 0x13 ; 调用磁盘BIOS
JNC fin ; 没出错的话,就跳转到fine
ADD SI,1 ; 往SI+1
CMP SI,5 ; 比较SI与5
JAE error ; SI >= 5 大于5时跳转到error
MOV AH,0x00
MOV DL,0x00 ; A驱动器
INT 0x13 ; 重置驱动器
JMP retry
;======================================END===========================================
; 読み終わったけどとりあえずやることないので寝る
fin:
HLT ; 何かあるまでCPUを停止させる
JMP fin ; 無限ループ
error:
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
msg:
DB 0x0a, 0x0a ; 改行を2つ
DB "load error"
DB 0x0a ; 改行
DB 0
RESB 0x7dfe-$ ; 0x7dfeまでを0x00で埋める命令
DB 0x55, 0xaa
           

The newly added code in this section is converted into C language, roughly as follows (for reference only, after all, it is also a rookie)

ErrorHandling()
{
    static int SI=0;
    AH=0x002;
    AL=1;
    BX=0;
    DL=0x00;
    BOOL VAL=ExecutivDrive() ;
    if(FALSE == VAL)
    {
        执行fine函数;
    }
    else
    {
        SI++;
    }
    if(SI >= 5)
    {
        执行error函数;
    }
    else
    {
        AH=0x00;
        DL=0x00;
        BOOL VAL =ExecutivDrive();//执行驱动器
        if(TRUE == VAL)
        {
            ErrorHandling();
        }
    }
}
 
 
ExecutivDrive()
{
    INT  0x13;
}           

Three, read to 18 sectors

The main purpose of this section is to teach us how to use loops to read and write the contents of other sector cylinders. The same content of the next session will naturally be.

; haribote-ipl
; TAB=4
 
 
        ORG        0x7c00            ; このプログラムがどこに読み込まれるのか
 
 
; 以下は標準的なFAT12フォーマットフロッピーディスクのための記述
 
 
        JMP        entry
        DB        0x90
        DB        "HARIBOTE"        ; ブートセクタの名前を自由に書いてよい(8バイト)
        DW        512                ; 1セクタの大きさ(512にしなければいけない)
        DB        1                ; クラスタの大きさ(1セクタにしなければいけない)
        DW        1                ; FATがどこから始まるか(普通は1セクタ目からにする)
        DB        2                ; FATの個数(2にしなければいけない)
        DW        224                ; ルートディレクトリ領域の大きさ(普通は224エントリにする)
        DW        2880            ; このドライブの大きさ(2880セクタにしなければいけない)
        DB        0xf0            ; メディアのタイプ(0xf0にしなければいけない)
        DW        9                ; FAT領域の長さ(9セクタにしなければいけない)
        DW        18                ; 1トラックにいくつのセクタがあるか(18にしなければいけない)
        DW        2                ; ヘッドの数(2にしなければいけない)
        DD        0                ; パーティションを使ってないのでここは必ず0
        DD        2880            ; このドライブ大きさをもう一度書く
        DB        0,0,0x29        ; よくわからないけどこの値にしておくといいらしい
        DD        0xffffffff        ; たぶんボリュームシリアル番号
        DB        "HARIBOTEOS "    ; ディスクの名前(11バイト)
        DB        "FAT12   "        ; フォーマットの名前(8バイト)
        RESB    18                ; とりあえず18バイトあけておく
 
 
; プログラム本体
 
 
entry:
        MOV        AX,0            ; レジスタ初期化
        MOV        SS,AX
        MOV        SP,0x7c00
        MOV        DS,AX
 
 
; ディスクを読む
 
 
        MOV        AX,0x0820
        MOV        ES,AX
        MOV        CH,0            ; シリンダ0
        MOV        DH,0            ; ヘッド0
        MOV        CL,2            ; セクタ2
readloop:
        MOV        SI,0            ; 失敗回数を数えるレジスタ
retry:
        MOV        AH,0x02            ; AH=0x02 : ディスク読み込み
        MOV        AL,1            ; 1セクタ
        MOV        BX,0
        MOV        DL,0x00            ; Aドライブ
        INT        0x13            ; 调用磁盘BIOS
;===============================这次添加的新内容START=================================
        JNC        next            ; 没有出错就跳转到next
        ADD        SI,1            ; 往SI中+1  注释:把他当作C语言中的临时变量或者说静态变量就好了
        CMP        SI,5            ; 比较SI与5
        JAE        error           ; SI >= 5 だったらerrorへ
        MOV        AH,0x00
        MOV        DL,0x00         ; Aドライブ
        INT        0x13            ; ドライブのリセット
        JMP        retry
next:
        MOV        AX,ES           ; 把内存地址后移0x200
        ADD        AX,0x0020       ; 0x0020是十六进制下512除以16的结果。所以这里的意思就是下一个512的地方。我们知道最开始的启动区就是512,我们以512为一个扇区。
        MOV        ES,AX           ; ADD ES,0x020 という命令がないのでこうしている
        ADD        CL,1            ; CL+1 注释: 这里的意思是当读取一个扇区成功后紧接着读下一个扇区。
        CMP        CL,18           ; 比较CL与18  注释:是否18个扇区都读完了 
        JBE        readloop        ; 如果CL <= 18 就跳转到read loop  注释:小于等于就跳转
;这一段代码主要是为了读完18个扇区,这从最后的CL 与18的比较也能看出来。如果没有读完就返回最上面,如果读完了就继续执行到下面fine中
;======================================END===========================================
 
; 読み終わったけどとりあえずやることないので寝る
 
 
fin:
        HLT                        ; 何かあるまでCPUを停止させる
        JMP        fin                ; 無限ループ
 
 
error:
        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
msg:
        DB        0x0a, 0x0a        ; 改行を2つ
        DB        "load error"
        DB        0x0a            ; 改行
        DB        0
 
 
        RESB    0x7dfe-$        ; 0x7dfeまでを0x00で埋める命令
 
 
        DB        0x55, 0xaa
            

Four, 10 cylinders

Note: C0-H0-S1 (cylinder 0; head 0, short for sector 1); in each king CL in the previous section + 1, the sector is changed. This will read the cylinder. It can be seen that in the case of the i of the bit reading the book, the first guess is to add a loop on the previous section. A cmp less than or equal to 10 is enough. (Pure speculation, not to change)

; haribote-ipl
; TAB=4
 
 
CYLS    EQU        10                ; 相当于宏定义,将CYLS的值等于10
 
 
        ORG        0x7c00            ; このプログラムがどこに読み込まれるのか
 
 
; 以下は標準的なFAT12フォーマットフロッピーディスクのための記述
 
 
        JMP        entry
        DB        0x90
        DB        "HARIBOTE"        ; ブートセクタの名前を自由に書いてよい(8バイト)
        DW        512                ; 1セクタの大きさ(512にしなければいけない)
        DB        1                ; クラスタの大きさ(1セクタにしなければいけない)
        DW        1                ; FATがどこから始まるか(普通は1セクタ目からにする)
        DB        2                ; FATの個数(2にしなければいけない)
        DW        224                ; ルートディレクトリ領域の大きさ(普通は224エントリにする)
        DW        2880            ; このドライブの大きさ(2880セクタにしなければいけない)
        DB        0xf0            ; メディアのタイプ(0xf0にしなければいけない)
        DW        9                ; FAT領域の長さ(9セクタにしなければいけない)
        DW        18                ; 1トラックにいくつのセクタがあるか(18にしなければいけない)
        DW        2                ; ヘッドの数(2にしなければいけない)
        DD        0                ; パーティションを使ってないのでここは必ず0
        DD        2880            ; このドライブ大きさをもう一度書く
        DB        0,0,0x29        ; よくわからないけどこの値にしておくといいらしい
        DD        0xffffffff        ; たぶんボリュームシリアル番号
        DB        "HARIBOTEOS "    ; ディスクの名前(11バイト)
        DB        "FAT12   "        ; フォーマットの名前(8バイト)
        RESB    18                ; とりあえず18バイトあけておく
 
 
; プログラム本体
 
 
entry:
        MOV        AX,0            ; レジスタ初期化
        MOV        SS,AX
        MOV        SP,0x7c00
        MOV        DS,AX
 
 
; ディスクを読む
 
 
        MOV        AX,0x0820
        MOV        ES,AX
        MOV        CH,0            ; シリンダ0
        MOV        DH,0            ; 磁头0
        MOV        CL,2            ; 扇区2
readloop:
        MOV        SI,0            ; 记录失败次数的寄存器
retry:
        MOV        AH,0x02            ; AH=0x02 : ディスク読み込み
        MOV        AL,1            ; 1个扇区 注释:这里是读写扇区的数目,和上面的CL是不同的
        MOV        BX,0
        MOV        DL,0x00            ; Aドライブ
        INT        0x13            ; ディスクBIOS呼び出し
        JNC        next            ; エラーがおきなければnextへ
        ADD        SI,1            ; SIに1を足す
        CMP        SI,5            ; SIと5を比較
        JAE        error            ; SI >= 5 だったらerrorへ
        MOV        AH,0x00
        MOV        DL,0x00            ; Aドライブ
        INT        0x13            ; ドライブのリセット
        JMP        retry
next:
        MOV        AX,ES            ; アドレスを0x200進める
        ADD        AX,0x0020
        MOV        ES,AX            ; ADD ES,0x020 という命令がないのでこうしている
        ADD        CL,1            ; CLに1を足す
        CMP        CL,18            ; CLと18を比較
        JBE        readloop        ; CL <= 18 だったらreadloopへ
;===============================这次添加的新内容START=================================
        MOV        CL,1            ;这里为什么读完18个扇区后,读下一个柱面的时候,CL先+1呢? 整个磁盘是一个循环。洗一个柱面从第一个扇区开始读写的。
        ADD        DH,1            ;有两个磁头,正反面,反正我是这样理解的
        CMP        DH,2
        JB        readloop        ; 如果DH < 2 就跳转到readloop。
        MOV        DH,0            ;反面读完了,那么从正面在开始读,磁头便置零了
        ADD        CH,1            ;好了,柱面也开始+1了
        CMP        CH,CYLS        ; 这里还用了一个宏定义。代表10个柱面
        JB        readloop        ; 如果CH < CYLS 就跳转到readloop
;======================================END===========================================
 
; 読み終わったけどとりあえずやることないので寝る
 
 
fin:
        HLT                        ; 何かあるまでCPUを停止させる
        JMP        fin                ; 無限ループ
 
 
error:
        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
msg:
        DB        0x0a, 0x0a        ; 改行を2つ
        DB        "load error"
        DB        0x0a            ; 改行
        DB        0
 
 
        RESB    0x7dfe-$        ; 0x7dfeまでを0x00で埋める命令
 
 
        DB        0x55, 0xaa
            

At this point, the production of the startup area is completed. In fact, looking back here, the author only installed 10×2×18×512= 184320byte = 180KB content into memory without error. Here's the question: what do you do when you load into a class? Can our program (main in C) run? What if my main is more than that number? Oh here is just the startup area, it can then call the main function? Harm here or do not understand, can not give an example, really special garbage, and then look at the back:

Five, start to develop the operating system Well, I think this section is too ridiculous. It means that I don't really understand it, and I know roughly what's going on. Think about it and don't know what's going on.

Sixth, execute the operating system from the boot area

Application of ORG. The other five verses of the earth have already been said

; haribote-ipl
; TAB=4
 
 
CYLS    EQU        10                ; どこまで読み込むか
 
 
        ORG        0x7c00            ; このプログラムがどこに読み込まれるのか
 
 
; 以下は標準的なFAT12フォーマットフロッピーディスクのための記述
 
 
        JMP        entry
        DB        0x90
        DB        "HARIBOTE"        ; ブートセクタの名前を自由に書いてよい(8バイト)
        DW        512                ; 1セクタの大きさ(512にしなければいけない)
        DB        1                ; クラスタの大きさ(1セクタにしなければいけない)
        DW        1                ; FATがどこから始まるか(普通は1セクタ目からにする)
        DB        2                ; FATの個数(2にしなければいけない)
        DW        224                ; ルートディレクトリ領域の大きさ(普通は224エントリにする)
        DW        2880            ; このドライブの大きさ(2880セクタにしなければいけない)
        DB        0xf0            ; メディアのタイプ(0xf0にしなければいけない)
        DW        9                ; FAT領域の長さ(9セクタにしなければいけない)
        DW        18                ; 1トラックにいくつのセクタがあるか(18にしなければいけない)
        DW        2                ; ヘッドの数(2にしなければいけない)
        DD        0                ; パーティションを使ってないのでここは必ず0
        DD        2880            ; このドライブ大きさをもう一度書く
        DB        0,0,0x29        ; よくわからないけどこの値にしておくといいらしい
        DD        0xffffffff        ; たぶんボリュームシリアル番号
        DB        "HARIBOTEOS "    ; ディスクの名前(11バイト)
        DB        "FAT12   "        ; フォーマットの名前(8バイト)
        RESB    18                ; とりあえず18バイトあけておく
 
 
; プログラム本体
 
 
entry:
        MOV        AX,0            ; レジスタ初期化
        MOV        SS,AX
        MOV        SP,0x7c00
        MOV        DS,AX
 
 
; ディスクを読む
 
 
        MOV        AX,0x0820
        MOV        ES,AX
        MOV        CH,0            ; シリンダ0
        MOV        DH,0            ; ヘッド0
        MOV        CL,2            ; セクタ2
readloop:
        MOV        SI,0            ; 失敗回数を数えるレジスタ
retry:
        MOV        AH,0x02            ; AH=0x02 : ディスク読み込み
        MOV        AL,1            ; 1セクタ
        MOV        BX,0
        MOV        DL,0x00            ; Aドライブ
        INT        0x13            ; ディスクBIOS呼び出し
        JNC        next            ; エラーがおきなければnextへ
        ADD        SI,1            ; SIに1を足す
        CMP        SI,5            ; SIと5を比較
        JAE        error            ; SI >= 5 だったらerrorへ
        MOV        AH,0x00
        MOV        DL,0x00            ; Aドライブ
        INT        0x13            ; ドライブのリセット
        JMP        retry
next:
        MOV        AX,ES            ; アドレスを0x200進める
        ADD        AX,0x0020
        MOV        ES,AX            ; ADD ES,0x020 という命令がないのでこうしている
        ADD        CL,1            ; CLに1を足す
        CMP        CL,18            ; CLと18を比較
        JBE        readloop        ; CL <= 18 だったらreadloopへ
        MOV        CL,1
        ADD        DH,1
        CMP        DH,2
        JB        readloop        ; DH < 2 だったらreadloopへ
        MOV        DH,0
        ADD        CH,1
        CMP        CH,CYLS
        JB        readloop        ; CH < CYLS だったらreadloopへ
 
 
; 読み終わったのでharibote.sysを実行だ!
 
;===============================这次添加的新内容START=================================
        JMP        0xc200            
        ;这里就是,将之前说的180KB的内容装进了内存中,并且我们知道了我们的程序在0xc200的位置
        ;所以前面做的只是读取,这里有点犯迷糊。仔细想一想,之前是读取磁盘的内容到一个内存中
        ;假设他们的地址从0~100,现在我们读完之后,到自己的内存中c200的位置去执行。好吧反正我是觉得挺绕的。
        ;另外我们的磁盘大小就是180KB,我想知道如果程序不在这个180 中怎么办?或者180没读完怎么办?????
;======================================END===========================================
error:
        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        "load error"
        DB        0x0a            ; 改行
        DB        0
 
 
        RESB    0x7dfe-$        ; 0x7dfeまでを0x00で埋める命令
 
 
        DB        0x55, 0xaa
 
 
 
 
七,确认操作系统的执行情况
        注释:这节主要的目的是给显示其以色彩。调用显使能
; haribote-ipl
; TAB=4
 
 
CYLS    EQU        10                ; どこまで読み込むか
 
 
        ORG        0x7c00            ; このプログラムがどこに読み込まれるのか
 
 
; 以下は標準的なFAT12フォーマットフロッピーディスクのための記述
 
 
        JMP        entry
        DB        0x90
        DB        "HARIBOTE"        ; ブートセクタの名前を自由に書いてよい(8バイト)
        DW        512                ; 1セクタの大きさ(512にしなければいけない)
        DB        1                ; クラスタの大きさ(1セクタにしなければいけない)
        DW        1                ; FATがどこから始まるか(普通は1セクタ目からにする)
        DB        2                ; FATの個数(2にしなければいけない)
        DW        224                ; ルートディレクトリ領域の大きさ(普通は224エントリにする)
        DW        2880            ; このドライブの大きさ(2880セクタにしなければいけない)
        DB        0xf0            ; メディアのタイプ(0xf0にしなければいけない)
        DW        9                ; FAT領域の長さ(9セクタにしなければいけない)
        DW        18                ; 1トラックにいくつのセクタがあるか(18にしなければいけない)
        DW        2                ; ヘッドの数(2にしなければいけない)
        DD        0                ; パーティションを使ってないのでここは必ず0
        DD        2880            ; このドライブ大きさをもう一度書く
        DB        0,0,0x29        ; よくわからないけどこの値にしておくといいらしい
        DD        0xffffffff        ; たぶんボリュームシリアル番号
        DB        "HARIBOTEOS "    ; ディスクの名前(11バイト)
        DB        "FAT12   "        ; フォーマットの名前(8バイト)
        RESB    18                ; とりあえず18バイトあけておく
 
 
; プログラム本体
 
 
entry:
        MOV        AX,0            ; レジスタ初期化
        MOV        SS,AX
        MOV        SP,0x7c00
        MOV        DS,AX
 
 
; ディスクを読む
 
 
        MOV        AX,0x0820
        MOV        ES,AX
        MOV        CH,0            ; シリンダ0
        MOV        DH,0            ; ヘッド0
        MOV        CL,2            ; セクタ2
readloop:
        MOV        SI,0            ; 失敗回数を数えるレジスタ
retry:
        MOV        AH,0x02            ; AH=0x02 : ディスク読み込み
        MOV        AL,1            ; 1セクタ
        MOV        BX,0
        MOV        DL,0x00            ; Aドライブ
        INT        0x13            ; ディスクBIOS呼び出し
        JNC        next            ; エラーがおきなければnextへ
        ADD        SI,1            ; SIに1を足す
        CMP        SI,5            ; SIと5を比較
        JAE        error            ; SI >= 5 だったらerrorへ
        MOV        AH,0x00
        MOV        DL,0x00            ; Aドライブ
        INT        0x13            ; ドライブのリセット
        JMP        retry
next:
        MOV        AX,ES            ; アドレスを0x200進める
        ADD        AX,0x0020
        MOV        ES,AX            ; ADD ES,0x020 という命令がないのでこうしている
        ADD        CL,1            ; CLに1を足す
        CMP        CL,18            ; CLと18を比較
        JBE        readloop        ; CL <= 18 だったらreadloopへ
        MOV        CL,1
        ADD        DH,1
        CMP        DH,2
        JB        readloop        ; DH < 2 だったらreadloopへ
        MOV        DH,0
        ADD        CH,1
        CMP        CH,CYLS
        JB        readloop        ; CH < CYLS だったらreadloopへ
 
 
; 読み終わったのでharibote.sysを実行だ!
 
 
;===============================这次添加的新内容START=================================
 
        MOV        [0x0ff0],CH        ; 记下IPL读到哪里了。  注释:咱也不知道这里是干啥用的,后面看看再说
                                        ;理解:大致意思是我们当前在哪一个柱面
        JMP        0xc200
;======================================END===========================================
 
error:
        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        "load error"
        DB        0x0a            ; 改行
        DB        0
 
 
        RESB    0x7dfe-$        ; 0x7dfeまでを0x00で埋める命令
 
 
        DB        0x55, 0xaa



           
;haribote.nas
; haribote-os
; TAB=4
 
 
 
 
 
;===============================这次添加的新内容START=================================
        ORG        0xc200            ; 这个程序要被装在到内存的什么地方呢?  
                                     ;这个意思就是说,我们的程序所有的最初的地方是从这个地址开始的
 
 
        MOV        AL,0x13            ; 这里的AL和之前的启动区的AL 和 AH不大一样。注意区分!这里是VGA显卡,320×200×8位彩色
        MOV        AH,0x00
        INT        0x10            ;没猜错这里的INT就是显卡的 那个BIOS,和之前的CPU的BIOS一样的方式。先设置参数,在调用这里。上面的AH应该就是参数了
;======================================END===========================================
fin:
        HLT
        JMP        fin           

interpretation:

Eight, 32-bit preparation

; haribote-os
; TAB=4
 
 
; BOOT_INFO関係
CYLS    EQU        0x0ff0            ; 设定启动区
LEDS    EQU        0x0ff1
VMODE    EQU        0x0ff2            ; 关于颜色数目的信息。颜色的位数
SCRNX    EQU        0x0ff4            ; 分辨率的X
SCRNY    EQU        0x0ff6            ; 分辨率的Y
VRAM    EQU        0x0ff8            ; 图像缓冲区的开始地址  注释:VRAM是显卡内存
 
 
        ORG        0xc200            ; 这个程序要装载到的内存的地方
 
 
        MOV        AL,0x13            ; VGA显卡,320x200x8位彩色
        MOV        AH,0x00
        INT        0x10
        MOV        BYTE [VMODE],8    ; 记录画面模式
        MOV        WORD [SCRNX],320
        MOV        WORD [SCRNY],200
        MOV        DWORD [VRAM],0x000a0000
 
 
; 用BIOS取得键盘上各种LED指示灯的状态
 
 
        MOV        AH,0x02
        INT        0x16             ; keyboard BIOS
        MOV        [LEDS],AL
 
 
fin:
        HLT
        JMP        fin           
30 days of homebrew operating system --- day 3
;asmhead.nas
; haribote-os boot asm
; TAB=4
 
 
BOTPAK    EQU        0x00280000        ; bootpackのロード先
DSKCAC    EQU        0x00100000        ; ディスクキャッシュの場所
DSKCAC0    EQU        0x00008000        ; ディスクキャッシュの場所(リアルモード)
 
 
; BOOT_INFO関係
CYLS    EQU        0x0ff0            ; ブートセクタが設定する
LEDS    EQU        0x0ff1
VMODE    EQU        0x0ff2            ; 色数に関する情報。何ビットカラーか?
SCRNX    EQU        0x0ff4            ; 解像度のX
SCRNY    EQU        0x0ff6            ; 解像度のY
VRAM    EQU        0x0ff8            ; グラフィックバッファの開始番地
 
 
        ORG        0xc200            ; このプログラムがどこに読み込まれるのか
 
 
; 画面モードを設定
 
 
        MOV        AL,0x13            ; VGAグラフィックス、320x200x8bitカラー
        MOV        AH,0x00
        INT        0x10
        MOV        BYTE [VMODE],8    ; 画面モードをメモする(C言語が参照する)
        MOV        WORD [SCRNX],320
        MOV        WORD [SCRNY],200
        MOV        DWORD [VRAM],0x000a0000
 
 
; キーボードのLED状態をBIOSに教えてもらう
 
 
        MOV        AH,0x02
        INT        0x16             ; keyboard BIOS
        MOV        [LEDS],AL
;===============================这次添加的新内容START=================================
;这里就是为了系统能够调用C语言做的准备,但是作者目前没有说,期待之后的补充
; PICが一切の割り込みを受け付けないようにする
;    AT互換機の仕様では、PICの初期化をするなら、
;    こいつをCLI前にやっておかないと、たまにハングアップする
;    PICの初期化はあとでやる
 
 
        MOV        AL,0xff
        OUT        0x21,AL
        NOP                        ; OUT命令を連続させるとうまくいかない機種があるらしいので
        OUT        0xa1,AL
 
 
        CLI                        ; さらにCPUレベルでも割り込み禁止
 
 
; CPUから1MB以上のメモリにアクセスできるように、A20GATEを設定
 
 
        CALL    waitkbdout
        MOV        AL,0xd1
        OUT        0x64,AL
        CALL    waitkbdout
        MOV        AL,0xdf            ; enable A20
        OUT        0x60,AL
        CALL    waitkbdout
 
 
; プロテクトモード移行
 
 
[INSTRSET "i486p"]                ; 486の命令まで使いたいという記述
 
 
        LGDT    [GDTR0]            ; 暫定GDTを設定
        MOV        EAX,CR0
        AND        EAX,0x7fffffff    ; bit31を0にする(ページング禁止のため)
        OR        EAX,0x00000001    ; bit0を1にする(プロテクトモード移行のため)
        MOV        CR0,EAX
        JMP        pipelineflush
pipelineflush:
        MOV        AX,1*8            ;  読み書き可能セグメント32bit
        MOV        DS,AX
        MOV        ES,AX
        MOV        FS,AX
        MOV        GS,AX
        MOV        SS,AX
 
 
; bootpackの転送
 
 
        MOV        ESI,bootpack    ; 転送元
        MOV        EDI,BOTPAK        ; 転送先
        MOV        ECX,512*1024/4
        CALL    memcpy
 
 
; ついでにディスクデータも本来の位置へ転送
 
 
; まずはブートセクタから
 
 
        MOV        ESI,0x7c00        ; 転送元
        MOV        EDI,DSKCAC        ; 転送先
        MOV        ECX,512/4
        CALL    memcpy
 
 
; 残り全部
 
 
        MOV        ESI,DSKCAC0+512    ; 転送元
        MOV        EDI,DSKCAC+512    ; 転送先
        MOV        ECX,0
        MOV        CL,BYTE [CYLS]
        IMUL    ECX,512*18*2/4    ; シリンダ数からバイト数/4に変換
        SUB        ECX,512/4        ; IPLの分だけ差し引く
        CALL    memcpy
 
 
; asmheadでしなければいけないことは全部し終わったので、
;    あとはbootpackに任せる
 
 
; bootpackの起動
 
 
        MOV        EBX,BOTPAK
        MOV        ECX,[EBX+16]
        ADD        ECX,3            ; ECX += 3;
        SHR        ECX,2            ; ECX /= 4;
        JZ        skip            ; 転送するべきものがない
        MOV        ESI,[EBX+20]    ; 転送元
        ADD        ESI,EBX
        MOV        EDI,[EBX+12]    ; 転送先
        CALL    memcpy
skip:
        MOV        ESP,[EBX+12]    ; スタック初期値
        JMP        DWORD 2*8:0x0000001b
 
 
waitkbdout:
        IN         AL,0x64
        AND         AL,0x02
        JNZ        waitkbdout        ; ANDの結果が0でなければwaitkbdoutへ
        RET
 
 
memcpy:
        MOV        EAX,[ESI]
        ADD        ESI,4
        MOV        [EDI],EAX
        ADD        EDI,4
        SUB        ECX,1
        JNZ        memcpy            ; 引き算した結果が0でなければmemcpyへ
        RET
; memcpyはアドレスサイズプリフィクスを入れ忘れなければ、ストリング命令でも書ける
 
 
        ALIGNB    16
GDT0:
        RESB    8                ; ヌルセレクタ
        DW        0xffff,0x0000,0x9200,0x00cf    ; 読み書き可能セグメント32bit
        DW        0xffff,0x0000,0x9a28,0x0047    ; 実行可能セグメント32bit(bootpack用)
 
 
        DW        0
GDTR0:
        DW        8*3-1
        DD        GDT0
 
 
        ALIGNB    16
bootpack:
;======================================END===========================================
 
 
    
void HariMain(void)
{
 
 
fin:
    /* ここにHLTを入れたいのだが、C言語ではHLTが使えない! */
    goto fin;
 
 
}           

Read on