Added files

This commit is contained in:
Broken Pipe
2026-01-04 13:54:33 +10:00
parent 435fe91271
commit 62b6d9772b
57 changed files with 9501 additions and 3 deletions
+2 -2
View File
@@ -1,2 +1,2 @@
# Auto detect text files and perform LF normalization # Treat all files as binary so we don't screw them up
* text=auto * binary
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+177
View File
@@ -0,0 +1,177 @@
MSDOS 2.0 RELEASE
The 2.0 Release of MSDOS includes five 5 1/4 double density single sided
diskettes or three 8 iinch CP/M 80 format diskettes.
The software/documentation on the five inch diskettes is arranged
as follows:
1. DOS distribution diskette. This diskette contains files which
should be distriibuted to all users. This allows the DOS distri-
bution diskette to meet the requirements of users of high level
language compilers as well as users running only applications.
Many compilers marketed independently through the retail channel
(including those of Microsoft) assume LINK comes with the DOS, as
in the case of IBM. How you choose to distrubute BASIC (contracted
for separately) is up to you.
2. Assembly Language Development System diskette. This diskette
contains files of interest to assembly language programmers.
High level language programmers do not need these programs unless
they are writing assembly language subroutines. IBM chose to
unbundle this package from the DOS distribution diskette (except
for DEBUG), but you do not have to do so.
3. PRINT and FORMAT diskette. This diskette contains .ASM source
files which are necessary to assemble the print spooler, which you
may wish to customize for greater performance. .OBJ files are also
included for the FORMAT utility.
4. Skeltal BIOS and documentation diskette. This diskette contains
the skeltal BIOS source code and the SYSINIT and SYSIMES object
modules which must be linked with your BIOS module. The proper
sequence for linking is BIOS - SYSINIT - SYSIMES.
A profiler utiliity is also included on the diskette, but this
is not intended for end-users. This is distributed for use by
your development staff only and is not supported by Microsoft
If you do decide to distribute it, it is at your own risk!
5. Documentation. Features of 2.0 are documented on this disk.
The user manual contains some significant errors. Most of these are
due to last minute changes to achieve a greater degree of compatibility
with IBM's implementation of MS-DOS (PC DOS). This includes the use
of "\" instead of "/" as the path separator, and "/" instead of "-"
as the switch character. For transporting of batch files across
machines, Microsoft encourages the use of "\" and "/" respectively
in the U.S. market. (See DOSPATCH.TXT for how you can overide this.
The user guide explains how the end-user can override this in CONFIG.SYS).
Both the printer echo keys and insert mode keys have now been made to
toggle. The default prompt (this may also be changed by the user
with the PROMPT command) has been changed from "A:" to "A>".
We apologize for any inconveniences these changes may have caused
your technical publications staff.
Here is what you need to do to MSDOS 2.0 to create a shipable product:
(see "Making a Bootable Diskette" below)
1. BIOS. If you have developed a BIOS for the Beta Test 2.0 version
You should link your BIOS module to SYSINIT.OBJ and SYSIMES.OBJ.
You must modify your BIOS to accomodate the call back to the BIOS
at the end of SYSINIT. If you have no need for this call, simply
find a far RET and label it RE_INIT and declare it public.
An example of this can be found in the skeletal BIOS. In addition
please add support for the new fast console output routine as
described in the device drivers document. We strongly recommend
that you adapt the standard boot sector format also described in
device drivers. Once again, please refer to the skeletal BIOS.
If you have not yet implemented version 2.0 please read the device
drivers document. Microsoft strongly recommends that machines
incorporating integrated display devices with memory mapped video
RAM implement some sort of terminal emulations through the use of
escape sequences. The skeletal BIOS includes a sample ANSI
terminal driver.
2. Please refer to DOSPATCH.TXT for possible changes you might wish
to make. We strongly recommend that you not patch the switch
characters for the U.S. market. Your one byte serial number
will be issued upon signing the license agreement. Please patch
the DOS accordingly. If you wish to serialize the DOS, this is
described in DOSPATCH.TXT. Please patch the editing template
definitions. Please note the addition of the Control-Z entry
at the beginning of the table. Also note that the insert switches
have now both been made to toggle.
3. Utilities. FORMAT must be configured for each specific system.
GENFOR is a generic example of a system independent format module,
but it is not recommended that this be distributed to your customers.
Link in the following order: FORMAT, FORMES, (your format module).
The print spooler is distributed as an executable file, which only
prints during wait for keyboard input. If you wish with your
implementation to steal some compute time when printing as well,
you will need to customize it and reassemble. Please note that
you can use a printer-ready or timer interrupt. The former is more
efficient, but ties the user to a specific device. Sample code
is conditionaled out for the IBM PC timer interrupt.
The following problems are known to exist:
1. Macro assembler does not support the initialization of 10-byte
floating point constants in 8087 emulation mode - the last two bytes
are zero filled.
2. LIB has not been provided. The version which incorporates support
for 2.0 path names will be completed in a couple of weeks. The
1.x version should work fine if you cannot wait. Because the library
manager acts as a counterpart to the linker, we recommend that it
be distributed with the DOS distribution diskette as opposed to the
assembly language development system.
3. International (French, German, Japanese, and U.K.) versions will be
available in several months.
4. COMMAND.ASM is currently too large to assemble on a micro. It is
being broken down into separate modules so it can be asembled on
a machine. Source licensees should realize that the resultant
binaries from the new version will not correspond exactly to the
old version.
5. If you have any further questions regarding the MSDOS 2.0 distribution
please contact Don Immerwahr (OEM technical support (206) 828-8086).
Sincerely yours,
Chris Larson
MS-DOS Product Marketing Manager
(206) 828-8080
BUILDING A BOOTABLE (MSDOS FORMAT) DISKETTE
1. In implementing MSDOS on a new machine, it is highly recommended
that an MSDOS machine be available for the development.
Please note that utilities shipped with MSDOS 2.0 use MSDOS 2.0
system calls and WILL NOT not run under MSDOS 1.25.
2. Use your MSDOS development machine and EDLIN or a word processor
package to write BOOT.ASM, your bootstrap loader BIOS.ASM and
your Format module.
3. Use MASM, the Microsoft Macro-86 Assembler, to assemble these
modules. LINK is then used to link together the .OBJ modules in
the order specified.
4. Link creates .EXE format files which are not memory image files
and contain relocation information in their headers. Since your
BIOS and BOOT routines will not be loaded by the EXE loader in
MSDOS, they must first be turned into memory image files by
using the EXE2BIN utility.
5. The easiest thing to do is to (using your development machine)
FORMAT a single sided diskette without the system. Use DEBUG
to load and write your BOOT.COM bootstrap loader to the BOOT
sector of that diskette. You may decide to have your bootstrap
load BIOS and let the BIOS load MSDOS or it may load both. Note that
the Bootstrap loader will have to know physically where to go on
the disk to get the BIOS and the DOS. COMMAND.COM is loaded
by the SYSINIT module.
6. Use the COPY command to copy your IO.SYS file (what the
BIOS-SYSINIT-SYSIMES module is usually called) onto the disk
followed by MSDOS.SYS and COMMAND.COM. You may use DEBUG
to change the directory attribute bytes to make these files hidden.
CAUTION:
At all times, the BIOS writer should be careful to preserve the state
of the DOS - including the flags. You should be also be cautioned that
the MSDOS stack is not deep. You should not count on more than one or
two pushes of the registers.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+62
View File
@@ -0,0 +1,62 @@
There are three locations in the DOS where OEMs may want to
patch in information specific to their installation.
The first is the location of the default switch character.
This character is one byte at DEBUG location 1E5, and is
set to '/'. To change it to '-' (XENIX compatible)
do:
DEBUG MSDOS.SYS
>e1e5
XXXX:01E5 2F. <at this point give the desired
new switch character in HEX and
hit return>
>w
Writing YYYY Bytes
>q
If the byte at 1E5 is not 2F, look around in the immediate
vacinity (do d1e0) for it. It is the only 2F in that area.
The second is the location of the 24 bit user number and the
8 bit OEM number. These values are returned by the GET_VERSION
system call.
The user number is 3 bytes starting at
debug location 683, The OEM number is one byte at debug location
686. The user number is initialized to 0, the OEM number to -1
and they immediatly follow the Microsoft Copyright message. If these
bytes are not zero, look for the four bytes following the
Copyright message which should be in the vacinity of 683.
OEMs should request an OEM number from Microsoft if they
want one of their very own, this prevents selecting one someone
else already has.
The third is the location of the editing template definitions.
This is a table which defines the two byte edit function keys
for system call 10 and for EDLIN. This table is at debug location
33EA, and should start with a 1B. If the byte at 33EA is not
1B, look around in the immediate vacinity. Here is what the
default table looks like. It is a definition for the Zenith
Z-19 terminal:
ESCCHAR DB 1BH ;The Escape character, Nul (0) on IBM
ESCTAB:
DB "Z" ;5AH Put a ^Z in the template, F6 on IBM
DB "S" ;53H Copy one char, --> on IBM
DB "V" ;56H Skip one char, DEL on IBM
DB "T" ;54H Copy to char, F2 on IBM
DB "W" ;57H Skip to char, F4 on IBM
DB "U" ;55H Copy line, F3 on IBM
DB "E" ;45H Kill line, Not used on IBM
DB "J" ;4AH Reedit line, F5 on IBM
DB "D" ;44H Backspace, <-- on IBM
DB "P" ;50H Toggle insert mode, INS on IBM
DB "Q" ;51H Toggle insert mode, INS on IBM
DB "R" ;52H Escape char, F7 on IBM
DB "R" ;52H End of table, must be same as previos character

