linux 0.11 bootsect.s中的BIOS部分解读

        电脑启动以后,最先由BIOS自检然后加载磁盘第一扇区数据到内存中,然后把CPU第一条指令设置到这块内存后由CPU执行余下的操作。以下来探索一下,BIOS究竟做了什么,怎么工作的。我参考的资料是维基百科:http://en.wikipedia.org/wiki/BIOS  http://en.wikipedia.org/wiki/BIOS_interrupt_call

After completing the POST, the motherboard BIOS scans for extension ROMs in an area of the "upper memory area" space and runs each ROM found, in order. To discover memory-mapped ISA option ROMs during the boot process, BIOS implementations scan real-mode address space from 0x0C0000 to 0x0F0000 on 2 KiB boundaries, looking for a ROMsignature: 0x55 followed by 0xAA. In a valid expansion ROM, this signature is followed by a single byte indicating the number of 512-byte blocks it occupies in real memory. The next byte contains an offset describing the option ROM's entry point. A checksum of the specified number of 512-byte blocks is calculated, and if the ROM has a valid checksum the BIOS transfers control to the specified entry address. At this point, the expansion ROM code takes over,using BIOS services to register interrupt vectors for use by post-boot applications, to provide a user configuration interface, or to display diagnostic information.       

    自检不是这里说的重点,跳过不说;BIOS自检后,已经收集到从哪一个盘启动的信息;

 For a disk drive or a device that logically emulates a disk drive, such as an USB Flash drive or perhaps a tape drive, to perform this check the BIOS attempts to load the first sector (boot sector) from the disk to memory address 0x007C00, and checks for the boot sector signature 0x55 0xAA in the last two bytes of the (512 byte long) sector. If the sector cannot be read (due to a missing or blank disk, or due to a hardware failure), or if the sector does not end with the boot signature, the BIOS considers the disk unbootable and proceeds to check the next device.

    BIOS会尝试从第一启动盘的第一个扇区读取数据写到物理内存的0x007c00这个位置;然后检查内存中的0x007dfe和0x007dff上是0x55 0xaa,这个算是启动扇区的签名,如果没有这个标志,就认为这个读取到的数据是不正确的启动数据。如果无法读取指定第一个启动盘的第一个扇区数据或检测启动扇区签名不正确,或者校验和不对,那么就会认为这个启动盘无法启动,转而去检查第二启动盘。

    从这里来解析linux0.11里的bootsect.s中的代码段:

SETUPLEN = 4				! nr of setup-sectors
BOOTSEG  = 0x07c0			! original address of boot-sector
INITSEG  = 0x9000			! we move boot here - out of the way
SETUPSEG = 0x9020			! setup starts here
SYSSEG   = 0x1000			! system loaded at 0x10000 (65536).
ENDSEG   = SYSSEG + SYSSIZE		! where to stop loading

! ROOT_DEV:	0x000 - same type of floppy as boot.
!		0x301 - first partition on first drive etc
ROOT_DEV = 0x306

entry start
start:
	mov	ax,#BOOTSEG
	mov	ds,ax
	mov	ax,#INITSEG
	mov	es,ax
	mov	cx,#256
	sub	si,si
	sub	di,di
	rep
	movw
	jmpi	go,INITSEG
go:	mov	ax,cs
	mov	ds,ax
	mov	es,ax
! put stack at 0x9ff00.
	mov	ss,ax
	mov	sp,#0xFF00		! arbitrary value >>512

BOOTSEG设置为0x07c0是对应的实模式内存地址的段地址;这个值是由于BIOS的规定而设置的。BIOS从第一扇区把bootsect的代码加载到了0x07c0段后,然后从start开始执行;接下来的有一个int 13需要再分析。

! load the setup-sectors directly after the bootblock.
! Note that 'es' is already set up.

load_setup:
	mov	dx,#0x0000		! drive 0, head 0
	mov	cx,#0x0002		! sector 2, track 0
	mov	bx,#0x0200		! address = 512, in INITSEG
	mov	ax,#0x0200+SETUPLEN	! service 2, nr of sectors
	int	0x13			! read it
	jnc	ok_load_setup		! ok - continue
	mov	dx,#0x0000
	mov	ax,#0x0000		! reset the diskette
	int	0x13
	j	load_setup
这里使用了BIOS中断INT 0x13将seetup模块从磁盘第2个扇区开始读到0x90200开始处,共读4个扇区。那么,来看一下BIOS的中断机制以及其中的int 0x13是怎么操作运行的。参考 http://en.wikipedia.org/wiki/BIOS_interrupt_call

