《30天自制操作系统》day3

内容1:制作IPL

重点总结:

  1. 学习并理解IPL概念,掌握IPL启动过程;
  2. 学习软盘的结构图及各个部分(柱面,磁头,扇区等)表示的含义;
  3. 学习并理解缓冲区地址等相关概念;
  4. 学习并掌握如何试错。

概念阐述:

(1)汇编指令:

a.JC

JC即“jump if carry”,如果进位标志是1的话,就跳转。

b.JNC

JNC即“jump if not carry”,如果进位标志是0的话,就跳转。

c.JAE

JAE即“jump if above or equal”,如果大于或者等于,就跳转。

(2)INT 0x13

AH=0x02;(读盘)

AH=0x03;(写盘)

AH=0x04;(校验)

AH=0x0c;(寻道)

AL=处理对象的扇区数;(只能同时处理连续的扇区)

CH=柱面号&0xff;

CL=扇区号(0-5位)|(柱面号&0x300)>>2;

DH=磁头号;

DL=驱动器号;

ES:BX=缓冲地址;(校验及寻道时不使用)

返回值;

FLACS.CF==0:没有错误,AH=0

FLACS.CF==1:有错误,错误号码存入AH内(与重置功能一样)

(3)软盘

·柱面有80个(0~79号)

·每个柱面有18个扇区(1~18号)

CH:柱面号:0       

CL:扇区号:0

DH:磁头号:2

DL:驱动器号:0

一张软盘有80个柱面,2个磁头,18个扇区,且一个扇区有512个字节。

所以,一张软盘的容量是:

80*2*18*512=1474560Byte=1440KB

含有IPL的启动区,位于C0-H0-S1(柱面0,磁头0,扇区1的缩写,下个扇区是C0-H0-S2)

 

关键代码:

1)制作IPL代码添加部分

              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

2Makefile重新修改部分

TOOLPATH = ../z_tools/

MAKE     = $(TOOLPATH)make.exe -r

NASK     = $(TOOLPATH)nask.exe

EDIMG    = $(TOOLPATH)edimg.exe

IMGTOL   = $(TOOLPATH)imgtol.com

COPY     = copy

DEL      = del

#在这里将原来代码中重复的部分利用MAKE等替代,增强了代码整体的可读性,但是整体代码思路和模式不变。

default :

                     $(MAKE) img

#文件命名规则

ipl.bin : ipl.nas Makefile

                     $(NASK) ipl.nas ipl.bin ipl.lst

haribote.img : ipl.bin Makefile

                     $(EDIMG)   imgin:../z_tools/fdimg0at.tek \

                            wbinimg src:ipl.bin len:512 from:0 to:0   imgout:haribote.im

# 命令

asm :

                     $(MAKE) ipl.bin

img :

                     $(MAKE) haribote.img

run :

                     $(MAKE) img

                     $(COPY) haribote.img ..\z_tools\qemu\fdimage0.bin

                     $(MAKE) -C ../z_tools/qemu

install :

                     $(MAKE) img

                     $(IMGTOL) w a: haribote.img

clean :

                     -$(DEL) ipl.bin

                     -$(DEL) ipl.lst

src_only :

                     $(MAKE) clean

                     -$(DEL) haribote.img

3)试错代码添加部分

; 读磁盘

 

              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                        ; 没出错的话跳转到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

结果显示:

内容2:读入扇区和柱面

重点总结:

  1. 理解并学会如何读入18个扇区;
  2. 理解并学会如何读入10个柱面

关键代码:

(1)读入18个扇区

; 读磁盘

 

              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时,跳转到erro

              MOV             AH,0x00

              MOV             DL,0x00               ; A驱动器

              INT        0x13                    ; 重置驱动器

              JMP       retry

next:

              MOV             AX,ES                   ; 把内存地址后移0x200 2*16^2=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,“jump if below or equal”小于等于则跳转

(2)读入10个柱面

CYLS      EQU              10                        ; 定义初识变量,10个柱面

next:

              MOV             AX,ES                   ; 把内存地址后移0x200 2*16^2=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

              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

注:JB,“jump if below”小于则跳转

内容3:着手开发操作系统并启动,确认操作系统执行情况

重点总结:

  1. 初步编写操作系统程序,查看文件内容;
  2. 学会如何从启动区启动操作系统;
  3. 学会调用新的BIOS函数确定操作系统的执行情况。

关键代码:

(1)着手开发

fin:

              HLT

              JMP       fin

(2)从启动区执行

; haribote-os

; TAB=4

 

              ORG              0xc200                 ; 载入启动区地址。

fin:

              HLT

              JMP       fin

 

; 根据haribote.sys内容修改

 

              JMP       0xc200

(3)确认执行情况

; haribote-os

; TAB=4

 

              ORG              0xc200                 ; 这个程序的地址会被装载到什么地方呢?

 

              MOV             AL,0x13               ; VGA显卡,320x200x8位彩色

              MOV             AH,0x00

              INT        0x10

fin:

              HLT

              JMP       fin

结果显示:

(1)着手开发

 

(2)从启动区执行

(3)确认执行情况

内容432位前期准备与C语言导入

重点总结:

  1. 理解16位与32位操作系统差异,能够调用BIOS;
  2. 明白显卡内存的含义,掌握如何使用显卡内存;
  3. 学习并理解C语言转化为机器语言的过程,最终实现C代码导入。

关键代码:

; haribote-os

; TAB=4

 

; 有关BOOT_INFO

CYLS      EQU              0x0ff0                  ; 设定启动区

LEDS      EQU              0x0ff1

VMODE EQU              0x0ff2                  ; 关于颜色数目的信息,颜色的位数

SCRNX   EQU              0x0ff4                  ; 分辨率的X(screen X)

SCRNY   EQU              0x0ff6                  ; 分辨率的Y(screen Y)

VRAM    EQU              0x0ff8                  ; 图像缓冲区的开始地址

 

              ORG              0xc200             ; 这个程序将要被装载到内存的什么地方呢?

 

              MOV             AL,0x13               ; VGA显卡,320x200x8bit彩色

              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

 

bookpack.c:

void HariMain(void)

{

fin:

       /* 这里想写上HLT,但是C语言中不能使用HLT */

       goto fin;

 

}

内容5:实现HLT

重点总结:

  1. 利用汇编语言编写函数;
  2. 学会设置WCOFF模式,设定成32位机器语言模式;
  3. 理解并学习文件命名规则,明白“链接”的含义。

关键代码:

naskfunc:

; naskfunc

; TAB=4

 

[FORMAT "WCOFF"]                        ; 制作目标文件的模式  

[BITS 32]                                          ; 制作32位模式用的机械语言

 

 

; 制作目标文件的信息

 

[FILE "naskfunc.nas"]              ; 程序中包含的函数名

 

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

 

 

; 以下是实际的函数

 

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

 

_io_hlt: ; void io_hlt(void);

              HLT

              RET

 

bookpack.c:

/* 告诉C编译器,有一个函数在别的文件里 */

 

void io_hlt(void);

 

/* 是函数声明却不用{},而用;,这表示的意思是:函数是在别的文件中,你自己找一下吧*/

 

void HariMain(void)

{

 

fin:

       io_hlt(); /* 执行naskfunc.nas里面的_io_hlt */

       goto fin;

 

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值