热门关键字:  ubuntu  分区  Fedora  linux系统进程  函数

当前位置 :| 主页>Linux教程>内核研究>

bootsect.s注释

来源: 作者: 时间:2008-08-27 Tag: 点击:

/*
* 跳转到移动后的INITSEG:go处执行
*/
ljmp $INITSEG, $go
# bde - changed 0xff00 to 0x4000 to use debugger at 0x6400 up (bde). We
# would not have to worry about this if we checked the top of memory. Also
# my BIOS can be configured to put the wini drive tables in high memory
# instead of in the vector table. The old stack might have clobbered(击倒,使惨败) the
# drive table.
/*
* 12Byte用来存放磁盘参数表(disk para-meter table)
*/
go: movw $0x4000 - 12, %di # 0x4000 is an arbitrary value(任意值) >=
# length of bootsect + length of
# setup + room for stack;
# 12 is disk parm size.
movw %ax, %ds # ax and es already contain INITSEG
movw %ax, %ss
movw %di, %sp # put stack at INITSEG:0x4000-12.
# Many BIOSs default disk parameter tables will not recognize(认可,公认)
# multi-sector reads beyond the maximum sector number specified
# in the default diskette parameter tables - this may mean ?
# sectors in some cases.
#
# Since single sector reads are slow and out of question,
# we must take care of this by creating new parameter tables
# (for the first disk) in RAM. We will set the maximum sector
# count to 36 - the most we will encounter(遇到,相遇) on an ED 2.88
#
# High does not hurt(伤害,受伤). Low does.
#
# Segments are as follows: ds = es = ss = cs -[= ??] INITSEG, fs = 0,
# and gs is unused.
/*
* BIOS中断向量表中断1Eh的地址0:78h处,放置的是指向软盘参数表的指针.现在需要更改
* 软盘参数表中"每磁道的扇区数",而软盘参数表放在BIOS ROM中,我们无法修改. 所以将
* 其复制到指定的RAM参数表中,再进行修改.然后将BIOS的中断向量表中0:78h处的远指针
* 修改为指向RAM中新复制的软盘参数表.
*/
movw %cx,%fs # set fs to 0
movw $0x78, %bx # fs:bx is parameter table address
pushw %ds
/*
* LDS OPS, OPD - 传送偏移地址及数据段首址
* (OPS) ->OPD, (OPS + 2) ->DS
*/
ldsw %fs:(%bx), %si # ds:si is source
movb $6, %cl # copy 12 bytes
pushw %di # di = 0x4000-12.
rep # do not need cld -> done on line 66
movsw
popw %di
popw %ds
/*
* 指定"每磁道的扇区数"为36
*/
movb $36, 0x4(%di) # patch(修补) sector count
movw %di, %fs:(%bx)
movw %es, %fs:2(%bx)
# Load the setup-sectors directly after the bootblock.
# Note that 'es' is already set up.
# Also, cx = 0 from rep movsw above.
/* 从磁盘上读入紧邻着bootsect的setup程序 */
load_setup:
/* 重置磁盘驱动器,使得刚才对"每磁道的扇区数"的设定发挥功能 */
/*
* INT 13H: 直接磁盘服务(Direct Disk Service).
* 功能00H: 磁盘系统复位.AH=00H,DL=驱动器,00H~7FH:软盘; 80H~0FFH:硬盘.
*/
xorb %ah, %ah # reset FDC
xorb %dl, %dl
int $0x13
/*
* 功能02H: 读扇区.
* AH=02H,AL=扇区数,CH=柱面,CL=扇区,DH=磁头,DL=驱动器,00H~7FH:软盘;80H~0FFH:硬盘
* ES:BX=缓冲区地址.
* 出口参数:CF=0——操作成功,AH=00H,AL=传输的扇区数,否则AH=状态代码.
*/
xorw %dx, %dx # drive 0, head 0
movb $0x02, %cl # sector 2, track 0
movw $0x0200, %bx # address = 512, in INITSEG
movb $0x02, %ah # service 2, "read sector(s)"
movb setup_sects, %al # (assume all on head 0, track 0)
int $0x13 # read it
jnc ok_load_setup # ok - continue

/* 读盘错误处理 */
pushw %ax # dump error code
call print_nl
movw %sp, %bp
call print_hex
popw %ax
jmp load_setup

ok_load_setup:
# Get disk drive parameters, specifically number of sectors/track.
# It seems that there is no BIOS call to get the number of sectors.
# Guess 36 sectors if sector 36 can be read, 18 sectors if sector 18
# can be read, 15 if sector 15 can be read. Otherwise guess 9.
/*
* 猜测软盘"每磁道的扇区数",试着从大到小读36,18,15,0扇区,如果读取成功,说明磁盘上的每
* 磁道扇区数足以达到试读的数
*/
movw $disksizes, %si # table of sizes to try
probe_loop:
lodsb
cbtw # extend to word
movw %ax, sectors
cmpw $disksizes + 4, %si
jae got_sectors # if all else fails, try 9

xchgw %cx, %ax # cx = track and sector
xorw %dx, %dx # drive 0, head 0
xorb %bl, %bl
movb setup_sects, %bh
incb %bh
shlb %bh # address after setup (es = cs) [逻辑左移 ??]
int $0x13
jc probe_loop # try next value


