30天自制操作系统---第3天

一,制作真正的IPL(启动程序装载器)
今天的目的是将昨天的启动程序装载器来装载程序。
        ①:磁盘最初的512字节是启动区。为了装载下一个512字节内容的程序,对之前的程序进行修改,得到了今天的harib00a程序;
        ②:缓冲区地址 是内存地址。将磁盘里面的程序加载到内存中  
 
; 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
 
二:试错
        目的:就是为了防止再软盘出现偶尔错误的时候,程序不会立即终止,仍然去尝试再次读取磁盘,才有了第二节的程序:
        注释:JNC:进位标志是0的话跳转    JAE大于或等于时跳转
        
; 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

 

 
本节新添加的代码转化成C语言,大致如下(仅供参考,毕竟也是个菜鸡)
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;
}

 

 
三,读到18扇区
        这节的目的主要就是教会我们怎么利用循环读写其他扇区 柱面的内容。 同样的下一届的内容也就自然会了。
; 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
 

 

 
 
 
四,10个柱面
        注释:C0-H0-S1(柱面0;磁头0,扇区1的缩写);上一节中每次王CL中+1,更改的就是扇区。这把要读柱面。可以看出,在位看书的i情况下,先行猜测,是在上一节上,在加个循环。来个cmp小于等于10  就行了。(纯属猜测,也不行改了)
        
; 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
 

 

 
 
到这里是完成了启动区的制作。其实到这里回过头来看下,作者只是将10×2×18×512=184320byte=180KB内容完整无误的装在到内存里面了。这里有个疑问:装载到类里面然后干啥? 我们的程序(C语言的main)就能运行了? 如果我的main不止这个数呢? 哦 这里只是启动区,它可以接着调用main函数? 害这里还是不理解,不能举一反三,真特么的垃圾,接着往后面看:
 

 
五,着手开发操作系统
        好吧我觉的这节太扯了。表示其实没有真的看懂,大致知道怎么回事。仔细想想又不知道具体是怎么回事。
    
 
 
六,从启动区执行操作系统
        对ORG的应用。其他的在地五节已经讲过了
 
; 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

 

解释:
 
 
八,32位的前期准备
        
; 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

 

 
 
 
九:开始导入C语言
        
;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;
 
 
}

 

 
 
 
 
 
 
posted @ 2021-02-22 22:56  怎因一双媚眼惹尘埃  阅读(463)  评论(2编辑  收藏