13hLow Level Disk Services
AH Description
00hReset Disk Drives
01hCheck Drive Status
02hRead Sectors
03hWrite Sectors
04hVerify Sectors
05hFormat Track
08hGet Drive Parameters
09hInit Fixed Drive Parameters
0ChSeek To Specified Track
0DhReset Fixed Disk Controller
15hGet Drive Type
16hGet Floppy Drive Media Change Status
17hSet Disk Type
18hSet Floppy Drive Media Type
41hExtended Disk Drive (EDD) Installation Check
42hExtended Read Sectors
43hExtended Write Sectors
44hExtended Verify Sectors
45hLock/Unlock Drive
46hEject Media
47hExtended Seek
48hExtended Get Drive Parameters
49hExtended Get Media Change Status
4EhExtended Set Hardware Configuration
可以看到调用int 0x13时,ah = 0x02; 也就是叫中断处理例程去处理Read Sector功能。其他参数我没有在维基或别的地方找到答案,直接按赵炯的书上说的:

al = 需要读出的扇区数量

ch = 磁道号的低8位; cl =开始扇区(位0-5),磁道号高2位(位6-7);

dh = 磁头号;        dl = 驱动器号(如果是硬盘则位7要置位);

es:bx ->指向数据缓冲区:如果出错则CF标志置位,ah中是出错码。

    另外问题来了:中断描述符表在哪里,中断处理例程又在哪里?什么时候放的?

    根据赵炯书上说明:bootsect代码为什么不把系统模块直接加载到物理地址0x0000开始处而要在setup程序中再进行移动呢?这是因为在随后执行的setup代码开始部分还需要利用ROM BIOS中的中断调用来获取机器的一些参数(比如int0x13获取setup代码)。当BIOS初始化时会在物理内存开始处放置一个大小为0x400字节的中断向量表,因此需要在使用完BIOS的中断调用后才能将这个区域覆盖掉。

    中断处理例程在哪里?没找到依据,有一个网友说在E000:0到F000:0之间。

    中断到底是中断CPU还是中断BIOS?根据维基上的BIOS中断表,看起来像是BIOS的中断;但是int 0x13代码bootsect运行时是在CPU执行的。我没找到明确答案。


补充:http://book.51cto.com/art/201106/270092.htm

BIOS程序被固化在计算机主机板上的一块很小的ROM芯片里。通常,不同的主机板所用的BIOS也有所不同,就启动部分而言,各种类型的BIOS的基本原理大致相似。为了便于大家理解,我们选用的BIOS程序只有8KB,所占地址段为0xFE000~0xFFFFF,如图1-1所示。现在CS:IP已经指向了0xFFFF0这个位置,这意味着BIOS开始启动了。随着BIOS程序的执行,屏幕上会显示显卡的信息、内存的信息……说明BIOS程序在检测显卡、内存……这期间,有一项对启动(boot)操作系统至关重要的工作,那就是BIOS在内存中建立中断向量表和中断服务程序。

小贴士

ROM(Read Only Memory):只读存储器,现在通常用闪存芯片做ROM。虽然闪存芯片在特定的条件下是可写的,但在谈到主机板上存储BIOS的闪存芯片时,业内人士把它看作ROM。ROM有一个特性,就是断电之后仍能保存信息,这一点与硬盘类似。

BIOS程序在内存最开始的位置(即:0x00000)用1KB的内存空间(0x00000~ 0x003FF)构建中断向量表,并在紧挨着它的位置用256字节的内存空间构建BIOS数据区(0x00400~0x004FF),在大约56KB以后的位置(0x0E05B)加载了8KB左右的与中断向量表相应的若干中断服务程序,图1-2中精确地标注了这些位置。

小贴士

一个容易计算的方法:0x00100是256个字节,0x00400就是4×256字节=1024字节,即1KB。因为是从0x00000开始计算,所以1KB的高地址端不是0x00400,而是0x00400-1,也就是0x003FF。

 
图1-2 BIOS在内存中加载中断向量表和中断服务程序

中断向量表中有256个中断向量,每个中断向量占4个字节,其中两个字节是CS的值,两个字节是IP的值,每个中断向量都指向一个具体的中断服务程序。

    根据研究查证,中断向量在BIOS初始化过程中加载到内存当中的,但是我查阅维基上的POST资料,POST过程没有加载中断向量和中断服务程序到内存的过程。按上面的说法,是在初始化过程加载了,现在就不再考究到底是初始化的哪一步加载了。

    中断例程加载在0xE05B位置(根据不同的BIOS估计有不同吧?)。

    中断是谁的中断的问题:只有一个级联了两个8295A中断处理器的中断处理构件,BIOS中是没有的。处理BIOS中断的时候,如int 0x13,是由加载到内存的中断例程完成内容填充的。至于从哪里找到硬盘数据,会是在自检的时候?不追究了。








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值