+904
View File
@@ -0,0 +1,904 @@
include DOSMAC.ASM
IF2
%OUT DOSSYM in Pass 2
ENDIF
IFNDEF ALTVECT
ALTVECT EQU 0 ;FALSE
ENDIF
BREAK <Control character definitions>
c_DEL EQU 7Fh ; ASCII rubout or delete previous char
c_BS EQU 08h ; ^H ASCII backspace
c_CR EQU 0Dh ; ^M ASCII carriage return
c_LF EQU 0Ah ; ^J ASCII linefeed
c_ETB EQU 17h ; ^W ASCII end of transmission
c_NAK EQU 15h ; ^U ASCII negative acknowledge
c_ETX EQU 03h ; ^C ASCII end of text
c_HT EQU 09h ; ^I ASCII tab
BREAK <BPB Definition>
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; ;
; C A V E A T P R O G R A M M E R ;
; ;
; Certain structures, constants and system calls below are private to ;
; the DOS and are extremely version-dependent. They may change at any ;
; time at the implementors' whim. As a result, they must not be ;
; documented to the general public. If an extreme case arises, they ;
; must be documented with this warning. ;
; ;
; Those structures and constants that are subject to the above will be ;
; marked and bracketed with the flag: ;
; ;
; C A V E A T P R O G R A M M E R ;
; ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
BREAK <Bios Parameter Block>
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
; Bios Parameter Block definition
; This structure is used to build a full DPB
BPBLOCK STRUC
BPSECSZ DW ? ; Size in bytes of physical sector
BPCLUS DB ? ; Sectors/Alloc unit
BPRES DW ? ; Number of reserved sectors
BPFTCNT DB ? ; Number of FATs
BPDRCNT DW ? ; Number of directory entries
BPSCCNT DW ? ; Total number of sectors
BPMEDIA DB ? ; Media descriptor byte
BPFTSEC DW ? ; Number of sectors taken up by one FAT
BPBLOCK ENDS
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
BREAK <Disk I/O Buffer Header>
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
; Field definition for I/O buffer information
BUFFINFO STRUC
NEXTBUF DD ? ; Pointer to next buffer in list
; The next two items are often refed as a word
BUFDRV DB ? ; Logical drive # assoc with buffer FF = free
BUFDIRTY DB ? ; Dirty flag
BUFPRI DB ? ; Buffer selection priority (see EQUs below)
VISIT DB ? ; Visit flag for buffer pool scans
BUFSECNO DW ? ; Sector number of buffer
; The next two items are often refed as a word
BUFWRTCNT DB ? ; For FAT sectors, # times sector written out
BUFWRTINC DB ? ; " " " , # sectors between each write
BUFDRVDP DD ? ; Pointer to drive parameters
BUFFINFO ENDS
BUFINSIZ EQU SIZE BUFFINFO
; Size of structure in bytes
FREEPRI EQU 0
LBRPRI EQU 2 ; Last byte of buffer read
LBWPRI EQU 4 ; Last byte written
RPRI EQU 6 ; Read but not last byte
WPRI EQU 8 ; Written but not last byte
DIRPRI EQU 15 ; Directory Sector
FATPRI EQU 30 ; FAT sector
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
BREAK <User stack inside of system call>
; Location of user registers relative user stack pointer
user_environ STRUC
user_AX DW ?
user_BX DW ?
user_CX DW ?
user_DX DW ?
user_SI DW ?
user_DI DW ?
user_BP DW ?
user_DS DW ?
user_ES DW ?
user_IP DW ?
user_CS DW ?
user_F DW ?
user_environ ENDS
BREAK <interrupt definitions>
INTTAB EQU 20H
INTBASE EQU 4 * inttab
ENTRYPOINT EQU INTBASE+40H
IF ALTVECT
ALTTAB EQU 0F0H
ALTBASE EQU 4 * ALTTAB
ENDIF
;
; interrupt assignments
;
IF NOT ALTVECT
int_abort EQU INTTAB ; abort process
int_command EQU int_abort+1 ; call MSDOS
int_terminate EQU int_abort+2 ; int to terminate address
int_ctrl_c EQU int_abort+3 ; ^c trapper
int_fatal_abort EQU int_abort+4 ; hard disk error
int_disk_read EQU int_abort+5 ; logical sector disk read
int_disk_write EQU int_abort+6 ; logical sector disk write
int_keep_process EQU int_abort+7 ; terminate program and stay resident
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
int_spooler EQU int_abort+8 ; spooler call
int_fastcon EQU int_abort+9 ; fast CON interrupt
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
ELSE
int_abort EQU INTTAB ; abort process
int_command EQU int_abort+1 ; call MSDOS
int_terminate EQU ALTTAB ; int to terminate address
int_ctrl_c EQU int_terminate+1 ; ^c trapper
int_fatal_abort EQU int_terminate+2 ; hard disk error
int_disk_read EQU int_abort+5 ; logical sector disk read
int_disk_write EQU int_abort+6 ; logical sector disk write
int_keep_process EQU int_abort+7 ; terminate program and stay resident
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
int_spooler EQU int_terminate+3 ; spooler call
int_fastcon EQU int_abort+9 ; fast CON interrupt
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
ENDIF
addr_int_abort EQU 4 * int_abort
addr_int_command EQU 4 * int_command
addr_int_terminate EQU 4 * int_terminate
addr_int_ctrl_c EQU 4 * int_ctrl_c
addr_int_fatal_abort EQU 4 * int_fatal_abort
addr_int_disk_read EQU 4 * int_disk_read
addr_int_disk_write EQU 4 * int_disk_write
addr_int_keep_process EQU 4 * int_keep_process
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
addr_int_spooler EQU 4 * int_spooler
addr_int_fastcon EQU 4 * int_fastcon
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
BREAK <Disk map>
; MSDOS partitions the disk into 4 sections:
;
; phys sector 0: +-------------------+
; | | boot/reserved |
; | +-------------------+
; | | File allocation |
; v | table(s) |
; | (multiple copies |
; | are kept) |
; +-------------------+
; | Directory |
; +-------------------+
; | File space |
; +-------------------+
; | Unaddressable |
; | (to end of disk) |
; +-------------------+
;
; All partition boundaries are sector boundaries. The size of the FAT is
; adjusted to maximize the file space addressable.
BREAK <Directory entry>
;
; +---------------------------+
; | (12 BYTE) filename/ext | 0 0
; +---------------------------+
; | (BYTE) attributes | 11 B
; +---------------------------+
; | (10 BYTE) reserved | 12 C
; +---------------------------+
; | (WORD) time of last write | 22 16
; +---------------------------+
; | (WORD) date of last write | 24 18
; +---------------------------+
; | (WORD) First cluster | 26 1A
; +---------------------------+
; | (DWORD) file size | 28 1C
; +---------------------------+
;
; First byte of filename = E5 -> free directory entry
; = 00 -> end of allocated directory
; Time: Bits 0-4=seconds/2, bits 5-10=minute, 11-15=hour
; Date: Bits 0-4=day, bits 5-8=month, bits 9-15=year-1980
;
dir_entry STRUC
dir_name DB 11 DUP (?) ; file name
dir_attr DB ? ; attribute bits
dir_pad DB 10 DUP (?) ; reserved for expansion
dir_time DW ? ; time of last write
dir_date DW ? ; date of last write
dir_first DW ? ; first allocation unit of file
dir_size_l DW ? ; low 16 bits of file size
dir_size_h DW ? ; high 16 bits of file size
dir_entry ENDS
attr_read_only EQU 1h
attr_hidden EQU 2h
attr_system EQU 4h
attr_volume_id EQU 8h
attr_directory EQU 10h
attr_archive EQU 20h
attr_all EQU attr_hidden+attr_system+attr_directory
; OR of hard attributes for FINDENTRY
attr_ignore EQU attr_read_only+attr_archive
; ignore this(ese) attribute(s)
; during search first/next
attr_changeable EQU attr_read_only+attr_hidden+attr_system+attr_archive
; changeable via CHMOD
BREAK <File allocation Table information>
;
; The File Allocation Table uses a 12-bit entry for each allocation unit on the
; disk. These entries are packed, two for every three bytes. The contents of
; entry number N is found by 1) multiplying N by 1.5; 2) adding the result to
; the base address of the Allocation Table; 3) fetching the 16-bit word at this
; address; 4) If N was odd (so that N*1.5 was not an integer), shift the word
; right four bits; 5) mask to 12 bits (AND with 0FFF hex). Entry number zero
; is used as an end-of-file trap in the OS and is passed to the BIOS to help
; determine disk format. Entry 1 is reserved for future use. The first
; available allocation unit is assigned entry number two, and even though it is
; the first, is called cluster 2. Entries greater than 0FF8H are end of file
; marks; entries of zero are unallocated. Otherwise, the contents of a FAT
; entry is the number of the next cluster in the file.
;
; Clusters with bad sectors are tagged with FF7H. Any non-zero number would do
; because these clusters show as allocated, but are not part of any allocation
; chain and thus will never be allocated to a file. A particular number is
; selected so that disk checking programs know what to do (ie. a cluster with
; entry FF7H which is not in a chain is not an error).
BREAK <DPB structure>
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
DIRSTRLEN EQU 64 ; Max length in bytes of directory strings
dpb STRUC
dpb_drive DB ? ; Logical drive # assoc with DPB (A=0,B=1,...)
dpb_UNIT DB ? ; Driver unit number of DPB
dpb_sector_size DW ? ; Size of physical sector in bytes
dpb_cluster_mask DB ? ; Sectors/cluster - 1
dpb_cluster_shift DB ? ; Log2 of sectors/cluster
dpb_first_FAT DW ? ; Starting record of FATs
dpb_FAT_count DB ? ; Number of FATs for this drive
dpb_root_entries DW ? ; Number of directory entries
dpb_first_sector DW ? ; First sector of first cluster
dpb_max_cluster DW ? ; Number of clusters on drive + 1
dpb_FAT_size DB ? ; Number of records occupied by FAT
dpb_dir_sector DW ? ; Starting record of directory
dpb_driver_addr DD ? ; Pointer to driver
dpb_media DB ? ; Media byte
dpb_first_access DB ? ; This is initialized to -1 to force a media
; check the first time this DPB is used
dpb_next_dpb DD ? ; Pointer to next Drive parameter block
dpb_current_dir DW ? ; Cluster number of start of current directory
; 0 indicates root, -1 indicates invalid
; (disk ? changed)
dpb_dir_text DB DIRSTRLEN DUP(?)
; ASCIZ string of current directory
dpb ENDS
DPBSIZ EQU SIZE dpb ; Size of the structure in bytes
DSKSIZ = dpb_max_cluster ; Size of disk (temp used during init only)
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
BREAK <File Control Block definition>
;
; Field definition for FCBs
; The FCB has the following structure:
;
; +---------------------------+
; | Drive indicator(byte) |
; +---------------------------+
; | Filename (8 chars) |
; +---------------------------+
; | Extension (3 chars) |
; +---------------------------+
; | Current Extent(word) |
; +---------------------------+
; | Record size (word) |
; +---------------------------+
; | File Size (2 words) |
; +---------------------------+
; | Date of write |
; +---------------------------+
; | Time of write |
; +---------------------------+
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
; | Flags: |
; | bit 7=0 file/1 device |
; | bit 6=0 if dirty |
; | bits 0-5 deviceid |
; +---------------------------+
; | first cluster in file |
; +---------------------------+
; | position of last cluster |
; +---------------------------+
; | last cluster accessed | 12 bit-+--- packed in 3 bytes
; +---------------------------+ |
; | parent directory | <------+
; +---------------------------+
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; | next record number |
; +---------------------------+
; | random record number |
; +---------------------------+
;
sys_fcb STRUC
fcb_drive DB ?
fcb_name DB 8 DUP (?)
fcb_ext DB 3 DUP (?)
fcb_EXTENT DW ?
fcb_RECSIZ DW ? ; Size of record (user settable)
fcb_FILSIZ DW ? ; Size of file in bytes; used with the following
; word
fcb_DRVBP DW ? ; BP for SEARCH FIRST and SEARCH NEXT
fcb_FDATE DW ? ; Date of last writing
fcb_FTIME DW ? ; Time of last writing
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
fcb_DEVID DB ? ; Device ID number, bits 0-5 if file.
; bit 7=0 for file, bit 7=1 for I/O device
; If file, bit 6=0 if dirty
; If I/O device, bit 6=0 if EOF (input)
; Bit 5=1 if Raw mode
; Bit 0=1 if console input device
; Bit 1=1 if console output device
; Bit 2=1 if null device
; Bit 3=1 if clock device
fcb_FIRCLUS DW ? ; First cluster of file
fcb_CLUSPOS DW ? ; Position of last cluster accessed
fcb_LSTCLUS DW ? ; Last cluster accessed and directory
DB ? ; pack 2 12 bit numbers into 24 bits...
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
fcb_NR DB ? ; Next record
fcb_RR DB 4 DUP (?) ; Random record
sys_fcb ENDS
FILDIRENT = fcb_FILSIZ ; Used only by SEARCH FIRST and
; SEARCH NEXT
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
devid_file_clean EQU 40h ; true if file and not written
devid_file_mask_drive EQU 3Fh ; mask for drive number
devid_device EQU 80h ; true if a device
devid_device_EOF EQU 40h ; true if end of file reached
devid_device_raw EQU 20h ; true if in raw mode
devid_device_special EQU 10h ; true if special device
devid_device_clock EQU 08h ; true if clock device
devid_device_null EQU 04h ; true if null device
devid_device_con_out EQU 02h ; true if console output
devid_device_con_in EQU 01h ; true if consle input
;
; structure of devid field as returned by IOCTL is:
;
; BIT 7 6 5 4 3 2 1 0
; |---|---|---|---|---|---|---|---|
; | I | E | R | S | I | I | I | I |
; | S | O | A | P | S | S | S | S |
; | D | F | W | E | C | N | C | C |
; | E | | | C | L | U | O | I |
; | V | | | L | K | L | T | N |
; |---|---|---|---|---|---|---|---|
; ISDEV = 1 if this channel is a device
; = 0 if this channel is a disk file
;
; If ISDEV = 1
;
; EOF = 0 if End Of File on input
; RAW = 1 if this device is in Raw mode
; = 0 if this device is cooked
; ISCLK = 1 if this device is the clock device
; ISNUL = 1 if this device is the null device
; ISCOT = 1 if this device is the console output
; ISCIN = 1 if this device is the console input
;
; If ISDEV = 0
; EOF = 0 if channel has been written
; Bits 0-5 are the block device number for
; the channel (0 = A, 1 = B, ...)
;
devid_ISDEV EQU 80h
devid_EOF EQU 40h
devid_RAW EQU 20h
devid_SPECIAL EQU 10H
devid_ISCLK EQU 08h
devid_ISNUL EQU 04h
devid_ISCOT EQU 02h
devid_ISCIN EQU 01h
devid_block_dev EQU 1Fh ; mask for block device number
;
; find first/next buffer
;
find_buf STRUC
find_buf_sattr DB ? ; attribute of search
find_buf_drive DB ? ; drive of search
find_buf_name DB 11 DUP (?) ; formatted name
find_buf_LastEnt DW ? ; LastEnt
find_buf_ThisDPB DD ? ; This DPB
find_buf_DirStart DW ? ; DirStart
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
find_buf_attr DB ? ; attribute found
find_buf_time DW ? ; time
find_buf_date DW ? ; date
find_buf_size_l DW ? ; low(size)
find_buf_size_h DW ? ; high(size)
find_buf_pname DB 13 DUP (?) ; packed name
find_buf ENDS
BREAK <Process data block>
;
; Process data block (otherwise known as program header)
;
FilPerProc EQU 20
Process_data_block STRUC
PDB_Exit_Call DW ? ; INT int_abort system terminate
PDB_block_len DW ? ; size of execution block
DB ?
PDB_CPM_Call DB 5 DUP (?) ; ancient call to system
PDB_Exit DD ? ; pointer to exit routine
PDB_Ctrl_C DD ? ; pointer to ^C routine
PDB_Fatal_abort DD ? ; pointer to fatal error
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
PDB_Parent_PID DW ? ; PID of parent (terminate PID)
PDB_JFN_Table DB FilPerProc DUP (?)
; indices into system table
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
PDB_environ DW ? ; seg addr of environment
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
PDB_User_stack DD ? ; stack of self during system calls
PDB_PAD1 DB 1Eh DUP (?)
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
PDB_Call_system DB 5 DUP (?) ; portable method of system call
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
PDB_PAD2 DB 6h DUP (?) ;
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
Process_data_block ENDS
BREAK <EXEC and EXE file structures>
;
; EXEC arg block - load/go program
;
;
; The following get used as arguments to the EXEC system call. They indicate
; whether or not the program is executed or whether or not a program header
; gets created.
;
exec_func_no_execute EQU 1 ; no execute bit
exec_func_overlay EQU 2 ; overlay bit
Exec0 STRUC
Exec0_environ DW ? ; seg addr of environment
Exec0_com_line DD ? ; pointer to asciz command line
Exec0_5C_FCB DD ? ; default fcb at 5C
Exec0_6C_FCB DD ? ; default fcb at 6C
Exec0 ENDS
Exec1 STRUC
Exec1_environ DW ? ; seg addr of environment
Exec1_com_line DD ? ; pointer to asciz command line
Exec1_5C_FCB DD ? ; default fcb at 5C
Exec1_6C_FCB DD ? ; default fcb at 6C
Exec1_SP DW ? ; stack pointer of program
Exec1_SS DW ? ; stack seg register of program
Exec1_IP DW ? ; entry point IP
Exec1_CS DW ? ; entry point CS
Exec1 ENDS
Exec3 STRUC
Exec3_load_addr DW ? ; seg address of load point
Exec3_reloc_fac DW ? ; relocation factor
Exec3 ENDS
;
; Exit codes in upper byte
;
Exit_terminate EQU 0
Exit_abort EQU 0
Exit_Ctrl_C EQU 1
Exit_Hard_Error EQU 2
Exit_Keep_process EQU 3
;
; EXE file header
;
EXE_file STRUC
exe_signature DW ? ; must contain 4D5A (yay zibo!)
exe_len_mod_512 DW ? ; low 9 bits of length
exe_pages DW ? ; number of 512b pages in file
exe_rle_count DW ? ; count of reloc entries
exe_par_dir DW ? ; number of paragraphs before image
exe_min_BSS DW ? ; minimum number of para of BSS
exe_max_BSS DW ? ; max number of para of BSS
exe_SS DW ? ; stack of image
exe_SP DW ? ; SP of image
exe_chksum DW ? ; checksum of file (ignored)
exe_IP DW ? ; IP of entry
exe_CS DW ? ; CS of entry
exe_rle_table DW ? ; byte offset of reloc table
exe_iov DW ? ; overlay number (0 for root)
exe_sym_tab DD ? ; offset of symbol table in file
EXE_file ENDS
exe_valid_signature EQU 5A4Dh
exe_valid_old_signature EQU 4D5Ah
symbol_entry STRUC
sym_value DD ?
sym_type DW ?
sym_len DB ?
sym_name DB 255 dup (?)
symbol_entry ENDS
BREAK <Internal system file table format>
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
;
; system file table
;
sft STRUC
sft_link DD ?
sft_count DW ? ; number of entries
sft_table DW ? ; beginning of array of the following
sft ENDS
;
; system file table entry
;
sf_entry STRUC
sf_ref_count DB ? ; number of processes sharing fcb
sf_mode DB ? ; mode of access
sf_attr DB ? ; attribute of file
sf_fcb DB (SIZE sys_fcb) DUP (?)
; actual FCB
sf_entry ENDS
sf_default_number EQU 5h
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
BREAK <Memory arena structure>
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
;
; arena item
;
arena STRUC
arena_signature DB ? ; 4D for valid item, 5A for last item
arena_owner DW ? ; owner of arena item
arena_size DW ? ; size in paragraphs of item
arena ENDS
arena_owner_system EQU 0 ; free block indication
arena_signature_normal EQU 4Dh ; valid signature, not end of arena
arena_signature_end EQU 5Ah ; valid signature, last block in arena
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
BREAK <Machine instruction definitions>
mi_INT EQU 0CDh
mi_Long_JMP EQU 0EAh
mi_Long_CALL EQU 09Ah
mi_Long_RET EQU 0CBh
BREAK <Standard I/O assignments>
stdin EQU 0
stdout EQU 1
stderr EQU 2
stdaux EQU 3
stdprn EQU 4
BREAK <Xenix subfunction assignments>
open_for_read EQU 0
open_for_write EQU 1
open_for_both EQU 2
BREAK <Xenix error codes>
;
; XENIX calls all return error codes through AX. If an error occurred then the
; carry bit will be set and the error code is in AX. If no error occurred then
; the carry bit is reset and AX contains returned info.
;
no_error_occurred EQU 0 ?
error_invalid_function EQU 1
error_file_not_found EQU 2
error_path_not_found EQU 3
error_too_many_open_files EQU 4
error_access_denied EQU 5
error_invalid_handle EQU 6
error_arena_trashed EQU 7
error_not_enough_memory EQU 8
error_invalid_block EQU 9
error_bad_environment EQU 10
error_bad_format EQU 11
error_invalid_access EQU 12
error_invalid_data EQU 13
;**** unused EQU 14
error_invalid_drive EQU 15
error_current_directory EQU 16
error_not_same_device EQU 17
error_no_more_files EQU 18
alloc_not_enough_memory EQU error_not_enough_memory
alloc_arena_trashed EQU error_arena_trashed
close_invalid_handle EQU error_invalid_handle
close_invalid_function EQU error_invalid_function
chdir_path_not_found EQU error_path_not_found
chmod_path_not_found EQU error_path_not_found
chmod_access_denied EQU error_access_denied
chmod_invalid_function EQU error_invalid_function
creat_access_denied EQU error_access_denied
creat_path_not_found EQU error_path_not_found
creat_too_many_open_files EQU error_too_many_open_files
curdir_invalid_drive EQU error_invalid_drive
dealloc_invalid_block EQU error_invalid_block
dealloc_arena_trashed EQU error_arena_trashed
dup_invalid_handle EQU error_invalid_handle
dup_too_many_open_files EQU error_too_many_open_files
dup2_invalid_handle EQU error_invalid_handle
exec_invalid_function EQU error_invalid_function
exec_bad_environment EQU error_bad_environment
exec_bad_format EQU error_bad_format
exec_not_enough_memory EQU error_not_enough_memory
exec_file_not_found EQU error_file_not_found
filetimes_invalid_function EQU error_invalid_function
filetimes_invalid_handle EQU error_invalid_handle
findfirst_file_not_found EQU error_file_not_found
findfirst_no_more_files EQU error_no_more_files
findnext_no_more_files EQU error_no_more_files
international_invalid_function EQU error_invalid_function
ioctl_invalid_handle EQU error_invalid_handle
ioctl_invalid_function EQU error_invalid_function
ioctl_invalid_data EQU error_invalid_data
lseek_invalid_handle EQU error_invalid_handle
lseek_invalid_function EQU error_invalid_function
mkdir_path_not_found EQU error_path_not_found
mkdir_access_denied EQU error_access_denied
open_invalid_access EQU error_invalid_access
open_file_not_found EQU error_file_not_found
open_access_denied EQU error_access_denied
open_too_many_open_files EQU error_too_many_open_files
read_invalid_handle EQU error_invalid_handle
read_access_denied EQU error_access_denied
rename_file_not_found EQU error_file_not_found
rename_not_same_device EQU error_not_same_device
rename_access_denied EQU error_access_denied
rmdir_path_not_found EQU error_path_not_found
rmdir_access_denied EQU error_access_denied
rmdir_current_directory EQU error_current_directory
setblock_invalid_block EQU error_invalid_block
setblock_arena_trashed EQU error_arena_trashed
setblock_not_enough_memory EQU error_not_enough_memory
setblock_invalid_function EQU error_invalid_function
unlink_file_not_found EQU error_file_not_found
unlink_access_denied EQU error_access_denied
write_invalid_handle EQU error_invalid_handle
write_access_denied EQU error_access_denied
BREAK <system call definitions>
ABORT EQU 0 ; 0 0
STD_CON_INPUT EQU 1 ; 1 1
STD_CON_OUTPUT EQU 2 ; 2 2
STD_AUX_INPUT EQU 3 ; 3 3
STD_AUX_OUTPUT EQU 4 ; 4 4
STD_PRINTER_OUTPUT EQU 5 ; 5 5
RAW_CON_IO EQU 6 ; 6 6
RAW_CON_INPUT EQU 7 ; 7 7
STD_CON_INPUT_NO_ECHO EQU 8 ; 8 8
STD_CON_STRING_OUTPUT EQU 9 ; 9 9
STD_CON_STRING_INPUT EQU 10 ; 10 A
STD_CON_INPUT_STATUS EQU 11 ; 11 B
STD_CON_INPUT_FLUSH EQU 12 ; 12 C
DISK_RESET EQU 13 ; 13 D
SET_DEFAULT_DRIVE EQU 14 ; 14 E
FCB_OPEN EQU 15 ; 15 F
FCB_CLOSE EQU 16 ; 16 10
DIR_SEARCH_FIRST EQU 17 ; 17 11
DIR_SEARCH_NEXT EQU 18 ; 18 12
FCB_DELETE EQU 19 ; 19 13
FCB_SEQ_READ EQU 20 ; 20 14
FCB_SEQ_WRITE EQU 21 ; 21 15
FCB_CREATE EQU 22 ; 22 16
FCB_RENAME EQU 23 ; 23 17
GET_DEFAULT_DRIVE EQU 25 ; 25 19
SET_DMA EQU 26 ; 26 1A
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
GET_DEFAULT_DPB EQU 31 ; 31 1F
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
FCB_RANDOM_READ EQU 33 ; 33 21
FCB_RANDOM_WRITE EQU 34 ; 34 22
GET_FCB_FILE_LENGTH EQU 35 ; 35 23
GET_FCB_POSITION EQU 36 ; 36 24
SET_INTERRUPT_VECTOR EQU 37 ; 37 25
CREATE_PROCESS_DATA_BLOCK EQU 38 ; 38 26
FCB_RANDOM_READ_BLOCK EQU 39 ; 39 27
FCB_RANDOM_WRITE_BLOCK EQU 40 ; 40 28
PARSE_FILE_DESCRIPTOR EQU 41 ; 41 29
GET_DATE EQU 42 ; 42 2A
SET_DATE EQU 43 ; 43 2B
GET_TIME EQU 44 ; 44 2C
SET_TIME EQU 45 ; 45 2D
SET_VERIFY_ON_WRITE EQU 46 ; 46 2E
; Extended functionality group
GET_DMA EQU 47 ; 47 2F
GET_VERSION EQU 48 ; 48 30
KEEP_PROCESS EQU 49 ; 49 31
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
GET_DPB EQU 50 ; 50 32
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
SET_CTRL_C_TRAPPING EQU 51 ; 51 33
GET_INDOS_FLAG EQU 52 ; 52 34
GET_INTERRUPT_VECTOR EQU 53 ; 53 35
GET_DRIVE_FREESPACE EQU 54 ; 54 36
CHAR_OPER EQU 55 ; 55 37
INTERNATIONAL EQU 56 ; 56 38
; XENIX CALLS
; Directory Group
MKDIR EQU 57 ; 57 39
RMDIR EQU 58 ; 58 3A
CHDIR EQU 59 ; 59 3B
; File Group
CREAT EQU 60 ; 60 3C
OPEN EQU 61 ; 61 3D
CLOSE EQU 62 ; 62 3E
READ EQU 63 ; 63 3F
WRITE EQU 64 ; 64 40
UNLINK EQU 65 ; 65 41
LSEEK EQU 66 ; 66 42
CHMOD EQU 67 ; 67 43
IOCTL EQU 68 ; 68 44
XDUP EQU 69 ; 69 45
XDUP2 EQU 70 ; 70 46
CURRENT_DIR EQU 71 ; 71 47
; Memory Group
ALLOC EQU 72 ; 72 48
DEALLOC EQU 73 ; 73 49
SETBLOCK EQU 74 ; 74 4A
; Process Group
EXEC EQU 75 ; 75 4B
EXIT EQU 76 ; 76 4C
WAIT EQU 77 ; 77 4D
FIND_FIRST EQU 78 ; 78 4E
; Special Group
FIND_NEXT EQU 79 ; 79 4F
; SPECIAL SYSTEM GROUP
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
SET_CURRENT_PDB EQU 80 ; 80 50
GET_CURRENT_PDB EQU 81 ; 81 51
GET_IN_VARS EQU 82 ; 82 52
SETDPB EQU 83 ; 83 53
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
GET_VERIFY_ON_WRITE EQU 84 ; 84 54
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
DUP_PDB EQU 85 ; 85 55
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
RENAME EQU 86 ; 86 56
FILE_TIMES EQU 87 ; 87 57
SET_OEM_HANDLER EQU 248 ; 248 F8
OEM_C1 EQU 249 ; 249 F9
OEM_C2 EQU 250 ; 250 FA
OEM_C3 EQU 251 ; 251 FB
OEM_C4 EQU 252 ; 252 FC
OEM_C5 EQU 253 ; 253 FD
OEM_C6 EQU 254 ; 254 FE
OEM_C7 EQU 255 ; 255 FF
SUBTTL
+393
View File
@@ -0,0 +1,393 @@
FORMAT - formats a new disk, clears the FAT and DIRECTORY
and optionally copies the SYSTEM and COMMAND.COM to this
new disk.
Command syntax:
FORMAT [drive:][/switch1][/switch2]...[/switch16]
Where "drive:" is a legal drive specification and if
omitted indicates that the default drive will be used.
There may be up to 16 legal switches included in the
command line.
The OEM must supply five (NEAR) routines to the program
along with 6 data items. The names of the routines are INIT,
DISKFORMAT, BADSECTOR, WRTFAT and DONE, and their flow of
control (by the Microsoft module) is like this:
|
+---------+
| INIT |
+---------+
|
|<------------------------------+
+------------+ |
| DISKFORMAT | |
+------------+ |
|<-------+ |
+-----------+ |-This loop is done |- This loop done
| BADSECTOR | | for each group of | once for each disk
+-----------+ | bad sectors | to be formatted.
|----->--+ | If variable HARDFLAG
| | is set then the loop
+----------+ | is only performed
| | | once.
| WRTFAT | |
+----------+ |
| |
+------+ |
| DONE | |
+------+ |
+---->--------------------------+
The INIT, DISKFORMAT, and BADSECTOR routines are free
to use any MS-DOS system calls, except for calls that cause
disk accesses on the disk being formatted. DONE may use
ANY calls, since by the time it is called the new disk has
been formatted.
The following data must be declared PUBLIC in a module
provided by the OEM:
SWITCHLIST - A string of bytes. The first byte is count
N, followed by N characters which are the switches to
be accepted by the command line scanner. Alphabetic
characters must be in upper case (the numeric
characters 0-9 are allowed). The last three switches,
normally "O", "V" and "S", have pre-defined meanings.
The "S" switch is the switch which causes the
system files IO.SYS, MSDOS.SYS, and COMMAND.COM to be
transfered to the disk after it is formatted thus
making a "S"ystem disk. The switch can be some letter
other than "S", but the last switch in the list is
assumed to have the meaning "transfer system",
regardles of what the particular letter is.
The second to the last switch, "V", causes FORMAT
to prompt the user for a volume label after the disk
is formatted. Again, as with "S", the particular
letter is not important but rather the position in the
list.
The third to the last switch, "O", causes FORMAT to
produce an IBM Personal Computer DOS version 1.X
compatible disk. Normally FORMAT causes a 0 byte to
be placed in the first byte of each directory entry
instead of the 0E5 Hex free entry designator. This
results in a very marked directory search performance
increase due to an optimization in the DOS. Disks
made this way cause trouble on IBM PC DOS 1.X
versions, however, which did not have this
optimization. The 0 byte fools IBM 1.X versions into
thinking these entries are allocated instead of free,
NOTE that IBM Personnal Computer DOS version 2.00 and
MS-DOS version 1.25 will have no trouble with these
disks, since they have the same optimization. The "O"
switch causes FORMAT to re-do the directory with a 0E5
Hex byte at the start of each entry so that the disk
may be used with 1.X versions of IBM PC DOS, as well
as MS-DOS 1.25/2.00 and IBM PC DOS 2.00. This switch
should only be given when needed because it takes a
fair amount of time for FORMAT to perform the
conversion, and it noticably decreases 1.25 and 2.00
performance on disks with few directory entries.
Up to 16 switches are permitted. Normally a "C"
switch is specified for "Clear". This switch should
cause the formatting operation to be bypassed (within
DISKFORMAT or BADSECTOR). This is provided as a
time-saving convenience to the user, who may wish
to "start fresh" on a previosly formatted and used
disk.
HARDFLAG - BYTE location which specifies whether the
OEM routine is formatting a fixed disk or a a drive
with removable media. A zero indicates removable
media, any other value indicates a fixed disk. The
status of this byte only effect the messages printed
by the main format module. This value should be
set or reset by the OEM supplied INIT routine.
FATID - BYTE location containing the value to be used
in the first byte of the FAT. Must be in the range
F8 hex to FF hex.
STARTSECTOR - WORD location containing the sector number
of the first sector of the data area.
FATSPACE - WORD location containing the address of the
start of the FAT area. A FAT built in this area
will be written to disk using the OEM supplied WRTFAT
subroutine. 6k is sufficient to store any FAT. This
area must not overlap the FREESPACE area.
FREESPACE - WORD location which contains the address
of the start of free memory space. This is where
the system will be loaded, by the Microsoft module,
for transferring to the newly formatted disk. Memory
should be available from this address to the end
of memory, so it is typically the address of the
end of the OEM module.
The following routines must be declared PUBLIC in the
OEM-supplied module:
INIT - An initialization routine. This routine is called
once at the start of the FORMAT run after the switches
have been processed. This routine should perform
any functions that only need to be done once per
FORMAT run. An example of what this routine might
do is read the boot sector into a buffer so that
it can be transferred to the new disks by DISKFORMAT.
If this routine returns with the CARRY flag set it
indicates an error, and FORMAT will print "Format
failure" and quit. This feature can be used to detect
conflicting switches (like specifying both single
and double density) and cause FORMAT to quit without
doing anything.
DISKFORMAT - Formats the disk according to the options
indicated by the switches and the value of FATID
must be defined when it returns (although INIT may
have already done it). This routine is called once
for EACH disk to be formatted. If neccessary it
must transfer the Bootstrap loader. If any error
conditions are detected, set the CARRY flag and return
to FORMAT. FORMAT will report a 'Format failure'
and prompt for another disk. (If you only require
a clear directory and FAT then simply setting the
appropriate FATID, if not done by INIT, will be all
that DISKFORMAT must do.)
BADSECTOR - Reports the sector number of any bad sectors
that may have been found during the formatting of
the disk. This routine is called at least once for
EACH disk to be formatted, and is called repeatedly
until AX is zero or the carry flag is set. The carry
flag is used just as in DISKFORMAT to indicate an
error, and FORMAT handles it in the same way. The
first sector in the data area must be in STARTSECTOR
for the returns from this routine to be interpreted
correctly. If there are bad sectors, BADSECTOR must
return a sector number in in register BX, the number
of consecutive bad sectors in register AX, and carry
clear. FORMAT will then process the bad sectors
and call BADSECTOR again. When BADSECTOR returns
with AX = 0 this means there are no more bad sectors;
FORMAT clears the directory and goes on to DONE,
so for this last return BX need not contain anything
meaningful.
FORMAT processes bad sectors by determining their
corresponding allocation unit and marking that unit
with an FF7 hex in the File Allocation Table. CHKDSK
understands the FF7 mark as a flag for bad sectors
and accordingly reports the number of bytes marked
in this way.
NOTE: Actual formatting of the disk can be done in
BADSECTOR instead of DISKFORMAT on a "report as you
go" basis. Formatting goes until a group of bad
sectors is encountered, BADSECTOR then reports them
by returning with AX and BX set. FORMAT will then
call BADSECTOR again and formatting can continue.
WRTFAT - This routine is called after the disk is
formatted and bad sectors have been reported. Its
purpose is to write all copies of the FAT from the
area of memory referenced by FATSPACE to the drive
just formatted. It may be possible to use INT 26H
to perform the write, or a direct BIOS call. Whether
this is possible depends on whether the FAT ID byte
is used by the BIOS to determine the media in the
drive. If it is, these methods will probably fail
because there is no FAT ID byte on the disk yet (in
this case WRTFATs primary job is to get the FAT ID
byte out on the disk and thus solve the chicken and
egg problem).
DONE - This routine is called after the formatting is
complete, the disk directory has been initialized,
and the system has been transferred. It is called
once for EACH disk to be formatted. This gives the
chance for any finishing-up operations, if needed.
If the OEM desires certain extra files to be put
on the diskette by default, or according to a switch,
this could be done in DONE. Again, as in BADSECTOR
and DISKFORMAT, carry flag set on return means an
error has occurred: 'Format failure' will be printed
and FORMAT will prompt for another disk.
The following data is declared PUBLIC in Microsoft's FORMAT
module:
SWITCHMAP - A word with a bit vector indicating what
switches have been included in the command line. The
correspondence of the bits to the switches is
determined by SWITCHLIST. The right-most
(highest-addressed) switch in SWITCHLIST (which must
be the system transfer switch, normally "S")
corresponds to bit 0, the second from the right,
normally "V" to bit 1, etc. For example, if
SWITCHLIST is the string "7,'AGI2OVS'", and the user
specifies "/G/S" on the command line, then bit 6 will
be 0 (A not specified), bit 5 will be 1 (G specified),
bits 4,3,2 and 1 will be 0 (neither I,2,O or V
specified), and bit 0 will be 1 (S specified).
Bits 0,1 and 2 are the only switches used in
Microsoft's FORMAT module. These switches are used 1)
after INIT has been called, to determine if it is
necessary to load the system; 2) after the last
BADSECTOR call, to determine if the system is to be
written, E5 directory conversion is to be done, and/or
a volume label is to be asked for. INIT may force
these bits set or reset if desired (for example, some
drives may never be used as system disk, such as hard
disks). After INIT, the "S" bit may be turned off
(but not on, since the system was never read) if
something happens that means the system should not be
transferred.
After INIT, a second copy of SWITCHMAP is made
internally which is used to restore SWITCHMAP for
each disk to be formatted. FORMAT itself will turn
off the system bit if bad sectors are reported in
the system area; DISKFORMAT and BADSECTOR are also
allowed to change the map. However, these changes
affect only the current disk being formatted, since
SWITCHMAP is restored after each disk. (Changes
made to SWITCHMAP by INIT do affect ALL disks.)
DRIVE - A byte containing the drive specified in the
command line. 0=A, 1=B, etc.
Once the OEM-supplied module has been prepared, it must linked
with Microsoft's FORMAT.OBJ module and the FORMES.OBJ module.
If the OEM-supplied module is called OEMFOR.OBJ, then the
following linker command will do:
LINK FORMAT FORMES OEMFOR;
This command will produce a file called FORMAT.EXE. FORMAT
has been designed to run under MS-DOS as a simple binary
.COM file. This conversion is performed by LOCATE (EXE2BIN)
with the command
LOCATE FORMAT.EXE FORMAT.COM
which will produce the file FORMAT.COM.
;*****************************************
;
; A Sample OEM module
;
;*****************************************
CODE SEGMENT BYTE PUBLIC 'CODE'
; This segment must be
; named CODE, it must be
; PUBLIC, and it's
; classname must be 'CODE'
ASSUME CS:CODE,DS:CODE,ES:CODE
; Must declare data and routines PUBLIC
PUBLIC FATID,STARTSECTOR,SWITCHLIST,FREESPACE
PUBLIC INIT,DISKFORMAT,BADSECTOR,DONE,WRTFAT
PUBLIC FATSPACE,HARDFLAG
; This data defined in Microsoft-supplied module
EXTRN SWITCHMAP:WORD,DRIVE:BYTE
INIT:
; Read the boot sector into memory
CALL READBOOT
...
; Set FATID to double sided if "D" switch specified
TEST SWITCHMAP,10H
JNZ SETDBLSIDE
...
RET
DISKFORMAT:
...
; Use the bit map in SWITCHMAP to determine
; what switches are set
TEST SWITCHMAP,8 ;Is there a "/C"?
JNZ CLEAR ; Yes -- clear operation
; requested jump around the
; format code
< format the disk >
CLEAR:
...
; Transfer the boot from memory to the new disk
CALL TRANSBOOT
...
RET
; Error return - set carry
ERRET:
STC
RET
BADSECTOR:
...
RET
WRTFAT:
...
WRTFATLOOP:
< Set up call to write out a fat to disk>
...
MOV BX,[FATSPACE]
< Write out one fat to disk>
JC ERRET
...
< Decrement fat counter >
JNZ WRTFATLOOP
CLC ;Good return
RET
DONE:
...
RET
; Default Single sided
FATID DB 0FEH
HARDFLAG DB 0
STARTSECTOR DW 9
SWITCHLIST DB 5,"DCOVS" ; "OVS" must be the last
; switches in the list
FATSPACE DW FATBUF
FREESPACE DW ENDBOOT
BOOT DB BOOTSIZE DUP(?) ; Buffer for the
; boot sector
FATBUF DB 6 * 1024 DUP(?) ; Fat buffer
ENDBOOT LABEL BYTE
CODE ENDS
END
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+1645
View File
File diff suppressed because it is too large Load Diff
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+501
View File
@@ -0,0 +1,501 @@
TITLE HRDDRV.SYS for the ALTOS ACS-86C.
; Hard Disk Drive for Version 2.x of MSDOS.
; Constants for commands in Altos ROM.
ROM_CONSTA EQU 01 ;Return status AL of console selected in CX.
ROM_CONIN EQU 02 ;Get char. from console in CX to AL
ROM_CONOUT EQU 03 ;Write char. in DL to console in CX.
ROM_PMSG EQU 07 ;Write string ES:DX to console in CX.
ROM_DISKIO EQU 08 ;Perform disk I/O from IOPB in ES:CX.
ROM_INIT EQU 10 ;Returns boot console and top memory ES:DX.
CODE SEGMENT
ASSUME CS:CODE,DS:CODE,ES:CODE,SS:CODE
ORG 0 ;Starts at an offset of zero.
PAGE
SUBTTL Device driver tables.
;-----------------------------------------------+
; DWORD pointer to next device | 1 word offset.
; (-1,-1 if last device) | 1 word segement.
;-----------------------------------------------+
; Device attribute WORD ; 1 word.
; Bit 15 = 1 for chacter devices. ;
; 0 for Block devices. ;
; ;
; Charcter devices. (Bit 15=1) ;
; Bit 0 = 1 current sti device. ;
; Bit 1 = 1 current sto device. ;
; Bit 2 = 1 current NUL device. ;
; Bit 3 = 1 current Clock device. ;
; ;
; Bit 13 = 1 for non IBM machines. ;
; 0 for IBM machines only. ;
; Bit 14 = 1 IOCTL control bit. ;
;-----------------------------------------------+
; Device strategy pointer. ; 1 word offset.
;-----------------------------------------------+
; Device interrupt pointer. ; 1 word offset.
;-----------------------------------------------+
; Device name field. ; 8 bytes.
; Character devices are any valid name ;
; left justified, in a space filled ;
; field. ;
; Block devices contain # of units in ;
; the first byte. ;
;-----------------------------------------------+
DSKDEV: ;Header for hard disk driver.
DW -1,-1 ;Last device
DW 2000H ;Is a block device
DW STRATEGY
DW DSK_INT
MEMMAX DB 1 ;Number of Units
PAGE
SUBTTL Dispatch tables for each device.
DSK_TBL:DW DSK_INI ;0 - Initialize Driver.
DW MEDIAC ;1 - Return current media code.
DW GET_BPB ;2 - Get Bios Parameter Block.
DW CMDERR ;3 - Reserved. (currently returns error)
DW DSK_RED ;4 - Block read.
DW BUS_EXIT ;5 - (Not used, return busy flag)
DW EXIT ;6 - Return status. (Not used)
DW EXIT ;7 - Flush input buffer. (Not used.)
DW DSK_WRT ;8 - Block write.
DW DSK_WRV ;9 - Block write with verify.
DW EXIT ;10 - Return output status.
DW EXIT ;11 - Flush output buffer. (Not used.)
DW EXIT ;12 - IO Control.
PAGE
SUBTTL Strategy and Software Interrupt routines.
;Define offsets for io data packet
IODAT STRUC
CMDLEN DB ? ;LENGTH OF THIS COMMAND
UNIT DB ? ;SUB UNIT SPECIFIER
CMD DB ? ;COMMAND CODE
STATUS DW ? ;STATUS
DB 8 DUP (?)
MEDIA DB ? ;MEDIA DESCRIPTOR
TRANS DD ? ;TRANSFER ADDRESS
COUNT DW ? ;COUNT OF BLOCKS OR CHARACTERS
START DW ? ;FIRST BLOCK TO TRANSFER
IODAT ENDS
PTRSAV DD 0 ;Strategy pointer save.
;
; Simplistic Strategy routine for non-multi-Tasking system.
;
; Currently just saves I/O packet pointers in PTRSAV for
; later processing by the individual interrupt routines.
;
STRATP PROC FAR
STRATEGY:
MOV WORD PTR CS:[PTRSAV],BX
MOV WORD PTR CS:[PTRSAV+2],ES
RET
STRATP ENDP
;
; Ram memory driver interrupt routine for processing I/O packets.
;
DSK_INT:
PUSH SI ;Save SI from caller.
MOV SI,OFFSET DSK_TBL
;
; Common program for handling the simplistic I/O packet
; processing scheme in MSDOS 2.0
;
ENTRY: PUSH AX ;Save all nessacary registers.
PUSH CX
PUSH DX
PUSH DI
PUSH BP
PUSH DS
PUSH ES
PUSH BX
LDS BX,CS:[PTRSAV] ;Retrieve pointer to I/O Packet.
MOV AL,[BX.UNIT] ;AL = Unit code.
MOV AH,[BX.MEDIA] ;AH = Media descriptor.
MOV CX,[BX.COUNT] ;CX = Contains byte/sector count.
MOV DX,[BX.START] ;DX = Starting Logical sector.
XCHG DI,AX ;Save Unit and Media Temporarily.
MOV AL,[BX.CMD] ;Retrieve Command type. (1 => 11)
XOR AH,AH ;Clear upper half of AX for calculation.
ADD SI,AX ;Compute entry pointer in dispatch table.
ADD SI,AX
CMP AL,11 ;Verify that not more than 11 commands.
JA CMDERR ;Ah, well, error out.
XCHG AX,DI
LES DI,[BX.TRANS] ;DI contains addess of Transfer address.
;ES contains segment.
PUSH CS
POP DS ;Data segment same as Code segment.
JMP [SI] ;Perform I/O packet command.
PAGE
SUBTTL Common error and exit points.
BUS_EXIT: ;Device busy exit.
MOV AH,00000011B ;Set busy and done bits.
JMP SHORT EXIT1
CMDERR: MOV AL,3 ;Set unknown command error #.
;
; Common error processing routine.
; AL contains actual error code.
;
; Error # 0 = Write Protect violation.
; 1 = Unkown unit.
; 2 = Drive not ready.
; 3 = Unknown command in I/O packet.
; 4 = CRC error.
; 5 = Bad drive request structure length.
; 6 = Seek error.
; 7 = Unknown media discovered.
; 8 = Sector not found.
; 9 = Printer out of paper.
; 10 = Write fault.
; 11 = Read fault.
; 12 = General failure.
;
ERR_EXIT:
MOV AH,10000001B ;Set error and done bits.
STC ;Set carry bit also.
JMP SHORT EXIT1 ;Quick way out.
EXITP PROC FAR ;Normal exit for device drivers.
EXIT: MOV AH,00000001B ;Set done bit for MSDOS.
EXIT1: LDS BX,CS:[PTRSAV]
MOV [BX.STATUS],AX ;Save operation compete and status.
POP BX ;Restore registers.
POP ES
POP DS
POP BP
POP DI
POP DX
POP CX
POP AX
POP SI
RET ;RESTORE REGS AND RETURN
EXITP ENDP
PAGE
subttl Hard Disk drive control.
;
; Read command = 09 hex.
; Write command = 02 hex.
; Seek command = 10 hex.
; Recal command = 20 hex.
; Rezero command = 40 hex.
; Reset command = 80 hex.
;
; Busy = 01 hex.
; Operation Complete = 02 hex.
; Bad Sector = 04 hex.
; Record Not found = 08 hex.
; CRC error = 10 hex.
; (not used) = 20 hex.
; Write fault = 40 hex.
; Drive Ready = 80 hex.
;
hd_read equ 09h
hd_writ equ 02h
hd_wmsk equ 5dh
hd_rmsk equ 9ch
page
SUBTTL Altos monitor ram and 8089 IOPB structures.
;
; Structure to reference 8089 and ROM command table.
;
SIOPB STRUC
DB 4 DUP (?) ;Monitor Use Only
OPCODE DB ? ;I/O operation code.
DRIVE DB ? ;Logical drive spec.
TRACK DW ? ;Logical track number.
HEAD DB ? ;Logical head number.
SECTOR DB ? ;Logical sector to start with.
SCOUNT DB ? ;Number of logical sectors in buffer.
RETCODE DB ? ;Error code after masking.
RETMASK DB ? ;Error mask.
RETRIES DB ? ;Number of retries before error exit.
DMAOFF DW ? ;Buffer offset address.
DMASEG DW ? ;Buffer segment.
SECLENG DW ? ;Sector Length.
DB 6 DUP (?) ;8089 use only.
SIOPB ENDS
IOPB SIOPB <,0,0,0,0,0,0,0,0,0,0,0,0,>
PAGE
SUBTTL Common Drive parameter block definitions on Altos.
DBP STRUC
JMPNEAR DB 3 DUP (?) ;Jmp Near xxxx for boot.
NAMEVER DB 8 DUP (?) ;Name / Version of OS.
;------- Start of Drive Parameter Block.
SECSIZE DW ? ;Sector size in bytes. (dpb)
ALLOC DB ? ;Number of sectors per alloc. block. (dpb)
RESSEC DW ? ;Reserved sectors. (dpb)
FATS DB ? ;Number of FAT's. (dpb)
MAXDIR DW ? ;Number of root directory entries. (dpb)
SECTORS DW ? ;Number of sectors per diskette. (dpb)
MEDIAID DB ? ;Media byte ID. (dpb)
FATSEC DW ? ;Number of FAT Sectors. (dpb)
;------- End of Drive Parameter Block.
SECTRK DW ? ;Number of Sectors per track.
HEADS DW ? ;Number of heads per cylinder.
HIDDEN DW ? ;Number of hidden sectors.
DBP ENDS
HDDRIVE DBP <,,512,4,0,2,256,4000,0F5H,3,12,4,0>
INI_TAB DW OFFSET HDDRIVE.SECSIZE
PAGE
SUBTTL Media check routine
;
; Media check routine.
; On entry:
; AL = memory driver unit number.
; AH = media byte
; On exit:
;
; [MEDIA FLAG] = -1 (FF hex) if disk is changed.
; [MEDIA FLAG] = 0 if don't know.
; [MEDIA FLAG] = 1 if not changed.
;
MEDIAC: LDS BX,CS:[PTRSAV]
MOV BYTE PTR [BX.TRANS],1
JMP EXIT
PAGE
SUBTTL Build and return Bios Parameter Block for a diskette.
;
; Build Bios Parameter Blocks.
;
; On entry: ES:BX contains the address of a scratch sector buffer.
; AL = Unit number.
; AH = Current media byte.
;
; On exit: Return a DWORD pointer to the associated BPB
; in the Request packet.
;
GET_BPB:
MOV SI,OFFSET HDDRIVE+11
LDS BX,CS:[PTRSAV]
MOV WORD PTR [BX.COUNT],SI
MOV WORD PTR [BX.COUNT+2],CS
JMP EXIT
PAGE
SUBTTL MSDOS 2.x Disk I/O drivers.
;
; Disk READ/WRITE functions.
;
; On entry:
; AL = Disk I/O driver number
; AH = Media byte.
; ES = Disk transfer segment.
; DI = Disk transfer offset in ES.
; CX = Number of sectors to transfer
; DX = Logical starting sector.
;
; On exit:
; Normal exit through common exit routine.
;
; Abnormal exit through common error routine.
;
DSK_RED:
MOV AH,HD_READ
JMP SHORT DSK_COM
DSK_WRV:
DSK_WRT:
MOV AH,HD_WRIT
DSK_COM:
MOV SI,OFFSET HDDRIVE ;Keeps code size down.
MOV [IOPB.DMASEG],ES
MOV [IOPB.DMAOFF],DI
MOV DI,[SI.SECSIZE]
MOV [IOPB.SECLENG],DI
MOV [IOPB.RETRIES],1
MOV [IOPB.RETMASK],05DH ;Error return mask.
MOV [IOPB.OPCODE],AH
MOV [IOPB.DRIVE],4 ;Drive 4 is only available.
ADD DX,[SI.HIDDEN] ;Account for invisible sectors.
MOV BP,CX ;Save number of sectors to R/W
DSK_IO1:
PUSH DX ;Save starting sector.
MOV AX,DX
MOV DX,0 ;32 bit divide coming up.
MOV CX,[SI.SECTRK]
DIV CX ;Get track+head and start sector.
MOV [IOPB.SECTOR],DL ;Starting sector.
MOV BL,DL ;Save starting sector for later.
MOV DX,0
MOV CX,[SI.HEADS]
DIV CX ;Compute head we are on.
MOV [IOPB.HEAD],DL
MOV [IOPB.TRACK],AX ;Track to read/write.
MOV AX,[SI.SECTRK] ;Now see how many sectors
INC AL ; we can burst read.
SUB AL,BL ;BL is the starting sector.
MOV AH,0
POP DX ;Retrieve logical sector start.
CMP AX,BP ;See if on last partial track+head.
JG DSK_IO2 ;Yes, on last track+head.
SUB BP,AX ;No, update number of sectors left.
ADD DX,AX ;Update next starting sector.
JMP SHORT DSK_IO3
DSK_IO2:MOV AX,BP ;Only read enough of sector
MOV BP,0 ;to finish buffer and clear # left.
DSK_IO3:MOV [IOPB.SCOUNT],AL
MOV DI,AX ;Save number sectors for later.
MOV BX,ROM_DISKIO
MOV CX,OFFSET IOPB
PUSH CS
POP ES
CALL ROM_CALL ;Do disk operation.
MOV AL,[IOPB.RETCODE] ;Get error code.
OR AL,AL
JNZ DERROR
MOV AX,DI ;Retrieve number of sectors read.
MOV CX,[SI.SECSIZE] ;Number of bytes per sector.
PUSH DX
MUL CX
POP DX
TEST AL,0FH ;Make sure no strange sizes.
JNZ SERR1
MOV CL,4
SHR AX,CL ;Convert number of bytes to para.
ADD AX,[IOPB.DMASEG]
MOV [IOPB.DMASEG],AX
OR BP,BP
JNZ DSK_IO1 ;Still more to do.
MOV AL,0
JMP EXIT ;All done.
SERR1: MOV AL,12
JMP ERR_EXIT
PAGE
SUBTTL Disk Error processing.
;
; Disk error routine.
;
DERROR:
LDS BX,CS:[PTRSAV]
MOV [BX.COUNT],0
PUSH CS
POP DS
MOV BL,-1
MOV AH,AL
MOV BH,14 ;Lenght of table.
MOV SI,OFFSET DERRTAB
DERROR2:INC BL ;Increment to next error code.
LODS BYTE PTR CS:[SI]
CMP AH,AL ;See if error code matches disk status.
JZ DERROR3 ;Got the right error, exit.
DEC BH
JNZ DERROR2 ;Keep checking table.
MOV BL,12 ;Set general type of error.
DERROR3:MOV AL,BL ;Now we've got the code.
JMP ERR_EXIT
DERRTAB DB 00H ; 0. Write protect error
DB 00H ; 1. Unknown unit.
DB 00H ; 2. Not ready error.
DB 00H ; 3. Unknown command.
DB 10H ; 4. CRC error
DB 00H ; 5. Bad drive request.
DB 00H ; 6. Seek error
DB 00H ; 7. Unknown media.
DB 08H ; 8. Sector not found
DB 00H ; 9. (Not used.)
DB 40H ;10. Write fault.
DB 04H ;11. Read fault.
DB 01H ;12. General type of failure.
PAGE
SUBTTL Common ROM call routine.
;
; Save all registers except CX, BX and AX.
ROMRTN DD 0FE000000H ;Main ROM entry point.
ROM_CALL:
PUSH DI
PUSH SI
PUSH BP
PUSH DX
PUSH ES
CALL CS:DWORD PTR [ROMRTN]
POP ES
POP DX
POP BP
POP SI
POP DI
RET
PAGE
SUBTTL Hard Disk Drive initalization routine.
DSK_INI:
LDS BX,CS:[PTRSAV]
MOV BYTE PTR [BX.MEDIA],1
MOV WORD PTR [BX.TRANS],OFFSET DSK_INI
MOV WORD PTR [BX.TRANS+2],CS
MOV WORD PTR [BX.COUNT],OFFSET INI_TAB
MOV WORD PTR [BX.COUNT+2],CS
JMP EXIT
CODE ENDS
END

