30天自制操做系统-3

我依稀记得当初看到这一节标题的时候很是很是的兴奋,由于能够用C语言了。windows

首先是咱们要来制做真正的IPL了,回顾一下,IPL就是那512个启动字节,让他来引导真正的操做系统,由于512个字节太少了,不能作太多逻辑。安全

MOV        AX,0x0820
    MOV        ES,AX
    MOV        CH,0            ; 柱面0
    MOV        DH,0            ; 磁头0
    MOV        CL,2            ; 扇区2

    MOV        AH,0x02            ; AH=0x02 : 读盘
    MOV        AL,1            ; 1个扇区
    MOV        BX,0
    MOV        DL,0x00            ; A驱动器
    INT        0x13            ; 调用磁盘BIOS
    JC        error

这里又调用了一个中断,上一个中断是向显示器上输出一个字符,这个中断的做用就是对磁盘进行操做的,若是把他看成C语言或者其余高级语言来说会很方便,就是这是个对磁盘操做的函数,而后调用前,你给这些寄存器传一些参数,而后会经过标志位的方式返回读取结果,即CF标志位。函数

介绍一下软盘,这玩意儿淘宝上还能买到,我最开始学的时候买过,实体店早已看不到了,一点几MB的内存,我小仓老师的照片都放不了。。。要它何用。软盘分正反,叫磁头。柱面,能够理解在这个软盘上画了更多的圆圈,而后再分红扇形,也就有了,柱面和扇区。磁盘号是指那么多个软盘,你读哪一个。
咱们的IPL就会放在C0-H0-S1(也就是柱面0,磁头0,扇区1),本人不太理解,为啥柱面从0开始而扇区不是。
这里要介绍个新玩意儿了段寄存器,我记得我在学汇编时很经典的一句话,物理地址=段地址 x 10 + 偏移地址 (基于10进制,若是是16进制x16就行了)。若是指定用法就得把段寄存器与偏移地址写在一起,若是不写默认以DS做为默认段寄存器,昨天就用到了[],暂时还没讲这个东西次。记得和C语言保持一个习惯,变量初始化,这里的DS也记得初始化,否则会读到其余的内存地址去。
by the way Makefile里面的变量特别像PHP里的变量。oop

;多式几回操作系统

MOV        AX,0x0820
    MOV        ES,AX
    MOV        CH,0            ; 柱面0
    MOV        DH,0            ; 磁头0
    MOV        CL,2            ; 扇区2

    MOV        SI,0            ; 记录失败次数

retry:命令行

MOV        AH,0x02            ; AH=0x02 : 读盘
    MOV        AL,1            ; 1个扇区
    MOV        BX,0
    MOV        DL,0x00            ;  A驱动器
    INT        0x13            ; 调用磁盘BIOS
    JNC        fin                ; 若OK则跳转至fin
    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

JNC会去判断CF标志位的状态如果0则会跳转。
JAE大于等于则跳转code

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            ; 若OK则跳转至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(512字节)
    ADD        AX,0x0020
    MOV        ES,AX            ; ADD ES,0x020 由于没有这个指令因此只能找中介
    ADD        CL,1            ; 往CL里加1
    CMP        CL,18            ; 比较CL与18
    JBE        readloop        ; 若是CL <= 18 跳转至readloop

JBE只要是拿来控制读取到18扇区的,小于等于则跳转。
咱们知道磁盘读出来后的内容都放到了ES:BX了,然而咱们分别设置了ES与BX,因此程序也就装载到相应位置啦。
接下来是读取是个柱面,这里就不贴代码了。直接说说新指令把。
JB就是小于等于跳转。还有EQU 这个很是建议写一些常常要改的东西这样写,由于稍微作过项目就知道这种玩意儿不写成这样那是找骂呀。
如今磁盘上的180KB字节就存储在ES:BX这个地方啦。没什么太多难度,就是须要每句去理解。

着手开发操做系统啦。。。

