WIN98/98SE/ME 引导分区代码析
===============================================
; 本段代码负责将IO.SYS之前4个扇区之内容(IOSYSloader)读出并置于
;000700h~000EFF处,然后转向70:200h 运行之。
; 本段代码之前200h字节即一个扇区内容是由MBR引导代码从媒体读出放置在
;007C00h处,然后转向本段代码运行,
; 其寄存器设置如下:
; CS=DS=ES=SS=0. IP=7C00h, DI=SP=7C00H, SI=BP-->指向引导中的
;分区表项
; 流程如下:
; 1). 将磁盘参数表从ROM抄至RAM 0:522h,然后修订部分参数
; 2). 读入磁盘分区表至0:700h,检查4个分区表项确定磁盘是否支持INT13扩
;展, 以决定后续磁盘操作读入方式:
; 是采用经典的INT13 AH=2号调用,还是使用INT13 AH=42号扩展功
;能?
; 3). 读入引导记录其余二个扇区,在内存中紧随本段代码放置(0:7E00h)
; 如果读入发生错误,则读入引导记录之备份(一般在首个备份之后6个扇区位置).
; 4). 转向读入的引导记录之第3扇区开始处(0:8000h)继续运行
; 5). 逐个扇区读入根目录于0:700h处,找寻IO.SYS目录项,如果要用到FAT表,
; 则将一个FAT表扇区读入0:7E00h处使用。
; 6). 找到IO.SYS目录项后,从其中取出IO.SYS文件起始簇号,计算出IO.SYS之
; 文件首个扇区磁盘物理位置, 连续4个读至0:700h~0:EFFh处。
; 7). RETF至70:200h处运行。
; 它载入IOSYSloader至000700h~00EFFh,并转向它时,寄存器设置如下:
; CS=70, DS=ES=SS=0. IP=200h,
; DI:SI=32位的IO.SYS文件起始簇号
; BP=7C00h --> 指向引导中的引导记录
; SP=7BF8H
; SP+0~3 --> diosys_dir_clusterid dd -1
; 根目录起始簇号
; SP+4~7 --> ddir_starting_sector dd ?
; 根目录起
; The code in this sector is responsible for locating the IO.SYS
; and for placing the directory sector with this information at
; physical address 00500h. After loading in this sector, it reads in 4
;sectors
; of the IO.SYS at BIOSEG:0 and does a long jump to
;BIOSEG:200h.
; If no IO.SYS is found an error message is displayed and the user is
; prompted to reinsert another disk. If there is a disk error during the
; process, a message is displayed and things are halted.
; At the beginning of the boot sector, there is a table which describes
;the
; MSDOS structure of the media. This is equivalent to the BPB with
;some
; additional information describing the physical layout of the driver
;(heads, tracks, sectors)
===============================================
.386= 0522 edisk_para_table
equ 522h
;*(0000:0522=0D1h)
seg_a segment byte public use16
assume cs:seg_a, ds:seg_a
org 7C00h 7C00 real_start:
; xref 0100
7C00 EB 58 jmp short realstart
; (7C5A)
7C02 90 bos_id db 90h
; store operation-system id here
; Inter-segment boundary
7C03 4D 53 57 49 4E 34 aOSversion
db 'MSWIN4.1'
; system version number
7C09 2E 31
7C0B 00 02 08 20 00 02 wBytesPerSector dw 0200h
; 00h WORD Size of a physical sector
7C0D bSecsPerClust db 08h
; 02h BYTE Sectors per allocation unit
7C0E wReservedSecs dw 0020h
; 03h WORD Number of reserved sectors
7C10 bNumFats db 02h
; 05h BYTE Number of fats
7C11 00 00 00 00 F8 00 wNumDirEntries dw 00h
; 06h WORD Number of direc entries
7C13 wTotalSectors dw 0000h
; 08h WORD Number of sectors - number of hidden
;sectors (0 when 32 bit sector number)
7C15 bMediaByte db 0F8h
; 0Ah BYTE MediaByte byte
7C16 wNumFatSecs dw 0000h
; 0Bh WORD Number of fat sectors
7C18 3F 00 80 00 wSecPerTrack dw 003Fh
; 0Dh WORD Sectors per track
7C1A wNumHeads dw 0080h
; 0Fh WORD Number of drive heads
7C1C 0000003F dHiddenSecs dd 0000003Fh
; 11h DWORD Number of hidden sectors
7C20 C1 0F 7A 00 dBigTotalSecs dd 007A0FC1h
;15h DWORD 32 bit version of number of sectors
7C24 75 1E 00 00 00 00 dfat_sectors dd 00001E75h
; 19h DWORD number of sectors per FAT, FAT32 only
wfat_offset dw 0000h
; 1Dh WORD fat # of the sector containing IO.SYS dir.
7C2A 00 00 02 00 00 00 w7C2A dw 0000h
; 1Fh WORD ?, must be zero
7C2C diosys_dir_loc dd 00000002h
; 21h DWORD cluster # of IO.SYS DIR entries.(start from 2)
; or index # of fat-item containing that cluster.
; (start from 2 also)
7C30 01 00 06 00 dw 0001h
; 25h WORD ?
7C32 w2ndBootRec_loc dw 0006h
; 29h WORD location of the backup of boot record.
; it is sector offset after 1st boot record.
7C34 000C[00] db 13 dup(0)
7C40 80 00 29 bboot_driver db 80h
; 35h byte BootDrv
7C41 bCurrentHead db 00h
; 36h byte Current Head
7C42 bExtBootSig db 29h
; 37h byte ExtBootSig, check by BIOSloader.
7C43 0B 0C 5F 16 dSerialNum dd 165F0C0Bh
7C47 4E 4F 20 4E 41 4D aVolumeLabel db 'NO NAME '
7C52 aFatid db 'FAT32 '
7C4D 45 20 20 20 20 46
7C53 41 54 33 32 20 20
7C59 20
=============================================================================================
; First thing is to reset the stack to a better and more known
; place. The ROM may change, but we'd like to get the stack
; in the correct place.
7C5A realstart:
7C5A FA cli
; Disable interrupts
7C5B 33 C9 xor cx,cx
; Zero register
7C5D 8E D1 mov ss,cx
7C5F BC 7BF8 mov sp,7BF8h
; 7BF8~7CFF : 8 byte space reserved for trans
; parameter to IOSYSloader
; We copy the disk parameter table from rom to ram(0:522) since we
;need to change it,
; then set back int[1e]->0:522 (disk_parameter_vectors).
7C62 8E C1 mov es,cx
7C64 BD 0078 mov bp,4 * 01Eh
7C67 C5 76 00 lds si,dword ptr [bp]
; get address of disk_para_table in ROMBIOS
7C6A 1E push ds
7C6B 56 push si
7C6C 16 push ss
7C6D 55 push bp
7C6E BF 0522 mov di,edisk_para_table
; set new disk_para_table vector to 0:0522h
7C71 89 7E 00 mov [bp],di
7C74 89 4E 02 mov [bp+2],cx
7C77 B1 0B mov cl,0Bh
7C79 FC cld
7C7A F3/ A4 rep movsb
; copy disk_para_table from ROMBIOS to RAM 0:522h
7C7E BD 7C00 mov bp,7C00h
; point bp to beginning of this code to let's
; access data at header of code easy.
; Set the head settle time to 15ms because we don't have room
; to do a disk retry and then set sectors per from the value
; in the BPB
7C81 C6 45 FE 0F mov byte ptr [di-2],0Fh
; update head settle time
7C7C 8E D9 mov ds,cx
7C85 8B 46 18 mov ax,[bp+offset wSecPerTrack -7C00h]
7C88 88 45 F9 mov [di-7],al
; update end_of_track
; because boot record is not large enought to hold all binary code,
; we put other code of boot record to other 2 sectors,
; so we read it in memory following this block code now. (address 0:7E00)
; since legacy int 13 can't read sector after 8.4G on a new-style hard disk.
; so if we boot from harddisk,
; we check all 4 partition items in partition table
; and check it for item that disk_hiddensec == relative sectors
; if that, following int13 use new extension (func 42h) to read sector.
7C8B 38 4E 40 cmp [bp+offset bboot_driver -7C00h],cl
; cl =0
; boot by floppy disk?
7C8E 7D 25 jge short loc_readfollowing
; yes, just go by legacy int 13
; no, boot by hard disk,
; so we read in partition table to 0:700h
; and check the hd having large-os
7C90 8B C1 mov ax,cx
7C92 99 cwd
; dx:ax = 0, 32-nit fat logic sector number
7C93 BB 0700 mov bx,700h
; es:bx = 0:700h
7C96 E8 0097 call sread_1_sector
; read in partition table
7C99 72 1A jc short loc_readfollowing
; jump over if error occurs
; check all 4 partition item for large OS id,
; record it to bos_id with bit 1 =1.
; Format of partition record:
; Offset Size Sample Value Description
; 00h byte 80h boot indicator (80h = active partition)
; ...
; 04h byte 0Bh os_id <-------------------------------------------------\
; ... |
; 08h dword 0000003Fh relative sectors <-------------------------------\ |
; 0Ch dword 007A0FC1h length of partition in sectors | |
7C9B 83 EB 3A sub bx,3Ah ; bx = 700h +200h -2 -40h +08h -------------------+ |
7C9E 66| A1 7C1C mov eax,dHiddenSecs |
7CA2 loc_nextitem: |
7CA2 66| 3B 07 cmp eax,[bx] ; dHiddenSecs of BPB == relative sectors in partition ? |
7CA5 8A 57 FC mov dl,[bx-4] ; dl = 700h +200h -2 -40h +04h -------------------------+
7CA8 75 06 jnz short @F ; no
7CAA 80 CA 02 or dl,2 ; yes, set large-os id
7CAD 88 56 02 mov [bp+offset bos_id -7C00h],dl
7CB0 @@: ; xref 7CA8
7CB0 80 C3 10 add bl,10h
7CB3 73 ED jnc loc_nextitem ; loop until all 4 partition items
; now, we are ready to read in following 2 sectors of boot record.
; if error occured during reading,
; we try to load the backup of boot record.
;
7CB5 loc_readfollowing: ; xref 7C8E, 7C99
7CB5 BF 0002 mov di,2 ; retry times
7CB8 83 7E 16 00 cmp [bp+offset wNumFatSecs -7C00h],0 ;
; FAT32 ?
7CBC 75 45 jne short loc_errorexit ; no, since this BOOTREC is for FAT32 only, so error &halt
; yes, get location of the boot record
7CBE 8B 46 1C mov ax,[bp+offset dHiddenSecs -7C00h]
7CC1 8B 56 1E mov dx,[bp+offset dHiddenSecs -7C00h +2]
7CC4 B9 0003 mov cx,3
7CC7 loc_retry: ; xref 7CF4
7CC7 49 dec cx
7CC8 40 inc ax ; this 2 sectors are just following hidden sector
7CC9 75 01 jnz short @F ; inc dx:ax
7CCB 42 inc dx ;
7CCC @@: ; read it to 0:7E00
7CCC BB 7E00 mov bx,7E00h
7CCF E8 005F call sread_cx_sectors ; (7D31)
7CD2 73 26 jnc short loc_bootrec2_ok ; jump if correct
; error occurs
7CD4 B0 F8 mov al,0F8h ; value of al not used anywhere
7CD6 4F dec di ; retry anymore ?
7CD7 74 1D jz short loc_nomore_retry ; no
; yes, we can't read in 1st copy of following boot record,
; so we read the backup of it.
; the location of the backup is always 6 and stored
; in w2ndBootRec_loc (offset 7C32h),
; since location of legacy boot record at this offset
; is other things, so we check it validation first.
7CD9 8B 46 32 mov ax,[bp+offset w2ndBootRec_loc -7C00h]
; always = 0006
7CDC 33 D2 xor dx,dx
7CDE B9 0003 mov cx,3
7CE1 3B C8 cmp cx,ax ; w2ndBootRec_loc < 3 ?
7CE3 77 1E ja short loc_errorexit ; yes, error
7CE5 8B 76 0E mov si,[bp+offset wReservedSecs -7C00h]
7CE8 3B CE cmp cx,si
; reserved sectors < 3 ?
7CEA 73 17 jae short loc_errorexit
; no, error
7CEC 2B F1 sub si,cx
; reserved sectors - 3
7CEE 03 46 1C add ax,[bp+dHiddenSecs -7C00h]
7CF1 13 56 1E dc dx,[bp+dHiddenSecs -7C00h]
; dx:ax = dHiddenSecs + wReservedSecs w2ndBootRec_loc - 3
; that is the location of the 2nd copy of boot record
7CF4 EB D1 jmp short loc_retry
; (7CC7)
7CF6 loc_nomore_retry:
; xref 7CD7
7CF6 73 0B jnc short loc_errorexit
7CF8 EB 27 jmp short loc_errorio
; (7D21)
7CFA loc_bootrec2_ok:
; xref 7CD2
7CFA 83 7E 2A 00 cmp word ptr [bp+w7C2A -7C00h],0
; w7C2A must be zero, or 80h~FFh
7CFE 77 03 ja short loc_errorexit
; or, error
loc_bootrec_ready:
7D00 E9 02FD jmp bootrecord2start
; jump to 8000, that is second sector of boot record.
7D03 loc_errorexit:
; xref 7CBC, 7CE3, 7CEA, 7CF6, 7CFE
7D03 BE 7D7E mov si,offset msg01start ; 'Invalid system disk'
7D06 loc_display:
7D06 AC lodsb
; the 1st byte pointed by si is offset of the error message
7D07 98 cbw
7D08 03 F0 add si,ax
7D0A @@:
; xref 7D1A
7D0A AC lodsb
; get message byte one by one
; end of message detect
7D0B 84 C0 test al,al ; end and reboot?
7D0D 74 17 jz short loc_reboot
; yes
7D0F 3C FF cmp al,0FFh
; end and show 'Replace the disk, and then press any key'?
7D11 74 09 je short loc_show_presskey
; yes
7D13 B4 0E mov ah,0Eh
; other byte other than 00h and 0FFh, show it
7D15 BB 0007 mov bx,7 7D18 CD 10 int 10h
; write char al, teletype mode
; INT 10 - VIDEO - (TTY write)
; AH = 0Eh
; AL = character
; BH = display page (alpha modes)
; BL = foreground color (graphics modes)
; Note: char 07h (BEL), 08h (BS), 0Ah (LF), and 0Dh (CR) are
; interpreted and do the expected things
; 7D1A EB EE jmp short @B
; go next byte 7D1C
; xref 7D11
7D1C .BE 7D81 mov si,offset msg03start
; 'Replace the disk, and then press any key', 0Dh, 0Ah
7D1F EB E5 jmp short loc_display
; (7D06)
7D21 loc_errorio:
; xref 7CF8
7D21 .BE 7D7F mov si,offset msg 02start
; 'Disk I/O error'
7D24 EB E0 jmp short loc_display
; (7D06)
7D26 loc_reboot:
; xref 7D0D
7D26 98 cbw
; wait for response
7D27 CD 16 int 16h
; get character from keyboard
7D29 5E pop si
; reset disk parameter table back to
7D2A 1F pop ds
; rom
7D2B 66| 8F 04 pop dword ptr [si]
7D2E CD 19 int 19h
; Continue in loop till good disk
winme endp
;-----------------------------------------------------------------------------------------------------
; read in sectors
; In: es:bx - buffer to hold data
;dx:ax - 32 bit logic sector address of the sectors to be read in
; cx - number of sector to be read in
; Out: carry set if error occured.
; carry clear if successful
; es:bx - the unused buffer following data read in.
; dx:ax - 32 bit logic sector address of the following
;sector to be read in
; cx - number of un read sectors
; Called from: 7C96
7D30 sread_1_sector proc near
; dx:ax = 0, bx=700h
7D30 41 inc cx
; cx = 1
; Called from: 7CCF
7D31 sread_cx_sectors:
; dx:ax = logic sector number
; es:bx-->buffer
7D31 loc_read_cx_sectors:
; xref 7D7B
; 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. max 127 (7Fh).
; 3 Byte Reserved, must be 0
; 4 2Word Address of transfer buffer. Seg:Offset.
; 8 4word Starting logical block address
7D31 56 push si
; si->00: 0010 -Packet size in bytes
7D32 66| 6A 00 push dword ptr 0
; 02: 0001 -# of blocks to transfer.
7D35 52 push dx
; 04: bx -
7D36 50 push ax
; 06: es -es:bx Address of transfer buffer
7D37 06 push es
; 08: ax -
7D38 53 push bx
; 0A: dx -00:00:dx:ax (64 bit)
7D39 6A 01 push 1
; 0C: 0000 -64 bit starting logical block address
7D3B 6A 10 push 10h
; 0E: 0000 -
7D3D 8B F4 mov si,sp
; 10: si
7D3F 60 pusha
7D40 80 7E 02 0E cmp byte ptr [bp+2],0Eh
; support int13 extension ?
; FORMAT put 0Eh here if int 13 extension supportted.
7D44 75 04 jne short loc_oldint13
; 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.
7D46 B4 42 mov ah,42h
; new int13 use si-> parameter
7D48 EB 1D jmp short loc_issueint13
; (7D67)
; Convert a logical sector into Track/sector/head.
; dx
;ax has the sector number. cx has the number sectors to , we
; are going to use Simple 32 bit division here (why not 386 s?)
; LBA = (C1 * H0 + H1) * S0 + S1 - 1
; C1 = Selected Cylinder Number
; H0 = Number of Heads (Maximum Head Number +1)
; H1 = Selected Head Number
; S0 = Maximum Sector Number
; S1 = Selected Sector Number
7D4A loc_oldint13:
; xref 7D44
7D4A 91 xchg cx,ax
;
7D4B 92 xchg dx,ax
;
7D4C 33 D2 xor dx,dx
;
7D4E F7 76 18 div word ptr [bp+wSecPerTrack-7C00h]
;
7D51 91 xchg cx,ax
;
7D52 F7 76 18 div word ptr [bp+wSecPerTrack-7C00h]
7D55 42 inc dx
;
7D56 87 CA xchg cx,dx
;
7D58 F7 76 1A div word ptr [bp+wNumHeads-7C00h]
;
7D5B 8A F2 mov dh,dl
;
7D5D 8A E8 mov ch,al
;
7D5F C0 CC 02 ror ah,2
;
7D62 0A CC or cl,ah
;
7D64 B8 0201 mov ax,201h
7D67 loc_issueint13:
;
7D67 8A 56 40 mov dl,[bp+bboot_driver-7C00h]
7D6A CD 13 int 13h
; Disk dl=drive ? ah=func 02h
; read sectors to memory es:bx
; al=#,ch=cyl,cl=sectr,dh=head
7D6C 61 popa
; Restore all regs
7D6D 8D 64 10 lea sp,[si+10h]
;
7D70 5E pop si
7D71 72 0A jc short loc_ret_19
; jump to return if error
7D73 40 inc ax
; next logic sector
7D74 75 01 jnz short @F
7D76 42 inc dx
7D77 @@:
;xref 7D74
7D77 03 5E 0B add bx,[bp+wBytesPerSector-7C00h]
7D7A 49 dec cx
7D7B 75 B4 jnz loc_read_cx_sectors
;
7D7D loc_ret_19:
; xref 7D71
7D7D C3 retn
sread_1_sector endp
; if a message string end with 0FFh, that means
; we need display msg3, then reboot.
; if it is zero (00h), reboot system after diaplay.
7D7E 03 msg01start db 3
; offset 7d7e + 3 + 1 --> msg01
7D7F 18 msg02start db 18h
; offset 7d7f + 18h + 1 --> msg02
7D80 01 msg01start2 db 1
; offset 7d80 + 1 + 1 --> msg01
7D81 27 0D 0A 49 6E 76 msg03start db 27h
; offset 7d81 + 27h + 1 --> msg03
msg01 db 0Dh, 0Ah, 'Invalid system di'
7D87 61 6C 69 64 20 73
7D8D 79 73 74 65 6D 20
7D93 64 69
7D95 73 6B db 'sk'
7D97 FF db 0FFh
7D98 .0D 0A 44 69 73 6B msg02 db 0Dh, 0Ah, 'Disk I/O error'
7D9E 20 49 2F 4F 20 65
7DA4 72 72 6F 72
7DA8 FF db 0FFh
7DA9 .0D 0A 52 65 70 6C msg03 db 0Dh, 0Ah, 'Replace the disk, and '
7DAF 61 63 65 20 74 68
7DB5 65 20 64 69 73 6B
7DBB 2C 20 61 6E 64 20
7DC1 74 68 65 6E 20 70 db 'then press any key', 0Dh, 0Ah
7DC7 72 65 73 73 20 61
7DCD 6E 79 20 6B 65 79
7DD3 0D 0A
7DD5 00 00 00 db 0, 0, 0
7DD8 .49 4F 20 20 20 20 strIOSYS db 'IO SYS'
7DDE 20 20 53 59 53 4D
7DE4 53 44 4F 53 20 20
7DEA 20 53 59 53 7E
7DE0 strMSDOSSYS db 'MSDOS SYS'
7DEE wgomsg01 dw offset msg01start
7DEF 01 00 db 0
7DF1 .57 49 4E 42 4F 4F strWINBOOTSYS db 'WINBOOT SYS'
7DF7 54 20 53 59 53
7DFC 00 00 55 AA db 00h, 00h, 55h,0AAh
; bp-4 ddir_starting_sector dd ?
; start logic-sector-number of root dir
; bp-8 diosys_dir_clusterid dd -1
; fat index of directory entry location of io.sys
; The system is now prepared for us to begin reading.
; Now we determine logical sector numbers of the start of the directory
8000 bootrecord2start:
; xref 7D00
8000 FA cli
8001 66| 0F B6 46 10 movzx eax,[bp+offset bNumFats -7C00h]
8006 66| 8B 4E 24 mov ecx,[bp+offset dNumFatSecs -7C00h]
800A 66| F7 E1 mul ecx
800D 66| 03 46 1C add eax,[bp+offset dHiddenSecs -7C00h]
8011 66| 0F B7 56 0E movzx edx,[bp+offset wReservedSecs-7C00h]
8016 66| 03 C2 add eax,edx
; eax = NumFats * NumFatSecs + ReservedSecs + dHiddenSecs
8019 33 C9 xor cx,cx
801B 66| 89 46 FC mov [bp-4],eax
; start logic-sector-number of DIRs (00003D49)
801F 66| C7 46 F8 + mov dword ptr [bp-8],0FFFFFFFFh
FFFFFFFF ; mark end-of-fat
; First we treat diosys_dir_loc as cluster # of IO.SYS DIR entries.
; read in all root directories (one cluster).
;FAT look like this,
; 00000000: F8 FF FF 0F FF FF FF 07 - 9D A0 04 00 0C 00 00 00
; 00000010: 05 00 00 00 E1 10 00 00 - 07 00 00 00 04 00 00 00
; 00000020: 09 00 00 00 06 00 00 00 - 0B 00 00 00 2F 00 00 00
; 00000030: 30 00 00 00 0E 00 00 00 - 29 00 00 00 27 00 00 00
; 00000040: 11 00 00 00 12 00 00 00 - 13 00 00 00 14 00 00 00
; the 1st one (0FFFFFF8) is MEDIA_DESCRIPTOR
; and 2nd one (07FFFFFF) is actually used by root dir.
; so fat-index must start from 2.
8027 FA cli ; don't intrupt shld
8028 66| 8B 46 2C mov eax,[bp+offset diosys_dir_loc -7C00h]
; start cluster# of IO.SYS DIRs,
; must be > 2 & < 0FFFFFF8h
802C 66| 83 F8 02 cmp eax,2 ; > 2 ?
8030 0F 82 FCCF jb loc_errorexit ; no, error
8034 66| 3D 0FFFFFF8 cmp eax,0FFFFFF8h ; < 0FFFFFF8h ?
803A 0F 83 FCC5 jae loc_errorexit ; no, error
803E 66| 0F A4 C2 10 shld edx,eax,10h
; eax => dx:ax
8043 FB sti
; loc of DIR + sector offset = loc of "IO.SYS" dir entry
8044 loc_add_dir_loc:
; xref 8097
8044 52 push dx
8045 50 push ax
8046 FA cli ; don't intrupt shld
8047 66| C1 E0 10 shl eax,10h
804B 66| 0F AC D0 10 shrd eax,edx,10h
8050 66| 83 E8 02 sub eax,2
8054 66| 0F B6 5E 0D movzx ebx,byte ptr [bp+offset bSecsPerClust-7C00h]
8059 8B F3 mov si,bx
; retry times =bSecsPerClust
; that means try this cluster only.
805B 66| F7 E3 mul ebx
805E 66| 03 46 FC add eax,[bp-4] ; start logic-sector-number DIRs
8062 66| 0F A4 C2 10 shld edx,eax,10h
8067 FB sti