1.开机
当我们按下电脑开机键的时候,BIOS程序会充当搬运工的身份,将磁盘0盘0道1扇区(启动区)的代码原封不动的搬运到内存的0x07c0的位置,然后CPU就开始从0x07c0的位置不停机的运行着,具体运行什么内容,我们后面慢慢分析。
1.1什么是启动区
启动区:只要磁盘0盘0道1扇区的结尾的两个字节分别是0x55和0xaa,BIOS即可认为该扇区是启动区。
2.磁盘0盘0道1扇区的代码是什么
磁盘0盘0道1扇区的代码是位于boot文件夹下面的bootsect.s的二进制文件
3.bootsect.s代码讲解
mov ax,0x07c0
mov ds,ax
设置段寄存器的值,因为汇编限制,ds这些寄存器不可以直接赋值,我们需要通过ax寄存器进行赋值,ds是段寄存器,设置好了段寄存器,我们写地址的时候可以直接写偏移地址即可,不需要加段地址了,可以省很多重复性工作。
mov ax,BYTE PTR INITSEG ;// 将es段寄存器置为9000h
mov es,ax
mov cx,256 ;// 移动计数值 = 256字 = 512 字节
sub si,si ;// 源地址 ds:si = 07C0h:0000h
sub di,di ;// 目的地址 es:di = 9000h:0000h
rep movsw ;// 重复执行,直到cx = 0;移动1个字
这段代码的意思就是将内存地址0x7c00处的代码移动512字节,也就是复制到0x90000处。
; jmp INITSEG:[go] ;// 间接跳转。这里INITSEG指出跳转到的段地址。
db 0eah ;// 间接跳转指令码
dw go
dw INITSEG
go: mov ax,cs ;// 将ds、es和ss都置成移动后代码所在的段处(9000h)。
mov ds,ax ;// 由于程序中有堆栈操作(push,pop,call),因此必须设置堆栈。
mov es,axmov ss,ax
mov sp,0FF00h ;/* 由于代码段移动过了,所以要重新设置堆栈段的位置。
; sp只要指向远大于512偏移(即地址90200h)处
; 都可以。因为从90200h地址开始处还要放置setup程序,
; 而此时setup程序大约为4个扇区,因此sp要指向大
; 于(200h + 200h*4 + 堆栈大小)处。 */
go是一个标签,经过编译之后,会生成一个偏移地址。这段代码的意思就是跳转到go标签去执行程序。 这段代码就是一些准备工作,准备加载setup模块的代码数据。
load_setup:
;// 以下10行的用途是利用BIOS中断INT 13h将setup模块从磁盘第2个扇区
;// 开始读到90200h开始处,共读4个扇区。如果读出错,则复位驱动器,并
;// 重试,没有退路。
;// INT 13h 的使用方法如下:
;// ah = 02h - 读磁盘扇区到内存;al = 需要读出的扇区数量;
;// ch = 磁道(柱面)号的低8位; cl = 开始扇区(0-5位),磁道号高2位(6-7);
;// dh = 磁头号; dl = 驱动器号(如果是硬盘则要置为7);
;// es:bx ->指向数据缓冲区; 如果出错则CF标志置位。
mov dx,0000h ;// drive 0, head 0
mov cx,0002h ;// sector 2, track 0
mov bx,0200h ;// address = 512, in INITSEG
mov ax,0200h+SETUPLEN ;// service 2, nr of sectors
int 13h ;// read it
jnc ok_load_setup ;// ok - continue
mov dx,0000h
mov ax,0000h ;// reset the diskette
int 13h
jmp load_setupok_load_setup:
int 指令就是汇编指令里面的中断指令,根据中断号去中断描述符表里面找到段选择子和偏移地址 .
段选择子去全局描述符表找到段描述符,根据现在的段描述符和偏移地址就可以去找到程序入口地址,然后去执行。0x13是BIOS提取给我们写好的中断程序,是读取磁盘相关的函数。
这些代码,用途是利用BIOS中断INT 13h将setup模块从磁盘第2个扇区开始的数据,加载到内存0x90200处,共加载4个扇区(1-5扇区)