//计算机启动时CS=0xf000,IP=0xfff0,属于BIOS的地址范围,执行BIOS ROM中的代码
//BIOS程序检查硬件(POST),设置实模式下的中断向量表,指向BIOS芯片自身提供的BIOS中断调用的代码
//最后,BIOS把bootsect加载到内存中的0000:7c00处
//此时CS=0x0000,IP=0x7c00,SS、SP不变,仍然使用和BIOS程序使用的堆栈段
//引导扇区bootsect的作用:移动bootsect自身到0x90000,加载setup模块到0x90200,加载system模块到0x10000
SYSSIZE=0x3000 //默认内核的最大长度
.globl begtext, begdata, begbss, endtext, enddata, endbss
.text
begtext:
.data
begdata:
.begbss
begbss:
.text
SETUPLEN = 4 //setup程序所占的扇区数
BOOTSEG = 0x7c00
//bootsect的初始段地址,其实此时CS=0x0000,IP=0x7c00,但bootsect程序认为CS=0x7c00,IP=0;表示的地址是一样的
//在移到INITSEG之前只要不使用label表示的偏移地址就不会出错,因为编译器认为编译地址的起始偏移量为0
INITSEG = 0x9000 //移动bootsect的新段地址
SETUPSEG = 0x9020
SYSSEG = 0x1000
ENDSEG = SYSSEG + SYSSIZE
ROOT_DEV = 0x306 //指定root文件系统是第2个硬盘的第一个分区
entry start
start:
//移动bootsect自身到0x9000
mov ax, #BOOTSEG
mov ds, ax
mov ax, #INITSEG
mov es, ax
mov cx, #256
sub si, si
sud di, di
rep
movw
//移动bootsect自身到0x9000
jmpi go, INITSEG
go: mov ax, cs
mov ds, ax
mov es, ax
mow ss, ax
mov sp, #0xff00
load_setup:
mov dx, #0x0000 //驱动器0,磁头0
mov cx, #0x0002 //扇区2,磁道0
mov bx, #0x0200 //INITSEG端512偏移处
mov ax, #0x0200+SETUPLEN //服务号2,扇区数4
int 0x13
jnc ok_load_setup
mov dx, #0x0000
mov ax, #0x0000 //复位磁盘
int 0x13
j load_setup
ok_load_setup:
mov dl,#0x00
mov ax,#0x0800 //服务号8,获取磁盘参数
int 0x13
mov ch,#0x00
seg cs
mov sectors,cx //保存每磁道扇区数。
mov ax,#INITSEG
mov es,ax
//显示信息'Loading system ...'
mov ah,#0x03
xor bh,bh
int 0x10
mov cx,#24 ! 共24 个字符。
mov bx,#0x0007 ! page 0, attribute 7 (normal)
mov bp,#msg1
mov ax,#0x1301 ! write string, move cursor
int 0x10
//现在开始将system 模块加载到0x10000(64k)处。
mov ax,#SYSSEG
mov es,ax
call read_it //读磁盘上system模块
call kill_motor //关闭驱动器马达
seg cs
mov ax,root_dev
cmp ax,#0
jne root_defined
seg cs
mov bx,sectors
mov ax,#0x0208
cmp bx,#15
je root_defined
mov ax,#0x021c
cmp bx,#18
je root_defined
undef_root:
jmp undef_root
root_defined:
seg cs
mov root_dev,ax
//所有程序都加载完毕,跳转到setup程序去
jmpi 0,SETUPSEG
sread: .word 1+SETUPLEN
head: .word 0
track: .word 0
read_it:
mov ax,es
test ax,#0x0fff
die:
jne die
xor bx,bx
rp_read:
mov ax,es
cmp ax,#ENDSEG
jb ok1_read
ret
ok1_read:
seg cs
mov ax,sectors
sub ax,sread
mov cx,ax
shl cx,#9
add cx,bx
jnc ok2_read
je ok2_read
xor ax,ax
sub ax,bx
shr ax,#9
ok2_read:
call read_track
mov cx,ax
add ax,sread
seg cs
cmp ax,sectors
jne ok3_read
mov ax,#1
sub ax,head
jne ok4_read
inc track
ok4_read:
mov head,ax
xor ax,ax
ok3_read:
mov sread,ax
shl cx,#9
add bx,cx
jnc rp_read
mov ax,es
add ax,#0x1000
mov es,ax
xor bx,bx
jmp rp_read
read_track:
push ax
push bx
push cx
push dx
mov dx,track
mov cx,sread
inc cx
mov ch,dl
mov dx,head
mov dh,dl
mov dl,#0
and dx,#0x0100
mov ah,#2
int 0x13
jc bad_rt
pop dx
pop cx
pop bx
pop ax
ret
bad_rt:
mov ax,#0
mov dx,#0
int 0x13
pop dx
pop cx
pop bx
pop ax
jmp read_track
kill_motor:
push dx
mov dx,#0x3f2 ! 软驱控制卡的驱动端口,只写
mov al,#0 ! A 驱动器,关闭FDC,禁止DMA和中断请求,关闭马达
outb ! 将al 中的内容输出到dx 指定的端口去
pop dx
ret
sectors:
.word 0 ! 存放当前启动软盘每磁道的扇区数
msg1:
.byte 13,10 ! 回车、换行的ASCII 码
.ascii "Loading system ..."
.byte 13,10,13,10 ! 共24 个ASCII 码字符
.org 508 ! 表示下面语句从地址508(0x1FC)开始,所以root_dev
! 在启动扇区的第508 开始的2 个字节中
root_dev:
.word ROOT_DEV ! 这里存放根文件系统所在的设备号(init/main.c 中会用)
boot_flag:
.word 0xAA55 ! 硬盘有效标识
.text
endtext:
.data
enddata:
.bss
endbss:
linux引导扇区bootsect注释
最新推荐文章于 2023-03-28 10:36:30 发布