mirror of
https://github.com/microsoft/MS-DOS.git
synced 2024-11-29 17:15:47 +00:00
587 lines
22 KiB
NASM
587 lines
22 KiB
NASM
TITLE MS-DOS SYS Program
|
||
; SYS - Copies system programs IBMBIO.COM/IO.SYS and IBMDOS.COM/MSDOS.SYS
|
||
; 1.6 05/21/82 Added rev number message
|
||
; 1.61 06/04/82 Allow SYS to blank disk TimP at SCP
|
||
; 1.70 06/30/82 NON contiguous DOS allowed on 2.00 IBM. Allows SYS to
|
||
; 1.0 1.1 disks.
|
||
; 1.71 07/02/82 Put in CHDIRs to make sure everything done in root dir.
|
||
; 1.80 04/26/83 MZ make sys work in small machines; use full 2.0 system
|
||
; calls
|
||
; 1.81 07/22/83 ARR Added check in IBM version for valid FAT ID on
|
||
; destination because of IBM problem with SYSing to
|
||
; unformatted disks which are really formatted.
|
||
; Prints NoDest message for ridic IBM reasons, should
|
||
; have a better message.
|
||
|
||
FALSE EQU 0
|
||
TRUE EQU NOT FALSE
|
||
|
||
IBMJAPVER EQU FALSE
|
||
IBMVER EQU FALSE
|
||
MSVER EQU TRUE
|
||
|
||
.xlist
|
||
.xcref
|
||
INCLUDE DOSSYM.ASM
|
||
.cref
|
||
.list
|
||
|
||
|
||
DOSVER_LOW EQU 0136H ; Lowest acceptable DOS version number
|
||
DOSVER_HIGH EQU 020BH ; Highest acceptable DOS version
|
||
|
||
CODE SEGMENT WORD PUBLIC
|
||
CODE ENDS
|
||
|
||
CONST SEGMENT BYTE PUBLIC
|
||
CONST ENDS
|
||
|
||
DATA SEGMENT BYTE PUBLIC
|
||
DATA ENDS
|
||
|
||
DG GROUP CODE,DATA,CONST
|
||
|
||
DATA SEGMENT PUBLIC BYTE
|
||
|
||
EXTRN BADDRV:BYTE, BADDRVLen:WORD
|
||
EXTRN BADPARM:BYTE, BADPARMLen:WORD
|
||
EXTRN GETSYS:BYTE, GETSYSLen:WORD
|
||
EXTRN SYSDRV:BYTE
|
||
EXTRN NODEST:BYTE, NODESTLen:WORD
|
||
EXTRN BADSIZ:BYTE, BADSIZLen:WORD
|
||
EXTRN DONE:BYTE, DONELen:WORD
|
||
EXTRN BADVER:BYTE
|
||
|
||
IF IBMJAPVER
|
||
EXTRN BADDISK:BYTE, BADDISKLen:WORD
|
||
ENDIF
|
||
|
||
DEFALT DB 0
|
||
IF MSVER
|
||
BIOSName DB "A:\IO.SYS",0
|
||
DOSName DB "A:\MSDOS.SYS",0
|
||
ENDIF
|
||
IF IBMVER OR IBMJAPVER
|
||
BIOSName DB "A:\IBMBIO.COM",0
|
||
DOSName DB "A:\IBMDOS.COM",0
|
||
ENDIF
|
||
|
||
BIOSInFH DW ? ; file handle of source BIOS
|
||
BIOSLenLow DW 2 DUP (?) ; 32-bit length of BIOS
|
||
BIOSLenHigh DW 2 DUP (?) ; 32-bit length of BIOS
|
||
BIOSTime DW 2 DUP (?) ; place to store time of BIOS write
|
||
BIOSOutFH DW ? ; fh of BIOS destination
|
||
|
||
DOSInFH DW ? ; file handle of source DOS
|
||
DOSLenLow DW 2 DUP (?) ; 32-bit length of DOS
|
||
DOSLenHigh DW 2 DUP (?) ; 32-bit length of DOS
|
||
DOSTime DW 2 DUP (?) ; place to store time of DOS write
|
||
DOSOutFH DW ? ; fh of DOS destination
|
||
|
||
AllName DB "A:\*.*",0
|
||
|
||
cbBuf DW ? ; number of bytes in buffer
|
||
pDOS DW ? ; offset of beginning of DOS in buffer
|
||
pDOSEnd DW ? ; offset of end of DOS in buffer
|
||
|
||
IF IBMVER OR IBMJAPVER
|
||
BOOT DW 256 DUP (0)
|
||
IF IBMJAPVER
|
||
LLISTBUF DW 256 DUP (0)
|
||
ENDIF
|
||
ENDIF
|
||
|
||
IF IBMJAPVER
|
||
RELOC DW 1 DUP(?)
|
||
STARTSECTOR DW 1 DUP(?)
|
||
ENDIF
|
||
|
||
BUF LABEL BYTE ; beginning of area for file reads
|
||
|
||
DATA ENDS
|
||
|
||
CODE SEGMENT PUBLIC
|
||
|
||
ASSUME CS:DG,DS:DG,ES:DG,SS:DG
|
||
|
||
ORG 100H
|
||
|
||
Start:
|
||
JMP SHORT CheckVersion
|
||
|
||
IF IBMVER
|
||
DW OFFSET DG:BOOT
|
||
ENDIF
|
||
HEADER DB "Vers 1.81"
|
||
CheckVersion:
|
||
PUSH AX ; save drive letter validity
|
||
MOV AH,GET_VERSION
|
||
INT 21H ; get dos version
|
||
XCHG AH,AL ; Turn it around to AH.AL
|
||
CMP AX,DOSVER_LOW ; is it too low?
|
||
JB GOTBADDOS ; yes, error
|
||
CMP AX,DOSVER_HIGH ; too high?
|
||
JBE OKDOS ; yes, go check drive letter
|
||
GOTBADDOS:
|
||
MOV DX,OFFSET DG:BADVER ; message to dump
|
||
MOV AH,STD_CON_STRING_OUTPUT ; standard output device
|
||
INT 21H
|
||
INT 20H ; old style exit for compatability
|
||
|
||
OKDOS: POP AX ; get drive validity
|
||
JMP SHORT SYS ; go process
|
||
|
||
ERR0: MOV DX,OFFSET DG:BADPARM ; no drive letter
|
||
MOV CX,BadParmLen
|
||
JMP DisplayError
|
||
|
||
ERR1: MOV DX,OFFSET DG:BADDRV ; drive letter invalid
|
||
MOV CX,BadDrvLen
|
||
JMP DisplayError
|
||
|
||
ERR2: MOV AL,DEFALT ; get default drive number
|
||
ADD AL,'A'-1 ; turn into letter
|
||
MOV SYSDRV,AL ; place into middle of message
|
||
MOV DX,OFFSET DG:GETSYS
|
||
MOV CX,GETSYSLen ; length for output
|
||
MOV BX,stderr ; use stderr
|
||
MOV AH,Write ; Ask for system disk
|
||
INT 21H
|
||
CALL GetKeystroke ; wait for him to type simething
|
||
XOR AL,AL ; valid drive spec now...
|
||
SYS:
|
||
CMP DS:(BYTE PTR 5DH)," " ; Was file specified?
|
||
JNZ ERR0 ; yes, no files are allowed -> error
|
||
CMP AL,-1 ; Invalid drive spec?
|
||
JZ ERR1 ; yes, must have valid drive -> error
|
||
CMP DS:(BYTE PTR 5CH),0 ; No drive specified?
|
||
JZ ERR1 ; yes, cannot sys to default drive error
|
||
MOV AH,GET_DEFAULT_DRIVE ; Get default drive
|
||
INT 21H
|
||
INC AL ; turn from phys drive to logical drive
|
||
MOV DEFALT,AL ; save it for possible printing
|
||
CMP DS:(BYTE PTR 5CH),AL ; did he specify the default drive?
|
||
JZ ERR1 ; yes, default drive not allowed
|
||
|
||
IF IBMVER ; Check for "valid" destination
|
||
PUSH AX
|
||
MOV AL,BYTE PTR DS:[5Ch]
|
||
DEC AL
|
||
MOV BX,OFFSET DG:BUF ; Temp space
|
||
MOV DX,1 ; Sector 1 (first sec of FAT)
|
||
MOV CX,DX ; One sector
|
||
INT 25H ; Read Fat sector
|
||
POP AX ; Flags
|
||
POP AX ; Real AX
|
||
JC OKFAT ; Don't error here, let a CREATE or
|
||
; some other call to the dest
|
||
; generate a more useful INT 24H
|
||
; error
|
||
CMP BYTE PTR [BUF],0F8H
|
||
JAE OKFAT
|
||
JMP ERR3
|
||
OKFAT:
|
||
ENDIF
|
||
|
||
ADD AL,'A'-1 ; turn into letter
|
||
MOV BIOSName,AL ; twiddle source name
|
||
MOV DOSName,AL ; twiddle source name
|
||
CLD
|
||
MOV DX,OFFSET DG:BIOSName ; source name
|
||
MOV DI,OFFSET DG:BIOSInFH ; pointer to block of data
|
||
CALL OpenFile
|
||
JC Err2 ; not found, go and try again
|
||
MOV DX,OFFSET DG:DOSName ; source of DOS
|
||
MOV DI,OFFSET DG:DOSInFH ; pointer to block of data
|
||
CALL OpenFile ; Look for DOS
|
||
JC ERR2 ; not there, go ask for a system disk
|
||
MOV CX,SP ; get lowest available spot
|
||
SUB CX,0200h+(OFFSET DG:BUF); leave room for all sorts of things
|
||
MOV cbBuf,CX ; store length away
|
||
CALL FillMem ; load up memory with files
|
||
|
||
IF IBMJAPVER
|
||
CALL READ_BOOT ; need to copy boot sector too
|
||
ENDIF
|
||
|
||
MOV AL,DS:(BYTE PTR 5CH) ; get drive of destination
|
||
|
||
IF IBMJAPVER
|
||
CALL CHECK_TRAN ; check for bootable device
|
||
JZ DOSWRT ; ok to boot
|
||
MOV DX,OFFSET DG:BADDISK ; incorrect format to boot
|
||
MOV CX,BadDiskLen
|
||
JMP DisplayError ; go error and quit
|
||
DOSWRT:
|
||
ENDIF
|
||
|
||
ADD AL,'A'-1 ; convert to letter
|
||
MOV BIOSName,AL ; point names at destination drive
|
||
MOV DOSName,AL
|
||
MOV AllName,AL ; look for any files
|
||
|
||
MOV AH,Find_First ; look for files
|
||
MOV DX,OFFSET DG:AllName ; path of where to look
|
||
MOV CX,Attr_Hidden+Attr_System ; attributes to find
|
||
INT 21H
|
||
JC PutSys ; no files - go and copy
|
||
|
||
IF MSVER
|
||
MOV DL,DS:(BYTE PTR 5CH) ; get drive number
|
||
MOV AH,GET_DRIVE_FREESPACE ; get free space available
|
||
INT 21H
|
||
MUL CX ; Compute size of cluster (secsiz*secperclus)
|
||
XCHG CX,AX ; move it to correct spot
|
||
MOV DX,OFFSET DG:BIOSName ; who to open
|
||
MOV AX,BIOSLenLow+2 ; get low part of size
|
||
MOV BX,BIOSLenHigh+2 ; get high size
|
||
CALL CHKLEN ; open and snoop size
|
||
JNZ ERR4 ; Must fit exact so MSDOS is in right place
|
||
MOV DX,OFFSET DG:DOSName ; other guy to open
|
||
MOV AX,DOSLenLow+2 ; get low part of size
|
||
MOV BX,DOSLenHigh+2 ; get high size
|
||
CALL CHKLEN ; open and snoop second size
|
||
JA ERR4 ; Must be enough (or too much) space
|
||
ENDIF
|
||
|
||
IF IBMVER OR IBMJAPVER
|
||
MOV DX,OFFSET DG:BIOSName ; open BIOS
|
||
MOV CX,7 ; attributes
|
||
MOV AH,Find_First
|
||
INT 21H
|
||
JNC FindDos
|
||
Err3J: JMP Err3 ; not found, go and complain
|
||
FindDos:
|
||
MOV DX,OFFSET DG:DOSName ; open DOS
|
||
MOV AH,Find_First
|
||
INT 21H
|
||
JC Err3J ; Not found, go complain
|
||
ENDIF
|
||
|
||
PUTSYS:
|
||
MOV DX,OFFSET DG:BIOSName ; who to change mode
|
||
MOV CX,0 ; undo attributes
|
||
MOV AX,(ChMod SHL 8) + 1 ; set the attributes
|
||
INT 21h
|
||
MOV DX,OFFSET DG:DOSName ; who to change mode
|
||
MOV CX,0 ; undo attributes
|
||
MOV AX,(ChMod SHL 8) + 1 ; set the attributes
|
||
INT 21h
|
||
MOV DX,OFFSET DG:BIOSName ; destination of BIOS
|
||
MOV CX,7 ; fancy attributes
|
||
MOV AH,Creat ; make a new one
|
||
INT 21h
|
||
MOV BIOSOutFH,AX ; save handle
|
||
MOV DX,OFFSET DG:DOSName ; destination of DOS
|
||
MOV AH,Creat ; make a new one
|
||
INT 21h
|
||
MOV DOSOutFH,AX ; save handle
|
||
Copy:
|
||
CALL DumpMem ; flush out memory
|
||
MOV AX,DOSLenHigh ; more DOS?
|
||
OR AX,DOSLenLow ; more low dos
|
||
OR AX,BIOSLenHigh ; more high BIOS
|
||
OR AX,BIOSLenLow ; more low BIOS
|
||
JZ AllDone ; nope, all done
|
||
CALL FillMem ; reload world
|
||
JMP Copy
|
||
ERR4:
|
||
MOV DX,OFFSET DG:BADSIZ
|
||
MOV CX,BadSizLen
|
||
JMP DisplayError
|
||
AllDone:
|
||
MOV CX,BIOSTime ; get time and date
|
||
MOV DX,BIOSTime+2
|
||
MOV BX,BIOSOutFH ; where to stuff the time
|
||
MOV AX,(File_Times SHL 8) + 1
|
||
INT 21h
|
||
MOV AH,Close
|
||
INT 21h
|
||
|
||
MOV CX,DOSTime ; get time and date
|
||
MOV DX,DOSTime+2
|
||
MOV BX,DOSOutFH ; where to stuff the time
|
||
MOV AX,(File_Times SHL 8) + 1
|
||
INT 21h
|
||
MOV AH,Close
|
||
INT 21h
|
||
|
||
IF IBMVER OR IBMJAPVER
|
||
CALL PUTBOOT ; copy the boot sector also
|
||
ENDIF
|
||
|
||
MOV DX,OFFSET DG:DONE ; all finished message
|
||
MOV CX,DoneLen
|
||
XOR AL,AL ; ok error code
|
||
SERROR:
|
||
PUSH AX
|
||
MOV BX,stderr
|
||
MOV AH,Write ; convenient place to display message
|
||
INT 21H
|
||
POP AX
|
||
ErrorExit:
|
||
MOV AH,EXIT ; bye and return error code
|
||
INT 21h
|
||
|
||
DisplayError:
|
||
MOV AL,1
|
||
JMP SERROR
|
||
FillMem:
|
||
MOV CX,cbBuf ; get length of buffer
|
||
MOV BX,BIOSInFH ; get bios source handle
|
||
MOV DX,OFFSET DG:BUF ; point to beginning of buffer
|
||
PUSH CX ; save away total length
|
||
CMP BIOSLenHigh,0 ; > 64K to read?
|
||
JA UseCX ; use CX
|
||
CMP BIOSLenLow,CX ; more left to read?
|
||
JA UseCX ; use CX
|
||
MOV CX,BIOSLenLow ; move new
|
||
UseCX:
|
||
MOV AH,Read
|
||
INT 21h ; read in what we can
|
||
ADD DX,AX ; update pointer for DOS Read
|
||
MOV pDOS,DX ; point to beginning of DOS
|
||
SUB BIOSLenLow,AX ; decrement remaining
|
||
SBB BIOSLenHigh,0 ; do 32 bit
|
||
POP CX ; get original length
|
||
SUB CX,AX ; this much is left
|
||
|
||
MOV BX,DOSInFH ; get bios source handle
|
||
CMP DOSLenHigh,0 ; > 64K to read?
|
||
JA UseCXDOS ; use CX
|
||
CMP DOSLenLow,CX ; more left to read?
|
||
JA UseCXDOS ; use CX
|
||
MOV CX,DOSLenLow ; move new
|
||
UseCXDOS:
|
||
MOV AH,Read
|
||
INT 21h ; read in what we can
|
||
ADD DX,AX ; update pointer for DOS Read
|
||
MOV pDOSEnd,DX ; point to End of dos DOS
|
||
SUB DOSLenLow,AX ; decrement remaining
|
||
SBB DOSLenHigh,0 ; do 32 bit arithmetic
|
||
return
|
||
|
||
OpenFile:
|
||
MOV AX,(OPEN SHL 8) + 0 ; open for reading only
|
||
INT 21H ; Look for BIOS
|
||
retc ; not found, go and try again
|
||
STOSW ; stash away handle
|
||
MOV BX,AX ; get ready for seeks
|
||
MOV AX,(LSeek SHL 8) + 2 ; seek relative to eof
|
||
XOR CX,CX ; zero offset
|
||
XOR DX,DX ; zero offset
|
||
INT 21h ; get offsets
|
||
STOSW ; save low part of size
|
||
STOSW ; save low part of size
|
||
MOV AX,DX
|
||
STOSW ; save high part of size
|
||
STOSW ; save high part of size
|
||
XOR DX,DX ; zero offset
|
||
MOV AX,(LSeek SHL 8) + 0 ; seek relative to beginning
|
||
INT 21h
|
||
MOV AX,(File_Times SHL 8) + 0
|
||
INT 21h ; get last write times
|
||
MOV AX,CX
|
||
STOSW ; save time
|
||
MOV AX,DX
|
||
STOSW ; save date
|
||
return
|
||
|
||
ERR3:
|
||
MOV DX,OFFSET DG:NODEST
|
||
MOV CX,NoDestLen
|
||
JMP DisplayError
|
||
|
||
DumpMem:
|
||
MOV DX,OFFSET DG:BUF ; get offset of bios start
|
||
MOV CX,pDOS ; beginning of next guy
|
||
SUB CX,DX ; difference is length
|
||
JZ DumpDos ; no bios to move
|
||
MOV BX,BIOSOutFH ; where to output
|
||
MOV AH,Write
|
||
INT 21h ; wham
|
||
DumpDos:
|
||
MOV DX,pDOS ; beginning of dos
|
||
MOV CX,pDOSEnd ; end of dos
|
||
SUB CX,DX ; difference is length
|
||
retz ; if zero no write
|
||
MOV BX,DOSOutFH ; where to output
|
||
MOV AH,Write
|
||
INT 21h ; wham
|
||
ret
|
||
|
||
IF MSVER
|
||
CHKLEN:
|
||
; CX has size of cluster, DX has pointer to file name
|
||
; Returns with flags set on (size of file) - (size of hole)
|
||
PUSH AX ; old size low
|
||
PUSH BX ; old size high
|
||
PUSH CX ; old cluster size
|
||
MOV AH,Find_First
|
||
MOV CX,7 ; attributes to search for
|
||
INT 21H
|
||
JC ERR3 ; cannot find file, error
|
||
POP CX ; get cluster size back
|
||
MOV DX,DS:[80h+find_buf_size_h] ; get destination size high
|
||
MOV AX,DS:[80h+find_buf_size_l] ; get size low
|
||
ADD AX,CX ; add cluster size
|
||
ADC DX,0 ; 32 bit add
|
||
SUB AX,1 ; adding CLUSSIZE-1
|
||
SBB DX,0 ; 32 bit dec
|
||
DIV CX ; compute new cluster size
|
||
POP DX ; get old high
|
||
POP BX ; get old low
|
||
PUSH AX ; save away dividend
|
||
MOV AX,BX ; put into correct register
|
||
ADD AX,CX ; do the same as above (+CLUSSIZE-1)/CLUSSIZE
|
||
ADC DX,0 ; 32 bit add
|
||
SUB AX,1 ; adding CLUSSIZE-1
|
||
SBB DX,0 ; 32 bit dec
|
||
DIV CX ; compute old cluster size
|
||
POP DX ; get new size
|
||
CMP AX,DX ; is old >= new?
|
||
return
|
||
ENDIF
|
||
|
||
IF IBMJAPVER
|
||
PUTBOOT:
|
||
CALL READ_LLIST ; Get the list sector and set new boot sector
|
||
MOV AL,DS:(BYTE PTR 5CH)
|
||
DEC AL ; A=0
|
||
MOV CX,1
|
||
XOR DX,DX
|
||
MOV BX,OFFSET DG:BOOT
|
||
INT 26H ; Write out new boot sector
|
||
POPF
|
||
CALL WRITE_LLIST ; Make and write out new list sector
|
||
RET
|
||
ENDIF
|
||
|
||
IF IBMVER
|
||
PUTBOOT:
|
||
MOV AH,GET_DPB
|
||
MOV DL,BYTE PTR DS:[5Ch] ; Target drive
|
||
INT 21H
|
||
ASSUME DS:NOTHING
|
||
MOV AL,[BX+16H] ; Media byte
|
||
PUSH CS
|
||
POP DS
|
||
ASSUME DS:DG
|
||
CMP AL,0FEH
|
||
JB RET1
|
||
TEST AL,1
|
||
JZ GOTBOOT
|
||
MOV BX,OFFSET DG:BOOT
|
||
MOV WORD PTR [BX+17],112 ; Set number of dir entries
|
||
MOV WORD PTR [BX+19],2*8*40 ; Set number of sectors
|
||
INC BYTE PTR [BX+21] ; Media = ff
|
||
INC WORD PTR [BX+26] ; Number of heads = 2
|
||
|
||
GOTBOOT:
|
||
MOV AL,BYTE PTR DS:[5Ch]
|
||
DEC AL
|
||
MOV BX,OFFSET DG:BOOT ; Boot sector
|
||
XOR DX,DX ; Sector 0
|
||
MOV CX,DX
|
||
INC CX ; One sector
|
||
INT 26H ; Write out 8 sector boot sector
|
||
POP AX ; Flags
|
||
RET1: RET
|
||
ENDIF
|
||
|
||
IF IBMJAPVER
|
||
READ_BOOT:
|
||
MOV AL,[DEFALT]
|
||
DEC AL ; A=0
|
||
MOV CX,1
|
||
XOR DX,DX
|
||
MOV BX,OFFSET DG:BOOT
|
||
INT 25H
|
||
POPF
|
||
MOV AX,[BOOT+108H] ; Get old first sector of data
|
||
MOV [RELOC],AX
|
||
RET
|
||
|
||
READ_LLIST:
|
||
MOV AL,DS:(BYTE PTR 5CH)
|
||
DEC AL ; A=0
|
||
MOV CX,1
|
||
MOV DX,[STARTSECTOR]
|
||
MOV BX,OFFSET DG:LLISTBUF
|
||
INT 25H
|
||
POPF
|
||
RET
|
||
|
||
WRITE_LLIST:
|
||
MOV AX,[STARTSECTOR]
|
||
MOV DX,AX
|
||
SUB AX,[RELOC] ; True reloc factor
|
||
MOV CL,BYTE PTR [LLISTBUF+0CH] ; Number of entries needing reloc
|
||
XOR CH,CH
|
||
JCXZ NO_RELOCS
|
||
MOV BX,OFFSET DG:LLISTBUF + 10H
|
||
RELLOOP:
|
||
ADD WORD PTR [BX+2],AX
|
||
ADD BX,10H
|
||
LOOP RELLOOP
|
||
NO_RELOCS:
|
||
MOV AL,DS:(BYTE PTR 5CH)
|
||
DEC AL ; A=0
|
||
MOV CX,1
|
||
MOV BX,OFFSET DG:LLISTBUF
|
||
INT 26H
|
||
POPF
|
||
RET
|
||
|
||
CHECK_TRAN:
|
||
; All registers preserved. Returns zero if SYS OK, NZ if SYS FAIL
|
||
; AL is drive (1=A,...) AL=0 is not valid
|
||
|
||
PUSH BX
|
||
PUSH AX
|
||
PUSH DS
|
||
MOV DL,AL
|
||
MOV AH,GET_DPB
|
||
INT 21H
|
||
MOV AX,[BX.dpb_first_sector] ; Get new first sector of data
|
||
MOV BH,[BX.dpb_media]
|
||
POP DS
|
||
MOV [STARTSECTOR],AX
|
||
MOV [BOOT+108H],AX ; Set new start of data in boot
|
||
POP AX
|
||
PUSH AX
|
||
MOV BL,AL
|
||
INT 11H ; IBM EQUIP CALL
|
||
ROL AL,1
|
||
ROL AL,1
|
||
AND AL,3
|
||
JNZ NOT_SINGLE
|
||
INC AL
|
||
NOT_SINGLE:
|
||
INC AL ; AL is now MAX floppy #
|
||
CMP BL,AL
|
||
POP AX
|
||
JBE CHECK_FLOP ; Is a floppy
|
||
XOR BL,BL ; Is Hard file
|
||
POP BX
|
||
RET
|
||
|
||
CHECK_FLOP:
|
||
CMP BH,0FBH ; Only floppy that boots
|
||
POP BX
|
||
RET
|
||
ENDIF
|
||
|
||
GetKeystroke:
|
||
MOV AX,(Std_CON_Input_Flush SHL 8) + Std_CON_Input_No_Echo
|
||
INT 21H
|
||
MOV AX,(Std_CON_Input_Flush SHL 8) + 0
|
||
INT 21H
|
||
|
||
return
|
||
|
||
CODE ENDS
|
||
END START
|
||
|