标签:
这是一个磁盘示意图:
一个磁盘有两面。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表示0面0磁道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
功能描述:读扇区
入口参数:AH=02H
AL=扇区数
CH=磁道
CL=开始扇区
DH=磁头
DL=驱动器号,00H~7FH:软盘;80H~0FFH:硬盘 这里我们的DL是0
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
标签:
原文地址:http://www.cnblogs.com/ya20151015/p/4942732.html