📄 win98se硬盘主引导记录代码反汇编分析.txt
字号:
0000:06C3 52 push dx
0000:06C4 99 cwd ; dx:ax = start_sector
0000:06C5 03 46 08 add ax,[bp+8] ; rel_sec (lo word)
0000:06C8 13 56 0A adc dx,[bp+0Ah] ; rel_sec (hi word)
; dx:ax = logic sector #, cx=# of sec to read
0000:06CB E8 0012 call int13ext ; call int13ext to read in boot record
0000:06CE 5A pop dx
0000:06CF EB D5 jmp short loc_int13extback
0000:06D1 loc_retry: ; xref 06A6
0000:06D1 4F dec di ; dec retry count
0000:06D2 74 E4 jz loc_endofretry
0000:06D4 33 C0 xor ax,ax
0000:06D6 CD 13 int 13h ; Disk dl=drive ? ah=func 00h
; reset disk, al=return status
0000:06D8 EB B8 jmp short loc_readin
0000:06DA 00 00 00 00 00 00 db 0, 0, 0, 0, 0, 0 ; reserved
mbr endp
; INT 13 extended read --------------------------------------------------------------------------------
; Entry:AH - 42h
; DL - Drive number
; DS:SI - Disk address packet
; Exit: carry clear
; AH - 0
; carry set
; AH - error code
; This function transfer sectors from the device to memory. In the event of an error,
; the block count field of the disk address packet contains the number of good blocks
; read before the error occurred.
;
; DS:SI -> Device address packet
; Offset Type Description
; 0 Byte Packet size in bytes. Shall be 10h.
; 1 Byte Reserved, must be 0
; 2 Byte Number of blocks to transfer. This field has a maximum value of 127 (7Fh).
; 3 Byte Reserved, must be 0
; 4 2Word Address of transfer buffer. The is the buffer which Read/Write operations will use
; to transfer the data. This is a 32-bit address of the form Seg:Offset.
; 8 4word Starting logical block address, on the target device, of the data to be transferred.
; This is a 64 bit unsigned linear address. If the device supports LBA addressing this
; value should be passed unmodified. If the device does not support LBA addressing
; the following formula holds true when the address is converted to a CHS value:
; LBA = (C1 * H0 + H1) * S0 + S1 - 1
; where: C1 = Selected Cylinder Number
; H0 = Number of Heads (Maximum Head Number + 1)
; H1 = Selected Head Number
; S0 = Maximum Sector Number
; S1 = Selected Sector Number
0000:06E0 int13ext proc near
; input dx:ax - 32 bit of logic sector address to read in
; cl - number of sector to read
; es:bx - buffer to hold data
; output carry clear if sucessful
; es:bx - end of read-in-data + 1
; carry set if error
0000:06E0 56 push si ; 10
0000:06E1 33 F6 xor si,si
0000:06E3 56 push si ; E
0000:06E4 56 push si ; C
0000:06E5 52 push dx ; A
0000:06E6 50 push ax ; 8 - 4W: Starting logical block address (dx:ax)
0000:06E7 06 push es ; 6 - 2W: Address of transfer buffer (es:bx)
0000:06E8 53 push bx ; 4
0000:06E9 51 push cx ; 2 - BY: Number of blocks to transfer
0000:06EA BE 0010 mov si,10h
0000:06ED 56 push si ; 0 - BY: packet size = 10h bytes
0000:06EE 8B F4 mov si,sp
0000:06F0 50 push ax
0000:06F1 52 push dx
0000:06F2 B8 4200 mov ax,4200h
0000:06F5 8A 56 24 mov dl,[bp+24h] ; boot record drive
0000:06F8 CD 13 int 13h
0000:06FA 5A pop dx
0000:06FB 58 pop ax
0000:06FC 8D 64 10 lea sp,[si+10h]
0000:06FF 72 0A jc short loc_ret
0000:0701 locloop_0701: ; move dx:ax to point end of buffer
0000:0701 40 inc ax
0000:0702 75 01 jnz short loc_0705
0000:0704 42 inc dx
0000:0705 loc_0705: ; xref 0702
0000:0705 80 C7 02 add bh,2
0000:0708 E2 F7 loop locloop_0701
0000:070A F8 clc
0000:070B loc_ret: ; xref 06FF
0000:070B 5E pop si
0000:070C C3 retn
int13ext endp
0000:070D loc_gobootrecok: ; xref 06B1
0000:070D EB 74 jmp short loc_bootrecok
0000:070F 49 6E 76 61 6C 69 msg1 db 'Invalid partition table', 0
0000:0715 64 20 70 61 72 74
0000:071B 69 74 69 6F 6E 20
0000:0721 74 61 62 6C 65 00
0000:0727 45 72 72 6F 72 20 msg2 db 'Error loading operating system', 0
0000:072D 6C 6F 61 64 69 6E
0000:0733 67 20 6F 70 65 72
0000:0739 61 74 69 6E 67 20
0000:073F 73 79 73 74 65 6D
0000:0745 00
0000:0746 4D 69 73 73 69 6E msg3 db 'Missing operating system'
0000:074C 67 20 6F 70 65 72
0000:0752 61 74 69 6E 67 20
0000:0758 73 79 73 74 65 6D
0000:075E 0025[00] db 37 dup (0) ; reserved space for message translation
0000:0783 loc_bootrecok: ; boot record ok, xref 070D
0000:0783 8B FC mov di,sp ; sp=7C00
0000:0785 1E push ds
0000:0786 57 push di
0000:0787 8B F5 mov si,bp ; ds:si -> 7C00
0000:0789 CB retf ; jump to 0:7C00 (that is boot record)
org 07BEh
part_table struc ;Offset Size Description
boot_ind db ? ; 00h BYTE boot indicator (80h = active partition) 0 - boot indicator
start_head db ? ; 01h BYTE partition start head
start_sector db ? ; 02h BYTE partition start sector (bits 0-5)
start_cyl db ? ; 03h BYTE partition start track (bits 8,9 in bits 6,7 of sector)
sys_id db ? ; 04h BYTE operating system indicator (see below)
end_head db ? ; 05h BYTE partition end head
end_sector db ? ; 06h BYTE partition end sector (bits 0-5)
end_cyl db ? ; 07h BYTE partition end track (bits 8,9 in bits 6,7 of sector)
rel_sec dd ? ; 08h DWORD sectors preceding partition
num_sec dd ? ; 0Ch DWORD length of partition in sectors
part_table ends ;Values for operating system indicator:
; 00h empty
; 01h DOS 12-bit FAT
; 04h DOS 16-bit FAT
; 05h DOS 3.3+ extended partition
; 06h DOS Large File System
; 0Bh DOS 32-bit FAT
; 0Ch DOS 32-bit FAT
; 0Eh DOS 32-bit FAT
0000:07BE 80 partition_tab label byte ; xref 061B
1boot_ind db 80h ; bootable
0000:07BF 01 01 00 0B 7F 7F 1start_head db 01h
1start_sector db 01h
1start_cyl db 00h
1sys_id db 0Bh ; DOS FAT32
1end_head db 7Fh
1end_sector db 7Fh
0000:07C5 C8 3F 00 00 00 41 1end_cyl db 0C8h
1rel_sec dd 0000003Fh
1num_sec dd 00383B41h
0000:07CB 3B 38 00 00
0000:07CE 00 00 41 2boot_ind db 00h
2start_head db 00h
2start_sector db 41h
0000:07D1 C9 05 7F FF 13 80 2start_cyl db 0C9h
2sys_id db 05h ; DOS extender
2end_head db 7Fh
2end_sector db 0FFh
2end_cyl db 13h
0000:07D5 2rel_sec dd 00383B80h
0000:07D7 3B 38 00 80 BA 28 2num_sec dd 0028BA80h
...
org 07FEh
0000:07FE 55 AA magicword dw 0AA55h
code_end label byte ; use this labelt to get length of code
_data ends ; xref 0615
end start
系统启动过程主要由一下几步组成(以硬盘启动为例):
1. 开机;
2. BIOS 加电或按reset键后都要进行系统复位,复位后指令地址为 0ffff:fff0,这个地方只有一条JMP指令, 跳转到系统自检 ( Power On Self Test -- POST )程序处;
3. 系统自检完成后,将硬盘的第一个扇区 (0头0道1扇区, 也就是Boot Sector)读入内存地址 0000:7c00 处;
4. 检查 (WORD) 0000:7dfe 是否等于 0xaa55, 若不等于则转去尝试其他启动介质, 如果没有其他启动介质 则显示 "No ROM BASIC" 然后死机;
5. 跳转到 0000:7c00 处执行 MBR 中的程序;
6. MBR程序 首先将自己复制到 0000:0600 处, 然后继续执行;
7. 在主分区表中搜索标志为活动的分区,如果没有发现活动分区或有不止一个活动分区, 则转停止;
8. 将活动分区的第一个扇区读入内存地址 0000:7c00 处;
9. 检查 (WORD) 0000:7dfe 是否等于 0xaa55, 若不等于则 显示 "Missing Operating System" 然后停止, 或尝 试软盘启动或;
10. 跳转到 0000:7c00 处继续执行特定系统的启动程序;
11. 启动系统...
以上步骤中 2,3,4,5 步是由 BIOS 的引导程序完成. 6,7,8,9,10步由MBR中的引导程序完成.
一般多系统引导程序 (如 SmartFDISK, BootStar, PQBoot 等)都是将标准主引导记录替换成自己的引导程序, 在运行系统启动程序之前让用户选择要启动的分区。
而某些系统自带的多系统引导程序 (如 lilo, NT Loader 等)则可以将自己的引导程序放在系统所处分区的第一个扇区中, 在 Linux中即为 SuperBlock (其实 SuperBlock 是两个扇区)。
注:以上各步骤中使用的是标准 MBR, 其他多系统引导程序的引导过程可能与此不同。
下面简要说明一下系统复位后的指令地址0ffff:fff0(物理地址0x0fffffff0):
在实地址模式下,内存有两个保留区域:系统初始化区和中断向量表区。地址0x00000~0x003ff 是为中断向量保留的,256个可能的中断,每一个保留4字节的跳转向量;地址0xfffffff0~0xffffffff是为系 统初始化保留的,此处一般只有一条JMP指令,跳到系统初始引导程序。
系统复位后,cs = 0x0f000、eip = 0x0000fff0,而系统初始引导程序安排在 0x0ffff0000~0x0ffffffff, 一般为ROM固件,使初始引导程序工作于内存实际地址空间以外的另一存储段中。此区域的16~31位都 应为1,cs及eip的初值已保证地址线的16~19位为1,而20~31位,即地址线的高12位,则须由硬件强制置 1,这由一个标志触发器在系统每次复位时置位实现触发。而由于段间转移指令要重新装入cs寄存器, 因此,每当执行段间转移指令时,此标志触发器复位,以后,再次访问时,不再向高12位地址线提供“1”信号,程序从此正常地工作于前1MB的地址空间。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -