在BIOS触发0x19中断将磁盘的第一个扇区(512B)加载到内存中后,计算机才真正开始执行磁盘上的程序。而这512B的程序就是bootsect.s,此时处理器还处于实模式内存寻址的最大范围是1M(0x0000-0xFFFF),接下来我们看看在bootsect.s的第一批代码中做了些什么?
</pre><pre name="code" class="cpp">SYSSIZE = 0x3000 //内核程序的大小
SETUPLEN = 4 //要加载的setup程序长度单位为扇区数
BOOTSEG = 0x07c0 //启动扇区被BIOS加载的位置,也就是现在所在的位置
INITSEG = 0x9000 //bootsect.s即将移动到的位置
SETUPSEG = 0x9020 //setup程序要被加载的开始位置
SYSSEG = 0x1000 //kernel加载的起始位置
ENDSEG = SYSSEG + SYSSIZE //kernel的结束位置
ROOT_DEV = 0x306 //根文件系统的设备号
上述代码声明了给一系列变量赋值,用于内存规划
</pre><pre name="code" class="cpp">entry start
start:
mov ax,#BOOTSEG //
mov ds,ax //
mov ax,#INITSEG //这段代码是将bootsect的代码从0x07C0
mov es,ax //复制到0x9020处
mov cx,#256 //
sub si,si //
sub di,di //
rep //
movw //
</pre>因为在后面的程序中,bootsect之前所在的位置会被其他程序覆盖,所以需要将bootsect程序的位置移动至0x90200处<p></p><p></p><p>复制完成之后,紧接着执行</p><p></p><pre code_snippet_id="403621" snippet_file_name="blog_20140623_7_6144482" name="code" class="cpp"> jmpi go,INITSEG
go: mov ax,cs
mov ds,ax
这个时候,开始加载setup(setup.s)程序到内存中了
还是老样子,加载setup,只不过这次通过寄存器指定了一系列信息方便中断服务程序访问磁盘
load_setup:
mov dx,#0x0000 //指定磁头为第0个
mov cx,#0x0002 //指定在第2个扇区,第0个磁道
mov bx,#0x0200 //setup在磁盘中的物理地址
mov ax,#0x0200+SETUPLEN //指定结束的位置
int 0x13 //中断读取磁盘
jnc ok_load_setup //加载完成,执行ok_load_setup
mov dx,#0x0000
mov ax,#0x0000 //重置磁盘
int 0x13
j load_setup
然后调用read_it加载system也就是kernel模块了
mov ax,#SYSSEG //指定system模块加载在内存中的位置
mov es,ax
call read_it
call kill_motor