Go.
继续之前,先阅读一下硬盘的寻址方式文档。
随意Google一篇:
[url]http://storage.chinabyte.com/249/3444249.shtml[/url]
关联的Stage 1 代码如下:
InBlock.gif00000019  A0407C            mov al,[0x7c40]
InBlock.gif0000001C  3CFF              cmp al,0xff
InBlock.gif0000001E  7402              jz 0x22
InBlock.gif00000020  88C2              mov dl,al
InBlock.gif00000022  52                push dx
InBlock.gif00000023  BE7F7D            mov si,0x7d7f
InBlock.gif00000026  E83401            call word 0x15d
InBlock.gif00000029  F6C280            test dl,0x80
InBlock.gif0000002C  7454              jz 0x82
InBlock.gif0000002E  B441              mov ah,0x41
InBlock.gif00000030  BBAA55            mov bx,0x55aa
InBlock.gif00000033  CD13               int 0x13
InBlock.gif00000035  5A                pop dx
InBlock.gif00000036  52                push dx
InBlock.gif00000037  7249              jc 0x82
InBlock.gif00000039  81FB55AA          cmp bx,0xaa55
InBlock.gif0000003D  7543              jnz 0x82
InBlock.gif0000003F  A0417C            mov al,[0x7c41]
InBlock.gif00000042  84C0              test al,al
InBlock.gif00000044  7505              jnz 0x4b
InBlock.gif00000046  83E101            and cx, byte +0x1
InBlock.gif00000049  7437              jz 0x82

困了,明天再来:)
OK, Coming->
先看第一段:

00000019  A0407C            mov al,[0x7c40]
0000001C  3CFF              cmp al,0xff
0000001E  7402              jz 0x22

按照boot.S如下注释,0x7c3E起始的12个字节如下定义:
stage1_version:
        .byte   COMPAT_VERSION_MAJOR, COMPAT_VERSION_MINOR
boot_drive:
        .byte   GRUB_INVALID_DRIVE      /* the disk to load stage2 from */
force_lba:
        .byte   0
stage2_address:
        .word   0x8000
stage2_sector:
        .long   1
stage2_segment:
        .word   0x800

而我dd出来的对应数据区为:
0000030: 83c6 1049 7419 382c 74f6 a0b5 07b4 0302  ...It.8,t.......
0000040: ff00 0020 0100 0000 0002                 ... ......
因此版本号为0302,这个与grub的0.9.6的关系我不清楚,暂时不管。
随后的0x40也就是mv al,[0x7c40]所load的内容为0xFF代表硬盘类型。引用如下 文章的描述:
 
InBlock.gif   [7C40] -> 80 ( "Boot Drive") NOTE: For those of you with multi-OS
InBlock.gif             booting systems, if your Linux installation with GRUB's
InBlock.gif             remaining software (stage2, menu file, etc.) is located
InBlock.gif             somewhere other than on the Primary Master drive, this
InBlock.gif             value will be 81, 82, etc. depending upon which drive
InBlock.gif             that Linux OS's /boot/grub directory is located.
InBlock.gif

0XFF么,应该是只此一家,别无分店了。如下链接 文章似乎可以印证这个说法。

Have a rest.//blog is good.
I'm coming {极端怀疑本文的可读性,不过作为一个过程挺好}

无论走那个分支,0x22处的push dx中的dl中已经包含了启动盘标识[0x80/0x81 ---]。

随后的
InBlock.gif00000023  BE7F7D            mov si,0x7d7f
InBlock.gif00000026  E83401            call word 0x15d

0x7d7f - 0x7c00 =  17F

17F处的字符串数据为:”GRUB “

InBlock.gif0000170: 06be 947d e830 00be 997d e82a 00eb fe47  ...}.0...}.*...G
InBlock.gif0000180: 5255 4220 0047 656f 6d00 4861 7264 2044  RUB .Geom.Hard D
InBlock.gif0000190: 6973 6b00 5265 6164 0020 4572 726f 7200  isk.Read. Error.

0x15D处的代码为:
InBlock.gif00000156  BB0100            mov bx,0x1
InBlock.gif00000159  B40E              mov ah,0xe
InBlock.gif0000015B  CD10               int 0x10
InBlock.gif0000015D  AC                lodsb
InBlock.gif0000015E  3C00              cmp al,0x0
InBlock.gif00000160  75F4              jnz 0x156
InBlock.gif00000162  C3                ret

//lunch,中秋就是好。
//Coming
显然,这段代码功能为利用int 10来显示字符串。
//废话比正文多。
//又是周末了,再来写。
先看lodsb功能:
LODSB∶ 指令助记符——字节装入(从字节串中取数)。它将DS段SI指出的字节数据送入AL寄存器中,并根据方向标志DF修改SI中的地址。即当DF=0时,地址加1 ;DF= 1 时,地址减1 。

这里的DF = 0 在这段代码中没有体现,也许是BIOS = STUB之间的一个约定。我理解,启动程序应该有一段CPU初始化代码才对。不知道GRUB为何这样,至少在以我所处理的嵌入式产品应该是初始化了CPU至少两次( Bootrom一次、 OS一次)。

至于int 10h的功能就很简明了,google到如下 链接说明得很清楚:
INT 10, E: write 'char' teletype
        AH = E
        AL = char (7,8,10,13: special action)
        BH = page(0)
        BL = foreground color (graphic)
        moves cursor

        ;Write command line:
                    mov si,82h    ;parameters in PSP
        mess: mov al,[si] ;each char
                    cmp al,0Dh    ;until CR
                    jz quit
                    mov bh,0        ;page 0
                    mov ah,0Eh
                    int 10h
                    inc si            ;next char
                    jmp mess
        quit:

        >INT 21.02: Display Character

由于前述dl = 0x80,因此
InBlock.gif00000029  F6C280            test dl,0x80
InBlock.gif0000002C  7454              jz 0x82
便将代码控制调整到0x82处了,在讨论0x82代码之前,先看本节关注的关键代码段:

0000002E    B441                            mov ah,0x41
00000030    BBAA55                        mov bx,0x55aa
00000033    CD13                            int 0x13
00000035    5A                                pop dx
00000036    52                                push dx
00000037    7249                            jc 0x82

00000039    81FB55AA                    cmp bx,0xaa55
0000003D    7543                            jnz 0x82

0000003F    A0417C                        mov al,[0x7c41]
00000042    84C0                            test al,al

00000044    7505                            jnz 0x4b
00000046    83E101                        and cx,byte +0x1
00000049    7437                            jz 0x82

如果,dl中存储的是stage2所在硬盘编号,0x8N。第一子段代码利用扩展int 13h的判断是否存在扩展服务调用(正如此 链接描述):

这个调用检验对特定的驱动器是否存在扩展功能. 如果进位标志置 1
则此驱动器不支持扩展功能. 如果进位标志为 0, 同时 BX = AA55h, 则
存在扩展功能. 此时 CX 的 0 位表示是否支持第一个子集, 1位表示是否
支持第二个子集.

随后的cmp bx 0xaa55确认是否存在合法的扩展,不存在直接跑到0x82(CHS),确实存在就将7c41(force_lba),就跑到0x4b去作LBA方式启动,否则依然0x82(CHS)方式读取stage2。我们的流程自然是0x82处的流程,下节我们来分析这个关键点。