WIN98/98SE/ME 引导分区代码析

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