Linux0.11内核--启动引导代码分析bootsect.s

Linux内核中的系统启动引导代码位于/boot目录下

Linux0.11内核--启动引导代码分析bootsect.s_第1张图片

但是,由于。Linus当时是在MINIX系统上开发Linux的,最初MINIX系统上还没有移植gas程序,因此Linus就使用了MINIX系统上的as86。

bootsect需要是16位的实模式程序。目前gas汇编器也支持16位的编译。所以现在也可以直接用as编译器直接编译。

下面是用at&t格式改写的bootsect.s代码

系统加电启动时,首先由BIOS读取bootsect代码到地址0x7c00处,然后首先将自己移动至地址0x9000处,大小是256个字,相当于512

字节。

如何实现内存块的复制,运用ds:si->es:di的方式,将ds所指的段移 到ps所指的段中去,cx中指定移动的次数。gas中的段间跳转指令 ljmp A,B,其中A代表目标段地址,B代表A段中的偏移值。

然后跳转到移动后代码的下一条语句执行,这是由于

ljmp $INITSEG, $go

跳转后,该指令自动修改CS代码段的值。

移动代码后,由于这是会使用pop,push,call等指令,需要使用堆栈段,所以需要重新设置段基址,0x9ff00。

然后通过BIOS的INT 0x13中断来从磁盘加载setup模块。

***************************************

BIOS中断INT 0x13读磁盘功能

读扇区:

ah=0x02 - 读磁盘扇区到内存;a1=需要读出的扇区数量

ch=磁道(柱面)号的低8位; c1=开始扇区(位0-5),磁道号高2 位(位6-7);

dh=磁头号; d1=驱动器号(如果是硬盘则位7要 置位),0为当前A驱动器

es:bx->指向数据缓冲区;如果出错则CF标志置位。

***************************************
然后再用BIOS的INT 0x13中断读磁盘参数
***************************************
BIOS中断INT 0x13取磁盘驱动器参数功能
ah=0x08 dl=驱动器号(如果是硬盘则要置位7为1)
返回信息
如果出错则CF置位,并且ah=状态码
ah=0,al=0,bl=驱动器类型(AT/PS2)
ch=最大磁道号的低8位,cl=每磁道最大扇区数(位0-5),最大磁道 号高2位(位6-7)
dh=最大磁头数,dl=驱动器数量
es:di->软驱磁盘参数表
***************************************
然后利用BIOS的INT 0x10中断读取光标位置并且输出信息
***************************************
BIOS中断0x10,读光标位置功能
功能号ah=0x03
输入:bh=页号
返回:ch=扫描开始线;cl=扫描结束线;dh=行号(0x00顶端);dl= 列号(0x00最左边)
***************************************
***************************************
BIOS中断0x10,显示字符串
功能号ah=0x13
输入:al=放置光标的方式及规定属性,0x01表示使用bl中的属性 值,光标停留在字符串结尾处。es:bp此寄存器指向要显示的字符串 起始位置处。cx=显示的字符串字符数。bh=显示页面号;bl=字符属 性,7为normal,dh=行号,dl=列号。
从磁盘上都数据必须位于64KB边界开始处。因为实模式下的寄存器为 16位,所以最大寻址为2^16=64KB,即段限长也为64KB,一次性最大 能拷贝的字节数也是64KB。
***************************************
.org伪指令
.org 508
指令表示表示后面的指令从地址508开始,linux0.11初始化时根文件 系统所在设备号就存放在0x90508(0x90000是bootsect.s程序的开始 处)开始的两个字节处。供后面的程序main.c调用。
为什么是508而不是510呢,因为510和511这首个扇区的最后两个字节 必须存放0xaa55,作为该盘是有效引导扇区的标志,仅供bios中的程 序加载引导扇区时识别使用。
最后加载system到0x10000处。
下面read_it和kill_monitor两个子程序待续.......
下面是加载内存的模块分布和移动。
Linux0.11内核--启动引导代码分析bootsect.s_第2张图片

你可能感兴趣的:(linux)