3 ; The BP register is initialized to 0x7c00, the start of
4 ; the boot sector. The SP register is initialized to
5 ; 0x7bf0, leaving 16 bytes of data storage space above
8 ; The DWORD that gets stored at 0x7bfc is the logical
9 ; sector number of the start of the data area.
11 ; The DWORD that gets stored at 0x7bf8 is ????????
13 ; The DWORD that gets stored at 0x7bf4 is ????????
15 ; The DWORD that gets stored at 0x7bf0 is ????????
34 MaxRootEntries dw 0 ;512 - Always zero for FAT32 volumes
35 TotalSectors dw 0 ;2880 - Always zero for FAT32 volumes
36 MediaDescriptor db 0f8h
37 SectorsPerFat dw 0 ;9 - Always zero for FAT32 volumes
45 SerialNumber dd 00000000h
46 VolumeLabel db 'NO NAME '
47 FileSystem db 'FAT16 '
50 00007C3E 33C9 xor cx,cx
51 00007C40 8ED1 mov ss,cx ; Setup stack
52 00007C42 BCF07B mov sp,0x7bf0 ; Give us 16 bytes (4 dwords) of space above stack
53 00007C45 8ED9 mov ds,cx
54 00007C47 B80020 mov ax,0x2000
55 00007C4A 8EC0 mov es,ax ; Setup ES:0000 == 2000:0000
57 00007C4D BD007C mov bp,0x7c00
58 00007C50 384E24 cmp [bp+BootDrive],cl ; Compare the boot drive to zero (I think they are testing for a hard disk drive number)
59 00007C53 7D24 jnl floppy_boot ; Nope, it's a floppy, skip partition table tests
60 00007C55 8BC1 mov ax,cx ; Move zero to AX
61 00007C57 99 cwd ; DX:AX now contains zero
62 00007C58 E83C01 call read_one_sector ; Try to read in the MBR sector
63 00007C5B 721C jc floppy_boot ; Read failed, continue
64 00007C5D 83EB3A sub bx,byte +0x3a ; BX comes back with 512, make it equal to 454 (offset of partition table in MBR)
65 00007C60 66A11C7C mov eax,[HiddenSectors] ; Put HiddenSectors in EAX
67 00007C64 26663B07 cmp eax,[es:bx] ; Compare partition table entry's start sector to HiddenSectors
68 00007C68 268A57FC mov dl,[es:bx-0x4] ; Get partition type byte for this entry
69 00007C6C 7506 jnz next_partition_entry ; If partition start sector != HiddenSectors then skip this entry
70 00007C6E 80CA02 or dl,0x2 ; Set the second bit in partition type?? I guess this makes types 4 & 6 identical
71 00007C71 885602 mov [bp+0x2],dl ; Save it on top of nop instruction (3rd byte of boot sector)
73 00007C74 80C310 add bl,0x10 ; Add 16 to bl (offset of next entry in partition table)
74 00007C77 73EB jnc find_our_partition ; Jump back until we hit the end of the partition table
76 ; We now have our partition type at 0000:7C02
77 ; If the type was 4 or 6 then that byte is 6
78 ; I can't imagine why the boot sector needs to store
79 ; this information, but hopefully I will uncover it
80 ; as I further disassemble this boot sector.
84 00007C79 33C9 xor cx,cx ; Zero out CX
85 00007C7B 8A4610 mov al,[bp+NumberOfFats] ; Get the number of FATs in AL (usually 2)
86 00007C7E 98 cbw ; Sign extend it into AX (AX == 2)
87 00007C7F F76616 mul word [bp+NumberOfFats] ; Multiply it with NumberOfFats PLUS the low byte of MaxRootEntries!!??
88 00007C82 03461C add ax,[bp+HiddenSectors] ; Result is in DX:AX
89 00007C85 13561E adc dx,[bp+HiddenSectors+2] ; Add HiddenSectors to DX:AX
90 00007C88 03460E add ax,[bp+ReservedSectors] ; Add ReservedSectors to DX:AX
91 00007C8B 13D1 adc dx,cx ; CX still contains zero
92 00007C8D 8B7611 mov si,[bp+MaxRootEntries] ; Get MaxRootEntries in SI
93 00007C90 60 pusha ; Save all registers (right now DX:AX has starting sector of root dir)
94 00007C91 8946FC mov [bp-0x4],ax ; Save the starting sector of the root directory
95 00007C94 8956FE mov [bp-0x2],dx ; Save it in the first 4 bytes before the boot sector
96 00007C97 B82000 mov ax,0x20 ; AX == 32 (size of a directory entry)
97 00007C9A F7E6 mul si ; Multiply it with MaxRootEntries (DX:AX == length in bytes of root directory)
98 00007C9C 8B5E0B mov bx,[bp+BytesPerSector] ; Get the BytesPerSector in BX
99 00007C9F 03C3 add ax,bx ; Add it to AX (what if this addition carries? MS should 'adc dx,0' shouldn't they?)
100 00007CA1 48 dec ax ; Subtract one (basically rounding up)
101 00007CA2 F7F3 div bx ; Divide DX:AX (length of root dir in bytes) by the size of a sector
102 00007CA4 0146FC add [bp-0x4],ax ; Add the number of sectors of the root directory to our other value
103 00007CA7 114EFE adc [bp-0x2],cx ; Now the first 4 bytes before the boot sector contain the starting sector of the data area
104 00007CAA 61 popa ; Restore all registers (DX:AX has start sector of root dir)
105 load_root_dir_sector:
106 00007CAB BF0000 mov di,0x0 ; Zero out di
107 00007CAE E8E600 call read_one_sector ; Read the first sector of the root directory
108 00007CB1 7239 jc print_disk_error_message ; Read failed, print disk error and reboot
110 00007CB3 26382D cmp [es:di],ch ; If the first byte of the directory entry is zero then we have reached the end
111 00007CB6 7417 jz print_ntldr_error_message; of the directory and NTLDR is not here so reboot
112 00007CB8 60 pusha ; Save all registers
113 00007CB9 B10B mov cl,0xb ; Put 11 in cl (length of filename in directory entry)
114 00007CBB BEA17D mov si,NTLDR ; Put offset of filename string in DS:SI
115 00007CBE F3A6 repe cmpsb ; Compare this directory entry against 'NTLDR '
116 00007CC0 61 popa ; Restore all the registers
117 00007CC1 7432 jz found_ntldr ; If we found NTLDR then jump
118 00007CC3 4E dec si ; SI holds MaxRootEntries, subtract one
119 00007CC4 7409 jz print_ntldr_error_message; If we are out of root dir entries then reboot
120 00007CC6 83C720 add di,byte +0x20 ; Increment DI by the size of a directory entry
121 00007CC9 3BFB cmp di,bx ; Compare DI to BX (DI has offset to next dir entry, BX has address of end of directory sector in memory)
122 00007CCB 72E6 jc search_directory ; If DI is less than BX loop again
123 00007CCD EBDC jmp short load_root_dir_sector ; Didn't find NTLDR in this directory sector, try again
124 print_ntldr_error_message:
125 00007CCF A0FB7D mov al,[NTLDR_ERR_offset_from_0x7d00]
127 00007CD2 B47D mov ah,0x7d
128 00007CD4 8BF0 mov si,ax
133 00007CD9 740C jz print_reboot_message
135 00007CDC 7413 jz reboot
136 00007CDE B40E mov ah,0xe
137 00007CE0 BB0700 mov bx,0x7
138 00007CE3 CD10 int 0x10
139 00007CE5 EBEF jmp short get_another_char
140 print_reboot_message:
141 00007CE7 A0FD7D mov al,[RESTART_ERR_offset_from_0x7d00]
142 00007CEA EBE6 jmp short putchars
143 print_disk_error_message:
144 00007CEC A0FC7D mov al,[DISK_ERR_offset_from_0x7d00]
145 00007CEF EBE1 jmp short putchars
147 00007CF1 CD16 int 0x16
148 00007CF3 CD19 int 0x19
150 00007CF5 268B551A mov dx,[es:di+0x1a] ; Get NTLDR start cluster in DX
151 00007CF9 52 push dx ; Save it on the stack
152 00007CFA B001 mov al,0x1 ; Read 1 cluster? Or is this one sector?
153 00007CFC BB0000 mov bx,0x0 ; ES:BX is the load address (2000:0000)
154 00007CFF E83B00 call read_cluster ; Do the read
155 00007D02 72E8 jc print_disk_error_message ; If it failed then reboot
156 00007D04 5B pop bx ; Get the start cluster of NTLDR in BX
157 00007D05 8A5624 mov dl,[bp+BootDrive] ; Get boot drive in DL
158 00007D08 BE0B7C mov si,0x7c0b
159 00007D0B 8BFC mov di,sp
160 00007D0D C746F03D7D mov word [bp-0x10],read_cluster
161 00007D12 C746F4297D mov word [bp-0xc],0x7d29
162 00007D17 8CD9 mov cx,ds
163 00007D19 894EF2 mov [bp-0xe],cx
164 00007D1C 894EF6 mov [bp-0xa],cx
165 00007D1F C606967DCB mov byte [0x7d96],0xcb
166 00007D24 EA03000020 jmp 0x2000:0x3
167 00007D29 0FB6C8 movzx cx,al
168 00007D2C 668B46F8 mov eax,[bp-0x8]
169 00007D30 6603461C add eax,[bp+HiddenSectors]
170 00007D34 668BD0 mov edx,eax
171 00007D37 66C1EA10 shr edx,0x10
172 00007D3B EB5E jmp short 0x7d9b
174 00007D3D 0FB6C8 movzx cx,al
177 00007D42 8A460D mov al,[bp+SectsPerCluster]
178 00007D45 32E4 xor ah,ah
180 00007D49 0346FC add ax,[bp-0x4]
181 00007D4C 1356FE adc dx,[bp-0x2]
182 00007D4F EB4A jmp short 0x7d9b
189 00007D55 6A01 push byte +0x1
190 00007D57 6A10 push byte +0x10
191 00007D59 91 xchg ax,cx
192 00007D5A 8B4618 mov ax,[bp+SectorsPerTrack]
193 00007D5D 96 xchg ax,si
194 00007D5E 92 xchg ax,dx
195 00007D5F 33D2 xor dx,dx
197 00007D63 91 xchg ax,cx
200 00007D67 87CA xchg cx,dx
201 00007D69 F7761A div word [bp+NumberOfHeads]
202 00007D6C 8AF2 mov dh,dl
203 00007D6E 8AE8 mov ch,al
204 00007D70 C0CC02 ror ah,0x2
205 00007D73 0ACC or cl,ah
206 00007D75 B80102 mov ax,0x201
207 00007D78 807E020E cmp byte [bp+0x2],0xe
208 00007D7C 7504 jnz 0x7d82
209 00007D7E B442 mov ah,0x42
210 00007D80 8BF4 mov si,sp
211 00007D82 8A5624 mov dl,[bp+BootDrive]
212 00007D85 CD13 int 0x13
215 00007D89 720B jc 0x7d96
217 00007D8C 7501 jnz 0x7d8f
219 00007D8F 035E0B add bx,[bp+BytesPerSector]
221 00007D93 7506 jnz 0x7d9b
227 00007D98 BB0000 mov bx,0x0
229 00007D9C 666A00 o32 push byte +0x0
230 00007D9F EBB0 jmp short 0x7d51
236 NTLDR_ERR db 0dh,0ah,'NTLDR is missing',0ffh
237 DISK_ERR db 0dh,0ah,'Disk error',0ffh
238 RESTART_ERR db 0dh,0ah,'Press any key to restart',0dh,0ah
243 NTLDR_offset_from_0x7d00 db 0
244 NTLDR_ERR_offset_from_0x7d00 db 0ach
245 DISK_ERR_offset_from_0x7d00 db 0bfh
246 RESTART_ERR_offset_from_0x7d00 db 0cch