;Note: 在ISO中,扇区大小至少为2048字节,大部分是2048字节(见ECMA-119),BIF引导文件位于14号扇区
00000000 E9FD03 jmp 0x400
00000003 skipping 0x1FA bytes ;filled with 0
000001FD 0055AA add [di-0x56],dl
000001FF skipping 0x201 bytes ;filled with 0
00000400 EB7E jmp short 0x480
00000402 6690D1B6867878
00000409 skipping 0x10 bytes
00000419 C201
0000041B skipping 0x65 bytes
;将本文件全部内容复制到0x1000处
;eax:0x0000aa55 ecs:00090000 edx:000000e0 ebx:00000000 esp:0000ffd6 ebp:00000000 esi:000e0000 rdi:0000f782
00000480 31C0 xor ax,ax
00000482 8ED8 mov ds,ax
00000484 8EC0 mov es,ax
00000486 8ED0 mov ss,ax
00000488 BC007C mov sp,0x7c00
0000048B 89E6 mov si,sp
0000048D BF0010 mov di,0x1000
00000490 B90004 mov cx,0x400
00000493 F3A5 rep movsw
;eax:0x00000000 ecs:00090000 edx:000000e0 ebx:00000000 esp:00007c00 ebp:00000000 esi:000e8400 rdi:00001800
;从内存地址0x149a继续往下执行
00000495 EA9A140000 jmp 0x0:0x149a
;暂不知道该指令有何作用
;[0x15b0]=0x0d000006
0000049A 8816B115 mov [0x15b1],dl
;[0x15b0]=0x0d00e006
;显示字符串
;[0x15b3-0x15da]0x0d0aNetBSD/x86 cd9660 Primary Bootstrap0x0d0a00
0000049E BEB315 mov si,0x15b3
;eax:0x00000000 ecs:00090000 edx:000000e0 ebx:00000000 esp:00007c00 ebp:00000000 esi:000e15b3 rdi:00001800
000004A1 E8EC00 call 0x590
;从扇区号16读取1个扇区到内存0x1800处
000004A4 66B810000000 mov eax,0x10 ;扇区号16
000004AA B601 mov dh,0x1 ;1个扇区
000004AC 66BB00180000 mov ebx,0x00001800 ;内存地址0x1800
000004B2 E88E00 call 0x543
000004B5 803F01 cmp byte [bx],0x1
000004B8 740F jz 0x4c9 ;找到了Primary Volume Descriptor
;未找到Primary Volume Descriptor
000004BA 6640 inc eax ;寻找下一个扇区
000004BC 803FFF cmp byte [bx],0xff ;如果是Volume Descriptor Set Terminator
000004BF 75E9 jnz 0x4aa ;如果不是Volume Descriptor Set Terminator,表明Descriptor未结束,继续读扇区
;如果是Volume Descriptor Set Terminator 说明Primary Volume Descriptor不存在
000004C1 BE0B16 mov si,0x160b
000004C4 E8C900 call 0x590 ;显示"Press any key to boot from CD"
000004C7 EB77 jmp short 0x540 ;暂停CPU运行
;找到了Primary Volume Descriptor,把根目录内容复制到地址0x2000处
000004C9 BB9C18 mov bx,0x189c ;根目录记录(Directory Record)
000004CC 668B4702 mov eax,[bx+0x2] ;根目录所在扇区
000004D0 668B570A mov edx,[bx+0xa] ;根目录数据大小(占4字节)
000004D4 66C1EA0B shr edx,0xb ;除以2048,得到所占扇区数 0x12345678
000004D8 88D6 mov dh,dl ;数据大小不能超过522240(0xFF*0x800)个字节
000004DA 66BB00200000 mov ebx,0x00002000
000004E0 E86000 call 0x543 ;读扇区
;开始在根目录寻找BOOT文件
000004E3 803F00 cmp byte [bx],0x0
000004E6 741D jz 0x505 ;读到了目录末尾
000004E8 89DE mov si,bx
000004EA 83C621 add si,0x21 ;指向文件名或目录名所在地址
000004ED 8A4F20 mov cl,[bx+0x20] ;文件名或目录名长度
000004F0 BF4116 mov di,0x1641 ;[0x1641-0x1648]=BOOT;10x00
000004F3 8A04 mov al,[si]
000004F5 3805 cmp [di],al
000004F7 7508 jnz 0x501
000004F9 46 inc si
000004FA 47 inc di
000004FB FEC9 dec cl
000004FD 75F4 jnz 0x4f3
000004FF EB0C jmp short 0x50d
00000501 031F add bx,[bx] ;如果文件名或目录名不是BOOT;1 继续读下一个目录
00000503 EBDE jmp short 0x4e3
;根目录不存在boot文件
00000505 BE3016 mov si,0x1630
00000508 E88500 call 0x590 ;显示"Can't find /boot"
0000050B EB33 jmp short 0x540 ;处理器进入暂停状态
;根目录存在boot文件
0000050D 668B4702 mov eax,[bx+0x2] ;boot文件所在扇区
00000511 668B570A mov edx,[bx+0xa] ;boot文件大小
00000515 6681C2FF070000 add edx,0x7ff ;当文件大小不是所占扇区的整数倍时,加上0x7ff可以把文件全部读完
0000051C 66C1EA0B shr edx,byte 0xb ;除以2048,得到文件所占扇区数
00000520 88D6 mov dh,dl ;dh指定了读取的扇区数,把dl赋值给dh
00000522 66BB00000100 mov ebx,0x10000 ;加载到内存0x10000处
00000528 E81800 call 0x543
0000052B 66BE08140000 mov esi,0x1408 ;
00000531 6631D2 xor edx,edx
00000534 8A16B115 mov dl,[0x15b1]
00000538 6631DB xor ebx,ebx
0000053B 9A00000010 call 0x1000:0x0 ;从boot开始执行
;CPU暂停运行
00000540 F4 hlt
00000541 EBFD jmp short 0x540
;-----------------@method:读扇区---------------------
;@param eax 需要读取扇区号(低32位)
; dh 读取扇区数(低8位)
; ebx 目的内存地址(32位) 要求16字节对齐
;@return null
;@description 初始值:[0x15a0-0x15af]=0x10000000000000000000000000000000 用来保存int 13h ah=0x42功能所需的16字节数据
; [0x15a0-0x15a1]=结构体长度(2字节),0x10表示数据长度是16字节,该值是固定的
; [0x15a2-0x15a3]=读取的扇区数(2字节)
; [0x15a4-0x15a5]=偏移地址(2字节)
; [0x15a6-0x15a7]=段地址(2字节)
; [0x15a8-0x15ab]=读取的扇区号的低32位(4字节)
; [0x15ac-0x15af]=读取的扇区号的高32位(4字节)
00000543 6660 pusha
00000545 66A3A815 mov [0x15a8],eax
00000549 66C1EB04 shr ebx,0x04 ;得到段地址
0000054D 891EA615 mov [0x15a6],bx
00000551 8836A215 mov [0x15a2],dh
;若读取超过32个扇区,先读32个
00000555 80FE20 cmp dh,0x20
00000558 7E05 jng 0x55f
0000055A C606A21520 mov byte [0x15a2],0x20
;有何用?
0000055F 8A16B115 mov dl,[0x15b1] ;[0x15b0-0x15b1]=0x06,0xe0, dl=0xe0
;将ds:si指向结构体入口地址
00000563 BEA015 mov si,0x15a0
00000566 B442 mov ah,0x42
;dx=01e0 dx在int 0x13前后没有变化,暂不清楚为何压栈
00000568 52 push dx
00000569 CD13 int 0x13
0000056B 5A pop dx
0000056C 7215 jc 0x583 ;读取失败
;读取成功
0000056E 8106A6150010 add word [0x15a6],0x1000 ;跳过0x10000个地址(0x20*0x800=0x10000)
00000574 668306A81520 add dword [0x15a8],byte+0x20 ;跳过20个扇区
0000057A 2A36A215 sub dh,[0x15a2] ;是否读完扇区,如果扇区未读完则继续读,如果读完该程序结束
0000057E 75D1 jnz 0x551
00000580 6661 popa
00000582 C3 ret
;读取失败
00000583 80FC80 cmp ah,0x80
00000586 74DE jz 0x566 ;超时错误再读 其他错误显示字符串,然后让CPU暂停运行
00000588 BEFD15 mov si,0x15fd ;[0x15fd-0x160a]=Can't read CD0x00
0000058B E80200 call 0x590
0000058E EBB0 jmp short 0x540
;-----------------@method:显示字符串--------------------
;@param ds:si 指向字符串所在地址
;@return null
00000590 60 pusha
00000591 AC lodsb
00000592 B40E mov ah,0xe
00000594 BB0100 mov bx,0x1 ;黑色背景,蓝色前景,不闪烁
00000597 CD10 int 0x10
00000599 AC lodsb
0000059A 84C0 test al,al
0000059C 75F4 jnz 0x592 ;字符串未结束,继续显示下一个字符
0000059E 61 popa
0000059F C3 ret
000005A0 10
000005A1 skipping 0xF bytes ;filled with 0
000005B0 06
000005B1 0000
000005B3 0D0A
000005B5 skipping 0x93 bytes ;NetBSD/x86 cd9660 Primary Bootstrap0x0D0A000D0A000D0APress any key to boot from CD0x00.0x00Can't read CD0x00Can't find Primary Volume Descriptor0x00Can't find /boot0x00
00000648 skipping 0x1B6 bytes ;filled with 0
000007FE 0000