神奇的0x07c0
第一步将硬盘中的0扇区的512字节的启动区代码boot引导源码载入内存中。
启动区的定义非常简单,只要硬盘中的 0 盘 0 道 1 扇区的 512 个字节的最后两个字节分别是 0x55 和 0xaa,那么 BIOS 就会认为它是个启动区。
然后给ds数据段赋值:0x07c0 表示偏移量,相当于内存中有一个变量使用,指向内存中引导区的地址。
有个小疑问就是为什么不直接赋值0x7c00,这是历史遗留问题,由于 x86 为了让自己在 16 位这个实模式下能访问到 20 位的地址线这个历史因素(不了解这个的就先别纠结为啥了),会偏移四位到0x7c00,也就是内存中引导区boot的地址
再来一次0x90000
接下来将内存地址 0x7c00 处开始往后的 512 字节的数据,原封不动复制到 0x90000 处。
然后将启动的cpu指针指向mov ax,cs处
接下来,会将bootsect后的四个扇区加载到,第一个扇区之后,也就是0x90200之后,以及将head.s+其他的系统相关代码约240个扇区加载到0x10000后
此时整个bootsect.s代码完成使命,我们根据cpu的指针进入到setup.s的地方0x90200,开始执行
准备就绪,开始行动
第一步调用显示中断服务,将光标位置确定下来。存储在dx中,最后将dx的内容存储到[0]这个内存地址中。
注意[0]是一个偏移地址,还需要加上段基址,所以[0]代表 0x90000,依此类推[2]为0x90002等等
接下来,还有很多调用中断方法
比如获取内存信息。
; Get memory size (extended mem, kB)
mov ah,#0x88
int 0x15
mov [2],ax
获取显卡显示模式。
; Get video-card data:
mov ah,#0x0f
int 0x10
mov [4],bx ; bh = display page
mov [6],ax ; al = video mode, ah = window width
检查显示方式并取参数
; check for EGA/VGA and some config parameters
mov ah,#0x12
mov bl,#0x10
int 0x10
mov [8],ax
mov [10],bx
mov [12],cx
获取第一块硬盘的信息。
; Get hd0 data
mov ax,#0x0000
mov ds,ax
lds si,[4*0x41]
mov ax,#INITSEG
mov es,ax
mov di,#0x0080
mov cx,#0x10
rep
movsb
获取第二块硬盘的信息。
; Get hd1 data
mov ax,#0x0000
mov ds,ax
lds si,[4*0x46]
mov ax,#INITSEG
mov es,ax
mov di,#0x0090
mov cx,#0x10
rep
movsb
接下来就是要整理一下内存中的数据,因为我们需要的数据基本获取完毕,也处理完毕了
同前面的原理一样,也是做了个内存复制操作,最终的结果是,把内存地址 0x10000 处开始往后一直到 0x90000 的内容,统统复制到内存的最开始的 0 位置,大概就是这么个效果。
最后内存会变成这样:
原先的0x7c00已经成为过去式,现在开始进行模式转换