参考书籍 Linux内核设计的艺术
BIOS已经把bootsect(也就是引导程序)载入内存了,它的作用就是把第二批和第三批程序陆续加载到内存中。为了把第二批和第三批程序加载到内存中的适当位置,bootsect首先做的工作就是规划内存。
设置这些位置(内存)就是为了确保将要载入内存的代码和已经载入内存的代码及数据各在其位,互不覆盖。
接下来,bootsect启动程序将它自身(全部的512B内容)从内存0x07C00(BOOTSEG)处复制至内存0x90000(INITSEG)处。
执行这个操作的代码如下:
mov ax ,#BOOTSEG
mov ds,ax
mov ax,#INITSEG
mov es,ax
mov cx ,#256
sub si,si
sub di,di
rep
movw
sub是减法运算。
比如
mov ax,2
mov bx,1
sub ax,bx
其中sub ax,bx就是ax中的值减bx中的值,等于1,然后把结果,也就是1,放入ax中。
rep是字符串操作指令MOVS,CMPS等的前缀,在CX不等于0的情况下,对字符串执行重复操作
movw解析参考点我
bootsect复制到新位置后,bootsect会执行以下代码
rep
movw
jmpi go,INITSEG
go:mov ax,cs
mov ds,ax
这两行代码十分巧妙
jmpi go,INITSEG
go:mov ax,cs
在内存的0x07C00和0x90000位置处有两段完全相同的代码。请大家注意,复制代码这件事本身也是要靠指令执行的,执行指令的过程就是CS和IP不断变化的过程。执行到jmpi go, INITSEG这行之前,代码的作用就是复制代码自身;执行了jmpi go, INITSEG之后,程序就转到执行0x90000这边的代码了。Linus的设计意图是跳转之后在新位置接着执行后面的mov ax, cs,而不是死循环。jmpi go, INITSEG与go: mov ax, cs配合,巧妙地实现了“到新位置后接着原来的执行序继续执行下去”的目的。厉害