这里做者给了一个很是简单的操做系统。。
but...这是历史的转折点,这毕竟是在启动区以外了,咱们要读取IPL以外的代码了,从harib00e(光盘目录)看得出来多了一个文件haribote.nas,这个就是咱们的操做系统啦,由刚才的main函数(IPL),调用到了这边来,而后做者经过二进制软件一顿分析,得出了以下结论 1.文件名会写在0x002600之后的地方 2.文件的内容会写在0x004200之后的地方 其实我在纠结一个问题,要是0x002600-0x004200之间都写了文件名咋办。不过他说的是0x002600之后,并不是之间,嗯,那我就放心了。知道这个文件的内存地址后,如今咱们就要来读取这个文件啦。

从启动区执行操做系统
若是咱们是把程序装载在0的位置那么直接使用0x004200就好了,但问题是操做系统有它应该放的位置,因此前面咱们放在了0x0820的位置,一开始做者说0x8000我小楞了一下,不是放在0x0820位置的吗?(我仍是解释一下,怕有些出血朋友不能理解到)首先,这是个段地址会进行偏移,偏移为0x8200,而后200,一想是512个字节,因此这就是咱们的启动区嘛,因此正确,就是0x8000。因此咱们的程序须要从0x8000+0x4200 = 0xc200地址读取咱们的hairbote.nas文件。

这里又新调用了一个“函数” int 0x10,配合上参数这个的做用是把屏幕弄成VGA图形模式,因此咱们要开始作图形界面啦,而非一部份书是作命令行模式的(固然这并不表明我对那种书的差评,我直是以为一上来作图形界面,会让初学者更又兴趣)

立刻要进入32位模式啦
优势固然是更多的内存空间可使用,与安全性。

; 有关BOOT_INFO
CYLS EQU 0x0ff0 ; 设定启动项
LEDS EQU 0x0ff1
VMODE EQU 0x0ff2 ; 关于颜色数目的信息。颜色的位数
SCRNX EQU 0x0ff4 ; 分辨率的X
SCRNY EQU 0x0ff6 ; 分辨率的Y
VRAM EQU 0x0ff8 ; 图像缓冲区的开始地址

ORG        0xc200            ; 将程序装载到0xc200处

    MOV        AL,0x13            ; VGA显卡,320*200*8位彩色
    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

这里呢,也没作啥实际的操做,就是把各类数据记录下来了,而后经过int 0x16取得了键盘上各类指示灯的状态

开始导入C语言
从一开始我就说要开始C语言了,结果到了今天快结束才开始说导入C语言
虽然说导入吧,其实有不少原理性的东西,在这里不会讲,其实里面就是后面的GDT等内容,我也是看到后面的GDT开始有些卡主了,因此这里做者没有讲,而是直接来看bootpack.c吧。
void HariMain(void)
{
fin:

goto fin;

}

看到这种代码,我又从新找回了自信,毕竟我不是那个时代过来的人,没有每天写过汇编,因此汇编和C,固然是C更亲近些。我想这玩意儿C代码也不用解释太多。至因而如何调用到这里来的,后面再细谈。
关于对编译器的解释,也很简单。解释的那么清楚,而后与windows,mac上如此成熟的集成开发环境作了对比,意思是相对于那种,咱们搞这么复杂,可是步奏是可控的。

最后做者必定要让计算机处于HALT那就来吧。

; naskfunc
; TAB=4

[FORMAT "WCOFF"] ; 制做目标文件的模式
[BITS 32] ; 制做32位模式用的机械语言

; 制做目标文件的信息

[FILE "naskfunc.nas"] ; 源文件名信息

GLOBAL    _io_hlt            ; 程序中包含的函数名

; 如下是实际的函数

[SECTION .text] ; 目标文件中写了这些以后再些程序

_io_hlt: ; void io_hlt(void);

HLT
    RET

而后回来在C语言声明一下,就能够调用啦,不过至于今天许多的细节问题,后面会又深刻讲解的。总的来讲咱们能够用C语言写代码啦。

相关文章
相关标签/搜索