Windows 95 Boot Sector

类别:编程语言 点击:0 评论:0 推荐:
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;
; Description:  Heroic attempt to disassemble the Windows 95 Boot Sector.
; Date:         16. Aug. 1998
; Author:       Mr. X
; Email:        unknown
; Comment:      This boot code is messy.
; Status:       PART I, II and III are now pretty much done.
; Important:    "SHLD EDX,EAX,16" This is a Microsoft Patent.
;               Also take a look at the "list near EOF"
;
; ---> CUT HERE IF YOU LIKE TO LISTEN TO ME <---
;
; This file will assemble into a fully functional (I hope) Win95B boot code.
;
;  tasm win95 /m
;  tlink win95,win95.bin /t
;
; Ask someone for the proper dropper code...
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;
; AFTER DISASSEMBLY I have this impression:
;
;  This is what Bill Gates said... when Win95 was going to be released:
;
;  "Gates: OK, then we're ready to press the CD's and start shipping out
;   this new load of shit, but of course nobody will notice... harr harr.
;   Employee: Hey, Mr. Gates what about the Boot Sector?? We haven't
;   written the FAT32 support routines there yet...
;   Gates: Ah, that's right... anybody?? We have just 45 minutes...
;   Employee #2: Well, I think I can hack some shit together...
;   Gates: Fine, go for it... remember you have only 44 minutes...
;   Employee #2: I think I can do it.
;   Gates: Fine, then I'll just go home... We've made it!!"
;
; FUNNY?
;
; There is some really strange code in this boot record....
;
; I bet Bill Gates hired some crazy mother fucker to write this shit.
; It seems like he had really tried to make the code fit within one sector.
; But when it didn't hid just decided to use three instead...
;
; This is a typical microsoft solution, they mix stupid 8086 code... with
; cheap solutions and then suddenly they use 386 code...
;
; And then there is the new FAT32 data structures where they have moved
; the volume label, FileSystem ID and serial number down to make room for
; some extended FAT32 variables... it sucks. Why not rearange the whole
; structure... An OS would not try to interpret the shit anyway, because
; the Partitioni Table SYSID has changed with FAT32.
;
; As I said... crazy mother fucker...
;
; Well, well... here's some of the stuff... with a mix of mine and sourcer's
; comments...
;
; Another thing about TASM, which I use, of course I didn't buy it... I'm
; have a shareware version on a 30 year trial period.
;
; Back to what I was about to say again... When I use the brXXXX variables
; in indexing with BP, TASM generates 16-bit offset in operands even when
; they are less than 128... the Win95 code uses byte offsets (I'm not sure
; if I'm expressing myself clear here). When I changed the code from:
;
; mov AX,[bp+brHPC] to mov AX,[bp+128], TASM did use the byte offset form...
; This made my code a little less readable... but the comments should give
; you an idea of what data is being accessed.
;
; Basically this boot sector code is 32 bit extension for a 16 bit patch to
; an 8 bit boot sector originally coded for a 4 bit microprocessor, written
; by a 2 bit company, that can't stand 1 bit of competition.
;
; ---> CUT HERE IF YOU DOES NOT LIKE TO LISTEN TO ME <---

.386C

CODE            SEGMENT USE16

               ASSUME  CS:CODE, DS:CODE, SS:NOTHING

; BOOT RECORD - PART I - MAIN BOOT SECTOR CODE

; Just so I've said it - ASM opcodes are only readable when capitalized,
; but I forgot to set the option in sourcer... so I wrote a small TP program
; that capitalized everything but what's after the semicolon...

Win95b          PROC    FAR

               JMP     SkipData        ; 0000h

brINT13Flag     DB      90H             ; 0002h - 0EH for INT13 AH=42 READ
brOEM           DB      'MSWIN4.1'      ; 0003h - OEM ID - Windows 95B
brBPS           DW      512             ; 000Bh - Bytes per sector
brSPC           DB      8               ; 000Dh - Sector per cluster
brResCount      DW      32              ; 000Eh - Reserved sectors
brFATs          DB      2               ; 0010h - FAT copies
brRootEntries   DW      0               ; 0011h - Root directory entries
brSectorCount   DW      0               ; 0013h - Sectors in volume, < 32MB
brMedia         DB      0F8H            ; 0015h - Media descriptor
brSPF           DW      0               ; 0016h - Sectors per FAT
brSPH           DW      63              ; 0018h - Sectors per head/track
brHPC           DW      128             ; 001Ah - Heads per cylinder
brHidden        DD      63              ; 001Ch - Hidden sectors
brSectors       DD      6305985         ; 0020h - Total number of sectors
brSPF32         DD      6153            ; 0024h - Sector per FAT (FAT32)
brFlags         DW      0               ; 0028h - Flags (FAT32)
brVersion       DW      0               ; 002Ah - FS Version (FAT32)
brRootCluster   DD      2               ; 002Ch - Root start cluster (FAT32)
brFSInfoSector  DW      1               ; 0030h - FS Info Sector (FAT32)
brBackupBoot    DW      6               ; 0032h - Backup Boot Record
brReserved      DB      6 DUP (0)       ; 0038h - Reserved
brShitter       DB      6 DUP (0)       ; 003Bh - Unused filler??
brDrive         DB      80H             ; 0040h - BIOS drive number
brHeadTemp      DB      00H             ; 0041h - Head/temp number????
brSignature     DB      29H             ; 0042h - Extended Boot Record sig.
brSerialNum     DD      404418EAH       ; 0043h - Volume serial number
brLabel         DB      'HARDDISK   '   ; 0047h - Volume label
brFSID          DB      'FAT32   '      ; 0052h - File System ID

SkipData:
               CLI
               XOR     CX,CX
               MOV     SS,CX                   ; SS=CX=0

       ; Set up stack 8 bytes below us, do you know why???
       ; Yes, it's because somewhere in this code, the shitter who
       ; wrote this... save the start of data area DWORD at 7C00H - 4 and
       ; the value -1 at 7C00H - 8... cool?

               MOV     SP,7C00H - 8            
               MOV     ES,CX                   ; ES=CX=0
               MOV     BP,78H                  

       ; Point DS:SI to INT 1E - DISKETTE PARAMS structure...

               LDS     SI,DWORD PTR SS:[BP]

PUSHDS
PUSHSI
PUSHSS
PUSHBP

               MOV     DI,522H

               MOV     SS:[BP],DI                 ; setup our INT 1E
               MOV     SS:[BP+2],CX

       ; copy 11 bytes from old diskette parameter table into
       ; es:522h, that is 0000:0522 or 0050:0022 - into the PrtScr/DOS area.
       ; I assume that 0001-0021 is used for something else 0050:0000 I know
       ; is the PrtScr flag byte.

               MOV     CL,11
               CLD
               REP     MOVSB
                                       
               MOV     DS,CX                   ; DS=CX=0

               MOV     BP,7C00H                ; point BP to start of us

               MOV     BYTE PTR [DI-2],0FH     ; modify head settle time

               MOV     AX,SS:[BP+18H]

               MOV     [DI-7],AL               ; modify sectors per track

       ; compare drive number with 0...
       ; if greater than or equal... go to MBRReadError
       ; I guess that lower than zero... must be -1 .. -128 (80H..FFH)
       ; Which would mean Harddisk boot...

               CMP     SS:[BP+40H],CL          ; Boot from diskette?
               JGE     MBRReadError

               MOV     AX,CX                   ; AX=CX=0
               CWD                             ; DX=AX[15]-> (ZerO)

               MOV     BX,0700H                ; Use 0000:0700 for sector
                                               ; read buffer

               CALL    ReadSector              ; load Master Boot Record
               JC      MBRReadError            ; error?

               SUB     BX,58                   ; BX = 08C6h (700h - 3Ah)
                                               ; point to "start" field
                           
               MOV     EAX,DS:[7C1CH]          ; load hidden sectors
CheckMBR:
               CMP     EAX,[BX]                ; Is this our entry??

               MOV     DL,[BX-4]               ; Put System ID in DL

               JNZ     NotOurs                 ; Jump if not our entry

       ; If system ID or "partition type", is 0Ch or 0Eh, ReadSector
       ; will use INT13/42H...

               OR      DL,2                    ; set bit 1, to allow for
                                               ; types 0Ch or 0Eh to be
                                               ; thought of as both 0Eh.

               MOV     SS:[BP+2],DL            ; set brINT13Flag
NotOurs:
               ADD     BL,16                   ; skip to next entry...
               JNB     CheckMBR                ; More entries?
MBRReadError:
               MOV     DI,2

       ; FAT32 - Is sector per FAT zero?

               CMP     WORD PTR SS:[BP+16H],0
               JNE     ShowErrMsg1

       ; Put number of hidden sectors in DX:AX

               MOV     AX,WORD PTR SS:[BP+1CH]
               MOV     DX,WORD PTR SS:[BP+1EH]

               MOV     CX,3    ; Boot Record is 3 sectors...

       ; Start loading reminder of Boot Record for FAT32
LoadIt:
               DEC     CX
               INC     AX                      ; next Boot Record sector

               JNZ     Skipper                 ; AX wrap-around?
               INC     DX                      ; Yes, inc DX too
Skipper:
               MOV     BX,7E00H                ; into 0000:7E00

               CALL    ReadSectorX             ; Read Sector
               JNC     ReadOK                  ; no error?

               MOV     AL,0F8H                 ; what's this????

DECDI
               JZ      NoMore                  ; Jump if no more sectors

               MOV     AX,SS:[BP+32H]          ; get backup boot sector
               XOR     DX,DX                  

               MOV     CX,3                    
               CMP     CX,AX                   ; compare backup BS num
               JA      ShowErrMsg1             ; with 3 (or vice versa)

                                               ; if 3 is higher than
                                               ; backup sector number,
                                               ; Bill's oooutta here...

               MOV     SI,SS:[BP+0EH]          ; SI = # of reserved sectors
               CMP     CX,SI
               JAE     ShowErrMsg1             ; same thing here... if 3 is
                                               ; higher then the number of
                                               ; reserved sectors... Bill's
                                               ; gone

               SUB     SI,CX                   ; get number reserved sectors
                                               ; excluding the three boot
                                               ; sectors...

       ; add number of hidden sectors to DX:AX

               ADD     AX,WORD PTR SS:[BP+1CH]
               ADC     DX,WORD PTR SS:[BP+1EH]

               JMP     LoadIt
NoMore:
               JNC     ShowErrMsg1             ; Jump if carry=0
               JMP     ShowErrMsg2
ReadOK:
               CMP     WORD PTR SS:[BP+2AH],0
               JA      ShowErrMsg1             ; Jump if not version 0.0?

               JMP     GOFAT32
ShowErrMsg1:
               MOV     SI,OFFSET ErrMsg1 + 7C00H
PrintMessage:
               LODSB                           ; get msg Skip length

               CBW
               ADD     SI,AX                   ; Skip control data
NextChar:
               LODSB                           ; get chacacter

TESTAL,AL
               JZ      LastChar                ; End of string?

               CMP     AL,-1
               JE      SkipChar                ; End of first part?

               MOV     AH,0EH                  ; TTY write character
               MOV     BX,7
               INT     10H

               JMP     NextChar                ; repeat write...
SkipChar:
               MOV     SI,OFFSET ErrMsg4 + 7C00H       ; point to tail message
               JMP     PrintMessage
ShowErrMsg2:
               MOV     SI,OFFSET ErrMsg2 + 7C00H
               JMP     PrintMessage
LastChar:
               CBW                     ; Ah, clever... save one byte, take
                                       ; advantage of the fact that LODSB
               INT     16H             ; returns the null-terminator.

               POP     SI              ; restore the stack... why???
               POP     DS              ; the stack is killed at startup...
               POP     DWORD PTR [SI]  

               INT     19H             ; BIOS bootstrap loader...

Win95b          ENDP

;==========================================================================
;                              READ SECTOR
;==========================================================================

ReadSector      PROC    NEAR

               INC     CX                      ; increase SECTOR COUNT
ReadSectorX:

rsReadMore:
PUSHSI
PUSHDWORD PTR 0
               PUSH    DX
               PUSH    AX
PUSHES
               PUSH    BX
PUSH1
PUSH10H

               MOV     SI,SP                   ; save stack pointer
                                               ; for later use by LEA

               PUSHA                           ; Save "all" registers

               CMP     BYTE PTR SS:[BP+2],0EH     ; Use INT13 extensions?
               JNE     rsOldINT13

               MOV     AH,42H                  ; Do ext INT13 READ
               JMP     RSDiskIO
rsOldINT13:
               XCHG    CX,AX                   ; swap CX and AX
               XCHG    DX,AX                   ; swap DX and AX
               XOR     DX,DX                   ; clear DX

               DIV     WORD PTR SS:[BP+18H]    ; div LBA_HI by sectors/track

               XCHG    CX,AX                   ; save result in CX and put
                                               ; the LBA_LO in AX

               DIV     WORD PTR SS:[BP+18H]    ; divide reminder and LBA_LO
                                               ; by sectors/track too

               INC     DX                      ; make sector 1-based

               XCHG    CX,DX                   ; save it in CX and get the
                                               ; result of the 1st division
                                               ; in DX

               DIV     WORD PTR SS:[BP+1AH]    ; divide this new result by
                                               ; heads per cylinder

               MOV     DH,DL                   ; save Head of CHS in DH
                                               ; head was in the reminder
                                               ; after the division above

               MOV     CH,AL                   ; save LO cylinder in CH
                                               ; cylinder was in the result
                                               ; after the division above

               ROR     AH,2                    ; rotate AH to make bits 8-9
                                               ; of cylinder appear as bits
                                               ; 6-7 in AH and...
               OR      CL,AH                   ; or it with the sector num

               MOV     AX,201H                 ; setup for READ - 1 sector
rsDiskIO:
               MOV     DL,SS:[BP+40H]          ; load drive number
               INT     13H                     ; call INT13

               POPA                            ; Restore "all" registers

       ; the entry code pushed 12h bytes on the stack...
       ; the last word pushed was 0001h, restore SP to point to it...

LEASP,[SI+10H]; Load effective addr

       ; Now, SI should contain 0001h

POPSI

       ; was there an error from INT13?

               JC      RSDone

               INC     AX                      ; increment LBA sector num
               JNZ     rsSkip                  ; wrap-around?

               INC     DX                      ; yes raise high word too
rsSkip:
               ADD     BX,SS:[BP+0BH]          ; increment by sector size

               DEC     CX                      ; decrement SECTOR COUNT
               JNZ     rsReadMore              ; Jump if more to read
rsDone:
               RET

ReadSector      ENDP

;============================================================================
;              DATA AREA FOR MESSAGES - IN "NORSK" NORWEGIAN
;============================================================================

ErrMsg1         DB      03H     ; Skip counter for message1
ErrMsg2         DB      18H     ; Skip counter for message2
ErrMsg3         DB      01H     ; Skip counter for message3
ErrMsg4         DB      27H     ; Skip counter for message4

               DB      13,10,'Ugyldig systemdisk ',-1
               DB      13,10,'Disk I/U-feil ',-1
               DB      13,10,'Sett inn en annen disk, og trykk en tast',13,10,0

;============================================================================

               DB      0,0                     ; Padding?

       ; ROOT file names to search for...?

IO_SYS          DB      'IO      SYS'
MSDOS_SYS       DB      'MSDOS   SYS'

               DB      7EH,1,0                 ; What is this?

WINBOOT_SYS     DB      'WINBOOT SYS'           ; When is this used?

               DB      0,0                     ; Padding?
               DW      0AA55H                  ; 1st Boot Signature

;
; BOOT RECORD - PART II - FSINFO sector
;
               DB      'RRaA'                  ; FAT32 Extension Signature

DB480 DUP (0)

; FSINFO information...

               DB      'rrAa'                  ; FAT32 FSINFO Signature

brFreeClusters  DD      56990           ; I have 233431040 bytes free!
brNextFree      DD      466175          ; My next free cluster!
               DD      3 DUP (0)       ; Reserved, acroding to FAT32API.HLP

               DW      ?               ; word padding

               DW      0AA55H                  ; 2nd Boot Signature
;
; BOOT RECORD - PART III - FAT32 specific code, I think? only Bill knows?
;
GOFAT32:
               CLI

       ; calculate total size of FAT area

               MOVZX   EAX,BYTE PTR SS:[BP+10H]        ; number of FATs
               MOV     ECX,SS:[BP+24H]                 ; sectors per FAT
               MUL     ECX                             ; mul'em

       ; add hidden sectors

               ADD     EAX,SS:[BP+1CH]

       ; add reserved sectors

               MOVZX   EDX,WORD PTR SS:[BP+0EH]
               ADD     EAX,EDX

               XOR     CX,CX           ; clear CX for some reason...
                                       ; By looking down the code, I can't
                                       ; seem to find out why CX is cleared
                                       ; It's set to 1 down there...
                                       ; before it's ever used...

       ; EAX will now point to the start of the data area (cluster 2)
       ; save start of data area below us at 0000:7BFC, or there around...

               MOV     SS:[BP-4],EAX

       ; Save another value to... This one is checked by GetFAT32Sector

               MOV     DWORD PTR SS:[BP-8],0FFFFFFFFH

       ; Oh... at Microsoft they take no chances... disable INTs again!
       ; This is what I call proper software writing! Hail M$

               CLI

       ; load Root Start Cluster in EAX

               MOV     EAX,SS:[BP+2CH]

       ; Is it cluster 2?

               CMP     EAX,2
               JB      ShowErrMsg1             ; error if less than 2

       ; Is it an EOF marker or something above?

               CMP     EAX,0FFFFFF8H
               JAE     ShowErrMsg1             ; error if it is

       ; Put upper 16-bits of cluster number into DX??

               SHLD    EDX,EAX,16

               STI                             ; Puh. Safe again.
GetRootCluster:
               PUSH    DX
               PUSH    AX

               CLI                             ; Eh?

       ; clear upper 16-bits of cluster number, and of course move up the
       ; lower bits...

               SHL     EAX,16

       ; shift lower 16-bits of cluster number back down, and at the same
       ; time shift in the high 16-bits in top of EAX?

               SHRD    EAX,EDX,16

       ; make cluster number 0-based... "the way it's supposed to be"

               SUB     EAX,2

       ; put Sectors Per Cluster in EBX

               MOVZX   EBX,BYTE PTR SS:[BP+0DH]

       ; save it in SI too! Yippi

               MOV     SI,BX

       ; calculate relative sector of first part of root... right?

               MUL     EBX

       ; add the "start of data area" value we saved below us!

               ADD     EAX,SS:[BP-4]

       ; Maybe now, some shitter is trying to make DX:AX what EAX is??
       ; Shift upper 16-bits of EAX into DX... and AX is lower bits...

               SHLD    EDX,EAX,10H

               STI; Enable interrupts
GetRootSector:

       ; Use 0070:0000 as a directory buffer...
       
               MOV     BX,0700H
               MOV     DI,BX

       ; read 1 sector

               MOV     CX,1

               CALL    ReadSectorX             ; this shit should be pretty
               JC      ShowErrMsg2             ; obvious...
CheckEntry:
               CMP     [DI],CH                 ; is the first entry of the
               JE      EndOfRoot               ; root empty???

               MOV     CL,11                   ; the stupid CP/M filenames
                                               ; are 11 bytes...
               PUSHSI

               MOV     SI,OFFSET IO_SYS + 7C00H

               REPE    CMPSB                   ; Is it IO.SYS?

               POPSI

               JZ      FoundOS         ; Yeah...

               ADD     DI,CX           ; add what's left after CMPSB
               ADD     DI,15H          ; and then 21 more...

       ; Yeah, yeah, anyway... point to the next dir entry...
       ; and check if it is above the last entry... INT13 increments
       ; BX with 512 on the sector read, so it points past the sector.

               CMP     DI,BX
               JB      CheckEntry                  ; Jump if below

       ; are there any more sectors in this cluster???

DECSI
               JNZ     GetRootSector           ; yeap, read more

               POP     AX              ; restore cluster number
               POP     DX

       ; Get FAT value... "GetFAT32value" will compare the value with
       ; -8, and the JB below continues if below... that is, non-EOF/BAD
       ; the "previous cluster" value is taken from DX:AX (as restored
       ; above with POP).

               CALL    GetFAT32value
               JB      GetRootCluster

       ; if not end of root... go to GetRootCluster..

EndOfRoot:                                      ; EOF/BAD cluster...
               ADD     SP,4                    ; clean up stack...
               JMP     ShowErrMsg1             ; and print error message
FoundOS:
               ADD     SP,4                    ; clean up...


       ; Now... DI should point just above the IO.SYS name...

       ; SI would be set to DirEntry[14H] - starting cluster (HI)
       ; DI would be set to DirEntry[1AH] - starting cluster (LO)

               MOV     SI,[DI+09H]
MOVDI,[DI+0FH]

       ; copy FAT32 starting cluster upper 16-bits to AX

               MOV     AX,SI

CLI; Disable interrupts

       ; shift cluster high into upper half of EAX and store lower half
       ; from DI into AX

               SHL     EAX,10H
               MOV     AX,DI

       ; cluster out of range??

               CMP     EAX,2                   ; clusters start with 2
               JB      InvalidCluster

               CMP     EAX,0FFFFFF8H           ; cluster 0FFFFFF8 is EOF
               JAE     InvalidCluster

               DEC     EAX                     ; make it 0-based...
               DEC     EAX

       ; Multiply cluster number with "sectors per cluster"

               MOVZX   ECX,BYTE PTR SS:[BP+0DH]
               MUL     ECX

       ; Add the "start of data area" value that was saved back there...

               ADD     EAX,SS:[BP-4]

       ; And for the N'th time, make DX:AX same as EAX - sector number.

               SHLD    EDX,EAX,10H

               STI                             ; aha...

               MOV     BX,0700H                ; IO.SYS loads here!

               PUSH    BX
               MOV     CX,4                    ; load 4 IO.SYS sectors
               CALL    ReadSectorX             ; 2K is minimum FAT32 cluster
               POP     BX                      ; size anyway...

               JC      ShowErrMsg2             ; error...???


       ; COMMENT:
       ;
       ; Now, there is enough code here... to read the entire IO.SYS
       ; file into memory. This code has code to go through the FAT,
       ; there is code to read cluster... bla bla. And still only 2K
       ; of IO.SYS is read. If the entire file was read... IO.SYS would
       ; not have to do this... well well.

       ; Is there a Mark Zibikowski in the room?

               CMP     WORD PTR [BX],'ZM'              ; EXE signature...
               JNE     InvalidCluster

       ; Is there a Barabara Jones in the room?

               CMP     WORD PTR DS:[0200H][BX],'JB'    ; IO.SYS signature?
               JE      ExecutIOSYS

       ; The above shit appear in the IO.SYS file at offsets 0 and 200h
       ; The MZ is the usual EXE signature while the "BJ" is unknown to
       ; me. Maybe they chose it because it translates to harmless code:
       ;
       ;   INC DX - DEC DX, pretty dull if you ask me
       ;
InvalidCluster:
               MOV     SI,OFFSET ErrMsg3 + 7C00H
               JMP     PrintMessage
ExecutIOSYS:
               DB      0EAH            ; Jump to IO.SYS at 0070:0200
               DW      0200H, 0070H

;==========================================================================
;                              GET FAT32 value
;==========================================================================

GetFAT32value   PROC    NEAR

               ADD     AX,AX                   ; Multiply DX:AX by 4,
               ADC     DX,DX
               ADD     AX,AX                   ; convert DX:AX from FAT32
               ADC     DX,DX                   ; index value to offset

       ; DX:AX is passed on as the FAT offset to lookup...

               CALL    GetFAT32Sector          ; read FAT sector

       ; the correct sector is returned... with DI as index...??
       ; At least that's what the MOV below assumes...

               CLI

               MOV     EAX,ES:[BX+DI]          ; EAX = cluster value

       ; mask of top 4 bits of because Microsoft say it's reserved.

               AND     EAX,0FFFFFFFH          

       ; Make DX:AX the cluster number too...

               SHLD    EDX,EAX,16              ; EAX[HI] into EDX[LO]

       ; Check for EOF/BAD

               CMP     EAX,0FFFFFF8H           ; Is it the EOF marker?

               STI                             ; return with ZF=1 if the
                                               ; last cluster was read??
               RET

GetFAT32value   ENDP

;==========================================================================
;                         GET FAT32 SECTOR
;==========================================================================

; On entry DX:AX is the FAT offset in bytes...

GetFAT32Sector  PROC    NEAR

       ; When this is called 0070:0200 seems to be the buffer in ES:BX
       ; but, the code below uses the DI value set down under here...

               MOV     DI,7E00H

CLI; Disable interrupts

       ; make EAX the sector number again... move DX into top of EAX...

               SHL     EAX,16
               SHRD    EAX,EDX,16

       ; move bytes per sector into ECX

               MOVZX   ECX,WORD PTR SS:[BP+0BH]

       ; divide EDX:EAX by BPS... EAX = sector, EDX = offset in sector...

               XOR     EDX,EDX
               DIV     ECX

       ; Check FAT sector number agains... saved value on stack...
       ; This one is initially -1 (also known as 0FFFFFFFFH)

               CMP     EAX,SS:[BP-8]  
               JE      LOC_30

       ; If sector is <> from -1, save this sector at 0000:7BF8

               MOV     SS:[BP-8],EAX  

       ; add hidden sectors...

               ADD     EAX,SS:[BP+1CH]

       ; add reserved sectors too...

               MOVZX   ECX,WORD PTR SS:[BP+0EH]
               ADD     EAX,ECX

       ; get FAT32 flags into EBX

               MOVZX   EBX,WORD PTR SS:[BP+28H]

       ; keep "Active FAT" bits 0-3

               AND     BX,0FH

       ; If zero, we're at the correct FAT

               JZ      CorrectFAT

       ; compare active FAT with number of FATs...

               CMP     BL,SS:[BP+10H]
               JAE     ShowErrMsg1     ; oops... invalid active FAT
               
               PUSH    DX              ; save DX for a while...

       ; save FAT sector in ECX

               MOV     ECX,EAX

       ; Put sectors per fat in EAX

               MOV     EAX,SS:[BP+24H]

       ; Multiply active FAT number with sectors per FAT

               MUL     EBX

       ; Add to first FAT sector number we already had...

               ADD     EAX,ECX

       ; NOW, EAX contains the correct FAT sector number.

               POP     DX
CorrectFAT:
               PUSH    DX

       ; And for the N'th time, make DX:AX same as EAX - sector number.

               SHLD    EDX,EAX,16

STI; Enable interrupts

               MOV     BX,DI                   ; read FAT sector into
                                               ; 0000:7E00

       ; They sucker who wrote this could have saved 1 byte by
       ; saying XOR CX,CX instead of MOV CX,1 and called ReadSector
       ; instead of ReadSectorX, because there is an INC CX at
       ; ReadSector... haha...

               MOV     CX,1                    ; 1 sector
               CALL    ReadSectorX

               POP     DX

               JC      ShowErrMsg2
LOC_30:
STI; Enable interrupts
               MOV     BX,DX
               RET

GetFAT32Sector  ENDP

       ; Properly align the sector's boot signature at the end of
       ; the 3rd boot sect0r.

               ORG     512 * 3 - 2

               DW      0AA55H                  ; 3rd Boot Signature

CODE            ENDS

               END

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;
;  CONCLUSION - THE END - HASTA LA VISTA - SLUTT - DET VAR ALT FOR I DAG.
;
;  OK, Folks. that was quite a bit of work. It got pretty simple after some
;  hours.
;
;  I would like to thank the following people...
;
; * V Communications for Sourcer.
; * Ralf Brown for the Interrupt List.
; * Uriah Heep, The Who and Blind Guardian, for providing music.
;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -




本文地址:http://com.8s8s.com/it/it22607.htm