/* 接下来要真正读入linux的kernel了,也就是在linux根目录下看到的"vmlinux". */
got_sectors:
/*
* INT 10H: 显示服务.AH=03H: 在文本坐标下,读取光标各种信息.BH=显示页码.
* 出口参数: CH=光标的起始行,CL=光标的终止行,DH=行(Y坐标),DL=列(X坐标).
*/
movw $INITSEG, %ax
movw %ax, %es # set up es
movb $0x03, %ah # read cursor pos
xorb %bh, %bh
int $0x10

/* 在屏幕上输出字符串"Loading". */

/*
* BH=页码,BL=属性(若AL=00H或01H),CX=显示字符串长度,(DH,DL)=坐标(行,列).
* ES:BP=显示字符串的地址,AL=显示输出方式.
* 0——字符串中只含显示字符,其显示属性在BL中.显示后,光标位置不变.
* 1——字符串中只含显示字符,其显示属性在BL中.显示后,光标位置改变.
* 2——字符串中含显示字符和显示属性.显示后,光标位置不变.
* 3——字符串中含显示字符和显示属性.显示后,光标位置改变.
*/
movw $9, %cx
movw $0x0007, %bx # page 0, attribute 7 (normal)
movw $msg1, %bp
movw $0x1301, %ax # write string, move cursor [写字符串并移动光标]
int $0x10 # tell the user we are loading...

movw $SYSSEG, %ax # ok, we have written the message, now
movw %ax, %es # we want to load system (at 0x10000)
call read_it /* 读磁盘上system模块,es为输入参数. */
call kill_motor /* 关闭驱动器马达,这样就可以知道驱动器的状态了. */
call print_nl
/* 此后,我们检查要使用哪个根文件系统设备(简称根设备).解说见0.11版本的P46. */
# After that we check which root-device to use. if the device is
# defined (!= 0), nothing is done and the given device is used.
# Otherwise, one of /dev/fd0H2880 (2,32) or /dev/PS0 (2,28) or /dev/at0 (2, 8)
# depending on the number of sectors we pretend(假装) to know we have.
/*
* 上面后两个设备文件的含义[0.11版本]:
* 在Linux中软驱的主设备号是2,次设备号 = type * 4 + nr, 其中nr为0-3分别对应软驱A,B,C或D;
* type是软驱的类型(2->1.2M或7->1.44M等).因为7 * 4 + 0 = 28,所以/dev/PS0(2,28)指的是1.44M
* A驱动器,其设备号是021c,同理/dev/at0(2,8)指的是1.2M A驱动器,设备号是0x0208.
*/

movw root_dev, %ax
orw %ax, %ax
jne root_defined

/* 每磁道扇区数.如sectors=15则是1.2Mb的驱动器.如sectors=18,则为1.44Mb软驱... */
movw sectors, %bx
movw $0x0208, %ax # /dev/ps0 - 1.2Mb
cmpw $15, %bx
je root_defined

movb $0x1c, %al # /dev/PS0 - 1.44Mb
cmpw $18, %bx
je root_defined

movb $0x20, %al # /dev/fd0H2880 - 2.88Mb
cmpw $36, %bx
je root_defined

movb $0, %al # /dev/fd0 - autodetect[自动侦查??]
root_defined:
movw %ax, root_dev /* 保存设备号. */
# After that (everything loaded), we jump to the setup-routine
# loaded directly after the bootblock:
/*
* 所有程序加载完毕,跳转到被加载在bootsect后面的setup程序去.
*/
ljmp $SETUPSEG, $0
# this routine Loads the system at address 0x10000, making sure
# no 64kB boundaries are crossed. We try to load it as fast as
# possible, loading whole tracks whenever we can.
# es = starting address segment (normally 0x1000)
sread: .word 0 # sectors read of current track [当前磁道中已读的扇区数]
head: .word 0 # current head [当前磁头号]
track: .word 0 # current track [当前磁道号]
read_it:
movb setup_sects, %al
incb %al
movb %al, sread /* 1个是引导扇区,4个是setup所在扇区 */


相关文章:
精通initramfs构建step by step
Linux利用kexec迅速切换内核
进程上下文VS中断上下文
内核通知链 学习笔记
linux spi子系统驱动分析
menuconfig 配置选项
《Linux操作系统内核实习》之练习一
udev详解
什么叫微内核,宏内核?
Linux 信号signal处理机制
开发简单的 Linux2.6 内核模块
删除内核的perl脚本
Linux2.6内核usb gadget驱动移植
GCC hacks in the Linux kernel
iomem
kernel学习的想法
让自己的驱动支持udev
linux内核编译步骤
内核的等待队列
Linux内核wait_queue深入分析
升级和删除内核
SD卡驱动分析2
Linux Kernel VDSO本地权限提升漏洞
内核中的TCP的追踪分析-15-TCP(IPV4)的客户端与
linux 2.6内核可加载模块的编译
内核模块HelloWorld
在环回接口上发送一个数据报
ARP初始化
1分钟编译FreeBSD内核
linux设备模型之uart驱动架构分析