mirror of
https://github.com/microsoft/MS-DOS.git
synced 2024-11-29 00:55:47 +00:00
627 lines
18 KiB
NASM
627 lines
18 KiB
NASM
|
TITLE GETSET - GETting and SETting MS-DOS system calls
|
|||
|
NAME GETSET
|
|||
|
;
|
|||
|
; System Calls which get and set various things
|
|||
|
;
|
|||
|
; $GET_VERSION
|
|||
|
; $GET_VERIFY_ON_WRITE
|
|||
|
; $SET_VERIFY_ON_WRITE
|
|||
|
; $SET_CTRL_C_TRAPPING
|
|||
|
; $INTERNATIONAL
|
|||
|
; $GET_DRIVE_FREESPACE
|
|||
|
; $GET_DMA
|
|||
|
; $SET_DMA
|
|||
|
; $GET_DEFAULT_DRIVE
|
|||
|
; $SET_DEFAULT_DRIVE
|
|||
|
; $GET_INTERRUPT_VECTOR
|
|||
|
; $SET_INTERRUPT_VECTOR
|
|||
|
; RECSET
|
|||
|
; $CHAR_OPER
|
|||
|
;
|
|||
|
.xlist
|
|||
|
;
|
|||
|
; get the appropriate segment definitions
|
|||
|
;
|
|||
|
INCLUDE DOSSEG.ASM
|
|||
|
|
|||
|
IFNDEF ALTVECT
|
|||
|
ALTVECT EQU 0 ; FALSE
|
|||
|
ENDIF
|
|||
|
|
|||
|
IFNDEF IBM
|
|||
|
IBM EQU 0
|
|||
|
ENDIF
|
|||
|
|
|||
|
CODE SEGMENT BYTE PUBLIC 'CODE'
|
|||
|
ASSUME SS:DOSGROUP,CS:DOSGROUP
|
|||
|
|
|||
|
.xcref
|
|||
|
INCLUDE DOSSYM.ASM
|
|||
|
INCLUDE DEVSYM.ASM
|
|||
|
.cref
|
|||
|
.list
|
|||
|
|
|||
|
|
|||
|
i_need VERFLG,BYTE
|
|||
|
i_need CNTCFLAG,BYTE
|
|||
|
i_need DMAADD,DWORD
|
|||
|
i_need CURDRV,BYTE
|
|||
|
i_need Current_Country,WORD
|
|||
|
i_need international_table,BYTE
|
|||
|
i_need INDOS,BYTE
|
|||
|
i_need SYSINITVAR,WORD
|
|||
|
i_need NUMIO,BYTE
|
|||
|
i_need SWITCH_CHARACTER,BYTE
|
|||
|
i_need DEVICE_AVAILABILITY,BYTE
|
|||
|
|
|||
|
USERNUM DW ? ; 24 bit user number
|
|||
|
DB ?
|
|||
|
IF IBM
|
|||
|
OEMNUM DB 0 ; 8 bit OEM number
|
|||
|
ELSE
|
|||
|
OEMNUM DB 0FFH ; 8 bit OEM number
|
|||
|
ENDIF
|
|||
|
|
|||
|
MSVERS EQU THIS WORD ; MS-DOS version in hex for $GET_VERSION
|
|||
|
MSMAJOR DB DOS_MAJOR_VERSION
|
|||
|
MSMINOR DB DOS_MINOR_VERSION
|
|||
|
|
|||
|
|
|||
|
BREAK <$Get_Version -- Return MSDOS version number>
|
|||
|
procedure $GET_VERSION,NEAR
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
|
|||
|
; Inputs:
|
|||
|
; None
|
|||
|
; Function:
|
|||
|
; Return MS-DOS version number
|
|||
|
; Outputs:
|
|||
|
; OEM number in BH
|
|||
|
; User number in BL:CX (24 bits)
|
|||
|
; Version number as AL.AH in binary
|
|||
|
; NOTE: On pre 1.28 DOSs AL will be zero
|
|||
|
|
|||
|
PUSH SS
|
|||
|
POP DS
|
|||
|
ASSUME DS:DOSGROUP
|
|||
|
MOV BX,[USERNUM + 2]
|
|||
|
MOV CX,[USERNUM]
|
|||
|
MOV AX,[MSVERS]
|
|||
|
invoke get_user_stack
|
|||
|
ASSUME DS:NOTHING
|
|||
|
MOV [SI.user_BX],BX
|
|||
|
MOV [SI.user_CX],CX
|
|||
|
MOV [SI.user_AX],AX ; Really only sets AH
|
|||
|
return
|
|||
|
$GET_VERSION ENDP
|
|||
|
|
|||
|
BREAK <$International - return country-dependent information>
|
|||
|
;
|
|||
|
; Inputs:
|
|||
|
; DS:DX point to a block
|
|||
|
; Function:
|
|||
|
; give users an idea of what country the application is running
|
|||
|
; Outputs:
|
|||
|
; AX = number of bytes transferred
|
|||
|
; DS:DX ->+---------------------------------+
|
|||
|
; | WORD Date/time format |
|
|||
|
; +---------------------------------+
|
|||
|
; | BYTE ASCIZ currency symbol |
|
|||
|
; +---------------------------------+
|
|||
|
; | BYTE ASCIZ thousands separator |
|
|||
|
; +---------------------------------+
|
|||
|
; | BYTE ASCIZ decimal separator |
|
|||
|
; +---------------------------------+
|
|||
|
|
|||
|
procedure $INTERNATIONAL,NEAR
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
MOV BL,AL
|
|||
|
PUSH DS
|
|||
|
POP ES
|
|||
|
PUSH DX
|
|||
|
POP DI
|
|||
|
PUSH SS
|
|||
|
POP DS
|
|||
|
ASSUME DS:DOSGROUP
|
|||
|
CMP DI,-1
|
|||
|
JZ international_set
|
|||
|
OR BL,BL
|
|||
|
JNZ international_find
|
|||
|
MOV SI,[Current_Country]
|
|||
|
MOV AX,WORD PTR [SI-2] ; Get size in AL, country code in AH
|
|||
|
MOV BL,AH ; Set country code
|
|||
|
JMP SHORT international_copy
|
|||
|
|
|||
|
international_find:
|
|||
|
CALL international_get
|
|||
|
JNC international_copy
|
|||
|
error country_not_found
|
|||
|
|
|||
|
international_get:
|
|||
|
MOV SI,OFFSET DOSGROUP:international_table
|
|||
|
international_next:
|
|||
|
LODSW ; Get size in AL, country code in AH
|
|||
|
CMP AL,-1
|
|||
|
JNZ check_code
|
|||
|
STC
|
|||
|
RET35:
|
|||
|
RET
|
|||
|
|
|||
|
check_code:
|
|||
|
CMP BL,AH
|
|||
|
JZ RET35 ; Carry clear
|
|||
|
XOR AH,AH
|
|||
|
ADD SI,AX
|
|||
|
JMP international_next
|
|||
|
|
|||
|
international_copy:
|
|||
|
MOV CL,AL
|
|||
|
XOR CH,CH
|
|||
|
PUSH DI
|
|||
|
REP MOVSB
|
|||
|
POP DI
|
|||
|
MOV WORD PTR ES:[DI.MAP_CALL + 2],CS ; Set segment for case map call
|
|||
|
international_ok:
|
|||
|
XOR AX,AX
|
|||
|
MOV AL,BL ; Return country code in AX
|
|||
|
transfer SYS_RET_OK
|
|||
|
|
|||
|
international_set:
|
|||
|
CALL international_get
|
|||
|
JNC international_store
|
|||
|
error country_not_found
|
|||
|
|
|||
|
international_store:
|
|||
|
MOV [Current_Country],SI
|
|||
|
JMP international_ok
|
|||
|
|
|||
|
$INTERNATIONAL ENDP
|
|||
|
|
|||
|
BREAK <$Get_Verify_on_Write - return verify-after-write flag>
|
|||
|
procedure $GET_VERIFY_ON_WRITE,NEAR
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
|
|||
|
; Inputs:
|
|||
|
; none.
|
|||
|
; Function:
|
|||
|
; returns flag
|
|||
|
; Returns:
|
|||
|
; AL = value of VERIFY flag
|
|||
|
|
|||
|
MOV AL,[VERFLG]
|
|||
|
return
|
|||
|
$GET_VERIFY_ON_WRITE ENDP
|
|||
|
|
|||
|
BREAK <$Set_Verify_on_Write - Toggle verify-after-write flag>
|
|||
|
procedure $SET_VERIFY_ON_WRITE,NEAR
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
|
|||
|
; Inputs:
|
|||
|
; AL = desired value of VERIFY flag
|
|||
|
; Function:
|
|||
|
; Sets flag
|
|||
|
; Returns:
|
|||
|
; None
|
|||
|
|
|||
|
AND AL,1
|
|||
|
MOV [VERFLG],AL
|
|||
|
return
|
|||
|
$SET_VERIFY_ON_WRITE ENDP
|
|||
|
|
|||
|
BREAK <$Set_CTRL_C_Trapping -- En/Disable ^C check in dispatcher>
|
|||
|
procedure $SET_CTRL_C_TRAPPING,NEAR
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
|
|||
|
; Inputs:
|
|||
|
; AL = 0 read ^C status
|
|||
|
; AL = 1 Set ^C status, DL = 0/1 for ^C off/on
|
|||
|
; Function:
|
|||
|
; Enable disable ^C checking in dispatcher
|
|||
|
; Outputs:
|
|||
|
; If AL = 0 then DL = 0/1 for ^C off/on
|
|||
|
|
|||
|
OR AL,AL
|
|||
|
JNZ CTRL_C_set
|
|||
|
invoke get_user_stack
|
|||
|
MOV AL,[CNTCFLAG]
|
|||
|
MOV BYTE PTR [SI.user_DX],AL
|
|||
|
return
|
|||
|
CTRL_C_set:
|
|||
|
DEC AL
|
|||
|
JNZ bad_val
|
|||
|
AND DL,01h
|
|||
|
MOV [CNTCFLAG],DL
|
|||
|
return
|
|||
|
bad_val:
|
|||
|
MOV AL,0FFH
|
|||
|
return
|
|||
|
$SET_CTRL_C_TRAPPING ENDP
|
|||
|
|
|||
|
BREAK <$Get_INDOS_Flag -- Return location of DOS critical-section flag>
|
|||
|
procedure $GET_INDOS_FLAG,NEAR
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
|
|||
|
; Inputs:
|
|||
|
; None
|
|||
|
; Function:
|
|||
|
; Returns location of DOS status for interrupt routines
|
|||
|
; Returns:
|
|||
|
; Flag location in ES:BX
|
|||
|
|
|||
|
invoke get_user_stack
|
|||
|
MOV [SI.user_BX],OFFSET DOSGROUP:INDOS
|
|||
|
MOV [SI.user_ES],SS
|
|||
|
return
|
|||
|
$GET_INDOS_FLAG ENDP
|
|||
|
|
|||
|
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
|
|||
|
; C A V E A T P R O G R A M M E R ;
|
|||
|
; ;
|
|||
|
procedure $GET_IN_VARS,NEAR
|
|||
|
; Return a pointer to interesting DOS variables This call is version
|
|||
|
; dependent and is subject to change without notice in future versions.
|
|||
|
; Use at risk.
|
|||
|
invoke get_user_stack
|
|||
|
MOV [SI.user_BX],OFFSET DOSGROUP:SYSINITVAR
|
|||
|
MOV [SI.user_ES],SS
|
|||
|
return
|
|||
|
$GET_IN_VARS ENDP
|
|||
|
; ;
|
|||
|
; C A V E A T P R O G R A M M E R ;
|
|||
|
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
|
|||
|
|
|||
|
BREAK <$Get_Drive_Freespace -- Return bytes of free disk space on a drive>
|
|||
|
procedure $GET_DRIVE_FREESPACE,NEAR
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
|
|||
|
; Inputs:
|
|||
|
; DL = Drive number
|
|||
|
; Function:
|
|||
|
; Return number of free allocation units on drive
|
|||
|
; Outputs:
|
|||
|
; BX = Number of free allocation units
|
|||
|
; DX = Total Number of allocation units on disk
|
|||
|
; CX = Sector size
|
|||
|
; AX = Sectors per allocation unit
|
|||
|
; = -1 if bad drive specified
|
|||
|
; This call returns the same info in the same registers (except for FAT pointer)
|
|||
|
; as the old FAT pointer calls
|
|||
|
|
|||
|
PUSH SS
|
|||
|
POP DS
|
|||
|
ASSUME DS:DOSGROUP
|
|||
|
MOV AL,DL
|
|||
|
invoke GETTHISDRV
|
|||
|
MOV AX,-1
|
|||
|
JC BADFRDRIVE
|
|||
|
invoke FATREAD
|
|||
|
XOR DX,DX
|
|||
|
MOV BX,2
|
|||
|
MOV CX,ES:[BP.dpb_max_cluster]
|
|||
|
DEC CX
|
|||
|
PUSH CX ; Save Total
|
|||
|
SCANFREE:
|
|||
|
invoke UNPACK
|
|||
|
JNZ NOTFREECLUS
|
|||
|
INC DX
|
|||
|
NOTFREECLUS:
|
|||
|
INC BX
|
|||
|
LOOP SCANFREE
|
|||
|
POP BX ; Remember Total
|
|||
|
MOV AL,ES:[BP.dpb_cluster_mask]
|
|||
|
INC AL
|
|||
|
XOR AH,AH
|
|||
|
MOV CX,ES:[BP.dpb_sector_size]
|
|||
|
BADFRDRIVE:
|
|||
|
invoke get_user_stack
|
|||
|
ASSUME DS:NOTHING
|
|||
|
MOV [SI. user_CX],CX
|
|||
|
MOV [SI.user_DX],BX
|
|||
|
MOV [SI.user_BX],DX
|
|||
|
MOV [SI.user_AX],AX
|
|||
|
return
|
|||
|
|
|||
|
$GET_DRIVE_FREESPACE ENDP
|
|||
|
|
|||
|
BREAK <$Get_DMA, $Set_DMA -- Get/Set current DMA address>
|
|||
|
procedure $GET_DMA,NEAR
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
|
|||
|
; Inputs:
|
|||
|
; None
|
|||
|
; Function:
|
|||
|
; Get DISK TRANSFER ADDRESS
|
|||
|
; Returns:
|
|||
|
; ES:BX is current transfer address
|
|||
|
|
|||
|
MOV BX,WORD PTR [DMAADD]
|
|||
|
MOV CX,WORD PTR [DMAADD+2]
|
|||
|
invoke get_user_stack
|
|||
|
MOV [SI.user_BX],BX
|
|||
|
MOV [SI.user_ES],CX
|
|||
|
return
|
|||
|
$GET_DMA ENDP
|
|||
|
|
|||
|
procedure $SET_DMA,NEAR ; System call 26
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
|
|||
|
; Inputs:
|
|||
|
; DS:DX is desired new disk transfer address
|
|||
|
; Function:
|
|||
|
; Set DISK TRANSFER ADDRESS
|
|||
|
; Returns:
|
|||
|
; None
|
|||
|
|
|||
|
MOV WORD PTR [DMAADD],DX
|
|||
|
MOV WORD PTR [DMAADD+2],DS
|
|||
|
return
|
|||
|
$SET_DMA ENDP
|
|||
|
|
|||
|
BREAK <$Get_Default_DPB,$Get_DPB -- Return pointer to DPB>
|
|||
|
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
|
|||
|
; C A V E A T P R O G R A M M E R ;
|
|||
|
; ;
|
|||
|
procedure $GET_DEFAULT_DPB,NEAR
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
|
|||
|
; Inputs:
|
|||
|
; DL = Drive number (always default drive for call 31)
|
|||
|
; Function:
|
|||
|
; Return pointer to drive parameter table for default drive
|
|||
|
; Returns:
|
|||
|
; DS:BX points to the DPB
|
|||
|
; AL = 0 If OK, = -1 if bad drive (call 50 only)
|
|||
|
|
|||
|
MOV DL,0
|
|||
|
entry $GET_DPB
|
|||
|
PUSH SS
|
|||
|
POP DS
|
|||
|
ASSUME DS:DOSGROUP
|
|||
|
MOV AL,DL
|
|||
|
invoke GETTHISDRV
|
|||
|
JC ISNODRV
|
|||
|
invoke FATREAD
|
|||
|
invoke get_user_stack
|
|||
|
ASSUME DS:NOTHING
|
|||
|
MOV [SI.user_BX],BP
|
|||
|
MOV [SI.user_DS],ES
|
|||
|
XOR AL,AL
|
|||
|
return
|
|||
|
|
|||
|
ISNODRV:
|
|||
|
MOV AL,-1
|
|||
|
return
|
|||
|
$GET_Default_dpb ENDP
|
|||
|
; ;
|
|||
|
; C A V E A T P R O G R A M M E R ;
|
|||
|
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
|
|||
|
|
|||
|
|
|||
|
BREAK <$Get_Default_Drive, $Set_Default_Drive -- Set/Get default drive>
|
|||
|
procedure $GET_DEFAULT_DRIVE,NEAR
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
|
|||
|
; Inputs:
|
|||
|
; None
|
|||
|
; Function:
|
|||
|
; Return current drive number
|
|||
|
; Returns:
|
|||
|
; AL = drive number
|
|||
|
|
|||
|
MOV AL,[CURDRV]
|
|||
|
return
|
|||
|
$GET_DEFAULT_DRIVE ENDP
|
|||
|
|
|||
|
procedure $SET_DEFAULT_DRIVE,NEAR
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
|
|||
|
; Inputs:
|
|||
|
; DL = Drive number for new default drive
|
|||
|
; Function:
|
|||
|
; Set the default drive
|
|||
|
; Returns:
|
|||
|
; AL = Number of drives, NO ERROR RETURN IF DRIVE NUMBER BAD
|
|||
|
|
|||
|
MOV AL,[NUMIO]
|
|||
|
CMP DL,AL
|
|||
|
JNB RET17
|
|||
|
MOV [CURDRV],DL
|
|||
|
RET17: return
|
|||
|
$SET_DEFAULT_DRIVE ENDP
|
|||
|
|
|||
|
|
|||
|
BREAK <$Get_Interrupt_Vector - Get/Set interrupt vectors>
|
|||
|
procedure $GET_INTERRUPT_VECTOR,NEAR
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
|
|||
|
; Inputs:
|
|||
|
; AL = interrupt number
|
|||
|
; Function:
|
|||
|
; Get the interrupt vector
|
|||
|
; Returns:
|
|||
|
; ES:BX is current interrupt vector
|
|||
|
|
|||
|
CALL RECSET
|
|||
|
LES BX,DWORD PTR ES:[BX]
|
|||
|
invoke get_user_stack
|
|||
|
MOV [SI.user_BX],BX
|
|||
|
MOV [SI.user_ES],ES
|
|||
|
return
|
|||
|
$GET_INTERRUPT_VECTOR ENDP
|
|||
|
|
|||
|
procedure $SET_INTERRUPT_VECTOR,NEAR ; System call 37
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
|
|||
|
; Inputs:
|
|||
|
; AL = interrupt number
|
|||
|
; DS:DX is desired new interrupt vector
|
|||
|
; Function:
|
|||
|
; Set the interrupt vector
|
|||
|
; Returns:
|
|||
|
; None
|
|||
|
|
|||
|
CALL RECSET
|
|||
|
MOV ES:[BX],DX
|
|||
|
MOV ES:[BX+2],DS
|
|||
|
return
|
|||
|
$SET_INTERRUPT_VECTOR ENDP
|
|||
|
|
|||
|
IF ALTVECT
|
|||
|
VECIN: ; INPUT VECTORS
|
|||
|
DB 22H ; Terminate
|
|||
|
DB 23H ; ^C
|
|||
|
DB 24H ; Hard error
|
|||
|
DB 28H ; Spooler
|
|||
|
LSTVEC DB ? ; ALL OTHER
|
|||
|
|
|||
|
VECOUT: ; GET MAPPED VECTOR
|
|||
|
DB int_terminate
|
|||
|
DB int_ctrl_c
|
|||
|
DB int_fatal_abort
|
|||
|
DB int_spooler
|
|||
|
LSTVEC2 DB ? ; Map to itself
|
|||
|
|
|||
|
NUMVEC = VECOUT-VECIN
|
|||
|
ENDIF
|
|||
|
|
|||
|
procedure RECSET,NEAR
|
|||
|
|
|||
|
IF ALTVECT
|
|||
|
PUSH SS
|
|||
|
POP ES
|
|||
|
MOV [LSTVEC],AL ; Terminate list with real vector
|
|||
|
MOV [LSTVEC2],AL ; Terminate list with real vector
|
|||
|
MOV CX,NUMVEC ; Number of possible translations
|
|||
|
MOV DI,OFFSET DOSGROUP:VECIN ; Point to vectors
|
|||
|
REPNE SCASB
|
|||
|
MOV AL,ES:[DI+NUMVEC-1] ; Get translation
|
|||
|
ENDIF
|
|||
|
|
|||
|
XOR BX,BX
|
|||
|
MOV ES,BX
|
|||
|
MOV BL,AL
|
|||
|
SHL BX,1
|
|||
|
SHL BX,1
|
|||
|
return
|
|||
|
recset ENDP
|
|||
|
|
|||
|
BREAK <$Char_Oper - hack on paths, switches so that xenix can look like PCDOS>
|
|||
|
;
|
|||
|
; input: AL = function:
|
|||
|
; 0 - read switch char
|
|||
|
; 1 - set switch char (char in DL)
|
|||
|
; 2 - read device availability
|
|||
|
; 3 - set device availability (0/FF in DL)
|
|||
|
; DL = 0 means /DEV/ must preceed device names
|
|||
|
; DL = Non0 means /DEV/ need not preeceed
|
|||
|
; output: (get) DL - character/flag
|
|||
|
;
|
|||
|
procedure $CHAR_OPER,NEAR
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
PUSH SS
|
|||
|
POP DS
|
|||
|
ASSUME DS:DOSGROUP
|
|||
|
OR AL,AL
|
|||
|
JNZ char_oper_set_switch
|
|||
|
MOV DL,[switch_character]
|
|||
|
JMP SHORT char_oper_ret
|
|||
|
char_oper_set_switch:
|
|||
|
DEC AL
|
|||
|
JNZ char_oper_read_avail
|
|||
|
MOV [switch_character],DL
|
|||
|
return
|
|||
|
char_oper_read_avail:
|
|||
|
DEC AL
|
|||
|
JNZ char_oper_set_avail
|
|||
|
MOV DL,[device_availability]
|
|||
|
JMP SHORT char_oper_ret
|
|||
|
char_oper_set_avail:
|
|||
|
DEC AL
|
|||
|
JNZ char_oper_bad_ret
|
|||
|
MOV [device_availability],DL
|
|||
|
return
|
|||
|
char_oper_bad_ret:
|
|||
|
MOV AL,0FFh
|
|||
|
return
|
|||
|
char_oper_ret:
|
|||
|
invoke get_user_stack
|
|||
|
MOV [SI.user_DX],DX
|
|||
|
return
|
|||
|
$CHAR_OPER ENDP
|
|||
|
|
|||
|
BREAK <$SetDPB - Create a valid DPB from a user-specified BPB>
|
|||
|
procedure $SETDPB,NEAR
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
|
|||
|
; Inputs:
|
|||
|
; ES:BP Points to DPB
|
|||
|
; DS:SI Points to BPB
|
|||
|
; Function:
|
|||
|
; Build a correct DPB from the BPB
|
|||
|
; Outputs:
|
|||
|
; ES:BP and DS preserved all others destroyed
|
|||
|
|
|||
|
MOV DI,BP
|
|||
|
ADD DI,2 ; Skip over dpb_drive and dpb_UNIT
|
|||
|
LODSW
|
|||
|
STOSW ; dpb_sector_size
|
|||
|
MOV DX,AX
|
|||
|
LODSB
|
|||
|
DEC AL
|
|||
|
STOSB ; dpb_cluster_mask
|
|||
|
INC AL
|
|||
|
XOR AH,AH
|
|||
|
LOG2LOOP:
|
|||
|
TEST AL,1
|
|||
|
JNZ SAVLOG
|
|||
|
INC AH
|
|||
|
SHR AL,1
|
|||
|
JMP SHORT LOG2LOOP
|
|||
|
SAVLOG:
|
|||
|
MOV AL,AH
|
|||
|
STOSB ; dpb_cluster_shift
|
|||
|
MOV BL,AL
|
|||
|
MOVSW ; dpb_first_FAT Start of FAT (# of reserved sectors)
|
|||
|
LODSB
|
|||
|
STOSB ; dpb_FAT_count Number of FATs
|
|||
|
MOV BH,AL
|
|||
|
LODSW
|
|||
|
STOSW ; dpb_root_entries Number of directory entries
|
|||
|
MOV CL,5
|
|||
|
SHR DX,CL ; Directory entries per sector
|
|||
|
DEC AX
|
|||
|
ADD AX,DX ; Cause Round Up
|
|||
|
MOV CX,DX
|
|||
|
XOR DX,DX
|
|||
|
DIV CX
|
|||
|
MOV CX,AX ; Number of directory sectors
|
|||
|
INC DI
|
|||
|
INC DI ; Skip dpb_first_sector
|
|||
|
MOVSW ; Total number of sectors in DSKSIZ (temp as dpb_max_cluster)
|
|||
|
LODSB
|
|||
|
MOV ES:[BP.dpb_media],AL ; Media byte
|
|||
|
LODSW ; Number of sectors in a FAT
|
|||
|
STOSB ; dpb_FAT_size
|
|||
|
MUL BH ; Space occupied by all FATs
|
|||
|
ADD AX,ES:[BP.dpb_first_FAT]
|
|||
|
STOSW ; dpb_dir_sector
|
|||
|
ADD AX,CX ; Add number of directory sectors
|
|||
|
MOV ES:[BP.dpb_first_sector],AX
|
|||
|
SUB AX,ES:[BP.DSKSIZ]
|
|||
|
NEG AX ; Sectors in data area
|
|||
|
MOV CL,BL ; dpb_cluster_shift
|
|||
|
SHR AX,CL ; Div by sectors/cluster
|
|||
|
INC AX
|
|||
|
MOV ES:[BP.dpb_max_cluster],AX
|
|||
|
MOV ES:[BP.dpb_current_dir],0 ; Current directory is root
|
|||
|
return
|
|||
|
$SETDPB ENDP
|
|||
|
; ;
|
|||
|
; C A V E A T P R O G R A M M E R ;
|
|||
|
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
|
|||
|
|
|||
|
do_ext
|
|||
|
|
|||
|
CODE ENDS
|
|||
|
END
|
|||
|
|