linux-0.11引导启动程序笔记
linux-0.11 的最开始的代码是启动区代码,放在 bootsect.s 文件中。
//代码用到的宏
BOOTSEG = 0x07c0; original address of boot-sector
INITSEG = 0x9000; we move boot here - out of the way
SETUPLEN = 4 ; nr of setup-sectors
//entry指定汇编指令入口地点,相当于 C语言中的main函数
entry start
start:
movax,#BOOTSEG //BOOTSEG = 0x07c0
movds,ax
//以上两段代码将 ds 寄存器中的值变为0x07c0,此后数据段基址为0x07c0
movax,#INITSEG //INITSEG = 0x9000
moves,ax //es = 0x9000
movcx,#256
subsi,si //源变址寄存器清零
subdi,di //目的变址寄存器清零
//rep表示重复执行下一条指令 n 次,n为 cx 寄存器的值
rep
//movw:将ds:si的内容复制到es:di,复制过去,原来的代码还在。rep 加上 movw 的使用方法据说是一种古老的汇编语法。
movw
//于是启动区代码被复制到了0x90000位置
jmpigo,INITSEG //跳转到0x9000:go处执行,go的地址取决于编译器。
//go标签处初始化了一些寄存器:ds, es , ss , sp ,
go:movax,cs
movds,ax //ds = 0x9000
moves,ax //es = 0x9000
; put stack at 0x9ff00.
movss,ax //ss = 0x9000
//sp指向0x9ff00
movsp,#0xFF00; arbitrary value >>512
; load the setup-sectors directly after the bootblock.
; Note that 'es' is already set up.
/*load_setup利用 BIOS 中断 INT 0x13 将 setup 模块从磁盘第二个扇区开始读到0x90200开始处,共读 4 个扇区。读出错,则复位驱动器并重试。INT 0x13的使用方法如下:
读扇区:
ah = 0x02 表示读磁盘扇区到内存,al = 需要读出的扇区数量
ch = 磁道(柱面)号的低 8 位,cl = 开始扇区(0-5位),磁道号高 2 位
dh = 磁头号,dl = 驱动器号(如果是硬盘则位 7 要置位)
es:bx 指向数据缓冲区。如果出错 CF 标志位置位。
*/
//硬件部分目前对我来说还是黑盒,如果后续有了解的话,会更新在5.9版本的学习笔记里。
load_setup:
movdx,#0x0000; drive 0, head 0
movcx,#0x0002; sector 2, track 0
movbx,#0x0200; address = 512, in INITSEG
movax,#0x0200+SETUPLEN; service 2, nr of sectors
//以上四行应该是int 0x13的参数
int0x13; read it
//jnc: CF = 0 时跳转,可以看成加法没有进位,减法没有借位时跳转
//中断程序执行完后,没出错 CF = 0 ,跳转到 ok_load_setup
jncok_load_setup; ok - continue
//如果出错,复位硬盘
movdx,#0x0000
movax,#0x0000; reset the diskette
int0x13
jload_setup //跳回load_setup
未完待续。。。
load_setup