操作系统与网络实现 之三

来源:互联网 发布:灰鸽子官网数据 编辑:程序博客网 时间:2024/05/29 15:34

 

关于磁盘的数据存储和定位

这是一个磁盘示意图:

clip_image001

一个磁盘有两面。0面和1面。

磁道80个,编号由外向里(0-79)

扇区(Sector)是磁盘存储的最小单位,一个扇区有512字节,一个磁道有18个扇区(1-18)

 

为方便存取文件必须对扇区进行编号,这编号称为软盘地址。软盘地址由磁头号、磁道号、扇区号三部分组成。

(1)磁头号。0面对应0号磁头,1面对应1号磁头。   

(2)磁道号。从软盘的最外侧00道开始,由外向里排列,3.5英寸高密软盘共80个磁道。

(3)扇区号。1号至18

软盘的大小计算方式如下:

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

如果我们用磁头号+磁道号+扇区号来表达,那么:0.0.1表示00磁道1扇区

读磁盘是这样的,在同一磁道里的18个扇区是连续读,读完这个磁道,转换磁头,那么就像下面这样:

0.0.1读至0.0.18,转换磁头,1.0.1读至1.0.18,转换磁头,0.1.1读至0.1.18,转换磁头,1.1.1读至1.1.18......

 

对应的我们将用到int 13h功能,这里介绍一下:

功能02H 
功能描述:读扇区 
入口参数:AH02H
AL
=扇区数 
CH
=磁道 
CL
=开始扇区 
DH
=磁头 
DL
=驱动器号,00H~7FH:软盘;80H~0FFH:硬盘   这里我们的DL0
ES:BX
=缓冲区的地址  也就是我们要写入的地址

 

 

下面我们看看将一个kernelloader.asm的可执行代码kernelloader.bin读到内存0x1000中的子程序,前面已经知道,boot.bin存放在0磁道第1个扇区,kernelloader.bin紧接着boot.bin,排列在0磁道第2个扇区,目前kernelloader共占据1个扇区512字节:

 

read_kernelloader:                                       ;读入 kernelloader 程序

  push              es

 

  .read_kernelloader:

  mov               ax , 0x1000                           ;kernelloader.bin 所在的段基址           

  mov               es , ax

  mov               bx , 0                                 ;写入到内存0x1000:0000

  mov               ah , 2

  mov               dh , 0                                 ;磁头

  mov               dl , 0                                  ;驱动器号

  mov               ch , 0                                  ;磁道0

  mov               cl , 2                                  ;2个扇区

  mov               al , 1                                  ;读入扇区数,每个扇区为 512B

  int               0x13 

  jc                .read_kernelloader

 

  pop               es

  ret

 

因为受512字节限制,boot.asm能做的事情实在有限,下面我们改变一下boot.asm功能,让它只负责读取kernelloader程序到内存0x1000:0000的地方,然后跳转到0x1000:0000执行kernelloader程序,这样可以摆脱boot启动程序只有512字节的限制,可以让kernelloader做许多事情。

两个程序如下:

boot.asm

[BITS 16]                                                  ;编译成16位的指令

[ORG 0x7C00]

jmp                 main

 

read_kernelloader:                                        ;读入 kernelloader 程序

  push              es

 

  .rk:

  mov               ax , 0x1000                            ;kernelloader.bin 所在的段基址           

  mov               es , ax

  mov               bx , 0

  mov               ah , 2

  mov               dl , 0

  mov               ch , 0

  mov               cl , 2

  mov               al , 1                                 ;读入扇区数,每个扇区为 512B

  int               0x13 

  jc                .rk

 

  pop               es

  ret

 

main:                                                       ;主程序         

  mov               ax , 0x0                               ;boot.bin 程序的段基址

  mov               ds , ax

 

  call              read_kernelloader                    ;读入 kernelloader 程序 

 

  jmp dword         0x1000:0                              ;跳转到 kernelloader 处执行

times 510-($-$$) db 0

db 0x55

db 0xAA

 

kernelloader程序将放在boot程序之后,目前小于512字节,也就是0面,0磁道,第二扇区开始,占据一个扇区的位置。

kernelloader.asm

[BITS 16]  

jmp main

ns db 0x48,0x65,0x6C,0x6C,0x6F,0x20,0x77,0x6F,0x72,0x6C,0x64,0x21,'f','r','o','m',' ','y','a'   ;;hello world!from ya

main:

mov ax, cs

mov ds, ax

mov es, ax

mov cx,19           ;循环19

mov bx,0            ;从数组[0]开始

mov ah,0eh

next:

mov al,[ns+bx]

int 10h

inc bx

dec cx

jnz next              ;cx不为0则继续

po:

jmp po

 

修改makefile文件,最后在bochs运行a.img,显示Hello world!from ya

makefile

######################

#声明要编译的所有组成,这里的ya是本工程名称,可以取任何名字,这里就用ya

######################

ya:out/boot.bin out/kernelloader.bin out/creat_img.exe out/write_in_img.exe A B C

#开始对各部分编译,注意不是空格是Tab

 

out/boot.bin:code/boot.asm

    nasm code/boot.asm -o out/boot.bin

out/kernelloader.bin:code/kernelloader.asm

    nasm code/kernelloader.asm -o out/kernelloader.bin

 

# 制作内核映象文件

out/creat_img.exe:code/creat_img.c

    gpp code/creat_img.c -o out/creat_img.exe

# 执行dos命令,在final目录下生成a.img文件

A:

    out/creat_img.exe final/a.img

 

# 写入文件,argv[1]=目标文件 argv[2]=源文件  argv[3]=写入偏移量  

#DOS下用法: write.exe a.img kernelloader.bin 512

out/write_in_img.exe:code/write_in_img.c

    gpp code/write_in_img.c -o out/write_in_img.exe

# 执行dos命令,向a.img写入代码,内容是boot.bin

# 0偏移量起始

B:

    out/write_in_img.exe final/a.img out/boot.bin 0

# 执行dos命令,向a.img写入代码,内容是kernelloader.bin

# boot.bin已经占用了512字节,512偏移量起始

C:

    out/write_in_img.exe final/a.img out/kernelloader.bin 512

 

 

0 0
原创粉丝点击