BIN
View File
Binary file not shown.
+705
View File
@@ -0,0 +1,705 @@
TITLE PROFIL - MS-DOS Profile program
;Profiler for MS-DOS 1.25 2.00
;
; Lots of stuff stolen from debug.
; User provides # of paragraphs per bucket, program is cut up accordingly.
; User also specifies clock interval
;System calls
PRINTBUF EQU 9
SETDMA EQU 26
CREATE EQU 22
OPEN EQU 15
CLOSE EQU 16
GETBUF EQU 10
BLKWRT EQU 40
BLKRD EQU 39
OUTCH EQU 2
SETBASE EQU 38
FCB EQU 5CH
BUFLEN EQU 80
; FCB offsets
RR EQU 33
RECLEN EQU 14
FILELEN EQU 16
;Segments in load order
CODE SEGMENT PUBLIC
CODE ENDS
DATA SEGMENT BYTE
DATA ENDS
INIT SEGMENT BYTE
INIT ENDS
DG GROUP CODE,DATA,INIT
;The data segment
DATA SEGMENT BYTE
ORG 0
ENDMES DB 13,10,"Program terminated normally",13,10,"$"
ABORTMES DB 13,10,"Program aborted",13,10,"$"
TOOBIG DB "Program too big",13,10,"$"
EXEBAD DB "EXE file bad",13,10,"$"
OUT_FCB LABEL WORD
DB 0
OUTNAME DB " PRF"
DB 30 DUP(0)
DB 80H DUP(?)
STACK LABEL WORD
BYTEBUF DB BUFLEN DUP(?) ;Processed input queue
AXSAVE DW ? ;See interrupt routine
BXSAVE DW ? ; " " "
PROG_AREA DW ? ;Segment of program start
;EXE file header
RUNVAR LABEL WORD
RELPT DW ?
LASTP LABEL WORD
RELSEG DW ?
PSIZE LABEL WORD
PAGES DW ?
RELCNT DW ?
HEADSIZ DW ?
DW ?
LOADLOW DW ?
PROG_SS LABEL WORD ;Program stack seg
INITSS DW ?
PROG_SP LABEL WORD ;Program SP
INITSP DW ?
DW ?
PROG_ENTRY EQU THIS DWORD
PROG_RA LABEL WORD ;Program start offset
INITIP DW ?
PROG_SA LABEL WORD ;Program start segment (may be different from PROG_AREA)
INITCS DW ?
RELTAB DW ?
RUNVARSIZ EQU $-RUNVAR
EXEFILE DB 0 ;Flag to indicate EXE file
DRV_VALID DW ? ;Init for AX register
OUTPUT_DATA LABEL WORD ;Start of the profile data
CLOCK_GRAIN DW ? ;Clock interval micro-seconds
BUCKET_NUM DW ? ;Number of buckets
BUCKET_SIZE DW ? ;Paragraphs per bucket
PROG_LOW_PA DW ? ;Start of program (PARA #)
PROG_HIGH_PA DW ? ;End of program (PARA #)
DOS_PA DW ? ;IO-DOS PARA boundry
HIT_IO DW 0 ;IO bucket
HIT_DOS DW 0 ;DOS bucket
HIT_HIGH DW 0 ;Above Program bucket
NUM_DATA_WORDS EQU ($-OUTPUT_DATA)/2 ;Number of word items
BUCKET LABEL WORD ;Bucket count area
;The following data will be overwritten when the buckets are initialized
LINEBUF DB BUFLEN,1,0DH ;Raw input buffer
DB BUFLEN DUP(?)
NOFILE DB "File not found",13,10,"$"
OUTERR DB "Cannot open output file",13,10,"$"
GRAIN_PROMPT DB "Sample time (micro-sec) >= 60 ? ","$"
SIZE_PROMPT DB "Number of paragraphs (16 bytes) per bucket? ","$"
PARAM_PROMPT DB "Parameters to program? ","$"
DATA ENDS
;The resident code portion
CODE SEGMENT PUBLIC
ASSUME CS:DG,DS:DG,ES:DG,SS:DG
;The clock interrupt routine
PUBLIC CLK_INTER
;Stuff provided by external clock handler routine
EXTRN CLOCKON:NEAR,CLOCKOFF:NEAR,LEAVE_INT:NEAR
ORG 100H
START:
CLD
MOV SP,OFFSET DG:STACK ;Use internal stack
CALL SETUP
;The following setup stuff cannot be done in SETUP because we're probably
; overwritting the INIT area
MOV DX,[PROG_AREA]
MOV AH,SETBASE
INT 21H ;Set base for program
MOV ES,[PROG_AREA]
PUSH SI ;Points to BYTEBUF
MOV DI,81H ;Set unformatted params
COMTAIL:
LODSB
STOSB
CMP AL,13
JNZ COMTAIL
SUB DI,82H ;Figure length
XCHG AX,DI
MOV BYTE PTR ES:[80H],AL
POP SI
MOV DI,FCB ;First param
MOV AX,2901H
INT 21H
MOV BYTE PTR [DRV_VALID],AL
MOV AX,2901H
MOV DI,6CH ;Second param
INT 21H
MOV BYTE PTR [DRV_VALID+1],AL
MOV AX,ES ;Prog segment to AX
MOV DX,[PROG_RA] ;Offset
CMP [EXEFILE],1
JZ EXELOAD ;EXE file
JMP BINFIL ;Regular file (.COM)
EXELOAD:
MOV AX,[HEADSIZ] ;Size of header in paragraphs
ADD AX,31
MOV CL,4
ROL AX,CL ;Size in bytes
MOV BX,AX
AND AX,0FE00H
AND BX,0FH
MOV WORD PTR DS:[FCB+RR],AX ;Position in file of program
MOV WORD PTR DS:[FCB+RR+2],BX ;Record size
MOV DX,[PAGES] ;Size in 512 byte blocks
DEC DX
XCHG DH,DL
ROL DX,1
MOV DI,DX
MOV SI,DX
AND DI,0FE00H
AND SI,1FFH
SUB DI,AX
SBB SI,BX
MOV AX,[LASTP]
OR AX,AX
JNZ PARTP
MOV AX,200H
PARTP:
ADD DI,AX
ADC SI,0
MOV AX,DI
ADD AX,15
AND AL,0F0H
OR AX,SI
MOV CL,4
ROR AX,CL
XCHG AX,CX
MOV BX,[PROG_AREA]
ADD BX,10H
MOV AX,WORD PTR DS:[2]
SUB AX,CX
MOV DX,OFFSET DG:TOOBIG
JB ERROR
CMP BX,AX
JA ERROR
CMP [LOADLOW],-1
JNZ LOADEXE
XCHG AX,BX
LOADEXE:
MOV BP,AX
XOR DX,DX
CALL READ
JC HAVEXE
BADEXE:
MOV DX,OFFSET DG:EXEBAD
ERROR:
MOV AH,PRINTBUF ;Print the message in DX
INT 21H
INT 20H ;Exit
HAVEXE:
MOV AX,[RELTAB] ;Get position of relocation table
MOV WORD PTR DS:[FCB+RR],AX
MOV WORD PTR DS:[FCB+RR+2],0
MOV DX,OFFSET DG:RELPT ;Four byte buffer
MOV AH,SETDMA
INT 21H
CMP [RELCNT],0
JZ NOREL
RELOC:
MOV AH,BLKRD
MOV DX,FCB
MOV CX,4
INT 21H ;Read in one relocation pointer
OR AL,AL
JNZ BADEXE
MOV DI,[RELPT] ;Pointer offset
MOV AX,[RELSEG] ;pointer segment
ADD AX,BP ;Bias with actual load segment
MOV ES,AX
ADD ES:[DI],BP ;Relocate
DEC [RELCNT]
JNZ RELOC
NOREL:
ADD [INITSS],BP
ADD [INITCS],BP
JMP SHORT PROGGO
BINFIL:
MOV WORD PTR DS:[FCB+RECLEN],1
MOV SI,-1
MOV DI,SI
CALL READ
MOV ES,[PROG_SA] ;Prog segment to ES
MOV AX,WORD PTR ES:[6]
MOV [PROG_SP],AX ;Default SP for non EXE files
DEC AH
MOV WORD PTR ES:[6],AX ;Fix size
PROGGO:
PUSH DS
MOV AX,[PROG_AREA]
MOV DS,AX
MOV DX,80H
MOV AH,SETDMA
INT 21H ;Set default disk transfer address
POP DS
MOV BX,[BUCKET_NUM]
SHL BX,1 ;Mult by 2 to get #bytes in bucket area
CLEAR:
MOV BUCKET[BX],0 ;Zero counts
SUB BX,2
JGE CLEAR
MOV DX,[CLOCK_GRAIN]
PUSH DS
POP ES
CLI ;Don't collect data yet
CALL CLOCKON ;Set the interrupt
MOV SI,[PROG_RA]
MOV DI,[PROG_AREA]
MOV BX,[PROG_SS]
MOV CX,[PROG_SP]
MOV AX,[DRV_VALID]
MOV DX,[PROG_SA]
MOV SS,BX
MOV SP,CX
XOR CX,CX
PUSH CX ;0 on prog stack
PUSH DX
PUSH SI
MOV DS,DI ;Set up segments
MOV ES,DI
STI ;Start collecting data
XXX PROC FAR
RET ;Hop to program
XXX ENDP
READ:
; AX:DX is disk transfer address (segment:offset)
; SI:DI is 32 bit length
RDLOOP:
MOV BX,DX
AND DX,000FH
MOV CL,4
SHR BX,CL
ADD AX,BX
PUSH AX
PUSH DX
PUSH DS
MOV DS,AX
MOV AH,SETDMA
INT 21H
POP DS
MOV DX,FCB
MOV CX,0FFF0H ;Keep request in segment
OR SI,SI ;Need > 64K?
JNZ BIGRD
MOV CX,DI ;Limit to amount requested
BIGRD:
MOV AH,BLKRD
INT 21H
SUB DI,CX ;Subtract off amount done
SBB SI,0 ;Ripple carry
CMP AL,1 ;EOF?
POP DX
POP AX ;Restore transfer address
JZ RET10
ADD DX,CX ;Bump transfer address by last read
MOV BX,SI
OR BX,DI ;Finished with request
JNZ RDLOOP
RET10: STC
RET
;Return here on termination or abort
TERMINATE:
CLI ;Stop collecting data
MOV DX,OFFSET DG:ENDMES
JMP SHORT WRITEOUT
ABORT:
CLI ;Stop collecting data
MOV DX,OFFSET DG:ABORTMES
WRITEOUT:
MOV AX,CS
MOV DS,AX
MOV SS,AX
MOV SP,OFFSET DG:STACK ;Use internal stack
PUSH DX
CALL CLOCKOFF ;Restore original clock routine
STI ;Back to normal clock
POP DX
MOV AH,PRINTBUF
INT 21H ;Apropriate termination message
MOV [OUT_FCB+14],2 ;Word size records
MOV DX,OFFSET DG:OUTPUT_DATA
MOV AH,SETDMA
INT 21H ;Set the transfer address
MOV CX,NUM_DATA_WORDS
ADD CX,[BUCKET_NUM]
MOV DX,OFFSET DG:OUT_FCB
MOV AH,BLKWRT
INT 21H ;Write out data
MOV DX,OFFSET DG:OUT_FCB
MOV AH,CLOSE
INT 21H
INT 20H ;Exit
;The clock interrupt routine
CLK_INTER PROC NEAR
CLI
PUSH DS
PUSH CS
POP DS ;Get profile segment
MOV [AXSAVE],AX
MOV [BXSAVE],BX
POP AX ;old DS
MOV BX,OFFSET DG:LEAVE_INT
PUSH BX
PUSH AX
PUSH ES
PUSH [AXSAVE]
PUSH [BXSAVE]
PUSH CX
PUSH DX
;Stack looks like this
;
; +18 OLDFLAGS
; +16 OLDCS
; +14 OLDIP
; +12 RETURN TO LEAVE_INT
; +10 OLDDS
; +8 OLDES
; +6 OLDAX
; +4 OLDBX
; +2 OLDCX
;SP-> OLDDX
MOV BX,SP
LES BX,DWORD PTR SS:[BX+14] ;Get CS:IP
MOV AX,BX
MOV CL,4
SHR AX,CL
MOV CX,ES
ADD AX,CX ;Paragraph of CS:IP
CMP AX,[DOS_PA] ;Below DOS?
JB IOHIT
CMP AX,[PROG_LOW_PA] ;Below program?
JB DOSHIT
CMP AX,[PROG_HIGH_PA] ;Above program?
JAE MISSH
SUB AX,[PROG_LOW_PA] ;Paragraph offset
XOR DX,DX
DIV [BUCKET_SIZE]
MOV BX,AX
SHL BX,1 ;Mult by 2 to get byte offset
INC BUCKET[BX]
JMP SHORT DONE
IOHIT:
INC [HIT_IO]
JMP SHORT DONE
DOSHIT:
INC [HIT_DOS]
JMP SHORT DONE
MISSH:
INC [HIT_HIGH]
DONE:
POP DX
POP CX
POP BX
POP AX
POP ES
POP DS
STI
RET ;To LEAVE_INT
CLK_INTER ENDP
CODE ENDS
;The init segment contains code to process input parameters
; It will be blasted as soon as the program to be run is read in
; And/or the bucket area is initialized
INIT SEGMENT BYTE
ORG 0
SETUP:
MOV DX,FCB
MOV AH,OPEN
INT 21H ;Open program file
AND AL,AL
JZ OPENOK
MOV DX,OFFSET DG:NOFILE
JMP ERROR
OPENOK:
XOR BX,BX
MOV WORD PTR DS:[FCB+RR],BX
MOV WORD PTR DS:[FCB+RR+2],BX ;RR to 0
MOV SI,FCB
MOV DI,OFFSET DG:OUT_FCB
MOV CX,4
REP MOVSW
MOVSB ;Transfer drive spec and file to output
MOV DX,OFFSET DG:OUT_FCB
MOV AH,CREATE
INT 21H ;Try to create the output file
AND AL,AL
JZ GETSIZE
MOV DX,OFFSET DG:OUTERR
JMP ERROR
GETSIZE: ;Get bucket size
MOV DX,OFFSET DG:SIZE_PROMPT
MOV AH,PRINTBUF
INT 21H
CALL INBUF
CALL SCANB
JZ GETSIZE ;SCANB went to CR
XOR BX,BX
INC BX ;Size >=1
CALL GETNUM
JC GETSIZE ;Bad number
MOV [BUCKET_SIZE],DX
CMP WORD PTR DS:[FCB+9],5800H+"E" ;"EX"
JNZ NOTEXE
CMP BYTE PTR DS:[FCB+11],"E"
JNZ NOTEXE
LOADEXEHEAD: ;Load the EXE header
MOV [EXEFILE],1
MOV DX,OFFSET DG:RUNVAR ;Read header in here
MOV AH,SETDMA
INT 21H
MOV CX,RUNVARSIZ
MOV DX,FCB
MOV WORD PTR DS:[FCB+RECLEN],1
OR AL,AL
MOV AH,BLKRD
INT 21H
CMP [RELPT],5A4DH ;Magic number
JZ EXEOK
JMP BADEXE
EXEOK:
MOV AX,[PAGES] ;Size of file in 512 byte blocks
MOV CL,5
SHL AX,CL ;Size in paragraphs
JMP SHORT SETBUCKET
NOTEXE:
MOV AX,WORD PTR DS:[FCB+FILELEN]
MOV DX,WORD PTR DS:[FCB+FILELEN+2] ;Size of file in bytes DX:AX
ADD AX,15
ADC DX,0 ;Round to PARA
MOV CL,4
SHR AX,CL
AND AX,0FFFH
MOV CL,12
SHL DX,CL
AND DX,0F000H
OR AX,DX ;Size in paragraphs to AX
MOV [PROG_RA],100H ;Default offset
SETBUCKET:
PUSH AX ;Save size
XOR DX,DX
DIV [BUCKET_SIZE]
INC AX ;Round up
MOV [BUCKET_NUM],AX
MOV BX,OFFSET DG:BUCKET
SHL AX,1 ;Number of bytes in bucket area
ADD AX,BX ;Size of profil in bytes
ADD AX,15 ;Round up to PARA boundry
MOV CL,4
SHR AX,CL ;Number of paragraphs in profil
INC AX ;Insurance
MOV BX,CS
ADD AX,BX
MOV [PROG_AREA],AX
CMP [EXEFILE],1
JZ SETBOUNDS
MOV AX,[PROG_AREA] ;Set up .COM segments
MOV [PROG_SS],AX
MOV [PROG_SA],AX
SETBOUNDS: ;Set the sample window
MOV BX,10H ;Get start offset
ADD BX,[PROG_AREA] ;PARA # of start
MOV [PROG_LOW_PA],BX
POP AX ;Recall size of PROG in paragraphs
ADD BX,AX
MOV [PROG_HIGH_PA],BX
SETDOS:
XOR DX,DX
MOV ES,DX ;look in interrupt area
MOV DX,WORD PTR ES:[82H] ;From int #20
MOV [DOS_PA],DX
PUSH DS
POP ES
GETGRAIN: ;Get sample interval
MOV DX,OFFSET DG:GRAIN_PROMPT
MOV AH,PRINTBUF
INT 21H
CALL INBUF
CALL SCANB
JZ GETGRAIN ;SCANB went to CR
MOV BX,60 ;Grain >=60
CALL GETNUM
JC GETGRAIN ;Bad number
MOV [CLOCK_GRAIN],DX
MOV DX,OFFSET DG:PARAM_PROMPT
MOV AH,PRINTBUF
INT 21H
CALL INBUF ;Get program parameters
MOV AX,2522H ;Set vector 22H
MOV DX,OFFSET DG:TERMINATE
INT 21H
MOV AL,23H ;Set vector 23H
MOV DX,OFFSET DG:ABORT
INT 21H
RET ;Back to resident code
GETNUM: ;Get a number, DS:SI points to buffer, carry set if bad
XOR DX,DX
MOV CL,0
LODSB
NUMLP:
SUB AL,"0"
JB NUMCHK
CMP AL,9
JA NUMCHK
CMP DX,6553
JAE BADNUM
MOV CL,1
PUSH BX
MOV BX,DX
SHL DX,1
SHL DX,1
ADD DX,BX
SHL DX,1
CBW
POP BX
ADD DX,AX
LODSB
JMP NUMLP
NUMCHK:
CMP CL,0
JZ BADNUM
CMP BX,DX
JA BADNUM
CLC
RET
BADNUM:
STC
RET
INBUF: ;Read in from console, SI points to start on exit
MOV AH,GETBUF
MOV DX,OFFSET DG:LINEBUF
INT 21H
MOV SI,2 + OFFSET DG:LINEBUF
MOV DI,OFFSET DG:BYTEBUF
CASECHK:
LODSB
CMP AL,'a'
JB NOCONV
CMP AL,'z'
JA NOCONV
ADD AL,"A"-"a" ;Convert to upper case
NOCONV:
STOSB
CMP AL,13
JZ INDONE
CMP AL,'"'
JNZ QUOTSCAN
CMP AL,"'"
JNZ CASECHK
QUOTSCAN:
MOV AH,AL
KILLSTR:
LODSB
STOSB
CMP AL,13
JZ INDONE
CMP AL,AH
JNZ KILLSTR
JMP SHORT CASECHK
INDONE:
MOV SI,OFFSET DG:BYTEBUF
;Output CR/LF
CRLF:
MOV AL,13
CALL OUT
MOV AL,10
OUT:
PUSH AX
PUSH DX
AND AL,7FH
XCHG AX,DX
MOV AH,OUTCH
INT 21H
POP DX
POP AX
RET
SCANB: ;Scan to first non-blank
PUSH AX
SCANNEXT:
LODSB
CMP AL," "
JZ SCANNEXT
CMP AL,9
JZ SCANNEXT
DEC SI
POP AX
EOLCHK:
CMP BYTE PTR[SI],13
RET
INIT ENDS
END START
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+35
View File
@@ -0,0 +1,35 @@
PROHST is a preliminary version of a utility to process the profile
file produced by the PROFIL utility of MSDOS.
Those of you familiar with MS-Pascal or MS-Fortran will have little
difficulty in understanding how the parameters work. There are three,
the .PRF filename, an optional histogram file (default extension .HST,
default name same as the .PRF file) and an optional link map. If the
link map was produced with the line number options PROHST will try
and relate buckets to line numbers. Otherwise, it will relate it to
module offsets. If you specify no map file (the default), addresses
relative to the start of the program will be used. The default extension
for the map file is .MAP.
a:prohst f;
this will produce a histogram for the file f.prf in f.hst and no map file
will be assumed.
a:prohst f,,;
this will produce a histogram for f.prf in f.hst and expects a f.map file.
a:prohst f,g,k
this produces a histogram for f.prf in g.hst and expects a map file k.map.
Note that if you select the map option with line numbers, the program will
appear to be looping. Never fear, go and have lunch or some other time
consuming pastime, and you will be suprised how long it took to produce
such a small file. Also, some of the line number/bucket correspondances are
not what they might be. Future version shoudl fix this. If you make a better
version, be sure to let me have a copy.
David Jones.

+403
View File
@@ -0,0 +1,403 @@
PROGRAM prohst(input,output);
{$debug- $line- $symtab+}
{**********************************************************************}
{* *}
{* prohst *}
{* *}
{* This program produces a histogram from the profile file produced *}
{* by the MS-DOS profile utility. It optionally reads the map file *}
{* generated when the program being profiled was linked, and writes *}
{* either the module address or, if available, the line number as *}
{* a prefix to the line of the graph which describes a particular *}
{* bucket. *}
{* *}
{* After using filbm (derived from the Pascal and Fortran front end *}
{* command scanner) to parse its parameters, prohst opens the map *}
{* file if specified, searches for the heading line, and then reads *}
{* the lines giving the names and positions of the modules. It builds *}
{* a linked list of module names and start addresses. *}
{* *}
{* It then reads the bucket file header and and bucket array elements *}
{* into a variable created on the heap. It simultaneously calculates *}
{* a normalization factor. It writes the profile listing header and *}
{* starts to write the profile lines. For each bucket, the address *}
{* is calculated. The first entry in the address/name linked list *}
{* is the lowest addressed module. This is initially the 'current' *}
{* module. The bucket address is compared with the current module *}
{* address. When it becomes the greater, the module name is written *}
{* to the listing and the next entry in the address/name list becomes *}
{* the current module. If line numbers are available, the bucket *}
{* address is also compared to the current line/address. This is *}
{* read and calculated directly from the file. Since there may be *}
{* more than one line per bucket, several entries may be read until *}
{* the addresses compare within the span of addresses encompassed by *}
{* a bucket (its 'width'). Note that the idiosyncracies of Pascal i/o *}
{* make it necessary to continually check for the end of the map file *}
{* and the complexity of this code is mainly due to an attempt to *}
{* make it reasonably resilient to changes in the format of the map *}
{* file. *}
{* *}
{**********************************************************************}
CONST
max_file = 32;
TYPE
filenam = LSTRING (max_file);
sets = SET OF 0..31;
address_pointer = ^address_record;
address_record = RECORD
next: address_pointer;
name: STRING (15);
address: WORD;
END;
VAR
i: INTEGER;
bucket: FILE OF WORD;
hist: TEXT;
map: TEXT;
first_address,
this_address: address_pointer;
current_base: WORD;
bucket_name,
hist_name,
map_name: filenam;
switches: sets;
line: LSTRING (100);
map_avail: BOOLEAN;
line_nos_avail: BOOLEAN;
norm: REAL;
per_cent: INTEGER;
real_bucket,
norm_bucket: REAL;
cum_per_cent,
real_per_cent: REAL;
bucket_num,
clock_grain,
bucket_size,
prog_low_pa,
prog_high_pa,
dos_pa,
hit_io,
hit_dos,
hit_high: WORD;
seg,
offset,
parcel: WORD;
address: WORD;
new_line_no,
line_no: WORD;
dummy : LSTRING (8);
name: LSTRING (20);
line_no_part: LSTRING (17);
start: LSTRING (6);
buckets: ^SUPER ARRAY [1 .. *] OF REAL;
this_bucket: WORD;
LABEL 1;
PROCEDURE filbm (VAR prffil, hstfil, mapfil: filenam;
VAR switches: sets); EXTERN;
FUNCTION realword (w: WORD): REAL;
BEGIN
IF ORD (w) < 0 THEN BEGIN
realword := FLOAT (maxint) + FLOAT (ORD (w - maxint));
END
ELSE BEGIN
realword := FLOAT (ORD(w));
END {IF};
END {realword};
PROCEDURE skip_spaces;
BEGIN
WHILE NOT eof(map) AND THEN map^ = ' ' DO BEGIN
get (map);
END {WHILE};
END {skip_spaces};
FUNCTION hex_char (ch: CHAR): WORD;
BEGIN
IF ch >= '0' AND THEN ch <= '9' THEN BEGIN
hex_char := WRD (ch) - WRD ('0');
END
ELSE IF ch >= 'A' AND THEN ch <= 'F' THEN BEGIN
hex_char := WRD (ch) - WRD ('A') + 10;
END
ELSE BEGIN
WRITELN ('Invalid hex character');
hex_char := 0;
END {IF};
END {hex_char};
FUNCTION read_hex (i :WORD): WORD;
VAR
hex_val: WORD;
BEGIN
skip_spaces;
hex_val := 0;
WHILE NOT eof (map) AND THEN i <> 0 DO BEGIN
hex_val := hex_val * 16 + hex_char (map^);
GET (map);
i := i - 1;
END {WHILE};
read_hex := hex_val;
END {read_hex};
FUNCTION read_h: WORD;
BEGIN
read_h := read_hex (4);
get (map);
get (map);
END;
FUNCTION read_word: WORD;
VAR
int_value: WORD;
BEGIN
int_value := 0;
IF NOT EOF (map) THEN BEGIN
READ (map, int_value);
END {IF};
read_word := int_value;
END {read_word};
FUNCTION map_digit: BOOLEAN;
BEGIN
map_digit := (map^ >= '0') OR (map^ <= '9');
END {map_digit};
BEGIN {prohst}
writeln (output, ' Profile Histogram Utility - Version 1.0');
writeln (output);
writeln (output, ' Copyright - Microsoft, 1983');
start := ' ';
filbm (bucket_name, hist_name, map_name, switches);
IF 31 IN switches THEN BEGIN
ABORT ('Map file must not be terminal', 0, 0);
END {IF};
IF NOT (28 IN switches) THEN BEGIN
ABORT ('No histogram file specified', 0, 0);
END {IF};
ASSIGN (bucket, bucket_name);
reset (bucket);
ASSIGN (hist, hist_name);
rewrite (hist);
map_avail := 29 IN switches;
line_nos_avail := FALSE;
IF map_avail THEN BEGIN
ASSIGN (map, map_name);
RESET (map);
WHILE NOT EOF (map) AND THEN start <> ' Start' DO BEGIN
READLN (map, start);
END {WHILE};
NEW (first_address);
this_address := NIL;
WHILE NOT EOF(map) DO BEGIN
READLN (map, line);
IF line.len < 6 OR ELSE line [2] < '0' OR ELSE
line [2] > '9' THEN BEGIN
BREAK;
END {IF};
IF this_address <> NIL THEN BEGIN
NEW (this_address^.next);
this_address := this_address^.next;
END
ELSE BEGIN
this_address := first_address;
END {IF};
this_address^.next := NIL;
this_address^.address := (hex_char (line [2]) * 4096) +
(hex_char (line [3]) * 256) +
(hex_char (line [4]) * 16) +
hex_char (line [5]);
FOR i := 1 TO 15 DO BEGIN
this_address^.name [i] := line [22 + i];
END {FOR};
END {WHILE};
WHILE NOT EOF (map) DO BEGIN
READLN (map, line_no_part);
IF line_no_part = 'Line numbers for ' THEN BEGIN
line_nos_avail := TRUE;
BREAK;
END {IF};
END {WHILE};
END {IF};
read (bucket, clock_grain, bucket_num, bucket_size,
prog_low_pa, prog_high_pa, dos_pa, hit_io, hit_dos, hit_high);
NEW (buckets,ORD (bucket_num));
norm := 0.0;
norm_bucket := 0.0;
FOR i := 1 TO ORD (bucket_num) DO BEGIN
read (bucket, this_bucket);
real_bucket := realword (this_bucket);
IF real_bucket > norm_bucket THEN BEGIN
norm_bucket := real_bucket;
END {IF};
norm := norm + real_bucket;
buckets^[i] := real_bucket;
END {FOR};
norm_bucket := 45.0/norm_bucket;
norm := 100.0/norm;
WRITELN (hist, 'Microsoft Profiler Output Listing');
WRITELN (hist);
WRITELN (hist, ORD (bucket_num):6, bucket_size:4,'-byte buckets.');
WRITELN (hist);
WRITELN (hist, 'Profile taken between ', prog_low_pa*16::16,
' and ', prog_high_pa*16::16, '.');
WRITELN (hist);
WRITELN (hist, 'DOS program address:', dos_pa::16);
WRITELN (hist);
WRITELN (hist, 'Number of hits in DOS: ', hit_dos:5,
' or ', realword (hit_dos) * norm:4:1, '%.');
WRITELN (hist, 'Number of hits in I/O: ', hit_io:5,
' or ', realword (hit_io) * norm:4:1, '%.');
WRITELN (hist, 'Number of hits high : ', hit_high:5,
' or ', realword (hit_high) * norm:4:1, '%.');
WRITELN (hist);
WRITELN (hist, ' Hits Addr. Line/ Cumul. % 0.0 ',
' ',
1.0/norm:1:1);
WRITELN (hist, ' Offset +----------------',
'----------------------------');
WRITELN (hist, name);
i := 0;
parcel := 0;
current_base := 0;
line_no := 0;
new_line_no := 0;
cum_per_cent := 0.0;
WHILE i < ORD (bucket_num) DO BEGIN
i := i + 1;
IF buckets^[i] < 0.9 THEN BEGIN
WRITELN (hist);
REPEAT
i := i + 1;
UNTIL (i = ORD (bucket_num)) OR ELSE buckets^[i] > 0.0;
END {IF};
address := bucket_size * (WRD (i) - 1);
WHILE map_avail AND THEN
address >= first_address^.address DO BEGIN
WRITELN (hist, ' ', first_address^.name);
current_base := first_address^.address;
first_address := first_address^.next;
END {WHILE};
WHILE line_nos_avail AND THEN NOT eof (map) AND THEN
address >= parcel DO BEGIN
skip_spaces;
WHILE (map^ < '0') OR (map^ > '9') DO BEGIN
IF EOF (map) THEN BEGIN
goto 1;
END {IF};
READLN (map);
skip_spaces;
END {WHILE};
line_no := new_line_no;
new_line_no := read_word;
seg := read_hex (4);
IF EOF (map) THEN BEGIN
GOTO 1;
END {IF};
IF map^ <> ':' THEN BEGIN
WRITELN ('Invalid map file');
END {IF};
get (map);
IF EOF (map) THEN BEGIN
GOTO 1;
END {IF};
offset := read_hex (3) + WRD (hex_char (map^) > 0);
get (map);
IF map^ <> 'H' THEN BEGIN
WRITELN ('Invalid map file');
END {IF};
IF EOF (map) THEN BEGIN
GOTO 1;
END {IF};
get (map);
parcel := seg + offset;
END {WHILE};
1: real_per_cent := buckets^[i] * norm;
cum_per_cent := cum_per_cent + real_per_cent;
per_cent := ROUND ( buckets^[i] * norm_bucket);
WRITE (hist, buckets^ [i]:6:0, ' ',
address*16:6:16);
IF line_no <> 0 THEN BEGIN
WRITE (hist, line_no:6);
line_no := 0;
END
ELSE IF map_avail AND THEN first_address <> NIL THEN BEGIN
WRITE (hist, ' #', address - first_address^.address:4:16);
END
ELSE BEGIN
WRITE (hist, ' ');
END {IF};
WRITELN (hist, ' ', cum_per_cent:5:1, ' ', real_per_cent:4:1, ' |',
'*': per_cent);
END {WHILE};
WRITELN (hist, ' +-----------------',
'------------------');
END.
+1377
View File
File diff suppressed because it is too large Load Diff
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+802
View File
@@ -0,0 +1,802 @@
MS-DOS 2.0 Device Drivers
INTRODUCTION
In the past, DOS-device driver (BIOS for those who are
familiar with CP/M) communication has been mediated with
registers and a fixed-address jump-table. This approach
has suffered heavily from the following two observations:
o The old jump-table ideas of the past are fixed in
scope and allow no extensibility.
o The past device driver interfaces have been written
without regard for the true power of the hardware.
When a multitasking system or interrupt driven
hardware is installed a new BIOS must be written
largely from scratch.
In MSDOS 2.0, the DOS-device driver interface has changed
from the old jump-table style to one in which the device
drivers are linked together in a list. This allows new
drivers for optional hardware to be installed (and even
written) in the field by other vendors or the user himself.
This flexibility is one of the major new features of MS-DOS
2.0.
Each driver in the chain defines two entry points; the
strategy routine and the interrupt routine. The 2.0 DOS
does not really make use of two entry points (it simply calls
strategy, then immediately calls interrupt). This dual entry
point scheme is designed to facilitate future multi-tasking
versions of MS-DOS. In multi-tasking environments I/O must
be asynchronous, to accomplish this the strategy routine
will be called to queue (internally) a request and return
quickly. It is then the responsibility of the interrupt
routine to perform the actual I/O at interrupt time by picking
requests off the internal queue (set up by the strategy
routine), and process them. When a request is complete,
it is flagged as "done" by the interrupt routine. The DOS
periodically scans the list of requests looking for ones
flagged as done, and "wakes up" the process waiting for the
completion of the request.
In order for requests to be queued as above it is no
longer sufficient to pass I/O information in registers, since
many requests may be pending at any one time. Therefore
the new device interface uses data "packets" to pass request
information. A device is called with a pointer to a packet,
this packet is linked into a global chain of all pending
I/O requests maintained by the DOS. The device then links
the packet into its own local chain of requests for this
particular device. The device interrupt routine picks
requests of the local chain for processing. The DOS scans
the global chain looking for completed requests. These
packets are composed of two pieces, a static piece which
has the same format for all requests (called the static
request header), which is followed by information specific
to the request. Thus packets have a variable size and format.
At this points it should be emphasized that MS-DOS 2.0
does not implement most of these features, as future versions
will. There is no global or local queue. Only one request
is pending at any one time, and the DOS waits for this current
request to be completed. For 2.0 it is sufficient for the
strategy routine to simply store the address of the packet
at a fixed location, and for the interrupt routine to then
process this packet by doing the request and returning.
Remember: the DOS just calls the strategy routine and then
immediately calls the interrupt routine, it is assumed that
the request is completed when the interrupt routine returns.
This additional functionality is defined at this time so
that people will be aware and thinking about the future.
FORMAT OF A DEVICE DRIVER
A device driver is simply a relocatable memory image
with all of the code in it to implement the device (like
a .COM file, but not ORGed at 100 Hex). In addition it has
a special header at the front of it which identifies it as
a device, defines the strategy and interrupt entry points,
and defines various attributes. It should also be noted
that there are two basic types of devices.
The first is character devices. These are devices which
are designed to do character I/O in a serial manner like
CON, AUX, and PRN. These devices are named (ie. CON, AUX,
CLOCK, etc.), and users may open channels (FCBs) to do I/O
to them.
The second class of devices is block devices. These
devices are the "disk drives" on the system, they can do
random I/O in pieces called blocks (usually the physical
sector size) and hence the name. These devices are not
"named" as the character devices are, and therefore cannot
be "opened" directly. Instead they are "mapped" via the
drive letters (A,B,C, etc.).
Block devices also have units. In other words a single
driver may be responsible for one or more disk drives. For
instance block device driver ALPHA (please note that we cannot
actually refer to block devices by a name!) may be
responsible for drives A,B,C and D, this simply means that
it has four units (0-3) defined and therefore takes up four
drive letters. Which units correspond to which drive letters
is determined by the position of the driver in the chain
of all drivers: if driver ALPHA is the first block driver
in the device chain, and it defines 4 units (0-3), then they
will be A,B,C and D. If BETA is the second block driver
and defines three units (0-2), then they will be E,F and
G and so on. MS-DOS 2.0 is not limited to 16 block device
units, as previous versions were. The theoretical limit
is 63 (2^6 - 1), but it should be noted that after 26 the
drive letters get a little strange (like ] \ and ^). NOTE:
Character devices cannot define multiple units (this because
they have only one name).
Here is what that special device header looks like:
+--------------------------------------+
| DWORD Pointer to next device |
| (Must be set to -1) |
+--------------------------------------+
| WORD Attributes |
| Bit 15 = 1 if char device 0 if blk |
| if bit 15 is 1 |
| Bit 0 = 1 if Current sti device |
| Bit 1 = 1 if Current sto output |
| Bit 2 = 1 if Current NUL device |
| Bit 3 = 1 if Current CLOCK dev |
| Bit 4 = 1 if SPECIAL |
| Bit 14 is the IOCTL bit (see below) |
| Bit 13 is the NON IBM FORMAT bit |
+--------------------------------------+
| WORD Pointer to Device strategy |
| entry point |
+--------------------------------------+
| WORD Pointer to Device interrupt |
| entry point |
+--------------------------------------+
| 8-BYTE character device name field |
| Character devices set a device name |
| For block devices the first byte is |
| The number of units |
+--------------------------------------+
Note that the device entry points are words. They must
be offsets from the same segment number used to point to
this table. Ie. if XXX.YYY points to the start of this
table, then XXX.strategy and XXX.interrupt are the entry
points.
A word about the Attribute field. This field is used
most importantly to tell the system whether this device is
a block or character device (bit 15). Most of other bits
are used to give selected character devices certain special
treatment (NOTE: these bits mean nothing on a block device).
Let's say a user has a new device driver which he wants to
be the standard input and output. Besides just installing
the driver he needs to tell SYSINIT (and the DOS) that he
wishes his new driver to override the current sti and sto
(the "CON" device). This is accomplished by setting the
attributes to the desired characteristics, so he would set
Bits 0 and 1 to 1 (note that they are separate!!). Similarly
a new CLOCK device could be installed by setting that
attribute, see the section at the end on the CLOCK device.
NOTE: that although there is a NUL device attribute, the
NUL device cannot be re-assigned. This attribute exists
for the DOS so that it can tell if the NUL device is being
used.
The NON IBM FORMAT bit applies only to block devices
and effects the operation of the get BPB device call (see
below).
The other bit of interest is the IOCTL bit which has
meaning on character or block devices. This bit tells the
DOS whether this device can handle control strings (via the
IOCTL system call).
If a driver cannot process control strings, it should
initially set this bit to 0. This tells the DOS to return
an error if an attempt is made (via IOCTL system call) to
send or receive control strings to this device. A device
which can process control strings should initialize it to
1. For drivers of this type, the DOS will make calls to
the IOCTL INPUT and OUTPUT device functions to send and
receive IOCTL strings (see IOCTL in the SYSTEM-CALLS
document).
The IOCTL functions allow data to be sent and received
by the device itself for its own use (to set baud rate, stop
bits, form length etc., etc.), instead of passing data over
the device channel as a normal read or write does. The
interpretation of the passed information is up to the device,
but it MUST NOT simply be treated as a normal I/O.
The SPECIAL bit applies only to character drivers and
more particularly to CON drivers. The new 2.0 interface
is a much more general and consistent interface than the
old 1.25 DOS interface. It allows for a number of additional
features of 2.0. It is also slower than 1.25 if old style
"single byte" system calls are made. To make most efficient
use of the interface all applications should block their
I/O as much as possible. This means make one XENIX style
system call to output X bytes rather than X system calls
to output one byte each. Also putting a device channel in
RAW mode (see IOCTL) provides a means of putting out
characters even FASTER than 1.25. To help alleviate the
CON output speed problem for older programs which use the
1 - 12 system calls to output large amounts of data the
SPECIAL bit has been implemented. If this bit is 1 it means
the device is the CON output device, and has implemented
an interrupt 29 Hex handler, where the 29 Hex handler is
defined as follows:
Interrupt 29h handlers
Input:
Character in AL
Function:
output the character in al to the user
screen.
Output:
None
Registers:
all registers except bx must be preserved.
No registers except for al have a known or
consistent value.
If a character device implements the SPECIAL bit, it
is the responsibility of the driver to install an address
at the correct location in the interrupt table for interrupt
29 Hex as part of its INIT code. IMPLICATION: There can
be only one device driver with the SPECIAL bit set in the
system. There is no check to insure this state.
WARNING: THIS FEATURE WILL NOT BE SUPPORTED IN FUTURE VERSIONS
OF THE OPERATING SYSTEM. IMPLICATION: Any application
(not device driver) which uses INT 29H directly will
not work on future versions, YOU HAVE BEEN WARNED.
In order to "make" a device driver that SYSINIT can
install, a memory image or .EXE (non-IBM only) format file
must be created with the above header at the start. The
link field should be initialized to -1 (SYSINIT fills it
in). The attribute field and entry points must be set
correctly, and if the device is a character device, the name
field must be filled in with the name (if a block device
SYSINIT will fill in the correct unit count). This name
can be any 8 character "legal" file name. In fact SYSINIT
always installs character devices at the start of the device
list, so if you want to install a new CON device all you
have to do is name it "CON". The new one is ahead of the
old one in the list and thus preempts the old one as the
search for devices stops on the first match. Be sure to
set the sti and sto bits on a new CON device!
NOTE: Since SYSINIT may install the driver anywhere, you
must be very careful about FAR memory references. You
should NOT expect that your driver will go in the same
place every time (The default BIOS drivers are exempted
from this of course).
INSTALLATION OF DEVICE DRIVERS
Unlike past versions MS-DOS 2.0 allows new device drivers
to be installed dynamically at boot time. This is
accomplished by the new SYSINIT module supplied by Microsoft,
which reads and processes the CONFIG.SYS file. This module
is linked together with the OEM default BIOS in a similar
manner to the way FORMAT is built.
One of the functions defined for each device is INIT.
This routine is called once when the device is installed,
and never again. The only thing returned by the init routine
is a location (DS:DX) which is a pointer to the first free
byte of memory after the device driver, (like a terminate
and stay resident). This pointer method can be used to "throw
away" initialization code that is only needed once, saving
on space.
Block devices are installed the same way and also return
a first free byte pointer as above, additional information
is also returned:
o The number of units is returned, this determines
logical device names. If the current maximum logical
device letter is F at the time of the install call,
and the init routine returns 4 as the number of units,
then they will have logical names G, H, I and J.
This mapping is determined by by the position of
the driver in the device list and the number of units
on the device (stored in the first byte of the device
name field).
o A pointer to a BPB (Bios Parameter Block) pointer
array is also returned. This will be similar to
the INIT table used in previous versions, but will
have more information in it. There is one table
for each unit defined. These blocks will be used
to build a DPB (Drive Parameter Block) for each of
the units. The pointer passed to the DOS from the
driver points to an array of n word pointers to BPBs
where n is the number of units defined. In this
way if all units are the same, all of the pointers
can point to the same BPB, saving space. NOTE: this
array must be protected (below the free pointer set
by the return) since the DPB will be built starting
at the byte pointed to by the free pointer. The
sector size defined must be less than or equal to
the maximum sector size defined at default BIOS init
time. If it isn't the install will fail. One new
piece of DPB info set from this table will be a "media
descriptor byte". This byte means nothing to the
DOS, but is passed to devices so that they know what
form of a DPB the DOS is currently using for a
particular Drive-Unit.
Block devices may take several approaches; they may be
dumb or smart. A dumb device would define a unit (and
therefore a DPB) for each possible media drive combination.
Unit 0 = drive 0 single side, unit 1 = drive 0 double side,
etc. For this approach media descriptor bytes would mean
nothing. A smart device would allow multiple media per unit,
in this case the BPB table returned at init must define space
large enough to accommodate the largest possible media
supported. Smart drivers will use the "media byte" to pass
around info about what media is currently in a unit. NOTE:
If the DPB is a "hybrid" made to get the right sizes, it
should give an invalid "media byte" back to the DOS.
The BOOT (default BIOS) drivers are installed pretty
much as above. The preset device list is scanned. If block
drivers are encountered they are installed as above (with
the exception that the break is not moved since the drivers
are already resident in the BIOS). Note that the logical
drive letters are assigned in list order, thus the driver
which is to have logical A must be the first unit of the
first block device in the list. The order of character
devices is also important. There must be at least 4 character
devices defined at boot which must be the first four devices
(of either type), the first will become standard input,
standard output, and standard error output. The second will
become standard auxiliary input and output, the third will
become standard list output, and the forth will become the
date/time (CLOCK) device. Thus the BIOS device list must
look like this:
->CON->AUX->PRN->CLOCK->any other block or character devices
THE DRIVER
A device driver will define the following functions:
Command Function
Code
0 INIT
1 MEDIA CHECK (Block only, NOP for character)
2 BUILD BPB " " " " "
3 IOCTL INPUT (Only called if device has IOCTL)
4 INPUT (read)
5 NON-DESTRUCTIVE INPUT NO WAIT (Char devs only)
6 INPUT STATUS " " "
7 INPUT FLUSH " " "
8 OUTPUT (write)
9 OUTPUT (Write) with verify
10 OUTPUT STATUS " " "
11 OUTPUT FLUSH " " "
12 IOCTL OUTPUT (Only called if device has IOCTL)
As mentioned before, the first entry point is the strategy
routine which is called with a pointer to a data block. This
call does not perform the request, all it does is queue it
(save the data block pointer). The second interrupt entry
point is called immediately after the strategy call. The
"interrupt" routine is called with no parameters, its primary
function is to perform the operation based on the queued
data block and set up any returns.
The "BUILD BPB" and "MEDIA CHECK" are the interesting
new ones, these are explained by examining the sequence of
events in the DOS which occurs when a drive access call (other
than read or write) is made:
I. Turn drive letter into DPB pointer by looking
for DPB with correct driver-unit number.
II. Call device driver and request media check for
Drive-Unit. DOS passes its current Media
descriptor byte (from DPB). Call returns:
Media Not Changed
Media Changed
Not Sure
Error
Error - If an error occurs the error code should
be set accordingly.
Media Not changed - Current DPB and media byte
are OK, done.
Media Changed - Current DPB and media are wrong,
invalidate any buffers for this unit, and
goto III.
Not Sure - If there are dirty buffers for this
unit, assume DPB and media byte are OK and
done. If nothing dirty, assume media changed,
invalidate any buffers for unit, and goto
III.
NOTE: If a hybrid DPB was built at init and
an invalid Media byte was set, the driver
should return media changed when this invalid
media byte is encountered.
III. Call device driver to build BPB with media byte
and buffer.
What the driver must do at step III is determine the
correct media that is currently in the unit, and return a
pointer to a BPB table (same as for the install call). This
table will be used as at init to build a correct DPB for
the unit If the determined media descriptor byte in the table
turns out to be the same as the one passed in, then the DOS
will not build a new table, but rather just use the old one.
Therefore in this case the driver doesn't have to correctly
fill in the other entries if desired.
The build BPB call also gets a pointer to a one sector
buffer. What this buffer contains is determined by the NON
IBM FORMAT bit in the attribute field. If the bit is zero
(device is IBM format compatible) then the buffer contains
the first sector of the first FAT, in particular the FAT
ID byte is the first byte of this buffer. NOTE: It must
be true that the BPB is the same, as far as location of the
FAT is concerned, for all possible media. This is because
this first FAT sector must be read BEFORE the actual BPB
is returned. If the NON IBM FORMAT bit is set then the
pointer points to one sector of scratch space which may be
used for anything.
CALL FORMAT
When the DOS calls a device driver to perform a finction,
it passes a structure (Drive Request Structure) in ES:BX
to perform operations and does a long call to the driver's
strategy entry point. This structure is a fixed length header
(Static Request Header) followed by data pertinent to the
operation being performed. NOTE: It is the drivers
responsibility to preserve machine state.
STATIC REQUEST HEADER ->
+-----------------------------+
| BYTE length of record |
| Length in bytes of this |
| Drive Request Structure |
+-----------------------------+
| BYTE unit code |
| The subunit the operation |
| is for (minor device) |
| (no meaning on character |
| devices) |
+-----------------------------+
| BYTE command code |
+-----------------------------+
| WORD Status |
+-----------------------------+
| 8 bytes reserved here for |
| two DWORD links. One will |
| be a link for the DOS queue |
| The other for the device |
| queue |
+-----------------------------+
STATUS WORD
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+---+---+--+--+--+--+---+---+--+--+--+--+--+--+--+--+
| E | | B | D | |
| R | RESERVED | U | O | ERROR CODE (bit 15 on)|
| R | | I | N | |
+---+---+--+--+--+--+---+---+--+--+--+--+--+--+--+--+
The status word is zero on entry and is set by the driver
interrupt routine on return.
Bit 8 is the done bit, it means the operation is complete.
For the moment the Driver just sets it to one when it exits,
in the future this will be set by the interrupt routine to
tell the DOS the operation is complete.
Bit 15 is the error bit, if it is set then the low 8
bits indicate the error:
0 Write Protect violation
(NEW) 1 Unknown Unit
2 Drive not ready
(NEW) 3 Unknown command
4 CRC error
(NEW) 5 Bad Drive Request Structure length
6 Seek error
(NEW) 7 Unknown media
8 Sector not found
(NEW) 9 Printer out of paper
A Write Fault
(NEW) B Read Fault
C General Failure
Bit 9 is the busy bit which is set only by status calls (see
STATUS CALL below).
Here is the data block format for each function:
READ or WRITE - ES:BX (Including IOCTL) ->
+------------------------------------+
| 13-BYTE Static Request Header |
+------------------------------------+
| BYTE Media descriptor from DPB |
+------------------------------------+
| DWORD transfer address |
+------------------------------------+
| WORD byte/sector Count |
---+------------------------------------+---
| WORD starting sector number |
| (ignored on Char Devs) |
+------------------------------------+
In addition to setting the status word, the driver must
set the Sector count to the actual number of sectors (or
bytes) transferred. NOTE: No error check is performed on
an IOCTL I/O call, driver MUST correctly set the return sector
(byte) count to the actual number of bytes transferred,
however.
NOTE: THE FOLLOWING APPLIES TO BLOCK DEVICE DRIVERS.
Under certain circumstances the BIOS may be asked to
do a write operation of 64K bytes which seems to be a "wrap
around" of the transfer address in the BIOS I/O packet. This
arises due to an optimization added to the write code in
MS-DOS. It will only manifest on user WRITEs which are within
a sector size of 64K bytes on files which are "growing" past
the current EOF. IT IS ALLOWABLE FOR THE BIOS TO IGNORE
THE BALANCE OF THE WRITE WHICH "WRAPS AROUND" IF IT SO
CHOOSES. For instance a WRITE of 10000H bytes worth of
sectors with a transfer address of XXX:1 could ignore the
last two bytes (remember that a user program can never request
an I/O of more than FFFFH bytes and cannot wrap around (even
to 0) in his transfer segment, so in this case the last two
bytes can be ignored).
NON DESRUCTIVE READ NO WAIT - ES:BX ->
+------------------------------------+
| 13-BYTE Static Request Header |
+------------------------------------+
| BYTE read from device |
+------------------------------------+
This call is analogous to the console input status call
on MS-DOS 1.25. If the character device returns Busy bit
= 0 (characters in buffer), then the next character that
would be read is returned. This character is NOT removed
from the input buffer (hence the term Non Destructive Read).
In essence this call allows the DOS to look ahead one input
character.
MEDIA CHECK - ES:BX ->
+------------------------------------+
| 13-BYTE Static Request Header |
+------------------------------------+
| BYTE Media Descriptor from DPB |
+------------------------------------+
| BYTE returned |
+------------------------------------+
In addition to setting status word, driver must set the
return byte.
Return Byte :
-1 Media has been changed
0 Don't know if media has been changed
1 Media has not been changed
If the driver can return -1 or 1 (by having a door-lock
or other interlock mechanism) the performance of MSDOS 2.0
is enhanced as the DOS need not reread the FAT for each
directory access.
BUILD BPB - ES:BX ->
+------------------------------------+
| 13-BYTE Static Request Header |
+------------------------------------+
| BYTE Media Descriptor from DPB |
+------------------------------------+
| DWORD Transfer Address |
| (points to one sectors worth of |
| scratch space or first sector |
| of FAT depending on the value |
| of the NON IBM FORMAT bit) |
+------------------------------------+
| DWORD Pointer to BPB |
+------------------------------------+
If the NON IBM FORMAT bit of the device is set, then
the DWORD Transfer Address points to a one sector buffer
which can be used for any purpose. If the NON IBM FORMAT
bit is 0, then this buffer contains the first sector of the
FAT; in this case the driver must not alter this buffer (this
mode is useful if all that is desired is to read the FAT
ID byte).
If IBM compatible format is used (NON IBM FORMAT BIT
= 0), then it must be true that the first sector of the first
FAT is located at the same sector on all possible media.
This is because the FAT sector will be read BEFORE the media
is actually determined.
In addition to setting status word, driver must set the
Pointer to the BPB on return.
In order to allow for many different OEMs to read each
other's disks, the following standard is suggested: The
information relating to the BPB for a particular piece of
media is kept in the boot sector for the media. In
particular, the format of the boot sector is:
+------------------------------------+
| 3 BYTE near JUMP to boot code |
+------------------------------------+
| 8 BYTES OEM name and version |
---+------------------------------------+---
B | WORD bytes per sector |
P +------------------------------------+
B | BYTE sectors per allocation unit |
+------------------------------------+
| | WORD reserved sectors |
V +------------------------------------+
| BYTE number of FATs |
+------------------------------------+
| WORD number of root dir entries |
+------------------------------------+
| WORD number of sectors in logical |
^ | image |
| +------------------------------------+
B | BYTE media descriptor |
P +------------------------------------+
B | WORD number of FAT sectors |
---+------------------------------------+---
| WORD sectors per track |
+------------------------------------+
| WORD number of heads |
+------------------------------------+
| WORD number of hidden sectors |
+------------------------------------+
The three words at the end are optional, the DOS doesn't
care about them (since they are not part of the BPB). They
are intended to help the BIOS understand the media. Sectors
per track may be redundant (could be figured out from total
size of the disk). Number of heads is useful for supporting
different multi-head drives which have the same storage
capacity, but a different number of surfaces. Number of
hidden sectors is useful for supporting drive partitioning
schemes.
Currently, the media descriptor byte has been defined
for a small range of media:
5 1/4" diskettes:
Flag bits:
01h - on -> 2 double sided
All other bits must be on.
8" disks:
FEh - IBM 3740 format, singled-sided, single-density,
128 bytes per sector, soft sectored, 4 sectors
per allocation unit, 1 reserved sector, 2 FATs,
68 directory entries, 77*26 sectors
FDh - 8" IBM 3740 format, singled-sided,
single-density, 128 bytes per sector, soft
sectored, 4 sectors per allocation unit, 4
reserved sectors, 2 FATs, 68 directory entries,
77*26 sectors
FEh - 8" Double-sided, double-density, 1024 bytes
per sector, soft sectored, 1 sector per allocation
unit, 1 reserved sector, 2 FATs, 192 directory
entries, 77*8*2 sectors
STATUS Calls - ES:BX ->
+------------------------------------+
| 13-BYTE Static Request Header |
+------------------------------------+
All driver must do is set status word accordingly and
set the busy bit as follows:
o For output on character devices: If it is 1 on
return, a write request (if made) would wait for
completion of a current request. If it is 0, there
is no current request and a write request (if made)
would start immediately.
o For input on character devices with a buffer a return
of 1 means, a read request (if made) would go to
the physical device. If it is 0 on return, then
there are characters in the devices buffer and a
read would return quickly, it also indicates that
the user has typed something. The DOS assumes all
character devices have an input type ahead buffer.
Devices which don't have them should always return
busy = 0 so that the DOS won't hang waiting for
something to get into a buffer which doesn't exist.
FLUSH Calls - ES:BX ->
+------------------------------------+
| 13-BYTE Static Request Header |
+------------------------------------+
This call tells the driver to flush (terminate) all
pending requests that it has knowledge of. Its primary use
is to flush the input queue on character devices.
INIT - ES:BX ->
+------------------------------------+
| 13-BYTE Static Request Header |
+------------------------------------+
| BYTE # of units |
+------------------------------------+
| DWORD Break Address |
---+------------------------------------+---
| DWORD Pointer to BPB array |
| (not set by Character devices) |
+------------------------------------+
The number of units, break address, and BPB pointer are
set by the driver.
FORMAT OF BPB (Bios Parameter Block) -
+------------------------------------+
| WORD Sector size in Bytes |
| Must be at least 32 |
+------------------------------------+
| BYTE Sectors/Allocation unit |
| Must be a power of 2 |
+------------------------------------+
| WORD Number of reserved sectors |
| May be zero |
+------------------------------------+
| BYTE Number of FATS |
+------------------------------------+
| WORD Number of directory entries |
+------------------------------------+
| WORD Total number of sectors |
+------------------------------------+
| BYTE Media descriptor |
+------------------------------------+
| WORD Number of sectors occupied by |
| FAT |
+------------------------------------+
THE CLOCK DEVICE
One of the most popular add on boards seems to be "Real
Time CLOCK Boards". To allow these boards to be integrated
into the system for TIME and DATE, there is a special device
(determined by the attribute word) which is the CLOCK device.
In all respects this device defines and performs functions
like any other character device (most functions will be "set
done bit, reset error bit, return). When a read or write
to this device occurs, exactly 6 bytes are transferred. This
I/O can be thought of as transferring 3 words which correspond
exactly to the values of AX, CX and DX which were used in
the old 1.25 DOS date and time routines. Thus the first
two bytes are a word which is the count of days since 1-1-80.
The third byte is minutes, the fourth hours, the fifth
hundredths of seconds, and the sixth seconds. Reading the
CLOCK device gets the date and time, writing to it sets the
date and time.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
+1657
View File
File diff suppressed because it is too large Load Diff
Binary file not shown.
+813
View File
@@ -0,0 +1,813 @@
MS-DOS 2.0
Utility Extensions
The following notation is used below:
[item] item is optional.
item* item is repeated 0 or more times.
item+ item is repeated 1 or more times.
{item1 | item2}
item1 is present or item 2 is present but
not both.
<object> indicates a syntactic variable.
COMMAND invokation
COMMAND [[<drive>:]<path>] [<cttydev>] [-D] [-P] [-C <string>]
-P If present COMMAND will be permanent, otherwise
this is a transient command.
-D If present COMMAND will not prompt for DATE and
TIME when it comes up.
d: Specifies device where command will look for
COMMAND.COM current default drive if absent.
<Path> Specifies a directory on device d: root
directory if absent.
<cttydev> Name of the CTTY device. /DEV/CON if absent
and command is permanent. The /DEV/ may be left
off if AVAILDEV is TRUE (see sysinit doc).
-C <string> If present -C must be the last switch.
This causes COMMAND to try to execute the string
as if the user had typed it at the standard input.
COMMAND executes this single command string and
then exits. If the -P switch is present it is
ignored (can't have a single command, permanent
COMMAND). NOTE: ALL of the text on the command
line after the -C is just passed on. It is not
processed for more arguments, this is why -C must
be last.
COMMAND extensions
IF <condition> <command>
where <condition> is one of the following:
ERRORLEVEL <number>
true if and only if the previous program EXECed by
COMMAND had an exit code of <number> or higher.
<string1> == <string2>
true if and only if <string1> and <string2> are
identical after parameter substitution. Strings
may not have embedded delimiters.
EXIST <filename>
true if and only if <filename> exists.
NOT <condition>
true if and only if <condition> is false.
The IF statement allows conditional execution of commands.
When the <condition> is true, then the <command> is
executed otherwise, the <command> is skipped.
Examples:
IF not exist /tmp/foo ECHO Can't find file /tmp/foo
IF $1x == x ECHO Need at least one parameter
IF NOT ERRORLEVEL 3 LINK $1,,;
FOR %%<c> IN <set> DO <command>
<c> can be any character but 0,1,2,3,..,9 (so there is no
confusion with the %0 - %9 batch parameters).
<set> is ( <item>* )
The %%<c> variable is sequentially set to each member of
<set> and then <command> is evaluated. If a member of
<set> is an expression involving * and/or ?, then the
variable is set to each matching pattern from disk. In
this case only one such <item> may be in the set, any
<item>s after the first are ignored.
Example:
FOR %%f IN ( *.ASM ) DO MASM %%f;
for %%f in (FOO BAR BLECH) do REM %%f to you
NOTE: The '%%' is needed so that after Batch parameter
(%0 - %9) processing is done, there is one '%' left.
If only '%f' were there, the batch parameter processor
would see the '%' then look at 'f', decide that '%f'
was an error (bad parameter reference) and throw out
the '%f' so that FOR would never see it. If the FOR
is NOT in a batch file, then only ONE '%' should be
used.
SHIFT
Currently, command files are limited to handling 10
parameters: %0 through %9. To allow access to more than
these, the command SHIFT will perform a 'pop' of the
command line parameters:
if %0 = "foo"
%1 = "bar"
%2 = "blech"
%3...%9 are empty
then a SHIFT will result in the following:
%0 = "bar"
%1 = "blech"
%2...%9 are empty
If there are more than 10 parameters given on a command
line, then the those that appear after the 10th (%9) will
be shifted one at a time into %9 by successive shifts.
:<label>
This is essentially a no-op. It defines a label in the
batch file for a subsequent GOTO. It may also be used to
put comment lines in batch files since all lines that
start with ':' are ignored.
GOTO <label>
Causes commands to be taken from the batch file beginning
with the line after the <label> definition. If no label
has been defined, the current batch file will terminate.
Example:
:foo
REM looping...
GOTO foo
will produce a infinite sequence of messages:
'REM looping...'
NOTE: Labels are case insensitive, :FOO == :foo == :Foo
ECHO [{ON | OFF | <message>}]
Normally, commands in a BATCH file are echoed onto the
standard output as they are seen by COMMAND. ECHO OFF
turns off this feature. ECHO ON turns echoing back on.
If ON or OFF is not specified and there is text following
the command, that text (a message) is echoed to standard
output. If there are no arguments at all, the current
setting of echo (on or off) is echoed to the standard
output in the form:
ECHO is xxx
Where xxx is "on" or "off".
Redirection of standard input/standard output.
Programs that read from the keyboard and write to the
screen are said to be doing I/O to the standard input and
standard output. Using any of the following will result
in I/O to these standard devices:
Writing to default handles 1 / read from default
handle 0.
Doing byte I/O using system calls 1, 2, 6-12.
These standard devices may be redirected to/from files by
the following in command line arguments:
> <filename>
causes <filename> to be created (or truncated to
zero length) and then assigns standard output to
that file. All output from the command will be
placed in the file.
< <filename>
causes standard input to be assigned to
<filename>. All input to the command will come
from this file. If end-of-file is reached, then
system calls 1, 2, 6-12 will return ^Z , while
reading from handle 0 will return zero characters.
>> <filename>
causes <filename> to be opened (created if
necessary) and positions the write pointer at the
end of the file so that all output will be
appended to the file.
Note that the above will not appear in the command line
that the program being invoked sees.
Examples:
DIR *.ASM > FOO.LST
Sends the output of the dir command to the file
FOO.LST.
FOR %0 IN (*.ASM) DO MASM %0; >>ERRS.LST
Sends all error output from assembling every .ASM file
into the file ERRS.LST.
Piping of standard I/O
It is often useful for the output of one program to be
sent as input to another program. A typical case is a
program that produces columnar output that must later be
sorted.
The pipe feature allows this to occur naturally is the
programs do all of their I/O to the standard devices.
For example, if we had a program SORT that read all of
it's standard input, sorted it and then wrote it to the
standard output, then we could get a sorted directory
listing as follows:
DIR | SORT
The | would cause all standard output generated by the
left-hand command to be sent to the standard input of the
right-hand command.
If we wanted the sorted directory to be sent to a file, we
type:
DIR | SORT >FILE
and away it goes.
The piping feature is implemented as sequential execution
of the procedures with redirection to and from temporary
files. In the example above, the following would be an
exact equivalent:
DIR >/tmp/std1
SORT </tmp/std1 >FILE
The pipe is not a real pipe but rather a quasi-pipe
that uses temporary files to hold the input and output as
it sequentially executes the elements of the pipe. These
files are created in the current directory, of the current
drive and have the form %PIPEx%.$$$, where x will be 1 or
2. This means that any program that runs in the pipe must
be sure to restore the current directory and drive if it
has changed them, otherwise the pipe files will be lost.
VER
Prints DOS version number.
VOL [<drive>:]
Prints the volume ID of the disk in drive d:. No d: does
default drive.
CHDIR [{<drive>: | <path>}]
Change directory, or print current. directory.If no
argument is given, the current directory on the default
drive is printed. If d: alone is given, the durrent
directory of drive d is printed. Otherwise the current
directory is set to path.
NOTE:"CD" is accepted as an abbreviation.
MKDIR <path> - Make a directory.
"MD" is accepted as an abbreviation.
RMDIR <path> - Remove a directory.
"RD" is accepted as an abbreviation.
The directory must be empty except for
'.' and '..'.
<path> - A standard XENIX style path with the optional
addition of a drive spec:
A:/FOO/BAR Full path
/FOO/BAR Full path, current drive
FOO/BAR Current dir relative
A:FOO/BAR " " "
VERIFY [{ON | OFF}]
Select/deselect verify after write mode. This supliments
the V switch to the COPY command. Once turned ON, it
stays on until some program changes it (via the set verify
system call) or the VERIFY OFF command is given. If no
argument is given, the current setting of VERIFY is
printed to the standard output in the form:
VERIFY is xxx
Where xxx is "on" or "off".
PATH [<path>{;<path>}*]
Set command search paths. This allows users to set
directories that should be searched for external commands
after a search of the current directory is made. The
default value is /bin. In addition there are two special
cases: PATH all by itself with no arguments will print
the current path. Path with the single argument ';' (ie.
"PATH ;") will set the NUL path (no directories other than
the current one searched). If no argument is given, the
current value of PATH is printed to the standard output in
the form:
PATH=text of path
or
No path
NOTE: On IBM systems, the default value of path is No
path.
EXIT
For COMMANDs run without the P switch, this causes COMMAND
to return. For a normal COMMAND it causes a return to
itself.
BREAK [{ON | OFF}]
Like in CONFIG.SYS, "BREAK ON" turns on the Control C
check in the DOS function dispatcher. "BREAK OFF" turns
it off. If no argument is given the setting of BREAK is
printed to the standard output in the form:
BREAK is xxx
Where xxx is "on" or "off".
PROMPT [<prompt-text>]
Set the system prompt. MS-DOS prompts are now user
settable, all of the text on the command line is taken to
be the new prompt. If no text is present the prompt is
set to the default prompt. There are meta strings for
various special prompts. These are of the form '$c' where
c is one of the following:
$ - The '$' character.
t - The time.
d - The date.
p - The current directory of the default drive.
v - The version number.
n - The default drive.
g - The '>' character.
l - The '<' character.
b - The '|' character.
s - The ' ' character.
e - The ESC character.
_ - A CR LF sequence.
EXAMPLE:
PROMPT $n:
Would set the normal MS-DOS prompt.
PROMPT $n>
Would det the normal PC-DOS prompt.
PROMPT Time = $t$_Date = $d
Would set a two line prompt which printed
Time = (current time)
Date = (current date)
NOTE: For '$c' sequences, lower case = upper case, and
any character not on the above list is mapped to
nothing.
SET (ENVNAME)=(ENVTEXT)
Set environment strings. This command inserts strings in
COMMAND's environment. For instance:
SET PROMPT=$n>
Duplicates the function of the PROMPT command.
SET PATH=p1;p2
Duplicates the function of the PATH command.
SET foo=bar
Puts the string FOO=bar into the environment (note the
case mapping of (ENVNAME)).
NOTE: Environments are very flexible, almost anything can
be put into the environment with the SET command; the
only requirement is that a single '=' be present in
the string.
CLS
Clear screen, causes the ANSI escape sequence ESC[2J to be
sent to standard output.
CTTY /DEV/dev - Change console TTY. For instance:
CTTY /DEV/AUX
Would move all command I/O to the AUX port.
CTTY /DEV/CON
Would move it back to the normal device. The
/dev/ prefix may be left off if AVAILDEV is
TRUE (see configuration-file doc).
COMMAND internal commands take path arguments.
DIR <path>
COPY <path> <path>
DEL(ERASE) <path>
If the path is a dir, all files in that dir
are deleted.
NOTE: The "Are you sure (Y/N)" prompt for DEL and
ERASE now uses buffered standard input, so
users must type a return after their answer.
This gives them the chance to correct if they
type 'y' by mistake.
TYPE <path> (must specify a file)
FILCOM - compare two files
The FILCOM program compares two files and produces a log
of differences between them. The comparison may be made
in two fashions; either on a line-by-line basis, or on a
byte-by-byte basis.
The line-by-line compare will isolate blocks of lines that
are different between the two files and will print the
blocks from each file. The line-by-line compare is the
default when neither of the two files being compared has
the extension .EXE, .COM, or .OBJ.
The byte-by-byte compare will display exactly which bytes
are different between the two files. If either file being
compared has extension .EXE, .COM, or .OBJ then the files
will be compared in byte-by-byte mode.
RECOVER - recover files from a trashed disk.
If a sector on a disk goes bad, you can recover either the
file that contained that sector (without the sector) or
the entire disk (if the bad sector was in the directory).
To recover a particular file:
RECOVER <file-to-recover>
This will cause the file to be read sector by sector and
to be have the bad sector skipped. Note that this implies
that the allocation unit containing the bad sector will be
read as much as possible. When such a bad sector is
found, its containing allocation unit is marked as bad,
thus preventing future allocations of that bad sector.
To recover a particular disk:
RECOVER <drive-letter>:
This will cause a scan to be made of the drive's FAT for
chains of allocation units (files). A new root directory
is then written that has entries of the form FILEnnnn.
Each FILEnnnn will point to the head of one of the
allocation unit chains.
If there are more chains than directory entries in the
root, RECOVER prints a message and leaves the un-RECOVERED
chains in the FAT so that RECOVER can be run again once
some room has been made in the ROOT.
DEBUG ON MS-DOS 2.0
When 2.0 DEBUG is invoked it sets up a program header
atoffset 0 in its program work area. On previous versions it
was OK to overwrite this header with impunity: this is true
of the default header set up if no <filespec> is given to
DEBUG. If DEBUGging a .COM or .EXE file, however, you must be
careful not to tamper with the header of the program below
address 5CH, to do this will probably result in a crash. It
is also important that an attempt is not made to "restart" a
program once the "program terminated normally" message is
given. The program must be reloaded with the N and L commands
in order for it to run properly.
NEW FEATURES
The A (Assemble) Command
FORMAT: A [<address>]
PURPOSE: To assemble 8086/8087/8088 mnemonics directly into
memory.
o If a syntax error is encountered, DEBUG responds with
^ Error
and redisplays the current assembly address.
o All numeric values are hexadecimal and may be entered
as 1-4 characters.
o Prefix mnemonics must be entered in front of the opcode
to which they refer. They may also be entered on a
separate line.
o The segment override mnemonics are CS:, DS:, ES:, and
SS:
o String manipulation mnemonics must explictly state the
string size. For example, the MOVSW must be used to
move word strings and MOVSB must be used to move byte
strings.
o The mnemonic for the far return is RETF.
o The assembler will automatically assemble short, near
or far jumps and calls depending on byte displacement
to the destination address. These may be overridden
with the NEAR or FAR prefix. For example:
0100:0500 JMP 502 ; a 2 byte short jump
0100:0502 JMP NEAR 505 ; a 3 byte near jump
0100:0505 JMP FAR 50A ; a 5 byte far jump
The NEAR prefix may be abbreviated to NE but the FAR
prefix cannot be abbreviated.
o DEBUG cannot tell whether some operands refer to a word
memory location or a byte memroy location. In this case
the data type must be explicity stated with the prefix
"WORD PTR" or "BYTE PTR". DEBUG will also except the
abbreviations "WO" and "BY". For example:
NEG BYTE PTR [128]
DEC WO [SI]
o DEBUG also cannot tell whether an operand refers to a
memory location or to an immediate operand. DEBUG uses
the common convention that operands enclosed in square
brackets refer to memory. For example:
MOV AX,21 ;Load AX with 21H
MOV AX,[21] ;Load AX with the contents
;of memory location 21H
o Two popular pseudo-instructions have also been included.
The DB opcode will assemble byte values directly into
memory. The DW opcode will assemble word values directly
into memory. For example:
DB 1,2,3,4,"THIS IS AN EXAMPLE"
DB 'THIS IS A QUOTE: "'
DB "THIS IS A QUOTE: '"
DW 1000,2000,3000,"BACH"
o All forms of the register indirect commands are supported.
For example:
ADD BX,34[BP+2].[SI-1]
POP [BP+DI]
PUSH [SI]
o All opcode synonyms are supported, For example:
LOOPZ 100
LOOPE 100
JA 200
JNBE 200
o For 8087 opcodes the WAIT or FWAIT prefix must be
explictly specified. For example:
FWAIT FADD ST,ST(3) ; This lines will assemble
; a FWAIT prefix
FLD TBYTE PTR [BX] ; This line will not
FORMAT enhancements
FORMAT will now install volume id's during the format
process. DIR and CHKDSK will display these volume id's.
User programs can read the volume id on a particular drive
by doing a 'search next' with the volume id attribute. It
is impossible, using normal DOS calls, to delete a volume
id or to create another one. The only way to create a
volume id is to reformat the disk.
NOTE: On IBM systems the V switch must be given to FORMAT
to have it do Volume IDs.
CHKDSK FOR MS-DOS 2.0
MS-DOS 2.0 has a tree structured directory scheme which
did not exist on previous versions of MS-DOS. As a result
CHKDSK is a much more complex program than in previous
versions since it must perform a tree traversal to find all of
the files on a given disk. It employes a depth first
traversal in order to accomplish this.
Previous versions of CHKDSK automatically "fixed"
disks (regardless of whether it was appropriate). CHKDSK 2.00
run normally will not alter the disk in any way, it simply
reports on any inconsistencies found. To actually "fix" a
disk CHKDSK must be run with the F switch (Fix). This allows
you to perhaps take some alternate (to CHKDSK repairs) action
before letting CHKDSK loose on your disk.
CHKDSK 2.00 will report on non-contiguous allocation units
(extents) for specified files. This is handy for gaging how
"fragmented" a disk volume has become. This is done by simply
giving a filespec:
CHKDSK B:*.*
This would report extents for all files in the current
directory for drive B after doing a normal consistency check
on drive B. Files which have many extents can be copied and
renamed to restore them to a contiguous state, thus improving
I/O performance to the files.
Previous versions of CHKDSK would simply free
allocation units which were marked as used, but were not
actually part of any file. CHKDSK 2.00 will recover these
"orphan" allocation units if specified. If orphan allocation
units are found, CHKDSK prompts for free or recover. Free
just frees the orphans as previous versions did, recover will
employ allocation chain analysis to create "orphan files" in
the root directory of the disk. These files will have the
form "%ORPHAN%.l$$" where l will take on some ASCII value
greater than '@'. These files may then be inspected to see if
valuable data was contained in them. If there is not enough
room to make all of the "orphan" files, CHKDSK leaves the
unrecovered chains in the FAT so that CHKDSK can be run again
(once some entries in the ROOT have been deleted). NOTE:
Making ORPHAN files is a SLOW process.
Verbose mode. CHKDSK 2.00 may be run with the V switch
which causes a trace of the files and directories being
processed to be printed as CHKDSK runs.
FILTERS FOR MS-DOS 2.0
A filter is a utility that reads from standard input,
modifies the information in some way, then writes the result
to standard output. In this way the data is said to have been
"filtered" by the program. Since different filters can be
piped together in many different ways a few filters can take
the place of a large number of specific purpose programs. The
following describes the filters that are provided with MS-DOS
2.0:
CIPHER <key word>
Cipher reads a program from standard input, encrypts it
using the key word provided by the user, then writes the
result to standard output. To decrypt the file simply run
CIPHER again using the same keyword. For example:
A>CIPHER MYSTERY <NSA.CIA >SECRET.FIL
This command line will read file NSA.CIA, encrypt it using
the key word "MYSTERY", then write the result to file
SECRET.FIL To view the original file the following command
line could be used:
A>CIPHER MYSTERY <SECRET.FIL
This will read file SECRET.FIL, decrypt the file using the
key word "MYSTERY", then write the result to standard output,
which in this case is the console.
FGREP
This filter takes as arguments a string and optionally a
series of file names. It will send to standard output all
lines from the files specified in the command line that
contain the string.
If no files are specified FGREP will take the input from
standard in. The format for the command line invocation of
FGREP is:
FGREP [<option>] <string> <filename>*
The options available are:
/v Will cause FGREP to output all lines NOT
containing the specified string.
/c Will cause FGREP to only print the count of
lines matched in each of the files.
/n Each line matched is preceded by its relative
line number in the file.
The string argument should be enclosed in double quotes.
Two double quotes in succession are taken as a single double
quote. So,
A>FGREP "Fool""s Paradise" book1.txt book2.txt bible
will output all lines from the book1.txt, book2.txt and bible
(in that order that contain the string: Fool"s Paradise .
And,
A>dir b: | fgrep /v "DAT"
will output all names of the files in disk b: which do not
contain the string DAT .
MORE
The filter MORE reads from standard input, sends one
screen full of information to standard output and then pauses
with message:
-- More --
Pressing the RETURN key will cause another screen full of
information to be written to standard output. This process
continues until all the input data is read.
SORT [/R] [/+n]
Sort reads from standard input, sorts the data, the writes
the information to standard output. The sort is done using
the ASCII collating sequence. There are switches which allow
the user to select various options:
R - Reverse the sort, that is make "Z" come before "A"
+n - Sort starting with column "n" where n is some integer.
The default is start the comparisons with column 1,
this switch allows the user to start in any column.
example:
A>SORT /R <UNSORT.TXT >SORT.TXT
This command line will read the file UNSORT.TXT, do a reverse
sort, then write the output to file SORT.TXT
A>DIR | SORT /+14
This command line will cause the output of the directory
command to be piped to the sort filter, the sort filter will
sort starting with column 14 (This is the column the file size
starts), then send the output to the console. Thus a
directory sorted by file size will be the result. To get real
fancy:
A>DIR | SORT /+14 | MORE
will do the same thing except that MORE will give you a chance
to read the directory before it scrolls off the screen.
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 1982-1983 Microsoft Corporation
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+4 -1
View File
@@ -1,2 +1,5 @@
# MS-DOS 2.00 OAK # MS-DOS 2.00 OAK
MS-DOS 2.00 OEM Adaptation Kit MS-DOS 2.00 OEM Adaptation Kit released by CHM. Images of the 5 disks and their
content extracted.
![MS-DOS 2.00 OAK Disks](./disks.jpg)
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB