一直以来做的东西很杂,现在突然有兴趣研究下开源的sourcecode,计划是从GRUB开始,逐步深入,希望自己能坚持下来。以自己以前的经验,只看不记忘得快,所以了,在这里写点notes。 看一点写一点,很多错误的地方也暂且放过了,以后逐渐更正。在这里,只为记录下学习过程。参考过的资料没有一一列出,谢谢无私奉献的网友们。
-------------------------------------------------------------------------------------------
1. stage1.s记录
-------------------------------------------------------------------------------------------
.globl _start; _start:
/*
* _start is loaded at 0x7c00 and is jumped to with CS:IP 0:0x7c00
*/
/*
* Beginning of the sector is compatible with the FAT/HPFS BIOS
* parameter block.
*/
jmp after_BPB
pgnotes: bios 的int19会将磁盘的第一个扇区读到0x7c00,并且将driver number记录在dx寄存器,然后jump过来;BPB是MBR中的一些固定信息,网上很多文章讲;
ljmp $0, $ABS(real_start)
pgnotes: ljmp一下是为了将cs设置为0?(FIXME)
MOV_MEM_TO_AL(ABS(boot_drive))
pgnotes:0xa0就是MOV AL,moffs8 ,可参考ia2;
pgnotes: 下面的代码顺着走,现在仅考虑grub安装在HDD上的情况,这样调用int 13 41function后,就顺利走到lba_mode;
movl %ebx, 8(%si)
pgnotes: this is the starting absolute block number, 这个值是stage2_sector=1;int 13 42function用初始化好的disk address packet,将sector1读出,拷贝到stage2_address=0x8000,jmp过去,就转入stage2/start.S执行了。
-------------------------------------------------------------------------------------------
2. /stage2/start.S记录
-------------------------------------------------------------------------------------------
#ifdef STAGE1_5
# define ABS(x) (x-_start+0x2000)
#else
# define ABS(x) (x-_start+0x8000)
pgnotes:代码一开始就有这几句,全局搜索,无STAGE1_5的define,所以ABS(x)会将相对地址+0x8000等于绝对地址,逆向推理,也可以发现和stage1.s的结尾对应起来了。但以后,需要针对编译好的grub,顺向了解安装后的位置。
/* this sets up for the first run through "bootloop" */
movw $ABS(firstlist - BOOTSEC_LISTSIZE), %di
pgnotes:这个语句较关键,firstlist是相对start.S的偏移,可以看程序末尾:
. = _start + 0x200 - BOOTSEC_LISTSIZE /*pgnotes:起始位置+一个扇区512字节数-8个字节的list长度*/
/* fill the first data listing with the default */
blocklist_default_start:
.long 2 /* this is the sector start parameter, in logical
sectors from the start of the disk, sector 0 */
/*pgnotes:4个字节,地址的逻辑扇区号是2,0为起始逻辑扇区号*/
blocklist_default_len:
/* this is the number of sectors to read */
#ifdef STAGE1_5
.word 0 /* the command "install" will fill this up */
#else
.word (STAGE2_SIZE + 511) >> 9/*pgnotes:2个字节,STAGE2_SIZE的所占的扇区长度*/
#endif
blocklist_default_seg:
#ifdef STAGE1_5
.word 0x220
#else
.word 0x820 /* this is the segment of the starting address
to load the data into */ /*pgnotes:2个字节,目标段地址*/
#endif
firstlist: /* this label has to be after the list data!!! */
pgnotes: start.S中主要使用这个list中的值将STAGE2_SIZE大小的内容读出,并用下面的copy_buffer逐步放到0x8200
处,
copy_buffer:
/* load addresses for copy from disk buffer to destination */
movw 6(%di), %es /* load destination segment */ /*pgnotes:2个字节,目标段地址*/
/* restore %ax */
popw %ax
pgnotes:ax是本次读出的扇区数,popw后左移5bits,加到目标段,这样得到下次copy到的目标段地址*/
最后程序通过ljmp $0, $0x8200,跳转到被copy的内容处继续运行。
总结: 这两个小程序分别被编译成512字节,代码简单、功能单一,主要用int13来逐步copy跳转,可能由于大小限制以及结构清晰的需要,而分成两个文件。由于自己没有全局的理解,以后再更正可能的错误。