layout | title | permalink |
---|---|---|
page |
MS-DOS Version 3.3 Programmer's Reference |
/pubs/pc/reference/microsoft/mspl13/msdos/dosref33/ |
{% raw %}
TITLE PAGE
───────────────────────────────────────────────────────────────────────────
Microsoft(R) MS-DOS(R)
Version 3.3
Programmer's Reference
───────────────────────────────────────────────────────────────────────────
Information in this document is subject to change without notice and does
not represent a commitment on the part of Microsoft Corporation. The
software described in this document is furnished under a license agreement
or nondisclosure agreement. The software may be used or copied only in
accordance with the terms of the agreement. The purchaser may make one copy
of the software for backup purposes. No part of this manual may be
reproduced or transmitted in any form or by any means, electronic or
mechanical, including photocopying and recording, for any purpose other
than the purchaser's personal use without the written permission of
Microsoft Corporation.
(c) Copyright Microsoft Corporation, 1988. All rights reserved.
Simultaneously published in the United States and Canada.
Microsoft(R), the Microsoft logo, MS(R), MS-DOS(R), and XENIX(R) are
registered trademarks of Microsoft Corporation.
IBM(R), IBM Personal Computer(R), IBM PC(R), and PC-DOS(R) are registered
trademarks of International Business Machines Corporation.
INTEL(R) is a registered trademark of Intel Corporation.
Contents
───────────────────────────────────────────────────────────────────────────
1 System Calls
1.1 Introduction
1.2 Standard Character Device I/O
1.3 Memory Management
1.4 Process Management
1.5 File and Directory Management
1.6 Microsoft Networks
1.7 National Language Support
1.8 Miscellaneous System-Management Functions
1.9 Old System Calls
1.10 Using the System Calls
1.11 Interupts
1.12 Function Requests
2 MS-DOS Device Drivers
2.1 Introduction
2.2 Format of a Device Driver
2.3 How to Create a Device Driver
2.4 Installing Device Drivers
2.5 Device Headers
2.6 Request Header
2.7 Device Driver Functions
2.8 The Media Descriptor Byte
2.9 Format of a Media Descriptor Table
2.10 The CLOCK Device
2.11 Anatomy of a Device Call
2.12 Two Sample Device Drivers
3 MS-DOS Technical Information
3.1 Introduction
3.2 MS-DOS Initialization
3.3 The Command Processor
3.4 MS-DOS Disk Allocation
3.5 MS-DOS Disk Directory
3.6 File Allocation Table (FAT)
3.7 MS-DOS Standard Disk Formats
4 MS-DOS Control Blocks and Work Areas
4.1 Introduction
4.2 Typical Contents of an MS-DOS Memory Map
4.3 MS-DOS Program Segment
5 National Language Support
5.1 Introduction
5.2 National Language Support Calls
5.3 Font Files
6 .Exe File Structure and Loading
6.1 Format of a File Header
6.2 The Relocation Table
7 Relocatable Object Module Formats
7.1 Introduction
7.2 Module Identification and Attributes
7.3 Conceptual Framework for Fixups
7.4 Record Sequence
7.5 Introducing the Record Formats
7.6 Microsoft Type Representations for Communal Variables
8 Programming Hints
8.1 Introduction
8.2 Interrupts
8.3 System Calls
8.4 Device Management
8.5 Memory Management
8.6 Process Management
8.7 File and Directory Management
8.8 Miscellaneous
Figures
Figure 1.1 Example of the 8088 Registers
Figure 1.2 Sample Program with Common Skeleton
Figure 2.1 Sample Device Header
Figure 2.2 Attribute Word for Character Devices
Figure 2.3 Attribute Word for Block Devices
Figure 2.4 Request Header
Figure 2.5 Status Field
Figure 2.6 Format of a Boot Sector
Figure 2.7 Format of a Clock Device
Figure 4.1 Program Segment Prefix
Figure 5.1 Font File Structure
Figure 7.1 Location Types
Tables
Table 1.1 Standard Character I/O Functions
Table 1.2 Memory-Management Function Requests
Table 1.3 Process-Management Function Requests
Table 1.4 Predefined Device Handles
Table 1.5 File-Related Function Requests
Table 1.6 File-Sharing Function Requests
Table 1.7 Device-Related Function Requests
Table 1.8 Directory-Related Function Requests
Table 1.9 File Attributes
Table 1.10 Microsoft Networks Function Requests
Table 1.11 National-Language-Support Function Requests
Table 1.12 Miscellaneous System-Management Function Requests
Table 1.13 Old System Calls and Their Replacements
Table 1.14 Format of the File Control Block (FCB)
Table 1.15 Error Codes Returned in AX
Table 1.16 MS-DOS Interrupts, Numeric Order
Table 1.17 MS-DOS Interrupts, Alphabetic Order
Table 1.18 MS-DOS Function Requests, Numeric Order
Table 1.19 MS-DOS Function Requests, Alphabetic Order
Table 1.20 Bit Values for Function 29H
Table 1.21 Sharing Mode Bit Values
Table 1.22 Access Code Bit Values
Table 1.23 MS-DOS Data Bit Values
Table 1.24 Contents of the Parameter Block
Table 1.25 Contents of the Parameter Block
Table 1.26 DTA Values After Successful Find First File
Table 1.27 Allocation Strategy
Table 2.1 For Character Devices:
Table 2.2 For Block Devices
Table 3.1 MS-DOS Standard Removable-Disk Formats
Table 3.2 MS-DOS Standard Removable-Disk Formats (High-Density)
Table 7.1 Object Module Record Format
Table 7.1 Combination Attribute Example
Chapter 1 System Calls
───────────────────────────────────────────────────────────────────────────
1.1 Introduction
1.1.1 System Calls That Have Been Superseded
1.2 Standard Character Device I/O
1.3 Memory Management
1.4 Process Management
1.4.1 Loading and Executing a Program
1.4.2 Loading an Overlay
1.5 File and Directory Management
1.5.1 Handles
1.5.2 File Related Function Requests
1.5.3 Device-Related Function Requests
1.5.4 Directory-Related Function Requests
1.5.5 File Attributes
1.6 Microsoft Networks
1.7 National Language Support
1.8 Miscellaneous System-Management Functions
1.9 Old System Calls
1.9.1 File Control Block (FCB)
1.10 Using the System Calls
1.10.1 Issuing an Interupt
1.10.2 Calling a Function Request
1.10.3 Using the Calls from a High-Level Language
1.10.4 Treatment of Registers
1.10.5 Handling Errors
1.10.6 System Call Descriptions
1.10.6.1 Sample Programs
1.10.6.2 Error Handling in Sample Programs
1.11 Interrupts
1.11.1 Conditions upon Entry
1.11.2 Requirements for an Interrupt 24H Handler
1.1 Introduction
The routines that MS-DOS uses to manage system operation and resources can
be called by any application program. Using these system calls makes it
easier to write machine-independent programs and increases the likelihood
that a program will be compatible with future versions of MS-DOS. MS-DOS
system calls fall into several categories:
■ Standard character device I/O
■ Memory management
■ Process management
■ File and directory management
■ Microsoft Network calls
■ National Language Support calls
■ Miscellaneous system functions
Applications invoke MS-DOS services by using software interrupts. The
current range of interrupts used for MS-DOS is 20H-27H; 28H-40H are
reserved. Interrupt 21H is the function request service; it provides
access to a wide variety of MS-DOS services. In some cases, the full AX
register is used to specify the requested function. Each interrupt or
function request uses values in various registers to receive or return
function-specific information.
1.1.1 System Calls That Have Been Superseded
Many system calls introduced in versions of MS-DOS earlier than 2.0 have
been superseded by function requests that are more efficient and easier to
use. Although MS-DOS still includes these old system calls, they should
not be used unless it is imperative that a program maintain backward-
compatibility with versions of MS-DOS before 2.0.
A table of the pre-2.0 system calls and a description of the File
Control Block (required by some of the old calls) appears in Section 1.8,
"Old System Calls."
The first part of this chapter explains how DOS manages its resources--
such as memory, files, and processes--and briefly describes the purpose of
most of the system calls. The remainder of the chapter describes each
interrupt and function request in detail.
The system-call descriptions are in numeric order, interrupts followed
by function requests. These descriptions include further detail on how
MS-DOS manages its resources.
Chapter 2 of this manual describes how to write an MS-DOS device driver.
Chapters 3, 4, and 5 contain more detailed information about MS-DOS,
including how it manages disk space, the control blocks it uses, and how it
loads and executes relocatable programs (files with an extension of .exe).
Chapter 6 describes the Intel object module format. Chapter 7 gives some
programming hints.
1.2 Standard Character Device I/O
The standard character function requests handle all input and output to and
from character devices such as consoles, printers, and serial ports. If a
program uses these function requests, its input and output can be
redirected.
Table 1.1 lists the MS-DOS function requests for managing standard
character input and output.
Table 1.1
Standard Character I/O Function Requests
╓┌──────────┌────────────────────┌───────────────────────────────────────────╖
Code Request Description
───────────────────────────────────────────────────────────────────────
Code Request Description
───────────────────────────────────────────────────────────────────────
01H Read Keyboard and Gets a character from standard input
Echo and echoes it to standard output
02H Display Character Sends a character to standard output
03H Auxiliary Input Gets a character from standard
auxiliary
04H Auxiliary Output Sends a character to standard
auxiliary
05H Print Character Sends a character to the standard
printer
06H Direct Console I/O Gets a character from standard input
or sends a character to standard
output
07H Direct Console Gets a character from standard input
Code Request Description
07H Direct Console Gets a character from standard input
Input
08H Read Keyboard Gets a character from standard input
09H Display String Sends a string to standard output
0AH Buffered Keyboard Gets a string from standard input
Input
0BH Check Keyboard Reports on the status of the
Status standard input buffer
0CH Flush Buffer, Read Empties the standard input buffer
Keyboard and calls one of the other standard
character I/O function requests
Although several of these standard character I/O function requests seem to
do the same thing, they are distinguished by whether they check for control
characters or echo characters from standard input to standard output. The
detailed descriptions later in this chapter point out the differences.
1.3 Memory Management
MS-DOS keeps track of which areas of memory are allocated by writing a
memory control block at the beginning of each. This control block
specifies the size of the memory area; the name of the process, if any,
that owns the memory area; and a pointer to the next area of memory. If the
memory area is not owned, it is available.
Table 1.2 lists the MS-DOS function requests for managing memory.
Table 1.2
Memory-Management Function Requests
╓┌──────────┌─────────────────┌──────────────────────────────────────────────╖
Code Request Description
───────────────────────────────────────────────────────────────────────
Code Request Description
───────────────────────────────────────────────────────────────────────
48H Allocate Memory Requests a block of memory
49H Free Allocated Frees a block of memory
Memory previously allocated with 48H
4AH Set Block Changes the size of an allocated
memory block
When a process requests additional memory with Function 48H (Allocate
Memory), MS-DOS searches for a block of available memory large enough to
satisfy the request. If it finds such a block of memory, it changes the
memory control block to show the owning process. If the block of memory is
larger than the requested amount, MS-DOS changes the size field of the
memory control block to the requested amount, writes a new memory control
block at the beginning of the unneeded portion showing that it is
available, and updates the pointers to add this memory to the chain of
memory control blocks. MS-DOS then returns the segment address of the
first byte of the allocated memory to the requesting process.
When a process releases an allocated block of memory with Function 49H
(Free Allocated Memory), MS-DOS changes the memory control block to show
that it is available (not owned by any process).
When a process uses Function 4AH (Set Block) to shrink an allocated
block of memory, MS-DOS builds a memory control block for the memory being
released and adds it to the chain of memory control blocks. When a process
tries to use Function 4AH (Set Block) to expand an allocated block of
memory, MS-DOS treats it as a request for additional memory rather than
returning the segment address of the additional memory to the requesting
process. However, MS-DOS simply chains the additional memory to the
existing memory block.
If MS-DOS can't find a block of available memory large enough to satisfy a
request for additional memory made with either Function 48H (Allocate
Memory) or Function 4AH (Set Block), MS-DOS returns an error code to the
requesting process.
When a program receives control, it should call Function 4AH (Set
Block) to shrink its initial memory-allocation block (the block that begins
with its Program Segment Prefix) to the minimum it requires. This frees
unneeded memory and makes the best application design for portability to
future multitasking environments.
When a program exits, MS-DOS automatically frees its initial memory-
allocation block before returning control to the calling program
(command.com is usually the calling program for application programs). The
DOS frees any memory owned by the exiting process.
Any program that changes memory that is not allocated to it will most
likely destroy at least one memory-management control block. This causes a
memory-allocation error the next time MS-DOS tries to use the chain of
memory control blocks; the only cure is to restart the system.
1.4 Process Management
MS-DOS uses several function requests to load, execute, and terminate
programs. Application programs can use these same function requests to
manage other programs.
Table 1.3 lists the MS-DOS function requests for managing processes.
Table 1.3
Process-Management Function Requests
╓┌────────────┌──────────────────┌───────────────────────────────────────────╖
Code Request Description
──────────────────────────────────────────────────────────────────────
31H Keep Process Terminates a process and
returns control to the
invoking process, but keeps
the terminated process in
memory
4BH Load and Execute Loads and executes a program
Program
4B03H Load Overlay Loads a program overlay
without executing it
Code Request Description
4CH End Process Returns control to the
invoking process
4DH Get Return Code Returns a code passed by an
of Child Process exiting child process
62H Get PSP Returns the segment address of
the current process's Program
Segment Prefix
1.4.1 Loading and Executing a Program
When a program uses Function 4BH (Load and Execute Program) to load and
execute another program, MS-DOS allocates memory, writes a Program Segment
Prefix (PSP) for the new program at offset 0 of the allocated memory, loads
the new program, and passes control to it. When the invoked program exits,
control returns to the calling program.
Command.com uses Function 4BH to load and execute command files.
Application programs have the same degree of control over process
management as does command.com.
In addition to these common features, there are some differences in the
way MS-DOS loads .com and .exe files.
Loading a .com Program
When command.com loads and executes a .com program, it allocates all
available memory to the application and sets the stack pointer 100H bytes
from the end of available memory. A .com program should set up its own
stack before shrinking its initial memory-allocation block with Function
4AH (Set Block) because the default stack is in the memory to be released.
If a newly loaded program is allocated all of memory--as a .com program
is--or requests all of available memory by using Function 48H (Allocate
Memory), MS-DOS allocates to it the memory occupied by the transient part
of command.com. If the program changes this memory, MS-DOS must reload the
transient portion of command.com before it can continue. If a program exits
(via Function 31H, Keep Process) without releasing enough memory, the
system halts and must be reset. To minimize this possibility, a .com
program should use Function 4AH (Set Block) to shrink its initial
allocation block before doing anything else, and before exiting, all
programs must release all memory they allocate by using Function 48H
(Allocate Memory).
Loading an .exe Program
When command.com loads and executes an .exe program, it allocates the size
of the program's memory image plus either the value in the MAX_ALLOC field
(offset 0CH) of the file header (if that much memory is available) or the
value in the MIN_ALLOC field (offset 0AH). The linker sets these fields.
Before passing control to the .exe file, MS-DOS uses the relocation
information in the file header to calculate the correct relocation
addresses.
For a more detailed description of how MS-DOS loads .com and .exe
files, see Chapter 3, "MS-DOS Technical Information," and Chapter 4,
"MS-DOS Control Blocks and Work Areas."
Executing a Program from Within Another Program
Since command.com builds pathnames, searches directory paths for executable
files, and relocates .exe files, the simplest way to load and execute a
program is to load and execute an additional copy of command.com, passing
it a command line that includes the /C switch, which invokes the .com or
.exe file. The description of Function 4B00H (Load and Execute Program)
describes how to do this.
1.4.2 Loading an Overlay
When a program uses Function 4B03H (Load Overlay) to load an overlay, it
must pass MS-DOS the segment address at which the overlay is to be loaded.
The program must call the overlay, which then returns directly to the
calling program. The calling program is in complete control: MS-DOS does
not write a PSP for the overlay or intervene in any other way.
MS-DOS does not check to see if the calling program owns the memory
where the overlay is to be loaded. If the calling program does not own the
memory, loading the overlay will most likely destroy a memory-control
block, causing an eventual memory-allocation error.
Therefore, a program that loads an overlay must either allow room for
the overlay when it calls Function 4AH (Set Block) to shrink its initial
memory-allocation block, or shrink its initial memory-allocation block to
the minimum and then use Function 48H (Allocate Memory) to allocate memory
for the overlay.
1.5 File and Directory Management
The MS-DOS hierarchical (multilevel) file system is similar to that of the
XENIX operating system. For a description of the multilevel directory
system and how to use it, see the MS-DOS User's Reference.
1.5.1 Handles
To create or open a file, a program passes MS-DOS a pathname and the
attribute to be assigned to the file. MS-DOS returns a 16-bit number,
called a handle. For most subsequent actions, MS-DOS requires only this
handle to identify the file.
A handle can refer to either a file or a device. MS-DOS predefines five
standard handles. These handles are always open, so you needn't open them
before you use them. Table 1.4 lists these predefined handles.
Table 1.4
Predefined Device Handles
╓┌─────────────┌─────────────────┌───────────────────────────────────────────╖
Handle Standard device Comment
──────────────────────────────────────────────────────────────────────
0 Input Can be redirected from command line
1 Output Can be redirected from command line
2 Error
3 Auxiliary
4 Printer
When MS-DOS creates or opens a file, it assigns the first available handle.
Since a program can have 20 open handles, including the five predefined
handles, it typically can open 15 extra files. By using Function 46H
(Force Duplicate File Handle), MS-DOS can temporarily force any of the five
predefined handles to refer to an alternate file or device. For more
information about Function 46H, see its description later in this chapter.
1.5.2 File-Related Function Requests
MS-DOS treats a file as a string of bytes; it assumes no record structure
or access technique. An application program imposes whatever record
structure it needs on this string of bytes. Reading from or writing to a
file requires only pointing to the data buffer and specifying the number of
bytes to read or write.
Table 1.5 lists the MS-DOS function requests for managing files.
Table 1.5
File-Related Function Requests
╓┌──────────┌─────────────────────────────┌──────────────────────────────────╖
Code Request Description
──────────────────────────────────────────────────────────────────────
3CH Create Handle Creates a file
3DH Open Handle Opens a file
3EH Close Handle Closes a file
3FH Read Handle Reads from a file
40H Write Handle Writes to a file
42H Move File Pointer Sets the read/write pointer in a
file
45H Duplicate File Handle Creates a new handle that refers
to the same file as an existing
handle
Code Request Description
46H Force Duplicate File Handle Makes an existing handle refer to
the same file as another existing
handle
5AH Create Temporary File Creates a file with a unique name
5BH Create New File Attempts to create a file, but
fails if a file with the same name
exists
67H Set Handle Count Increases or decreases the number
of files a program can have open
at one time
68H Commit File Flushes buffered data for a file
without closing it to ensure the
disk image of that file is current
File Sharing
Version 3.1 of MS-DOS introduces file sharing, which lets more than one
process share access to a file. File sharing operates only after the share
command has been executed to load file-sharing support. That is, you must
use the share command to take advantage of file sharing.
Table 1.6 lists the MS-DOS function requests for sharing files; if file
sharing is not in effect, these function requests cannot be used. Function
3DH (Open Handle) can operate in several modes. Here it is referred to in
the file-sharing modes, which require file sharing to be in effect.
(Compatibility mode is usable without file sharing in effect.)
Table 1.6
File-Sharing Function Requests
╓┌────────────┌─────────────┌────────────────────────────────────────────────╖
Code Request Description
──────────────────────────────────────────────────────────────────────
3DH Open Handle Opens a file by using one of the
file-sharing modes
Code Request Description
file-sharing modes
440BH IOCtl Retry (before Interrupt 24 is issued)
Specifies how many times to retry
an I/O operation that fails due
to a file-sharing violation
5C00H Lock Locks a region of a file
5C01H Unlock Unlocks a region of a file
1.5.3 Device-Related Function Requests
I/O Control for devices is implemented with Function 44H (IOCtl), which
includes several subfunctions necessary to perform device-related tasks.
Some forms of the IOCtl function request require that the device driver be
written to support the IOCtl interface. Table 1.7 lists the MS-DOS function
requests for managing devices.
Table 1.7
Device-Related Function Requests
╓┌────────────────┌─────────────────────────────┌────────────────────────────╖
Code Request Description
──────────────────────────────────────────────────────────────────────
4400H,01H IOCtl Data Gets or sets device
description
4402H,03H IOCtl Character Gets or sets character-
device control data
4404H,05H IOCtl Block Gets or sets block-device
control data
4406H,07H IOCtl Status Checks device input or
output status
4408H IOCtl Is Changeable Checks whether block device
contains removable medium
Code Request Description
440CH Generic IOCtl (for handles) Sets Generic IOCtl for
handles and supports code
pages for devices
440DH Generic IOCtl (for devices) Sets Generic IOCtl for
devices
440E,0FH Get/Set IOCtl Drive Map Gets or sets logical
drive map
Some forms of the IOCtl function request can be used only with Microsoft
Networks; these forms are listed in Section 1.6, "Microsoft Networks."
1.5.4 Directory-Related Function Requests
A directory entry is a 32-byte record that includes the file's name,
extension, date and time of last change, and size. An entry in a
subdirectory is identical to an entry in the root directory. Directory
entries are described in detail in Chapter 3, "MS-DOS Technical
Information."
The root directory on a disk has room for a fixed number of entries: 64
on a standard single-sided disk, 112 on a standard double-sided disk. For
hard disks, the number of directories depends on the DOS partition size. A
subdirectory is simply a file with a unique attribute; there can be as many
subdirectories on a disk as space allows. The depth of a directory
structure, therefore, is limited only by the amount of storage on a disk
and the maximum pathname length of 64 characters. Pre-2.0 disks appear to
have only a root directory that contains files but no subdirectories.
Table 1.8 lists the MS-DOS function requests for managing directories.
Table 1.8
Directory-Related Function Requests
╓┌──────────┌─────────────────────────────────┌──────────────────────────────╖
Code Request Description
──────────────────────────────────────────────────────────────────────
39H Create Directory Creates a subdirectory
Code Request Description
39H Create Directory Creates a subdirectory
3AH Remove Directory Deletes a subdirectory
3BH Change Current Directory Changes the current directory
41H Delete Directory Entry (Unlink) Deletes a file
43H Get/Set File Attributes (Chmod) Retrieves or changes the
attributes of a file
47H Get Current Directory Returns current directory for
a given drive
4EH Find First File Searches a directory for the
first entry that matches a
filename
4FH Find Next File Searches a directory for the
next entry that matches a
Code Request Description
next entry that matches a
filename
56H Change Directory Entry Renames a file
57H Get/Set Date/Time of File Changes the time and date of
last change in a directory
entry
1.5.5 File Attributes
Table 1.9 describes the file attributes and how they are represented in
the attribute byte of the directory entry (offset 0BH). The attributes can
be inspected or changed with Function 43H (Get/Set File Attributes
[Chmod]).
Table 1.9
File Attributes
╓┌───────────┌───────────────────────────────────────────────────────────────╖
Code Description
──────────────────────────────────────────────────────────────────────
00H Normal; can be read or written without
restriction
01H Read-only; cannot be opened for write; a
file with the same name cannot be created
02H Hidden; not found by directory search
04H System; not found by directory search
08H VolumeID; only one file can have this
attribute; it must be in the root directory
10H Subdirectory
20H Archive; set whenever the file is changed,
or cleared by the Backup command
The VolumeID (08H) and Subdirectory (10H) attributes cannot be changed with
Function 43H (Get/Set File Attributes [Chmod]).
1.6 Microsoft Networks
Microsoft Networks consists of a server and one or more workstations.
MS-DOS maintains an assign list that keeps track of which workstation
drives and devices have been redirected to the server. For a description of
operation and use of the network, see the Microsoft Networks 1.0 Manager's
Guide and Microsoft Networks 1.0 User's Guide.
Table 1.10 lists the MS-DOS function requests for managing a Microsoft
Networks workstation.
Table 1.10
Microsoft Networks Function Requests
╓┌────────────┌───────────────────┌──────────────────────────────────────────╖
Code Request Description
──────────────────────────────────────────────────────────────────────
4409H IOCtl Is Checks whether a drive letter refers to
Redirected Block a local or redirected drive
440AH IOCtl Is Checks whether a device name refers to a
Redirected Handle local or redirected device
5E00H Get Machine Name Gets the network name of the workstation
5E02H Printer Setup Defines a string of control characters
to be added at the beginning of each
file that is sent to a network
printer
5F02H Get Assign-List Gets an entry from the assign list,
Entry which shows the workstation drive letter
or device name and the net name of the
directory or device on the server to
which the entry is reassigned
Code Request Description
5F03H Make Assign-List Redirects a workstation drive or device
Entry to a server directory or device
5F04H Cancel Assign- Cancels the redirection of a workstation
List Entry drive or device to a server directory or
device
1.7 National Language Support
National language support for this version of MS-DOS includes these
major features:
■ Country-dependent information
■ Support for national keyboard layouts
■ Programming interfaces for national language support
■ Utility commands
Country-dependent information is available on a per-country basis and
includes the following:
■ Time, date, and currency
■ Lowercase-to-uppercase character-conversion tables
■ Collating sequence for character sorting
■ Valid single-byte characters used in filenames
Keyboard support for different keyboard layouts is provided and
selectable.
Table 1.11 lists the MS-DOS national-language-support system calls that
allow applications to use the country-dependent information just described.
Table 1.11
National Language-Support Function Requests
╓┌──────────┌──────────────────────────────────┌─────────────────────────────╖
Code Request Description
──────────────────────────────────────────────────────────────────────
65H Get Extended Country Information Returns standard
country information,
pointer to uppercase
table, pointer to
filename uppercasing
table, or pointer to
collating table
66H Get/Set Global Code Page Gets or sets the code
page used by the
kernel and all
devices.
1.8 Miscellaneous System-Management Functions
The remaining system calls manage other system functions and resources such
as drives, addresses, and the clock. Table 1.12 lists the MS-DOS function
requests for managing miscellaneous system resources and operation.
Table 1.12
Miscellaneous System-Management Function Requests
╓┌──────────┌───────────────────────┌────────────────────────────────────────╖
Code Request Description
─────────────────────────────────────────────────────────────────────
0DH Reset Disk Empties all file buffers
0EH Select Disk Sets the default drive
19H Get Current Disk Returns the default drive
1AH Set Disk Transfer Establishes the disk I/O buffer
Address
1BH Get Default Drive Returns disk-format data
Code Request Description
1BH Get Default Drive Returns disk-format data
Data
1CH Get Drive Data Returns disk-format data
25H Set Interrupt Vector Sets interrupt-handler address
29H Parse File Name Checks string for valid filename
2AH Get Date Returns system date
2BH Set Date Sets system date
2CH Get Time Returns system time
2DH Set Time Sets system time
2EH Set/Reset Verify Flag Turns disk verify on or off
2FH Get Disk Transfer Returns system-disk-I/O-buffer
Code Request Description
2FH Get Disk Transfer Returns system-disk-I/O-buffer
Address address
30H Get MS-DOS Version Returns MS-DOS version number
Number
33H CONTROL-C Check Returns CONTROL-C check status
35H Get Interrupt Vector Returns address of interrupt
handler
36H Get Disk Free Space Returns disk-space data
38H Get/Set Country Data Sets current country or
retrieves country information
54H Get Verify State Returns status of disk verify
1.9 Old System Calls
Most of the superseded system calls deal with files. Table 1.13 lists
these old calls and the function requests that have superseded them.
Although MS-DOS still includes these old system calls, they should not
be used unless a program must maintain backward-compatibility with earlier
versions of MS-DOS.
Table 1.13
Old System Calls and Their Replacements
╓┌─────────────────────────────────────────┌─────────────────────────────────╖
Old System Call Has Been Superseded By
Code Function Code Function
──────────────────────────────────────────────────────────────────────
00H Terminate Program 4CH End Process
0FH Open File 3DH Open Handle
10H Close File 3EH Close Handle
Old System Call Has Been Superseded By
Code Function Code Function
10H Close File 3EH Close Handle
11H Search for First Entry 4EH Find First File
12H Search for Next Entry 4FH Find Next File
13H Delete File 41H Delete Directory Entry
14H Sequential Read 3FH Read Handle
15H Sequential Write 40H Write Handle
16H Create File 3CH Create Handle
5AH Create Temporary File
5BH Create New File
17H Rename File 56H Change Directory Entry
21H Random Read 3FH Read Handle
Old System Call Has Been Superseded By
Code Function Code Function
21H Random Read 3FH Read Handle
22H Random Write 40H Write Handle
23H Get File Size 42H Move File Pointer
24H Set Relative Record 42H Move File Pointer
26H Create New PSP 4BH Load and Execute Program
27H Random Block Read 42H Move File Pointer
3FH Read Handle
28H Random Block Write 42H Move File Pointer
40H Write Handle
Code Interrupt Code Function
──────────────────────────────────────────────────────────────────────
20H Program Terminate 4CH End Process
Old System Call Has Been Superseded By
Code Function Code Function
20H Program Terminate 4CH End Process
27H Terminate But Stay Resident 31H Keep Process
1.9.1 File Control Block (FCB)
The old file-related function requests require that a program maintain a
File Control Block (FCB) for each file; this control block contains such
information as a file's name, size, record length, and pointer to current
record. MS-DOS does most of this housekeeping for the newer, handle-
oriented function requests.
Some descriptions of the old function requests refer to unopened and
opened FCBs. An unopened FCB contains only a drive specifier and filename.
An opened FCB contains all fields filled by Function 0FH (Open File).
The Program Segment Prefix (PSP) includes room for two FCBs at
offsets 5CH and 6CH. For a description of how to use the PSP and FCB
calls, see Chapter 4, "MS-DOS Control Blocks and Work Areas," Table 1.14
describes the FCB fields.
Table 1.14
Format of the File Control Block (FCB)
╓┌────────────┌──────┌──────┌────────────────────────────────────────────────╖
Offset
Hex Dec Bytes Field
──────────────────────────────────────────────────────────────────────
00H 0 1 Drive Number
01H 1 8 Filename
09H 9 3 Extension
0CH 12 2 Current Block
0EH 14 2 Record Size
10H 16 4 File Size
14H 20 2 Date of Last Write
16H 22 2 Time of Last Write
18H 24 8 Reserved
Offset
Hex Dec Bytes Field
18H 24 8 Reserved
20H 32 1 Current Record
21H 33 4 Relative Record
Fields of the FCB
Drive Number (offset 00H): Specifies the disk drive; 1 means drive A and
2 means drive B. If you use the FCB to create or open a file, you can set
this field to 0 to specify the default drive; Function 0FH (Open File) sets
the field to the number of the default drive.
Filename (offset 01H): Eight characters, left-aligned and padded
(if necessary) with blanks. If you specify a reserved device name (such
as PRN), do not put a colon at the end.
Extension (offset 09H): Three characters, left-aligned and padded (if
necessary) with blanks. This field can be all blanks (no extension).
Current Block (offset 0CH): Points to the block (group of 128 records)
that contains the current record. This field and the Current Record field
(offset 1FH) make up the record pointer. This field is set to zero by the
Open File system call.
Record Size (offset 0EH): The size of a logical record, in bytes. Set
to 128 by the Open File system call. If the record size is not 128 bytes,
you must set this field after opening the file.
File Size (offset 0FH): The size of the file, in bytes. The first word
of this 4-byte field is the low-order part of the size.
Date of Last Write (offset 13H): The date the file was created or last
updated. The year, month, and day are mapped into two bytes as follows:
Off set 14H Offset 13H
|Y|Y|Y|Y|Y|Y|Y|M| |M|M|M|D|D|D|D|D|
15 9 8 5 4 0
Time of Last Write (offset 15H): The time the file was created or last
updated. The hour, minutes, and seconds are mapped into two bytes as
follows:
Offset 16H Offset 15H
|H|H|H|H|H|M|M|M| |M|M|M|S|S|S|S|S|
15 11 10 5 4 0
Reserved (offset 17H): These fields are reserved for use by MS-DOS.
Current Record (offset 1FH): Points to one of the 128 records in the
current block. This field and the Current Block field (offset 0CH) make up
the record pointer. The Open File system call does not initialize this
field. You must set it before doing a sequential read or write to the file.
Relative Record (offset 20H): Points to the currently selected record,
counting from the beginning of the file (starting with 0). The Open File
system call does not initialize this field. You must set it before doing a
random read or write to the file. If the record size is less than 64 bytes,
both words of this field are used; if the record size is 64 bytes or more,
only the first three bytes are used.
───────────────────────────────────────────────────────────────────────────
Note
If you use the FCB at offset 5CH of the Program Segment Prefix, the last
byte of the Relative Record field is the first byte of the unformatted
parameter area that starts at offset 80H. This is the default Disk
Transfer Area.
───────────────────────────────────────────────────────────────────────────
Extended FCB
The Extended File Control Block is used to create or search for
directory entries of files with special attributes. It adds the following
7-byte prefix to the FCB:
Name Bytes Offset
───────────────────────────────────────────────────────────────────────────
Flag byte (FFH) 1 07H
Reserved 5 06H
Attribute byte 1 01H
File attributes are described earlier in this chapter in Section 1.5.5,
"File Attributes."
───────────────────────────────────────────────────────────────────────────
Note
You must remember to point to the beginning of the extended FCB if you
are using Functions 0FH-16H with extended FCBs.
───────────────────────────────────────────────────────────────────────────
1.10 Using the System Calls
The remainder of this chapter describes how to use the system calls in
application programs, and it lists the calls in numeric and alphabetic
order, describing each call in detail.
1.10.1 Issuing an Interrupt
MS-DOS reserves Interrupts 28H through 3FH for its own use, and
maintains the table of interrupt-handler addresses (the vector table) in
locations 80H-FCH. Also, in case you need to write your own routines for
three particular MS-DOS interrupt handlers (Program Terminate, CONTROL-C,
and Critical Error), this chapter includes descriptions of each. Function
requests have superseded most of these interrupts.
To issue an interrupt, move any required data into the registers and
give the INT instruction with the number of the interrupt you want.
1.10.2 Calling a Function Request
A function request is an MS-DOS routine for managing system resources. Use
the following procedure to call a function request:
1. Move any required data into the registers.
2. Move the function number into AH.
3. Move the action code, if required, into AL.
4. Issue Interrupt 21H.
1.10.3 Using the Calls from a High-Level Language
The system calls can be executed from any high-level language whose
modules can be linked with assembly-language modules. In addition to this
linking technique, you can:
■ Use the DOSXQQ function of Pascal-86 to call a function request
directly.
■ Use the CALL statement or USER function to execute the required
assembly-language code from the BASIC interpreter.
1.10.4 Treatment of Registers
When MS-DOS takes control after a function request, it switches to an
internal stack, and preserves any registers not used to return information
(except AX). The calling program's stack must be large enough to
accommodate the interrupt system--at least 128 bytes in addition to other
needs.
1.10.5 Handling Errors
Most of the function requests introduced with version 2.0 or later set
the Carry flag if there is an error, identifying the specific error by
returning a number in the AX register. Table 1.15 lists these error codes
and their meanings.
Table 1.15
Error Codes Returned in AX
╓┌────────────┌──────────────────────────────────────────────────────────────╖
Code Meaning
──────────────────────────────────────────────────────────────────────
Code Meaning
──────────────────────────────────────────────────────────────────────
1 Invalid function code
2 File not found
3 Path not found
4 Too many open files (no open handles left)
5 Access denied
6 Invalid handle
7 Memory control blocks destroyed
8 Insufficient memory
9 Invalid memory block address
10 Invalid environment
11 Invalid format
12 Invalid access code
13 Invalid data
14 Reserved
15 Invalid drive
16 Attempt to remove the current directory
17 Not same device
18 No more files
Code Meaning
18 No more files
19 Disk is write-protected
20 Bad disk unit
21 Drive not ready
22 Invalid disk command
23 CRC error
24 Invalid length (disk operation)
25 Seek error
26 Not an MS-DOS disk
27 Sector not found
28 Out of paper
29 Write fault
30 Read fault
31 General failure
32 Sharing violation
33 Lock violation
34 Wrong disk
35 FCB unavailable
Code Meaning
35 FCB unavailable
36-49 Reserved
50 Network request not supported
51 Remote computer not listening
52 Duplicate name on network
53 Network name not found
54 Network busy
55 Network device no longer exists
56 Net BIOS command limit exceeded
57 Network adapter hardware error
58 Incorrect response from network
59 Unexpected network error
60 Incompatible remote adapter
61 Print queue full
62 Queue not full
63 Not enough space for print file
64 Network name was deleted
65 Access denied
Code Meaning
65 Access denied
66 Network device type incorrect
67 Network name not found
68 Network name limit exceeded
69 Net BIOS session limit exceeded
70 Temporarily paused
71 Network request not accepted
72 Print or disk redirection is paused
73-79 Reserved
80 File exists
81 Reserved
82 Cannot make
83 Interrupt 24 failure
84 Out of structures
85 Already assigned
86 Invalid password
87 Invalid parameter
88 Net write fault
Code Meaning
88 Net write fault
To handle error conditions, put the following statement immediately after
calls that return errors:
JC <error>
<Error> represents the label of an error-handling routine that gets the
specific error condition by checking the value in AX. This routine then
takes appropriate action.
Some of the older system calls return a value in a register that
specifies whether the operation was successful. To handle such errors,
check the error code and take the appropriate action.
Extended Error Codes
Versions of MS-DOS after 2.0 have added new error messages. Any
programs that use the older system calls cannot use these new error
messages. To avoid incompatibility, MS-DOS maps these new error codes
to the old error code that most closely matches the new one.
Function 59H (Get Extended Error) has been added so that these new
calls can be used. It provides as much detail as possible about the most
recent error code returned by MS-DOS. The description of Function 59H
lists the new, more detailed error codes and shows how to use this function
request.
1.10.6 System Call Descriptions
Most system calls require that you move information into one or more
registers before issuing the call that returns information in the
registers. The description of each system call in this chapter includes
the following:
■ A diagram of the 8088 registers that shows their contents before and
after the system call
■ A more complete description of the register contents required before
the system call
■ A description of the processing performed
■ A more complete description of the register contents after the
system call
■ An example of how to use the system call
The following figure is a sample illustration of the 8088 registers,
showing how the information is presented. Shaded areas indicate that the
register receives or returns information used by the call.
┌──────────┬──────────┐
│▒▒▒▒AH▒▒▒▒│▒▒▒▒AL▒▒▒▒│
├──────────┼──────────┤
│ BH │ BL │
├──────────┼──────────┤
│ CH │ CL │
├──────────┼──────────┤
│▒▒▒▒DH▒▒▒▒│▒▒▒▒DL▒▒▒▒│
└──────────┴──────────┘
┌─────────────────────┐
│ SP │
├─────────────────────┤
│ BP │
├─────────────────────┤
│ SI │
├─────────────────────┤
│ DI │
└─────────────────────┘
┌─────────────────────┐
│ IP │
├──────────┬──────────┤
│ FLAGSH │▒▒FLAGSL▒▒│
└──────────┴──────────┘
┌─────────────────────┐
│ CS │
├─────────────────────┤
│▒▒▒▒▒▒▒▒▒▒DS▒▒▒▒▒▒▒▒▒│
├─────────────────────┤
│ SS │
├─────────────────────┤
│ ES │
└─────────────────────┘
Figure 1.1 Example of the 8088 Registers
1.10.6.1 Sample Programs
The sample programs show only data declarations and the code that you need
to use the system calls. Unless stated otherwise, each example assumes a
common program skeleton that defines the segments and returns control to
MS-DOS. Each sample program is intended to be executed as a .com file.
Figure 1.2 shows a complete sample program. The unshaded portion shows
what appears in this chapter; the shaded portions are the common skeleton.
───────────────────────────────────────────────────────────────────────────
code segment
assume cs:code,ds:code,es:nothing,ss:nothing
org 100H
start: jmp begin
;
filename db "b:\textfile.asc",0
buffer db 129 dup (?)
handle dw ?
;
begin: open_handle filename,0 ; Open the file
jc error_open ; Routine not shown
mov handle,ax ; Save handle
read_line: read_handle handle,buffer,128 ; Read 128 bytes
jc error_read ; Routine not shown
cmp ax,0 ; End of file?
je return ; Yes, go home
mov bx,ax ; No, AX bytes read
mov buffer[bx],"$" ; To terminate string
display buffer ; See Function 09H
jmp read_line ; Get next 128 bytes
return: end_process 0 ; Return to MS-DOS
last_inst: ; To mark next byte
;
code ends
end start
───────────────────────────────────────────────────────────────────────────
Figure 1.2 Sample Program with Common Skeleton
A macro has been defined for each system call to allow the examples to
be more complete programs, rather than isolated uses of the system calls.
These macros, plus some general-purpose ones, are used in the sample
programs. For instance, the sample program in the preceding figure
includes four such macros: open_handle, read_handle, display, and
end_process. All the macro definitions are listed at the end of this
chapter.
The macros assume the environment for a .com program as described in
Chapter 4; in particular, they assume that all the segment registers
contain the same value. To conserve space, the macros generally leave error
checking to the main code and do not protect registers. This keeps the
macros short, yet useful. You may find that such macros are a convenient
way to include system calls in your assembly-language programs.
1.10.6.2 Error Handling in Sample Programs
Whenever a system call returns an error code, the sample program shows
a test for the error condition and a jump to an error routine. To conserve
space, the error routines themselves aren't shown. Some error routines
might simply display a message and continue processing. For more serious
errors, the routine might display a message and end the program (performing
any required housekeeping, such as closing files).
Tables 1.16 through 1.19 list the Interrupts and Function Requests in
numeric and alphabetic order.
Table 1.16
MS-DOS Interrupts, Numeric Order
╓┌────────────────┌──────────────────────────────────────────────────────────╖
Interrupt Description
Interrupt Description
──────────────────────────────────────────────────────────────────────
20H Program Terminate
21H Function Request
22H Terminate Process Exit Address
23H CONTROL-C Handler Address
24H Critical-Error-Handler Address
25H Absolute Disk Read
26H Absolute Disk Write
27H Terminate But Stay Resident
28H-3FH Reserved
Table 1.17
MS-DOS Interrupts, Alphabetic Order
╓┌─────────────────────────────────────┌─────────────────────────────────────╖
Description Interrupt
──────────────────────────────────────────────────────────────────────
Absolute Disk Read 25H
Absolute Disk Write 26H
Description Interrupt
Absolute Disk Write 26H
CONTROL-C Handler Address 23H
Critical-Error-Handler Address 24H
Function Request 21H
Program Terminate 20H
Reserved 28H-3FH
Terminate Process Exit Address 22H
Terminate But Stay Resident 27H
Table 1.18
MS-DOS Function Requests, Numeric Order
╓┌──────────────────┌────────────────────────────────────────────────────────╖
Function Description
──────────────────────────────────────────────────────────────────────
00H Terminate Program
01H Read Keyboard And Echo
02H Display Character
03H Auxiliary Input
Function Description
03H Auxiliary Input
04H Auxiliary Output
05H Print Character
06H Direct Console I/O
07H Direct Console Input
08H Read Keyboard
09H Display String
0AH Buffered Keyboard Input
0BH Check Keyboard Status
0CH Flush Buffer, Read Keyboard
0DH Reset Disk
0EH Select Disk
0FH Open File
10H Close File
11H Search For First Entry
12H Search For Next Entry
13H Delete File
14H Sequential Read
15H Sequential Write
16H Create File
Function Description
16H Create File
17H Rename File
18H Reserved
19H Get Current Disk
1AH Set Disk Transfer Address
1BH Get Default Drive Data
1CH Get Drive Data
1DH-20H Reserved
21H Random Read
22H Random Write
23H Get File Size
24H Set Relative Record
25H Set Interrupt Vector
26H Create New PSP
27H Random Block Read
28H Random Block Write
29H Parse File Name
2AH Get Date
2BH Set Date
2CH Get Time
Function Description
2CH Get Time
2DH Set Time
2EH Set/Reset Verify Flag
2FH Get Disk Transfer Address
30H Get MS-DOS Version Number
31H Keep Process
32H Reserved
33H CONTROL-C Check
34H Reserved
35H Get Interrupt Vector
36H Get Disk Free Space
37H Reserved
38H Get/Set Country Data
39H Create Directory
3AH Remove Directory
3BH Change Current Directory
3CH Create Handle
3DH Open Handle
3EH Close Handle
3FH Read Handle
Function Description
3FH Read Handle
40H Write Handle
41H Delete Directory Entry (Unlink)
42H Move File Pointer
43H Get/Set File Attributes (Chmod)
4400H,4401H IOCtl Data
4402H,4403H IOCtl Character
4404H,4405H IOCtl Block
4406H,4407H IOCtl Status
4408H IOCtl Is Changeable
4409H IOCtl Is Redirected Block
440AH IOCtl Is Redirected Handle
440BH IOCtl Retry
440CH Generic IOCtl (for code page functions)
440DH Generic IOCtl (for devices)
440EH Get IOCtl Drive Map
440FH Set IOCtl Drive Map
45H Duplicate File Handle
46H Force Duplicate File Handle
47H Get Current Directory
Function Description
47H Get Current Directory
48H Allocate Memory
49H Free Allocated Memory
4AH Set Block
4BH Load and Execute Program
4B03H Load Overlay
4CH End Process
4DH Get Return Code of Child Process
4EH Find First File
4FH Find Next File
50H-53H Reserved
54H Get Verify State
55H Reserved
56H Change Directory Entry
57H Get/Set Date/Time of File
58H Get/Set Allocation Strategy
59H Get Extended Error
5AH Create Temporary File
5BH Create New File
5C00H Lock
Function Description
5C00H Lock
5C01H Unlock
5DH Reserved
5E00H Get Machine Name
5E02H Printer Setup
5F02H Get Assign-List Entry
5F03H Make Assign-List Entry
5F04H Cancel Assign-List Entry
60H-61H Reserved
62H Get PSP
63H,64H Reserved
65H Get Extended Country Information
66H Get/Set Global Code Page
67H Set Handle Count
68H Commit File
69H-7FH Reserved
Table 1.19
MS-DOS Function Requests, Alphabetic Order
╓┌──────────────────────────────────────────────┌────────────────────────────╖
Description Interrupt
──────────────────────────────────────────────────────────────────────
Allocate Memory 48H
Auxiliary Input 03H
Auxiliary Output 04H
Buffered Keyboard Input 0AH
Cancel Assign-List Entry 5F04H
Change Current Directory 3BH
Change Directory Entry 56H
Check Keyboard Status 0BH
Close File 10H
Close Handle 3EH
Commit FIle 68H
CONTROL-C Check 33H
Create Directory 39H
Create File 16H
Create Handle 3CH
Create New File 5BH
Create New PSP 26H
Description Interrupt
Create New PSP 26H
Create Temporary File 5AH
Delete Directory Entry (Unlink) 41H
Delete File 13H
Direct Console I/O 06H
Direct Console Input 07H
Display Character 02H
Display String 09H
Duplicate File Handle 45H
End Process 4CH
Find First File 4EH
Find Next File 4FH
Flush Buffer, Read Keyboard 0CH
Force Duplicate File Handle 46H
Free Allocated Memory 49H
Generic IOCtl (for devices) 440DH
Generic IOCtl (for code page functions) 440CH
Get Assign-List Entry 5F02H
Get Current Directory 47H
Get Current Disk 19H
Description Interrupt
Get Current Disk 19H
Get Date 2AH
Get Default Drive Data 1BH
Get Disk Free Space 36H
Get Disk Transfer Address 2FH
Get Drive Data 1CH
Get Extended Country Information 65H
Get Extended Error 59H
Get File Size 23H
Get Interrupt Vector 35H
Get IOCtl Drive Map 440EH
Get Machine Name 5E00H
Get MS-DOS Version Number 30H
Get PSP 62H
Get Return Code of Child Process 4DH
Get Time 2CH
Get Verify State 54H
Get/Set Allocation Strategy 58H
Get/Set Country Data 38H
Get/Set Date/Time Of File 57H
Description Interrupt
Get/Set Date/Time Of File 57H
Get/Set File Attributes (Chmod) 43H
Get/Set Global Code Page 66H
IOCtl Block 4404H,4405H
IOCtl Character 4402H,4403H
IOCtl Data 4400H,4401H
IOCtl Is Changeable 4408H
IOCtl Is Redirected Block 4409H
IOCtl Is Redirected Handle 440AH
IOCtl Retry 440BH
IOCtl Status 4406H,4407H
Keep Process 31H
Load and Execute Program 4BH
Load Overlay 4B03H
Lock 5C00H
Make Assign-List Entry 5F03H
Move File Pointer 42H
Open File 0FH
Open Handle 3DH
Parse File Name 29H
Description Interrupt
Parse File Name 29H
Print Character 05H
Printer Setup 5E02H
Random Block Read 27H
Random Block Write 28H
Random Read 21H
Random Write 22H
Read Handle 3FH
Read Keyboard 08H
Read Keyboard And Echo 01H
Remove Directory 3AH
Rename File 17H
Reserved 18H
Reserved 1DH-20H
Reserved 32H
Reserved 34H
Reserved 37H
Reserved 50H-53H
Reserved 55H
Reserved 5DH
Description Interrupt
Reserved 5DH
Reserved 60H-61H
Reserved 63H, 64H
Reserved 69H-7FH
Reset Disk 0DH
Search for First Entry 11H
Search for Next Entry 12H
Select Disk 0EH
Sequential Read 14H
Sequential Write 15H
Set Block 4AH
Set Date 2BH
Set Disk Transfer Address 1AH
Set Handle Count 67H
Set Interrupt Vector 25H
Set IOCtl Drive Map 440FH
Set Relative Record 24H
Set Time 2DH
Set/Reset Verify Flag 2EH
Terminate Program 00H
Description Interrupt
Terminate Program 00H
Unlock 5C01H
Write Handle 40H
A detailed description of each system call follows. These calls are listed
in numeric order, interrupts first, followed by function requests.
───────────────────────────────────────────────────────────────────────────
Note
Unless stated otherwise, in the system call descriptions--both text and
code--all numbers are in hexadecimal.
───────────────────────────────────────────────────────────────────────────
1.11 Interrupts
The following pages describe Interrupts 20H-27H.
Program Terminate (Interrupt 20H)
Call:
CS
Segment address of Program Segment Prefix
Return:
None
Comments:
Interrupt 20H terminates the current process and returns control to its
parent process. It also closes all open file handles and clears the disk
cache. When this interrupt is issued, CS must contain the segment address
of the Program Segment Prefix.
Interrupt 20H is provided only for compatibility with MS-DOS versions
prior to 2.0. New programs should use Function 4CH (End Process), which
permits returning a completion code to the parent process and does not
require CS to contain the segment address of the Program Segment Prefix.
The following exit addresses are restored from the Program Segment
Prefix:
Offset Exit Address
───────────────────────────────────────────────────────────────────────────
0AH Program terminate
0EH CONTROL-C
12H Critical error
All file buffers are flushed to disk.
───────────────────────────────────────────────────────────────────────────
Note
You should close all files that have changed in length before issuing
this interrupt. If you do not close a changed file, its length may not
be recorded correctly in the directory. See Functions 10H and 3EH for
a description of the Close File system calls. If sharing is loaded, you
should remove all locks before using Interrupt 20H. See Function 5CH
(Lock) for more information.
───────────────────────────────────────────────────────────────────────────
Macro Definition:
terminate macro
int 20H
endm
Example:
The following program displays a message and returns to MS-DOS. It uses
only the opening portion of the sample program skeleton shown in
Figure 1.2:
message db "displayed by INT20H example". 0DH, 0AH, "$"
;
begin: display message ;see Function 09H
terminate ;THIS INTERRUPT
code ends
end start
Function Request (Interrupt 21H)
Call:
AH
Function number
Other registers
As specified in individual function
Return:
None.
Comments:
As specified in individual function. Interrupt 21H causes MS-DOS to
carry out the function request whose number is in AH. See Section 1.12,
"Function Requests," for a description of the MS-DOS functions.
Example:
To call the Get Time function:
mov ah,2CH ;Get Time is Function 2CH
int 21H ;MS-DOS function request
Terminate Process Exit Address (Interrupt 22H)
This interrupt may be issued only by MS-DOS; user programs must never
issue it. If you must write your own terminate interrupt handler, use
Function 35H (Get Interrupt Vector) to get the address of the standard
routine, save the address, then use Function 25H (Set Interrupt Vector)
to change the Interrupt 22H entry in the vector table so that it points
to your routine.
When a program terminates, MS-DOS transfers control to the routine that
starts at the address in the Interrupt 22H entry in the vector table.
When MS-DOS creates a program segment, it copies this address into the
Program Segment Prefix, starting at offset 0AH.
CONTROL-C Handler Address (Interrupt 23H)
When you type CONTROL-C or CONTROL-BREAK (on IBM-compatibles), MS-DOS
transfers control as soon as possible to the routine that starts at the
address in the Interrupt 23H entry in the vector table. When MS-DOS creates
a program segment, it copies the address currently in the interrupt table
into the Program Segment Prefix, starting at offset 0EH.
This interrupt may be issued only by MS-DOS; user programs must never
issue it. If you must write your own CONTROL-C interrupt handler, use
Function Request 35H (Get Interrupt Vector) to get the address of the
standard routine, save the address, then use Function Request 25H (Set
Interrupt Vector) to change the Interrupt 23H entry in the vector table
to point to your routine.
If the CONTROL-C routine preserves all registers, it can end with an
IRET instruction (return from interrupt) to continue program execution.
If a user-written interrupt program returns with a long return, the program
uses the carry flag to determine whether or not the program will abort.
If the carry flag is set, it will abort; otherwise, execution will continue
as with a return by IRET.
If a user-written CONTROL-BREAK routine interrupts function calls 09H,
0AH, or buffered I/O, and if it continues execution with an IRET, then I/O
continues from the start of the line. MS-DOS always outputs a CONTROL-C
to the screen when it issues an Interrupt 23H. There is no way to turn
this off.
When the interrupt occurs, all registers are set to the value they had
when the original call to MS-DOS was made. There are no restrictions on
what a CONTROL-C handler can do--including calling MS-DOS functions--
as long as the program restores the registers.
If a CONTROL-C interrupts Function 09H or 0AH (Display String or
Buffered Keyboard Input), the three-byte sequence 03H-0DH-0AH (usually
displayed as C followed by a carriage-return) is sent to the display and
the function resumes at the beginning of the next line.
Suppose a program uses Function 4BH (Load and Execute Program) to create
a second Program Segment Prefix and execute a second program, which then
changes the CONTROL-C address in the vector table. MS-DOS restores this
CONTROL-C vector to its original value before returning control to the
calling program.
Critical-Error-Handler Address (Interrupt 24H)
If a critical error occurs during execution of an I/O function request
(this often means a fatal disk error), MS-DOS transfers control to the
routine at the address in the Interrupt 24H entry in the vector table. When
MS-DOS creates a program segment, it copies this address into the Program
Segment Prefix, starting at offset 12H.
This interrupt may be issued only by MS-DOS; user programs must never
issue it. If you must write your own critical-error interrupt handler,
use Function 35H (Get Interrupt Vector) to get the address of the standard
routine, save the address, then use Function 25H (Set Interrupt Vector)
to change the Interrupt 24H entry in the vector table to point to your
routine.
MS-DOS does not issue Interrupt 24H if a failure occurs during execution
Interrupt 25H (Absolute Disk Read) or Interrupt 26H (Absolute Disk Write).
A command.com error routines handles these errors. This routine retries
the disk operation, then gives you the choice of aborting the operation,
retrying it, allowing the system call to fail and the application process
to continue, or ignoring the error.
The following topics describe the requirements of an Interrupt 24H
routine, including the error codes, registers, and stack.
1.11.1 Conditions upon Entry
After retrying an I/O error five times, MS-DOS issues Interrupt 24H, unless
a File Allocation Table (FAT) or directory sector is involved. In those
cases, DOS performs three retries. The interrupt handler receives control
with interrupts disabled. AX and DI contain error codes, and BP contains
the offset (to the segment address in SI) of a Device Header control block
that describes the device on which the error occurred.
1.11.2 Requirements for an Interrupt 24H Handler
To issue the "Abort, Retry, Fail or Ignore" prompt to a user, a user-
written critical-error handler should first push the flags and execute
a FAR call to the address of the standard Interrupt 24H handler (the user
program that changed the Interrupt 24H vector also should have saved this
address). After a user responds to the prompt, MS-DOS returns control
to the user-written routine.
───────────────────────────────────────────────────────────────────────────
Note
There are source applications which will have trouble handling critical
errors, since this changes the stack frame.
───────────────────────────────────────────────────────────────────────────
The error handler can then do its processing, but before it does anything
else it must preserve BX, CX, DX, DS, ES, SS, and SP. Also, the error
handler may use only function calls 01-0CH (inclusive) and 59H (if it uses
any others, the error handler destroys the MS-DOS stack and leaves MS-DOS
in an unstable state). The contents of the Device Header should not be
changed.
It is recommended that Interrupt 24H routine fail critical errors and
let the application test for an extended error code when the Interrupt 21H
routine returns.
User Stack
This call uses the user stack that contains the following (starting
with the top of the stack):
IP MS-DOS registers from issuing Interrupt 24H
CS
FLAGS
AX User registers at time of original
BX INT 21H
CX
DX
SI
DI
BP
DS
ES
IP From the original INT 21H
CS from the user to MS-DOS
FLAGS
The registers are set such that if the user-written error handler issues an
IRET, MS-DOS responds according to the value in AL:
AL Action
───────────────────────────────────────────────────────────────────────────
0 Ignore the error.
1 Retry the operation.
2 Abort the program by issuing Interrupt 23H.
3 Fail the system call that is in progress.
Note that the ignore option may cause unexpected results, such as
causing MS-DOS to behave as if an operation had completed successfully.
Disk Error Code in AX
If bit 7 of AH is 0, the error occurred on a disk drive. AL contains the
failing drive (0=A, 1=B, etc.). Bit 0 of AH specifies whether the error
occurred during a read or write operation (0=read, 1=write), and bits 1
and 2 of AH identify the area of the disk where the error occurred:
Bits 1-2 Location of error
───────────────────────────────────────────────────────────────────────────
00 MS-DOS area
01 File Allocation Table
10 Directory
11 Data area
Bits 3-5 of AH specify valid responses to the error prompt:
Bit Value Response
───────────────────────────────────────────────────────────────────────────
3 0 Fail not allowed
1 Fail allowed
4 0 Retry not allowed
1 Retry allowed
5 0 Ignore not allowed
1 Ignore allowed
If you specify Retry but it isn't allowed, MS-DOS changes it to Fail. If
you specify Ignore but it isn't allowed, MS-DOS changes it to Fail. If you
specify Fail but it isn't allowed, MS-DOS changes it to Abort. The Abort
response is always allowed.
Other Device Error Code in AX
If bit 7 of AH is 1, either the memory image of the File Allocation Table
(FAT) is bad or an error occurred on a character device. The device header
pointed to by BP:SI contains a WORD of attribute bits that identify the
type of device and, therefore, the type of error.
The word of attribute bits is at offset 04H of the Device Header. Bit 15
specifies the type of device (0=block, 1=character).
If bit 15 is 0 (block device), the error was a bad memory image of the FAT.
If bit 15 is 1 (character device), the error was on a character device.
DI contains the error code, the contents of AL are undefined, and bits 0-3
of the attribute word have the following meaning:
Bit Meaning if Set
───────────────────────────────────────────────────────────────────────────
0 Current standard input
1 Current standard output
2 Current null device
3 Current clock device
See Chapter 2, "MS-DOS Device Drivers," for a complete description of
the Device Header control block.
Error Code in DI
The high byte of DI is undefined. The low byte contains the following
error codes:
Error code Description
───────────────────────────────────────────────────────────────────────────
0 Attempt to write on write-protected disk
1 Unknown unit
2 Drive not ready
3 Unknown command
4 CRC error in data
5 Bad drive request structure length
6 Seek error
7 Unknown media type
8 Sector not found
9 Printer out of paper
A Write fault
B Read fault
C General failure
A user-written Interrupt 24H handler can use Function 59H (Get Extended
Error) to get detailed information about the error that caused the
interrupt to be issued.
Absolute Disk Read (Interrupt 25H)
Call:
AL
Drive number
DS:BX
Disk Transfer Address
CX
Number of sectors
DX
Beginning relative sector
Return:
AL
Error code if CF=1
Flags
CF = 0 if successful
= 1 if not successful
Comments:
The registers must contain the following:
Register Contents
───────────────────────────────────────────────────────────────────────────
AL Drive number (0=A, 1=B, etc.)
BX Offset of Disk Transfer Address (from segment address in DS)
CX Number of sectors to read
DX Beginning relative sector
───────────────────────────────────────────────────────────────────────────
Warning
Avoid using this function unless absolutely necessary. Instead, you
should access files through normal MS-DOS function requests. There is no
guarantee of upward compatibility for the Absolute Disk I/O in future
releases of MS-DOS.
───────────────────────────────────────────────────────────────────────────
Interrupt 25H transfers control to the device driver and reads from the
disk to the Disk-Transfer Address the number of sectors specified in CX.
The interrupt has the same requirements as and processes identically to
Interrupt 26H (Absolute Disk Write), except that it reads data rather than
writes it. Also, since this interrupt does not check your input parameters
too closely, make sure they are reasonable. If you use unreasonable
parameters, you may get strange results or cause your system to crash.
───────────────────────────────────────────────────────────────────────────
Note
This call destroys all registers except the segment registers. So before
issuing the interrupt, save any registers that your program uses.
───────────────────────────────────────────────────────────────────────────
The system pushes the flags at the time of the call; they are still
there upon return. To prevent uncontrolled growth, be sure to pop the
stack upon return.
If the disk operation is successful, the Carry Flag (CF) is 0. If the
disk operation is not successful, CF is 1 and AL contains the MS-DOS error
code (see Interrupt 24H earlier in this section for the codes and their
meanings).
Macro Definition:
abs_disk_read macro disk,buffer,num_sectors,first_sector
mov al,disk
mov bx,offset buffer
mov cx,num_sectors
mov dx,first_sector
int 25H
popf
endm
Example:
The following program copies the contents of a single-sided disk in drive A
to the disk in drive B.
prompt db "Source in A, target in B",0DH,0AH
db "Any key to start. $"
first dw 0
buffer db 60 dup (512 dup (?)) ;60 sectors
;
begin: display prompt ;see Function 09H
read_kbd ;see Function 08H
mov cx,6 ;copy 6 groups of
;60 sectors
copy: push cx ;save the loop counter
abs_disk_read 0,buffer,60,first ;THIS INTERRUPT
abs_disk_write 1,buffer,60,first ;see INT 26H
add first,60 ;do the next 60 sectors
pop cx ;restore the loop counter
loop copy
Absolute Disk Write (Interrupt 26H)
Call:
AL
Drive number
DS:BX
Disk Transfer Address
CX
Number of sectors
DX
Beginning relative sector
Return:
AL
Error code if CF = 1
FLAGS
CF = 0 if successful
= 1 if not successful
Comments:
───────────────────────────────────────────────────────────────────────────
Warning
Avoid using this function unless absolutely necessary. Instead, you
should access files through normal MS-DOS function requests. There is
no guarantee of upward compatibility for the Absolute Disk I/O in future
releases of MS-DOS.
───────────────────────────────────────────────────────────────────────────
The registers must contain the following:
Register Contents
───────────────────────────────────────────────────────────────────────────
AL Drive number (0=A, 1=B, etc.)
BX Offset of Disk Transfer Address (from segment address in DS)
CX Number of sectors to write
DX Beginning relative sector
This interrupt transfers control to MS-DOS. The number of sectors
specified in CX is written from the Disk Transfer Address to the disk. Its
requirements and processing are identical to Interrupt 25H (Absolute Disk
Read), except data is written to the disk rather than read from it. Also,
since Interrupt 26H does not check your input parameters too closely, make
sure they are reasonable. If you use unreasonable parameters, you may get
strange results or cause your system to crash.
───────────────────────────────────────────────────────────────────────────
Note
This call destroys all registers except the segment registers. So before
issuing the interrupt, be sure to save any registers your program uses.
───────────────────────────────────────────────────────────────────────────
The system pushes the flags at the time of the call; they are still there
upon return. To prevent uncontrolled growth, be sure to pop the stack upon
return.
If the disk operation is successful, the Carry Flag (CF) is 0. If the
disk operation is not successful, CF is 1 and AL contains the MS-DOS error
code (see Interrupt 24H for the codes and their meanings).
Macro Definition:
abs_disk_write macro disk,buffer,num_sectors,first_sector
mov al,disk
mov bx,offset buffer
mov cx,num_sectors
mov dx,first_sector
int 26H
popf
endm
Example:
The following program copies the contents of a single-sided disk in drive A
to the disk in drive B, verifying each write. It uses a buffer of 32K
bytes.
off equ 0
on equ 1
;
prompt db "Source in A, target in B",0DH,0AH
db "Any key to start. $"
first dw 0
buffer db 60 dup (512 dup (?)) ;60 sectors
;
begin: display prompt ;see Function 09H
read_kbd ;see Function 08H
verify on ;see Function 2EH
mov cx,6 ;copy 6 groups of 60 sectors
copy: push cx ;save the loop counter
abs_disk_read 0,buffer,60,first ;see INT 25H
abs_disk_write 1,buffer,60,first ;THIS INTERRUPT
add first,60 ;do the next 60 sectors
pop cx ;restore the loop counter
loop copy
verify off ;see Function 2EH
Terminate But Stay Resident (Interrupt 27H)
Call:
CS:DX
Pointer to first byte following
last byte of code.
Return:
None
Comments:
This interrupt is provided only for compatibility with MS-DOS versions
prior to 2.0. Unless your resident program must be compatible with MS-DOS
versions before 2.0, you should use Function 31H (Keep Process) to install
it. Function 31H lets programs larger than 64K remain resident and allows
return information to be passed.
However, Interrupt 27H, which is often used to install device-specific
interrupt handlers, forces programs that are up to 64K to remain resident
after they terminate.
DX must contain the offset (from the segment address in CS) of the first
byte that follows the last byte of code in the program. When Interrupt 27H
is executed, the program terminates and control returns to MS-DOS, but the
program is not overlaid by other programs. Files left open are not closed.
When the interrupt is called, CS must contain the segment address of the
Program Segment Prefix (the value of DS and ES when execution started).
.Exe programs that are loaded into high memory must not use this
interrupt. Similarly, since it restores the Interrupt 22H, 23H, and
24H vectors, you should not use Interrupt 27H to install new CONTROL-C
or critical-error handlers.
Macro Definition:
stay_resident macro last_instruc
mov dx,offset last_instruc
inc dx
int 27H
endm
Example:
Since the most common use of Interrupt 27H is to install a machine-specific
routine, there is no general example that applies. The macro definition,
however, shows the calling syntax.
1.12 Function Requests
The following pages describe function calls 00H-68H.
Terminate Program (Function 00H)
Call:
AH = 00H
CS
Segment address of
Program Segment Prefix
Return:
None
Comments:
Function 00H performs the same function as Interrupt 20H. It terminates
the current process and returns control to its parent process. It also
closes all open file handles and clears the disk cache. When this
interrupt is issued, CS must contain the segment address of the Program
Segment Prefix.
The CS register must contain the segment address of the Program
Segment Prefix before you call this interrupt.
The following exit addresses are restored from the specified offsets
in the Program Segment Prefix:
Offset Exit Address
───────────────────────────────────────────────────────────────────────────
0AH Program terminate
0EH CONTROL-C
12H Critical error
All file buffers are flushed to disk.
───────────────────────────────────────────────────────────────────────────
Warning
Close all files that have changed in length before calling this function.
If you do not close a changed file, its length is not correctly recorded
in the directory. See Function 10H for a description of the Close File
system call.
───────────────────────────────────────────────────────────────────────────
Macro Definition:
terminate_program macro
xor ah,ah
int 21H
endm
Example:
The following program displays a message and returns to MS-DOS. It uses
only the opening portion of the sample program skeleton shown in Figure
1.2.
message db "Displayed by FUNC00H example", 0DH,0AH,"$"
;
begin: display message ;see Function 09H
terminate_program ;THIS FUNCTION
code ends
end start
Read Keyboard and Echo (Function 01H)
Call:
AH = 01H
Return:
AL
Character typed
Comments:
Function 01H waits for a character to be read from standard input, then
echoes the character to standard output and returns it in AL. If the
character is CONTROL-C, it executes Interrupt 23H.
Macro Definition:
read_kbd_and_echo macro
mov ah, 01H
int 21H
endm
Example:
The following program displays and prints characters as you type them.
If you press the RETURN key, the program sends a linefeed/carriage-return
sequence to both the display and the printer.
begin: read_kbd_and_echo ;THIS FUNCTION
print_char al ;see Function 05H
cmp al,0DH ;is it a CR?
jne begin ;no, print it
print_char 0AH ;see Function 05H
display_char 0AH ;see Function 02H
jmp begin ;get another character
Display Character (Function 02H)
Call:
AH = 02H
DL
Character to be displayed
Return:
None
Comments:
Function 02H sends the character in DL to standard output. If you press
CONTROL-C, it issues Interrupt 23H.
Macro Definition:
display_char macro character
mov dl,character
mov ah,02H
int 21H
endm
Example:
The following program converts lowercase characters to uppercase before
displaying them.
begin: read_kbd ;see Function 08H
cmp al,"a"
jl uppercase ;don't convert
cmp al,"z"
jg uppercase ;don't convert
sub al,20H ;convert to ASCII code
;for uppercase
uppercase: display_char al ;THIS FUNCTION
jmp begin: ;get another character
Auxiliary Input (Function 03H)
Call:
AH = 03H
Return:
AL
Character from auxiliary device
Comments:
Function 03H waits for a character from standard auxiliary devices (AUX,
COM1, COM2, COM3, COM4), then returns the character in AL. This system
call does not return a status or error code.
If you press CONTROL-C, it issues Interrupt 23H.
Macro Definition:
aux_input macro
mov ah,03H
int 21H
endm
Example:
The following program prints characters as soon as it receives them from
the auxiliary device. It stops printing when it receives an end-of-file
character (ASCII 26, or CONTROL-Z).
begin: aux_input ;THIS FUNCTION
cmp al,1AH ;end of file?
je return ;yes, all done
print_char al ;see Function 05H
jmp begin ;get another character
Auxiliary Output (Function 04H)
Call:
AH = 04H
DL
Character for auxiliary device
Return:
None
Comments:
Function 04H sends the character in DL to standard auxiliary. This system
call does not return a status or error code.
If you press CONTROL-C, it issues Interrupt 23H.
Macro Definition:
aux_output macro character
mov dl,character
mov ah,04H
int 21H
endm
Example:
The following program gets a series of strings of up to 80 bytes from the
keyboard and sends each string to the auxiliary device. It stops when you
type a null string (carriage-return only).
string db 81 dup(?) ;see Function 0AH
;
begin: get_string 80,string ;see Function 0AH
cmp string[1],0 ;null string?
je return ;yes, all done
mov cx, word ptr string[1] ;get string length
mov bx,0 ;set index to 0
send_it: aux_output string[bx+2] ;THIS FUNCTION
inc bx ;bump index
loop send_it ;send another character
jmp begin ;get another string
Print Character (Function 05H)
Call:
AH = 05H
DL
Character for printer
Return:
None
Comments:
Function 05H sends the character in DL to the standard printer. If you
press CONTROL-C, it issues Interrupt 23H. This function does not return
a status or error code.
Macro Definition:
print_char macro character
mov dl,character
mov ah,05H
int 21H
endm
Example:
The following program prints a walking test pattern on the printer. It
stops if you press CONTROL-C.
line_num db 0
;
begin: mov cx,60 ;print 60 lines
start_line: mov bl,33 ;first printable ASCII
;character (!)
add bl,line_num ;to offset one character
push cx ;save number-of-lines counter
mov cx,80 ;loop counter for line
print_it: print_char bl ;THIS FUNCTION
inc bl ;move to next ASCII character
cmp bl,126 ;last printable ASCII
;character (~)
jl no_reset ;not there yet
mov bl,33 ;start over with (!)
no_reset: loop print_it ;print another character
print_char 0DH ;carriage return
print_char 0AH ;linefeed
inc line_num ;to offset 1st char. of line
pop cx ;restore #-of-lines counter
loop start_line ;print another line
Direct Console I/O (Function 06H)
Call:
AH = 06H
DL
See text
Return:
AL
If DL = FFH before call,
then zero flag not set means AL
has character from standard input.
Zero flag set means there was not
a character to get, and AL = 0.
Comments:
The action of Function 06H depends on the value in DL when the function
is called:
Value in DL Action
───────────────────────────────────────────────────────────────────────────
FFH If a character has been read from standard input, it is
returned in AL and the zero flag is cleared (0); if a
character has not been read, the zero flag is set (1).
Not FFH The character in DL is sent to standard output.
This function does not check for CONTROL-C.
Macro Definition:
dir_console_io macro switch
mov dl,switch
mov ah,06H
int 21H
endm
Example:
The following program sets the system clock to 0 and displays the time
continuously. When you type any character, the display freezes; when you
type any character again, the clock is reset to 0 and the display starts
again.
time db "00:00:00.00",0DH,0AH,"$" ;see Function 09H
; ;for explanation of $
;
begin: set_time 0,0,0,0 ;see Function 2DH
read_clock: get_time ;see Function 2CH
CONVERT ch,time ;see end of chapter
CONVERT cl,time[3] ;see end of chapter
CONVERT dh,time[6] ;see end of chapter
CONVERT dl,time[9] ;see end of chapter
display time ;see Function 09H
dir_console_io FFH ;THIS FUNCTION
cmp al,0 ;character typed?
jne stop ;yes, stop timer
jmp read_clock ;no, keep timer
;running
stop: read_kbd ;see Function 08H
jmp begin ;start over
Direct Console Input (Function 07H)
Call:
AH = 07H
Return:
AL
Character from keyboard
Comments:
Function 07H waits for a character to be read from standard input, then
returns it in AL. This function does not echo the character or check
for CONTROL-C. (For a keyboard input function that echoes or checks for
CONTROL-C, see Function 01H or 08H.)
Macro Definition:
dir_console_input macro
mov ah,07H
int 21H
endm
Example:
The following program prompts for a password (eight characters maximum) and
places the characters into a string without echoing them.
password db 8 dup(?)
prompt db "Password: $" ;see Function 09H for
;explanation of $
begin: display prompt ;see Function 09H
mov cx,8 ;maximum length of password
xor bx,bx ;so BL can be used as index
get_pass: dir_console_input ;THIS FUNCTION
cmp al,0DH ;was it a carriage return?
je return ;yes, all done
mov password[bx],al ;no, put character in string
inc bx ;bump index
loop get_pass ;get another character
Read Keyboard (Function 08H)
Call:
AH = 08H
Return:
AL
Character from keyboard
Comments:
Function 08H waits for a character to be read from standard input, then
returns it in AL. If you press CONTROL-C, it issues Interrupt 23H. This
function does not echo the character. (For a keyboard input function
that echoes the character or checks for CONTROL-C, see Function 01H.)
Macro Definition:
read_kbd macro
mov ah,08H
int 21H
endm
Example:
The following program prompts for a password (eight characters maximum) and
places the characters into a string without echoing them.
password db 8 dup(?)
prompt db "Password: $" ;see Function 09H
;for explanation of $
begin: display prompt ;see Function 09H
mov cx,8 ;maximum length of password
xor bx,bx ;BL can be an index
get_pass: read_kbd ;THIS FUNCTION
cmp al,0DH ;was it a carriage return?
je return ;yes, all done
mov password[bx],al ;no, put char. in string
inc bx ;bump index
loop get_pass ;get another character
Display String (Function 09H)
Call:
AH = 09H
DS:DX
Pointer to string to be displayed
Return:
None
Comments:
Function 09H sends to standard output a string that ends with "$" (the $ is
not displayed).
The DX register must contain the offset (from the segment address in
DS) of the string.
Macro Definition:
display macro string
mov dx,offset string
mov ah,09H
int 21H
endm
Example:
The following program displays the hexadecimal code of the key that
is typed.
table db "0123456789ABCDEF"
result db " - 00H",0DH,0AH,"$" ;see text for
;explanation of $
begin: read_kbd_and_echo ;see Function 01H
xor ah,ah ;clear upper byte
convert ax,16,result[3] ;see end of chapter
display result ;THIS FUNCTION
jmp begin ;do it again
Buffered Keyboard Input (Function 0AH)
Call:
AH = 0AH
DS:DX
Pointer to input buffer
Return:
None
Comments:
Function 0AH gets a string from standard input. DX must contain the offset
(from the segment address in DS) of an input buffer of the following form:
Byte Contents
───────────────────────────────────────────────────────────────────────────
1 Maximum number of characters in buffer, including the carriage
return (you must set this value).
2 Actual number of characters typed, not counting the carriage
return (the function sets this value).
3-n Buffer; must be at least as long as the number in byte 1.
Characters are read from standard input and placed in the buffer
beginning at the third byte until a RETURN character (ASCII 0DH) is read.
If the buffer fills to one less than the maximum, additional characters
read are ignored and ASCII 07H (Bel) is sent to standard output until
a RETURN character is read. If you type the string at the console, it
can be edited as it is being entered. If you press CONTROL-C, it issues
Interrupt 23H.
MS-DOS sets the second byte of the buffer to the number of characters
read (not counting the carriage return).
Macro Definition:
get_string macro limit,string
mov dx,offset string
mov string,limit
mov ah,0AH
int 21H
endm
Example:
The following program gets a 16-byte (maximum) string from the keyboard and
fills a 24-line by 80-character screen with it.
buffer label byte
max_length db ? ;maximum length
chars_entered db ? ;number of chars.
string db 17 dup (?) ;16 chars + CR
strings_per_line dw 0 ;how many strings
;fit on line
crlf db 0DH,0AH
;
begin: get_string 17,buffer ;THIS FUNCTION
xor bx,bx ;so byte can be
;used as index
mov bl,chars_entered ;get string length
mov buffer[bx+2],"$" ;see Function 09H
mov al,50H ;columns per line
cbw
div chars_entered ;times string fits
;on line
xor ah,ah ;clear remainder
mov strings_per_line,ax ;save col. counter
mov cx,24 ;row counter
display_screen: push cx ;save it
mov cx,strings_per_line ;get col. counter
display_line: display string ;see Function 09H
loop display_line
display crlf ;see Function 09H
pop cx ;get line counter
loop display_screen ;display 1 more line
Check Keyboard Status (Function 0BH)
Call:
AH = 0BH
Return:
AL
00H = no characters in type-ahead buffer
FFH = characters in type-ahead buffer
Comments:
Function 0BH checks whether characters are available from standard input
(if standard input has not been redirected, it checks the type-ahead
buffer). If characters are available, AL returns FFH; if not, AL returns
0. If CONTROL-C is in the buffer, it issues Interrupt 23H.
Macro Definition:
check_kbd_status macro
mov ah,0BH
int 21H
endm
Example:
The following program displays the time continuously until you press
any key:
time db "00:00:00.00",0DH,0AH,"$"
.
.
begin: get_time ;see Function 2CH
byte_to_dec ch,time ;see end of chapter
byte_to_dec cl,time[3] ;see end of chapter
byte_to_dec dh,time[6] ;see end of chapter
byte_to_dec dl,time[9] ;see end of chapter
display time ;see Function 09H
check_kbd_status ;THIS FUNCTION
cmp al,0FFH ;has a key been typed?
je return ;yes, go home
jmp begin ;no, keep displaying
;time
Flush Buffer, Read Keyboard (Function 0CH)
Call:
AH = 0CH
AL
1, 6, 7, 8, or 0AH = the
corresponding function
is called.
Any other value = no
further processing.
Return:
AL
00H = Type-ahead buffer was
flushed; no other
processing performed.
Comments:
Function 0CH empties the standard input buffer (if standard input has not
been redirected, Function 0CH empties the type-ahead buffer). Further
processing depends on the value in AL when the function is called.
AL Action
───────────────────────────────────────────────────────────────────────────
1,6,7,8, or 0AH The corresponding MS-DOS function is executed.
Any other value No further processing; AL returns 0.
Macro Definition:
flush_and_read_kbd macro switch
mov al,switch
mov ah,0CH
int 21H
endm
Example:
The following program both displays and prints characters as you type them.
If you press the RETURN key, the program sends a carriage-return/linefeed
sequence to both the display and the printer.
begin: flush_and_read_kbd 1 ;THIS FUNCTION
print_char al ;see Function 05H
cmp al,0DH ;is it a carriage return?
jne begin ;no, print it
print_char 0AH ;see Function 05H
display_char 0AH ;see Function 02H
jmp begin ;get another character
Reset Disk (Function 0DH)
Call:
AH = 0DH
Return:
None
Comments:
Function 0DH flushes all file buffers to ensure that the internal buffer
cache matches the disks in the drives. It writes out buffers that have
been modified, and marks all buffers in the internal cache as free. This
function request is normally used to force a known state of the system;
CONTROL-C interrupt handlers should call this function.
This function does not update directory entries; you must close
changed files to update their directory entries (see Function 10H,
Close File).
Macro Definition:
reset_disk macro
mov ah,0DH
int 21H
endm
Example:
The following program flushes all file buffers and selects disk A.
begin: reset_disk
select_disk "A"
Select Disk (Function 0EH)
Call:
AH = 0EH
DL
Logical drive number
(0 = A, 1 = B, etc.)
Return:
AL
Number of logical drives
Comments:
Function 0EH selects the drive specified in DL (0=A, 1=B, etc.) as the
current logical drive. AL returns the number of logical drives.
───────────────────────────────────────────────────────────────────────────
Note
For future compatibility, treat the value returned in AL with care. For
example, if AL returns 5, it is not safe to assume that drives A, B, C,
D, and E are all valid drive designators.
───────────────────────────────────────────────────────────────────────────
Macro Definition:
select_disk macro disk
mov dl,disk[-64]
mov ah,0EH
int 21H
endm
Example:
The following program toggles between drive A and drive B to select the
current drive (in a two-drive system).
begin: current_disk ;see Function 19H
cmp al,00H ;drive A: selected?
je select_b ;yes, select B
select_disk "A" ;THIS FUNCTION
jmp return
select_b: select_disk "B" ;THIS FUNCTION
Open File (Function 0FH)
Call:
AH = 0FH
DS:DX
Pointer to unopened FCB
Return:
AL
00H = Directory entry found
FFH = No directory entry found
Comments:
Function 0FH opens a file. DX must contain the offset (from the segment
address in DS) of an unopened File Control Block (FCB). This call searches
the disk directory for the named file.
If the call finds a directory entry for the file, AL returns 0 and the
FCB is filled as follows:
■ If the drive code was 0 (current drive), it is changed to the actual
drive used (1=A, 2=B, etc.). This lets you change the current drive
without interfering with subsequent operations on this file.
■ Current Block (offset 0CH) is set to 0.
■ Record Size (offset 0EH) is set to the system default of 128.
■ File Size (offset 0FH), Date of Last Write (offset 13H), and Time of
Last Write (offset 15H) are set from the directory entry.
Before performing a sequential disk operation on the file, you must set
the Current Record field (offset 1FH). Before performing a random disk
operation on the file, you must set the Relative Record field (offset 20H).
If the default record size (128 bytes) is not correct, set it to the
correct length.
If the call doesn't find a directory entry for the file, or if the
file has the hidden or system attribute, AL returns 0FFH.
Macro Definition:
open macro fcb
mov dx,offset fcb
mov ah,0FH
int 21H
endm
Example:
The following program prints a file named textfile.asc that is on the disk
in drive B. If a partial record is in the buffer at end-of-file, the
routine that prints the partial record prints characters until it
encounters an end-of-file mark (ASCII 26, or CONTROL-Z).
fcb db 2,"TEXTFILEASC"
db 26 dup (?)
buffer db 128 dup (?)
;
begin: set_dta buffer ;see Function 1AH
open fcb ;THIS FUNCTION
read_line: read_seq fcb ;see Function 14H
cmp al,02H ;end of file?
je all_done ;yes, go home
cmp al,00H ;more to come?
jg check_more ;no, check for partial
;record
mov cx,80H ;yes, print the buffer
xor si,si ;set index to 0
print_it: print_char buffer[si] ;see Function 05H
inc si ;bump index
loop print_it ;print next character
jmp read_line ;read another record
check_more: cmp al,03H ;part. record to print?
jne all_done ;no
mov cx,80H ;yes, print it
xor si,si ;set index to 0
find_eof: cmp buffer[si],26 ;end-of-file mark?
je all_done ;yes
print_char buffer[si] ;see Function 05H
inc si ;bump index to next
;character
loop find_eof
all_done: close fcb ;see Function 10H
Close File (Function 10H)
Call:
AH = 10H
DS:DX
Pointer to opened FCB
Return:
AL
00H = Directory entry found
FFH = No directory entry found
Comments:
Function 10H closes a file. DX must contain the offset (to the segment
address in DS) of an opened FCB. This call searches the disk directory for
the file named in the FCB. If it finds a directory entry for the file, it
compares the location of the file with the corresponding entries in the
FCB. The call then updates the directory entry, if necessary, to match the
FCB, and AL returns 0.
After you change a file, you must call this function to update the
directory entry. You should close any FCB (even one for a file that has
not been changed) when you no longer need access to a file.
If this call doesn't find a directory entry for the file, AL
returns FFH.
Macro Definition:
close macro fcb
mov dx,offset fcb
mov ah,10H
int 21H
endm
Example:
The following program checks the first byte of the file named mod1.bas in
drive B to see if it is FFH and, if it is, prints a message.
message db "Not saved in ASCII format",0DH,0AH,"$"
fcb db 2,"MOD1 BAS"
db 26 dup (?)
buffer db 128 dup (?)
;
begin: set_dta buffer ;see Function 1AH
open fcb ;see Function 0FH
read_seq fcb ;see Function 14H
cmp buffer,0FFH ;is first byte FFH?
jne all_done ;no
display message ;see Function 09H
all_done: close fcb ;THIS FUNCTION
Search for First Entry (Function 11H)
Call:
AH = 11H
DS:DX
Pointer to unopened FCB
Return:
AL
00H = Directory entry found
FFH = No directory entry found
Comments:
Function 11H searches the disk directory for the first matching filename.
DX must contain the offset (from the segment address in DS) of an unopened
FCB. The filename in the FCB can include wildcard characters. To search
for hidden or system files, DX must point to the first byte of an
extended FCB prefix.
If this call does not find a directory entry for the filename in the
FCB, AL returns FFH.
But if the call does find a directory entry for the filename in the
FCB, AL returns 0 and the call creates an unopened FCB of the same type
(normal or extended) at the Disk Transfer Address as follows:
1. If the search FCB was normal, the first byte at the Disk Transfer
Address is set to the drive number used in the search (1=A, 2=B,
etc.) and the next 32 bytes contain the directory entry.
2. If the search FCB was extended, the first byte at the Disk Transfer
Address is set to FFH, the next 5 bytes are set to 00H, and the
following byte is set to the value of the attribute byte in the
search FCB. The remaining 33 bytes are the same as the result of
the normal FCB (drive number and 32 bytes of directory entry).
If you use Function 12H (Search for Next Entry) to continue searching
for matching filenames, you must not alter or open the original FCB
at DS:DX.
The attribute field is the last byte of the extended FCB fields that
precede the FCB (see earlier in this chapter). If the attribute field is
zero, Function 11H searches only normal file entries. It does not search
directory entries for hidden files, system files, volume label, and
subdirectories.
If the attribute field is hidden file, system file, or subdirectory
entry (02H, 04H, or 10H), or any combination of those values, this call
also searches all normal file entries. To search all directory entries
except the volume label, set the attribute byte to 16H (hidden file
and system file and directory entry).
If the attribute field is Volume ID (08H), the call searches only the
volume label entry.
Macro Definition:
search_first macro fcb
mov dx,offset fcb
mov ah,11H
int 21H
endm
Example:
The following program verifies the existence of a file named report.asm on
the disk in drive B.
yes db "FILE EXISTS.$"
no db "FILE DOES NOT EXIST.$"
crlf db 0DH,0AH,"$"
fcb db 2,"REPORT *ASM"
db 26 dup (?)
buffer db 128 dup (?)
;
begin: set_dta buffer ;see Function 1AH
search_first fcb ;THIS FUNCTION
cmp al,0FFH ;directory entry found?
je not_there ;no
display yes ;see Function 09H
jmp continue
not_there: display no ;see Function 09H
continue: display crlf ;see Function 09H
Search for Next Entry (Function 12H)
Call:
AH = 12H
DS:DX
Pointer to unopened FCB
Return:
AL
00H = Directory entry found
FFH = No directory entry found
Comments:
After you use Function 11H (Search for First Entry), you can use Function
12H to find any additional directory entries that match a filename
(containing wildcard characters). Function 12H searches the disk
directory for the next matching name. DX must contain the offset (from the
segment address in DS) of an FCB specified in a previous call to Function
11H. To search for hidden or system files, DX must point to the first byte
of an extended FCB prefix-one that includes the appropriate attribute
value.
If the call does not find a directory entry for the filename in the
FCB, AL returns FFH.
But if the call does find a directory entry for the filename in the
FCB, AL returns 0 and the call creates an unopened FCB of the same type
(normal or extended) at the Disk Transfer Address (see Function 11H for a
description of how the unopened FCB is formed).
Macro Definition:
search_next macro fcb
mov dx,offset fcb
mov ah,12H
int 21H
endm
Example:
The following program displays the number of files on the disk in drive B.
message db "No files",0DH,0AH,"$"
files db 0
fcb db 2,"???????????"
db 26 dup (?)
buffer db 128 dup (?)
;
begin: set_dta buffer ;see Function 1AH
search_first fcb ;see Function 11H
cmp al,0FFH ;directory entry found?
je all_done ;no, no files on disk
inc files ;yes, increment file
;counter
search_dir: search_next fcb ;THIS FUNCTION
cmp al,0FFH ;directory entry found?
je done ;no
inc files ;yes, increment file
;counter
jmp search_dir ;check again
done: convert files,10,message ;see end of chapter
all_done: display message ;see Function 09H
Delete File (Function 13H)
Call:
AH = 13H
DS:DX
Pointer to unopened FCB
Return:
AL
00H = Directory entry found
FFH = No directory entry found
Comments:
Function 13H deletes a file. DX must contain the offset (from the segment
address in DS) of an unopened FCB. This call searches the directory for a
matching filename. The filename in the FCB can contain wildcard characters.
If the call does not find a matching directory entry, AL returns FFH.
But if the call does find a matching directory entry, AL returns 0 and
the call deletes the entry from the directory. If the filename contains a
wildcard character, the call will delete all files which match.
Do not delete open files.
Macro Definition:
delete macro fcb
mov dx,offset fcb
mov ah,13H
int 21H
endm
Example:
The following program deletes each file on the disk in drive B that was
last written before December 31, 1982.
year dw 1982
month db 12
day db 31
files db 0
message db "No files deleted.",0DH,0AH,"$"
fcb db 2,"???????????"
db 26 dup (?)
buffer db 128 dup (?)
;
begin: set_dta buffer ;see Function 1AH
search_first fcb ;see Function 11H
cmp al,0FFH ;directory entry found?
jne compare ;yes
jmp all_done ;no, no files on disk
compare: convert_date buffer ;see end of chapter
cmp cx,year ;next several lines
jg next ;check date in directory
cmp dl,month ;entry against date
jg next ;above & check next file
cmp dh,day ;if date in directory
jge next ;entry isn't earlier.
delete buffer ;THIS FUNCTION
inc files ;bump deleted-files
;counter
next: search_next fcb ;see Function 12H
cmp al,00H ;directory entry found?
je compare ;yes, check date
cmp files,0 ;any files deleted?
je all_done ;no, display No files
;message.
convert files,10,message ;see end of chapter
all_done: display message ;see Function 09H
Sequential Read (Function 14H)
Call:
AH = 14H
DS:DX
Pointer to opened FCB
Return:
AL
00H = Read completed successfully
01H = EOF
02H = DTA too small
03H = EOF, partial record
Comments:
Function 14H reads a record from a specified file. DX must contain the
offset (from the segment address in DS) of an opened FCB. This call loads
the record pointed to by the Current Block field (offset 0CH) and Current
Record (offset 1FH) field at the Disk Transfer Address, then increments the
Current Block and Current Record fields.
The length of the record is taken from the Record Size field (offset
0EH) of the FCB.
AL returns a code that describes the processing:
Code Meaning
───────────────────────────────────────────────────────────────────────────
0 Read completed successfully
1 End-of-file; no data in the record
2 Not enough room at the Disk Transfer Address to read one record; read
canceled
3 End-of-file; a partial record was read and padded to the record
length with zeros
Macro Definition:
read_seq macro fcb
mov dx,offset fcb
mov ah,14H
int 21H
endm
Example:
The following program displays a file named textfile.asc that is on the
disk in drive B; its function is similar to the MS-DOS type command. If a
partial record is in the buffer at end-of-file, the routine that displays
the partial record displays characters until it encounters an end-of-file
mark (ASCII 26, or CONTROL-Z).
fcb db 2,"TEXTFILEASC"
db 26 dup (?)
buffer db 128 dup (?),"$"
;
begin: set_dta buffer ;see Function 1AH
open fcb ;see Function 0FH
read_line: read_seq fcb ;THIS FUNCTION
cmp al,02H ;DTA too small?
je all_done ;yes
cmp al,00H ;end-of-file?
jg check_more ;yes
display buffer ;see Function 09H
jmp read_line ;get another record
check_more: cmp al,03H ;partial record in buffer?
jne all_done ;no, go home
xor si,si ;set index to 0
find_eof: cmp buffer[si],26 ;is character EOF?
je all_done ;yes, no more to display
display_char buffer[si] ;see Function 02H
inc si ;bump index
jmp find_eof ;check next character
all_done: close fcb ;see Function 10H
Sequential Write (Function 15H)
Call:
AH = 15H
DS:DX
Pointer to opened FCB
Return:
AL
00H = Write completed successfully
01H = Disk full
02H = DTA too small
Function 15H writes a record to a specified file. DX must contain the
offset (from the segment address in DS) of an opened FCB. This call
writes the record pointed to by the Current Block field (offset 0CH) and
Current Record field (offset 1FH) at the Disk Transfer Address, then
increments the Current Block and Current Record fields.
The record size is taken from the value of the Record Size field
(offset 0EH) of the FCB. If the record size is less than a sector, the call
writes the data at the Disk Transfer Address to an MS-DOS buffer; MS-DOS
writes the buffer to disk when it contains a full sector of data, when the
file is closed, or when Function 0DH (Reset Disk) is issued.
AL returns a code that describes the processing:
Code Meaning
───────────────────────────────────────────────────────────────────────────
0 Write completed successfully
1 Disk full; write canceled
2 Not enough room at the Disk Transfer Address to write one record;
write canceled
Macro Definition:
write_seq macro fcb
mov dx,offset fcb
mov ah,15H
int 21H
endm
Example:
The following program creates a file named dir.tmp on the disk in drive B,
containing the disk number (0=A, 1=B, etc.) and filename from each
directory entry on the disk.
record_size equ 0EH ;offset of Record Size
; field in FCB
fcb1 db 2,"DIR TMP"
db 26 dup (?)
fcb2 db 2,"???????????"
db 26 dup (?)
buffer db 128 dup (?)
;
begin: set_dta buffer ;see Function 1AH
search_first fcb2 ;see Function 11H
cmp al,0FFH ;directory entry found?
je all_done ;no, no files on disk
create fcb1 ;see Function 16H
mov fcb1[record_size],12
;set record size to 12
write_it: write_seq fcb1 ;THIS FUNCTION
cmp al,0 ;write successful?
jne all_done ;no, go home
search_next fcb2 ;see Function 12H
cmp al,FFH ;directory entry found?
je all_done ;no, go home
jmp write_it ;yes, write the record
all_done: close fcb1 ;see Function 10H
Create File (Function 16H)
Call:
AH = 16H
DS:DX
Pointer to unopened FCB
Return:
AL
00H = Empty directory found
FFH = No empty directory available
Function 16H creates a file. DX must contain the offset(from the segment
address in DS) of an unopened FCB. MS-DOS searches the directory for an
entry that matches the specified filename or, if there is no matching
entry, an empty entry.
If MS-DOS finds a matching entry, it opens the file and sets the
length to zero (in other words, if you try to create a file that already
exists, MS-DOS erases it and creates a new, empty file). If MS-DOS doesn't
find a matching entry but does find an empty directory entry, it opens the
file and sets its length to zero. In either case, the call creates the
file, and AL returns 0. If MS-DOS doesn't find a matching entry and there
is no empty entry, the call doesn't create the file, and AL returns FFH.
You can assign an attribute to the file by using an extended FCB with
the attribute byte set to the appropriate value (see Extended FCB in
Section 1.9.1).
Macro Definition:
create macro fcb
mov dx,offset fcb
mov ah,16H
int 21H
endm
Example:
The following program creates a file named dir.tmp on the disk in drive B,
containing the disk number (0 = A, 1 = B, etc.) and filename from each
directory entry on the disk.
record_size equ 0EH ;offset of Record Size
; field of FCB
fcb1 db 2,"DIR TMP"
db 26 dup (?)
fcb2 db 2,"???????????"
db 26 dup (?)
buffer db 128 dup (?)
;
begin: set_dta buffer ;see Function 1AH
search_first fcb2 ;see Function 11H
cmp al,0FFH ;directory entry found?
je all_done ;no, no files on disk
create fcb1 ;THIS FUNCTION
mov fcb1[record_size],12
;set record size to 12
write_it: write_seq fcb1 ;see Function 15H
cmp al,0 ;write successful
jne all_done ;no, go home
search_next fcb2 ;see Function 12H
cmp al,FFH ;directory entry found?
je all_done ;no, go home
jmp write_it ;yes, write the record
all_done: close fcb1 ;see Function 10H
Rename File (Function 17H)
Call:
AH = 17H
DS:DX
Pointer to modified FCB
Return:
AL
00H = Directory entry found
FFH = No directory entry found
or destination already exists
Comments:
Function 17H changes the name of an existing file. DX must contain the
offset (from the segment address in DS) of an FCB with the drive number
and filename filled in, followed by a second filename at offset 11H. DOS
searches the disk directory for an entry that matches the first filename.
This filename can contain wildcard characters.
If MS-DOS finds a matching directory entry and there is no directory
entry that matches the second filename, it changes the filename in the
directory entry to match the second filename in the modified FCB. AL then
returns zero. If the second filename does contain a wildcard character,
this call does not change the corresponding characters in the filename
of the directory entry.
You cannot use this function request to rename a hidden file, a system
file, or a subdirectory. If MS-DOS does not find a matching directory entry
or if it finds an entry for the second filename, AL returns FFH.
Macro Definition:
rename macro fcb,newname
mov dx,offset fcb
mov ah,17H
int 21H
endm
Example:
The following program prompts for the name of a file and a new name; it
then renames the file.
fcb db 37 dup (?)
prompt1 db "Filename: $"
prompt2 db "New name: $"
reply db 15 dup(?)
crlf db 0DH,0AH,"$"
;
begin: display prompt1 ;see Function 09H
get_string 15,reply ;see Function 0AH
display crlf ;see Function 09H
parse reply[2],fcb ;see Function 29H
display prompt2 ;see Function 09H
get_string 15,reply ;see Function 0AH
display crlf ;see Function 09H
parse reply[2],fcb[16]
;see Function 29H
rename fcb ;THIS FUNCTION
Get Current Disk (Function 19H)
Call:
AH = 19H
Return:
AL
Currently selected drive
(0 = A, 1 = B, etc.)
Comments:
Function 19H returns the current drive in AL (0=A, 1=B, etc.).
Macro Definition:
current_disk macro
mov ah,19H
int 21H
endm
Example:
The following program displays the default drive in a two-drive system.
message db "Current disk is $"
crlf db 0DH,OAH,"$"
;
begin: display message ;see Function 09H
current_disk ;THIS FUNCTION
cmp al,00H ;is it disk A?
jne disk_b ;no, it's disk B:
display_char "A" ;see Function 02H
jmp all_done
disk_b: display_char "B" ;see Function 02H
all_done: display crlf ;see Function 09H
Set Disk Transfer Address (Function 1AH)set disk transfer address
Call:
AH = 1AH
DS:DX
Disk Transfer Address
Return:
None
Comments:
Function 1AH sets the Disk Transfer Address. DX must contain the offset
(from the segment address in DS) of the Disk Transfer Address. Disk
transfers cannot wrap around from the end of the segment to the beginning,
nor can they overflow into another segment.
If you do not set the Disk Transfer Address, MS-DOS defaults to offset
80H in the Program Segment Prefix. You can check the current Disk Transfer
Address with Function 2FH (Get Disk Transfer Address).
Macro Definition:
set_dta macro buffer
mov dx,offset buffer
mov ah,1AH
int 21H
endm
Example:
The following program prompts for a letter, converts it to its alphabetic
sequence (A=1, B=2, etc.), then reads and displays the corresponding record
from a file named alphabet.dat that is on the disk in drive B. The file
contains 26 records, each 28 bytes long.
record_size equ 0EH ;offset of Record Size
;field of FCB
relative_record equ 21H ;offset of Relative Record
; field of FCB
fcb db 2,"ALPHABETDAT"
db 26 dup (?)
buffer db 28 dup(?),"$"
prompt db "Enter letter: $"
crlf db 0DH,0AH,"$"
;
begin: set_dta buffer ;THIS FUNCTION
open fcb ;see Function 0FH
mov fcb[record_size],28 ;set record size
get_char: display prompt ;see Function 09H
read_kbd_and_echo ;see Function 01H
cmp al,0DH ;just a CR?
je all_done ;yes, go home
sub al,41H ;convert ASCII
;code to record #
mov fcb[relative_record],al
;set relative record
display crlf ;see Function 09H
read_ran fcb ;see Function 21H
display buffer ;see Function 09H
display crlf ;see Function 09H
jmp get_char ;get another character
all_done: close fcb ;see Function 10H
Get Default Drive Data (Function 1BH)
Call:
AH = 1BH
Return:
AL
Sectors per cluster
CX
Bytes per sector
DX
Clusters per drive
DS:BX
Pointer to FAT ID byte
Comments
Function 1BH retrieves data about the disk in the default drive.
The data returns in the following registers:
Register Contents
───────────────────────────────────────────────────────────────────────────
AL Number of sectors in a cluster (allocation unit)
CX Number of bytes in a sector
DX Number of clusters on the disk
BX returns the offset (to the segment address in DS) of the first
byte of the File Allocation Table (FAT), which identifies the type of disk
in the drive:
Value Type of Drive
───────────────────────────────────────────────────────────────────────────
FF Double-sided disk, 8 sectors per track, 40 tracks per side
FE Single-sided disk, 8 sectors per track, 40 tracks per side
FD Double-sided disk, 9 sectors per track, 40 tracks per side
FC Single-sided disk, 9 sectors per track, 40 tracks per side
F9 Double-sided disk, 15 sectors per track, 40 tracks per side
F9 Double-sided disk, 9 sectors per track, 80 tracks per side
F8 Fixed disk
This call is similar to Function 36H (Get Disk Free Space), except that it
returns the address of the FAT ID byte in BX instead of the number of
available clusters. It is also similar to Function 1CH (Get Drive Data),
except that it returns data on the disk in the default drive instead of on
the disk in a specified drive. For a description of how MS-DOS stores data
on a disk, including a description of the File Allocation Table, see
Chapter 3, "MS-DOS Technical Information."
───────────────────────────────────────────────────────────────────────────
Warning
The FAT ID byte is no longer adequate to identify the type of drive
being used. See Chapter 2, "MS-DOS Device Drivers," for more details.
───────────────────────────────────────────────────────────────────────────
Macro Definition:
def_drive_data macro
push ds
mov ah,1BH
int 21H
mov al,byte ptr[bx]
pop ds
endm
Example:
The following program displays a message that tells whether the default
drive is a disk or a fixed disk drive.
stdout equ 1
;
msg db "Default drive is "
dskt db "disk."
fixed db "fixed."
crlf db ODH,OAH
;
begin: write_handle stdout,msg,17 ;display message
jc write_error ;routine not shown
def_drive_data ;THIS FUNCTION
cmp byte ptr [bx],0F8H ;check FAT ID byte
jne disk ;it's a disk
write_handle stdout,fixed,6 ;see Function 40H
jc write_error ;see Function 40H
jmp short all_done ;clean up & go home
disk: write_handle stdout,dskt,9 ;see Function 40H
all_done: write_handle stdout,crlf,2 ;see Function 40H
jc write_error ;routine not shown
Get Drive Data (Function 1CH)
Call:
AH = 1CH
DL
Drive (0=default, 1=A, etc.)
Return:
AL
0FFH if drive number is invalid;
otherwise, sectors per cluster
CX
Bytes per sector
DX
Clusters per drive
DS:BX
Pointer to FAT ID byte
Comments:
Function 1CH retrieves data about the disk in the specified drive. DL must
contain the drive number (0=default, 1=A, etc.). The data returns in the
following registers:
Register Contents
───────────────────────────────────────────────────────────────────────────
AL Number of sectors in a cluster (allocation unit)
CX Number of bytes in a sector
DX Number of clusters on the disk
BX returns the offset (to the segment address in DS) of the first byte
of the File Allocation Table (FAT), which identifies the type of disk in
the drive:
Value Type of Drive
───────────────────────────────────────────────────────────────────────────
FF Double-sided disk, 8 sectors per track, 40 tracks per side
FE Single-sided disk, 8 sectors per track, 40 tracks per side
FD Double-sided disk, 9 sectors per track, 40 tracks per side
FC Single-sided disk, 9 sectors per track, 40 tracks per side
F9 Double-sided disk, 15 sectors per track, 40 tracks per side
F9 Double-sided disk, 9 sectors per track, 80 tracks per side
F8 Fixed disk
If the drive number in DL is invalid, AL returns 0FFH.
───────────────────────────────────────────────────────────────────────────
Warning
The FAT ID byte is no longer adequate to identify the type of drive being
used. See Chapter 2, "MS-DOS Device Drivers" for more details.
───────────────────────────────────────────────────────────────────────────
This call is similar to Function 36H (Get Disk Free Space), except that it
returns the address of the FAT ID byte in BX instead of the number of
available clusters. It is also similar to Function 1BH (Get Default Drive
Data), except that it returns data on the disk in the drive specified in DL
instead of the disk in the default drive. For a description of how MS-DOS
stores data on a disk, including a description of the File Allocation
Table, see Chapter 3, "MS-DOS Technical Information."
Macro Definition:
drive_data macro drive
push ds
mov dl,drive
mov ah,1BH
int 21H
mov al, byte ptr[bx]
pop ds
endm
Example:
The following program displays a message that tells whether drive B is a
disk or a fixed disk drive.
stdout equ 1
:
msg db "Drive B is "
dskt db "disk."
fixed db "fixed."
crlf db ODH,OAH
;
begin: write_handle stdout,msg,11 ;display message
jc write_error ;routine not shown
drive_data 2 ;THIS FUNCTION
cmp byte ptr [bx],0F8H ;check FAT ID byte
jne disk ;it's a disk
write_handle stdout,fixed,6 ;see Function 40H
jc write_error ;routine not shown
jmp all_done ;clean up & go home
disk: write_handle stdout,dskt,9 ;see Function 40H
all_done: write_handle stdout,crlf,2 ;see Function 40H
jc write_error ;routine not shown
Random Read (Function 21H)
Call:
AH = 21H
DS:DX
Pointer to opened FCB
Return:
AL
0 = Read completed successfully
1 = End of file, record empty
2 = DTA too small
3 = End of file, partial record
Comments:
Function 21H reads (into the Disk Transfer Address) the record pointed to
by the Relative Record field (offset 20H) of the FCB. DX must contain the
offset (from the segment address in DS) of an opened FCB. The Current Block
field (offset 0CH) and Current Record field (offset 1FH) are set to agree
with the Relative Record field (offset 20H). The record is then loaded at
the Disk Transfer Address. The record length is taken from the Record Size
field (offset 0EH) of the FCB.
AL returns a code that describes the processing:
Code Meaning
───────────────────────────────────────────────────────────────────────────
0 Read completed successfully
1 End-of-file; no data in the record
2 Not enough room at the Disk Transfer Address to read one record;
read canceled
3 End-of-file; a partial record was read and padded to the record
length with zeros
Macro Definition:
read_ran macro fcb
mov dx,offset fcb
mov ah,21H
int 21H
endm
Example:
The following program prompts for a letter, converts it to its alphabetic
sequence (A = 1, B = 2, etc.), then reads and displays the corresponding
record from a file named alphabet.dat that is on the disk in drive B. The
file contains 26 records, each 28 bytes long.
record_size equ 0EH ;offset of Record Size
;field of FCB
relative_record equ 21H ;offset of Relative Record
; field of FCB
fcb db 2,"ALPHABETDAT"
db 26 dup (?)
buffer db 28 dup(?),"$"
prompt db "Enter letter: $"
crlf db 0DH,0AH,"$"
;
begin: set_dta buffer ;see Function 1AH
open fcb ;see Function 0FH
mov fcb[record_size],28 ;set record size
get_char: display prompt ;see Function 09H
read_kbd_and_echo ;see Function 01H
cmp al,0DH ;just a CR?
je all_done ;yes, go home
sub al,41H ;convert ASCII code
;to record #
mov fcb[relative_record],al ;set relative
;record
display crlf ;see Function 09H
read_ran fcb ;THIS FUNCTION
display buffer ;see Function 09H
display crlf ;see Function 09H
jmp get_char ;get another char.
all_done: close fcb ;see Function 10H
Random Write (Function 22H)
Call:
AH = 22H
DS:DX
Pointer to opened FCB
Return:
AL
00H = Write completed successfully
01H = Disk full
02H = DTA too small
Comments:
Function 22H writes (from the Disk Transfer Address) the record pointed to
by the Relative Record field (offset 20H) of the FCB. DX must contain the
offset from the segment address in DS of an opened FCB. The Current Block
(offset 0CH) and Current Record (offset 1FH) fields are set to agree with
the Relative Record field (offset 20H). This record is then written from
the Disk Transfer Address.
The record length is taken from the Record Size field (offset 0EH) of
the FCB. If the record size is less than a sector, the data at the Disk
Transfer Address is written to a buffer, the buffer is written to disk when
it contains a full sector of data; or when a program closes the file, or
when it issues Function 0DH (Reset Disk).
AL returns a code that describes the processing:
Code Meaning
───────────────────────────────────────────────────────────────────────────
0 Write completed successfully
1 Disk is full
2 Not enough room at the Disk Transfer Address to write one record;
write canceled
Macro Definition:
write_ran macro fcb
mov dx,offset fcb
mov ah,22H
int 21H
endm
Example:
The following program prompts for a letter, converts it to its alphabetic
sequence (A = 1, B = 2, etc.), then reads and displays the corresponding
record from a file named alphabet.dat that is on the disk in drive B.
After displaying the record, it prompts you to enter a changed record. If
you type a new record, it is written to the file, but if you just press the
RETURN key, the record is not replaced. The file contains 26 records, each
28 bytes long.
record_size equ 0EH ;offset of Record Size
;field of FCB
relative_record equ 21H ;offset of Relative Record
; field of FCB
fcb db 2,"ALPHABETDAT"
db 26 dup (?)
buffer db 28 dup(?),0DH,0AH,"$"
prompt1 db "Enter letter: $"
prompt2 db "New record (RETURN for no change): $"
crlf db 0DH,0AH,"$"
reply db 28 dup (32)
blanks db 26 dup (32)
;
begin: set_dta buffer ;see Function 1AH
open fcb ;see Function 0FH
mov fcb[record_size],28 ;set record size
get_char: display prompt1 ;see Function 09H
read_kbd_and_echo ;see Function 01H
cmp al,0DH ;just a carriage return?
je all_done ;yes, go home
sub al,41H ;convert ASCII
;code to record #
mov fcb[relative_record],al
;set relative record
display crlf ;see Function 09H
read_ran fcb ;THIS FUNCTION
display buffer ;see Function 09H
display crlf ;see Function 09H
display prompt2 ;see Function 09H
get_string 27,reply ;see Function 0AH
display crlf ;see Function 09H
cmp reply[1],0 ;was anything typed
;besides CR?
je get_char ;no
;get another char.
xor bx,bx ;to load a byte
mov bl,reply[1] ;use reply length as
;counter
move_string blanks,buffer,26 ;see chapter end
move_string reply[2],buffer,bx ;see chapter end
write_ran fcb ;THIS FUNCTION
jmp get_char ;get another character
all_done: close fcb ;see Function 10H
Get File Size (Function 23H)
Call:
AH = 23H
DS:DX
Pointer to unopened FCB
Return:
AL
00H = Directory entry found
FFH = No directory entry found
Comments:
Function 23H returns the size of a specified file. DX must contain the
offset (from the segment address in DS) of an unopened FCB.
If there is a directory entry that matches the specified file, MS-DOS
divides the File Size field (offset 1CH) of the directory entry by the
Record Size field (offset 0EH) of the FCB, puts the result in the Relative
Record field (offset 20H) of the FCB, and returns 00 in AL.
You must set the Record Size field of the FCB to the correct value
before calling this function. If the Record Size field is not an even
divisor of the File Size field, the value set in the Relative Record field
is rounded up, yielding a value larger than the actual number of records.
If this call does not find a matching directory, AL returns FFH.
Macro Definition:
file_size macro fcb
mov dx,offset fcb
mov ah,23H
int 21H
endm
Example:
The following program prompts for the name of a file, opens the file to
fill in the Record Size field of the FCB, issues a File Size system call,
and displays the record length and number of records.
fcb db 37 dup (?)
prompt db "File name: $"
msg1 db "Record length: ",0DH,0AH,"$"
msg2 db "Records: ",0DH,0AH,"$"
crlf db 0DH,0AH,"$"
reply db 17 dup(?)
;
begin: display prompt ;see Function 09H
get_string 17,reply ;see Function 0AH
cmp reply[1],0 ;just a CR?
jne get_length ;no, keep going
jmp all_done ;yes, go home
get_length: display crlf ;see Function 09H
parse reply[2],fcb ;see Function 29H
open fcb ;see Function 0FH
file_size fcb ;THIS FUNCTION
mov ax,word ptr fcb[33] ;get record length
convert ax,10,msg2[9] ;see end of chapter
mov ax,word ptr fcb[14] ; get record number
convert ax,10,msg1[15] ;see end of chapter
display msg1 ;see Function 09H
display msg2 ;see Function 09H
all_done: close fcb ;see Function 10H
Set Relative Record (Function 24H)
Call:
AH = 24H
DS:DX
Pointer to opened FCB
Return:
None
Comments:
Function 24H sets the Relative Record field (offset 20H) to the file
address specified by the Current Block field (offset 0CH) and Current
Record field (offset 1FH). DX must contain the offset (from the segment
address in DS) of an opened FCB. You use this call to set the file pointer
before a Random Read or Write (Functions 21H, 22H, 27H, or 28H).
Macro Definition:
set_relative_record macro fcb
mov dx,offset fcb
mov ah,24H
int 21H
endm
Example:
The following program copies a file using the Random Block Read and Random
Block Write system calls. It speeds the copy by setting the record length
equal to the file size and the record count to 1, and by using a buffer of
32K bytes. It positions the file pointer by setting the Current Record
field (offset 1FH) to 1 and using Function 24H (Set Relative Record) to
make the Relative Record field (offset 20H) point to the same record that
the combination of the Current Block field (offset 0CH) and Current Record
field (offset 1FH) points to.
current_record equ 20H ;offset of Current Record
;field of FCB
fil_size equ 10H ;offset of File Size
; field of FCB
fcb db 37 dup (?)
filename db 17 dup(?)
prompt1 db "File to copy: $" ;see Function 09H for
prompt2 db "Name of copy: $" ;explanation of $
crlf db 0DH,0AH,"$"
file_length dw ?
buffer db 32767 dup(?)
;
begin: set_dta buffer ;see Function 1AH
display prompt1 ;see Function 09H
get_string 15,filename ;see Function 0AH
display crlf ;see Function 09H
parse filename[2],fcb ;see Function 29H
open fcb ;see Function 0FH
mov fcb[current_record],0 ;set Current Record field
set_relative_record fcb ;THIS FUNCTION
mov ax,word ptr fcb[fil_size] ;get file size
mov file_length,ax ;save it for ran_block_write
ran_block_read fcb,1,ax ;see Function 27H
display prompt2 ;see Function 09H
get_string 15,filename ;see Function 0AH
display crlf ;see Function 09H
parse filename[2],fcb ;see Function 29H
create fcb ;see Function 16H
mov fcb[current_record],0 ;set Current Record field
set_relative_record fcb ;THIS FUNCTION
mov ax,file_length ;get original file
ran_block_write fcb,1,ax ;see Function 28H
close fcb ;see Function 10H
Set Interrupt Vector (Function 25H)
Call:
AH = 25H
AL
Interrupt number
DS:DX
Pointer to interrupt-handling
routine
Return:
None
Comments:
Function 25H sets the address in the interrupt vector table for the
specified interrupt.
AL must contain the number of the interrupt. DX must contain the
offset (to the segment address in DS) of the interrupt-handling routine.
To avoid compatibility problems, programs should never set an interrupt
vector directly and should never use Interrupt 25H to read directly from
memory. To get a vector, use Function 35H (Get Interrupt Vector), and to
set a vector, use Function 25H, unless your program must be compatible with
MS-DOS versions earlier than 2.0.
Macro Definition:
set_vector macro interrupt,handler_start
mov al,interrupt
mov dx,offset handler_start
mov ah,25H
endm
Example:
Because interrupts tend to be machine-specific, no example is shown.
Create New PSP (Function 26H)
Call:
AH = 26H
DX
Segment address of new PSP
Return:
None
Comments:
This function request has been superseded. Use Function 4BH (Load and
Execute Program) to run a child process, unless your program must be
compatible with MS-DOS versions earlier than 2.0.
Function 26H creates a new Program Segment Prefix. DX must contain the
segment address where the new PSP is to be created.
Macro Definition:
create_psp macro seg_addr
mov dx,seg_addr
mov ah,26H
endm
Example:
Because Function 4BH (Load and Execute Program) and 4B03H (Load Overlay)
have superseded this function request, no example is shown.
Random Block Read (Function 27H)
Call:
AH = 27H
DS:DX
Pointer to opened FCB
CX
Number of blocks to read
Return:
AL
0 = Read completed successfully
1 = End of file, empty record
2 = DTA too small
3 = End of file, partial record
CX
Number of blocks read
Comments:
Function 27H reads one or more records from a specified file to the Disk
Transfer Address. DX must contain the offset (to the segment address in DS)
of an opened FCB. CX must contain the number of records to read. Reading
starts at the record specified by the Relative Record field (offset 20H);
you must set this field with Function 24H (Set Relative Record) before
calling this function.
DOS calculates the number of bytes to read by multiplying the value in
CX by the Record Size field (offset 0EH) of the FCB.
CX returns the number of records read. The Current Block field (offset
0CH), Current Record field (offset 1FH), and Relative Record field (offset
20H) are set to address the next record.
If you call this function with CX=0, no records are read.
AL returns a code that describes the processing:
Code Meaning
───────────────────────────────────────────────────────────────────────────
0 Read completed successfully
1 End-of-file; no data in the record
2 Not enough room at the Disk Transfer Address to read one record;
read canceled
3 End-of-file; a partial record was read and padded to
the record length with zeros
Macro Definition:
ran_block_read macro fcb,count,rec_size
mov dx,offset fcb
mov cx,count
mov word ptr fcb[14],rec_size
mov ah,27H
int 21H
endm
Example:
The following program copies a file by using Function 27H (Random Block
Read). This program speeds the copy process by specifying a record count
of 1 and a record length equal to the file size, and by using a buffer of
32K bytes; the file is read as a single record (compare to the sample
program for Function 28H that specifies a record length of 1 and a record
count equal to the file size).
current_record equ 20H ;offset of Current Record field
fil_size equ 10H ;offset of File Size field
;
fcb db 37 dup (?)
filename db 17 dup(?)
prompt1 db "File to copy: $" ;see Function 09H for
prompt2 db "Name of copy: $" ;explanation of $
crlf db 0DH,0AH,"$"
file_length dw ?
buffer db 32767 dup(?)
;
begin: set_dta buffer ;see Function 1AH
display prompt1 ;see Function 09H
get_string 15,filename ;see Function 0AH
display crlf ;see Function 09H
parse filename[2],fcb ;see Function 29H
open fcb ;see Function 0FH
mov fcb[current_record],0 ;set Current Record field
set_relative_record fcb ;see Function 24H
mov ax, word ptr fcb[fil_size]
;get file size
mov file_length,ax ;save it
ran_block_read fcb,1,ax ;THIS FUNCTION
display prompt2 ;see Function 09H
get_string 15,filename ;see Function 0AH
display crlf ;see Function 09H
parse filename[2],fcb ;see Function 29H
create fcb ;see Function 16H
mov fcb[current_record],0 ;set current Record field
set_relative_record fcb ;see Function 24H
ran_block_write fcb,1,ax ;see Function 28H
close fcb ;see Function 10H
Random Block Write (Function 28H)
Call:
AH = 28H
DS:DX
Pointer to opened FCB
CX
Number of blocks to write
(0 = set File Size field)
Return:
AL
00H = Write completed successfully
01H = Disk full
02H = End of segment
CX
Number of blocks written
Comments:
Function 28H writes one or more records to a specified file from the Disk
Transfer Address. DX must contain the offset (to the segment address in DS)
of an opened FCB; CX must contain either the number of records to write
or 0.
If CX is not 0, the specified number of records is written to the file,
starting at the record specified in the Relative Record field (offset 20H)
of the FCB. If CX is 0, no records are written, but MS-DOS sets the
File Size field (offset 1CH) of the directory entry to the value in the
Relative Record field (offset 20H) of the FCB. To satisfy this new file
size, disk allocation units are allocated or released, as required.
MS-DOS calculates the number of bytes to write by multiplying the
value in CX by the Record Size field (offset 0EH) of the FCB. CX returns
the number of records written; the Current Block field (offset 0CH),
Current Record field (offset 1FH), and Relative Record (offset 20H) field
are set to address the next record.
AL returns a code that describes the processing:
Code Meaning
───────────────────────────────────────────────────────────────────────────
0 Write completed successfully
1 Disk full. No records written
2 Not enough room at the Disk Transfer Address to write one record;
write canceled
Macro Definition:
ran_block_write macro fcb,count,rec_size
mov dx,offset fcb
mov cx,count
mov word ptr fcb[14],rec_size
mov ah,28H
int 21H
endm
Example:
The following program copies a file using Function 27H (Random Block Read)
and Function 28H (Random Block Write). This program speeds the copy process
by specifying a record count equal to the file size and a record length of
1, and by using a buffer of 32K bytes; the file is copied quickly with one
disk access each to read and write (compare to the sample program of
Function 27H, which specifies a record count of 1 and a record length
equal to file size).
current_record equ 20H ;offset of Current Record field
fil_size equ 10H ;offset of File Size field
;
fcb db 37 dup (?)
filename db 17 dup(?)
prompt1 db "File to copy: $" ;see Function 09H for
prompt2 db "Name of copy: $" ;explanation of $
crlf db 0DH,0AH,"$"
num_recs dw ?
buffer db 32767 dup(?)
;
begin: set_dta buffer ;see Function 1AH
display prompt1 ;see Function 09H
get_string 15,filename ;see Function 0AH
display crlf ;see Function 09H
parse filename[2],fcb ;see Function 29H
open fcb ;see Function 0FH
mov fcb[current_record],0;set Current Record field
set_relative_record fcb ;see Function 24H
mov ax, word ptr fcb[fil_size]
;get file size
mov num_recs,ax ;save it
ran_block_read fcb,num_recs,1 ;THIS FUNCTION
display prompt2 ;see Function 09H
get_string 15,filename ;see Function 0AH
display crlf ;see Function 09H
parse filename[2],fcb ;see Function 29H
create fcb ;see Function 16H
mov fcb[current_record],0 ;set Current Record field
set_relative_record fcb ;see Function 24H
ran_block_write fcb,num_recs,1 ;see Function 28H
close fcb ;see Function 10H
Parse File Name (Function 29H)
Call:
AH = 29H
AL
Controls parsing (see text)
DS:SI
Pointer to string to parse
ES:DI
Pointer to buffer for unopened FCB
Return:
AL
00H = No wildcard characters
01H = Wildcard characters used
FFH = Drive letter invalid
DS:SI
Pointer to first byte past
string that was parsed
ES:DI
Pointer to unopened FCB
Comments:
Function 29H parses a string for a filename of the form
drive:filename.extension. SI must contain the offset (to the segment
address in DS) of the string to parse; DI must contain the offset (to the
segment address in ES) of an area of memory large enough to hold an
unopened FCB. If the string contains a valid filename, this call creates
a corresponding unopened FCB at ES:DI.
AL controls the parsing. Bits 4-7 must be 0; bits 0-3 have the
following meaning:
Table 1.20
Bit values for Function 29H
╓┌──────────┌───────┌────────────────────────────────────────────────────────╖
Bit Value Meaning
────────────────────────────────────────────────────────────────────
0 0 Stop parsing if a file separator is encountered.
Bit Value Meaning
0 0 Stop parsing if a file separator is encountered.
1 Ignore leading separators.
1 0 Set the drive number in the FCB to 0 (current
drive) if the string does not contain a drive
number.
1 Leave the drive number in the FCB unchanged if
the string does not contain a drive number.
2 0 Set the filename in the FCB to eight blanks if
the string does not contain a filename.
1 Leave the filename in the FCB unchanged if the
string does not contain a filename.
3 1 Leave the extension in the FCB unchanged if the
string does not contain an extension.
Bit Value Meaning
0 Set the extension in the FCB to three blanks if
the string does not contain an extension.
If the string contains a filename or extension that includes an asterisk
(*), all remaining characters in the name or extension are set to question
marks (?).
Filename separators:
: ; . , = + / " [ ] \ < > | space tab
Filename terminators include all the filename separators, plus any control
character. A filename cannot contain a filename terminator, since if the
call encounters one, parsing stops.
If the string contains a valid filename:
■ AL returns 1 if the filename or extension contains a wildcard
character (* or ?); AL returns 0 if neither the filename nor
extension contains a wildcard character.
■ DS:SI points to the first character following the parsed string.
■ ES:DI points to the first byte of the unopened FCB.
If the drive letter is invalid, AL returns FFH. If the string does not
contain a valid filename, ES:DI+1 points to a blank.
Macro Definition:
parse macro string,fcb
mov si,offset string
mov di,offset fcb
push es
push ds
pop es
mov al,0FH ;bits 0-3 on
mov ah,29H
int 21H
pop es
endm
Example:
The following program verifies the existence of the file named in reply to
the prompt.
fcb db 37 dup (?)
prompt db "Filename: $"
reply db 17 dup(?)
yes db "File exists",0DH,0AH,"$"
no db "File does not exist",0DH,0AH,"$"
crlf db 0DH,0AH,"$"
;
begin: display prompt ;see Function 09H
get_string 15,reply ;see Function 0AH
parse reply[2],fcb ;THIS FUNCTION
display crlf ;see Function 09H
search_first fcb ;see Function 11H
cmp al,0FFH ;dir. entry found?
je not_there ;no
display yes ;see Function 09H
jmp return
not_there: display no
Get Date (Function 2AH)
Call:
AH = 2AH
Return:
CX
Year (1980-2099)
DH
Month (1-12)
DL
Day (1-31)
AL
Day of week (0=Sun., 6=Sat.)
Comments:
Function 2AH returns the current date set in the operating system as binary
numbers in CX and DX:
Register Contents
───────────────────────────────────────────────────────────────────────────
CX Year (1980-2099)
DH Month (1=January, 2=February, etc.)
DL Day of month (1-31)
AL Day of week (0=Sunday, 1=Monday, etc.)
Macro Definition:
get_date macro
mov ah,2AH
int 21H
endm
Example:
The following program gets the date, increments the day, increments the
month or year, if necessary, and sets the new date.
month db 31,28,31,30,31,30,31,31,30,31,30,31
;
begin: get_date ;THIS FUNCTION
inc dl ;increment day
xor bx,bx ;so BL can be used as index
mov bl,dh ;move month to index register
dec bx ;month table starts with 0
cmp dl,month[bx] ;past end of month?
jle month_ok ;no, set new date
mov dl,1 ;yes, set day to 1
inc dh ;and increment month
cmp dh,12 ;past end of year?
jle month_ok ;no, set new date
mov dh,1 ;yes, set month to 1
inc cx ;increment year
month_ok: set_date cx,dh,dl ;see Function 2AH
Set Date (Function 2BH)
Call:
AH = 2BH
CX
Year (1980-2099)
DH
Month (1-12)
DL
Day (1-31)
Return:
AL
00H = Date was valid
FFH = Date was invalid
Comments:
Function 2BH sets the date in the operating system (and in the CMOS clock,
if one exists). Registers CX and DX must contain a valid date in binary:
Register Contents
───────────────────────────────────────────────────────────────────────────
CX Year (1980-2099)
DH Month (1=January, 2=February, etc.)
DL Day of month (1-31)
If the date is valid, the call sets it and AL returns 0. If the date
is not valid, the function aborts and AL returns FFH.
Macro Definition:
set_date macro year,month,day
mov cx,year
mov dh,month
mov dl,day
mov ah,2BH
int 21H
endm
Example:
The following program gets the date, increments the day, increments the
month or year, if necessary, and sets the new date.
month db 31,28,31,30,31,30,31,31,30,31,30,31
;
begin: get_date ;see Function 2AH
inc dl ;increment day
xor bx,bx ;so BL can be used as index
mov bl,dh ;move month to index register
dec bx ;month table starts with 0
cmp dl,month[bx] ;past end of month?
jle month_ok ;no, set the new date
mov dl,1 ;yes, set day to 1
inc dh ;and increment month
cmp dh,12 ;past end of year?
jle month_ok ;no, set the new date
mov dh,1 ;yes, set the month to 1
inc cx ;increment year
month_ok: set_date cx,dh,dl ;THIS FUNCTION
Get Time (Function 2CH)
Call:
AH = 2CH
Return:
CH
Hour (0-23)
CL
Minutes (0-59)
DH
Seconds (0-59)
DL
Hundredths (0-99)
Comments:
Function 2CH returns the current time set in the operating system (and sets
the CMOS clock, if one exists) as binary numbers in CX and DX:
Register Contents
───────────────────────────────────────────────────────────────────────────
CH Hour (0-23)
CL Minutes (0-59)
DH Seconds (0-59)
DL Hundredths of a second (0-99)
Depending on how your hardware keeps time, some of these fields may be
irrelevant. As an example, many CMOS clock chips do not resolve more than
seconds. In such a case, the value in DL will probably always be 0.
Macro Definition:
get_time macro
mov ah,2CH
int 21H
endm
Example:
The following program displays the time continuously until you press
any key.
time db "00:00:00.00",0DH,"$"
;
begin: get_time ;THIS FUNCTION
byte_to_dec ch,time ;see end of chapter
byte_to_dec cl,time[3] ;see end of chapter
byte_to_dec dh,time[6] ;see end of chapter
byte_to_dec dl,time[9] ;see end of chapter
display time ;see Function 09H
check_kbd_status ;see Function 0BH
cmp al,0FFH ;has a key been pressed?
je return ;yes, terminate
jmp begin ;no, display time
Set Time (Function 2DH)
Call:
AH = 2DH
CH
Hour (0-23)
CL
Minutes (0-59)
DH
Seconds (0-59)
DL
Hundredths (0-99)
Return:
AL
00H = Time was valid
FFH = Time was invalid
Comments:
Function 2DH sets the time in the operating system. Registers CX and DX
must contain a valid time in binary:
Register Contents
───────────────────────────────────────────────────────────────────────────
CH Hour (0-23)
CL Minutes (0-59)
DH Seconds (0-59)
DL Hundredths of a second (0-9)
Depending on how your hardware keeps time, some of these fields may be
irrelevant. As an example, many CMOS clock chips do not resolve more than
seconds. In such a case, the value in DL will not be relevant.
If the time is valid, the call sets it and AL returns 0. If the time
is not valid, the function aborts and AL returns FFH.
Macro Definition:
set_time macro hour,minutes,seconds,hundredths
mov ch,hour
mov cl,minutes
mov dh,seconds
mov dl,hundredths
mov ah,2DH
int 21H
endm
Example:
The following program sets the system clock to 0 and displays the time
continuously. When you type a character, the display freezes; when you type
another character, the clock is reset to 0 and the display starts again.
time db "00:00:00.00",0DH,0AH,"$"
;
begin: set_time 0,0,0,0 ;THIS FUNCTION
read_clock: get_time ;see Function 2CH
byte_to_dec ch,time ;see end of chapter
byte_to_dec cl,time[3] ;see end of chapter
byte_to_dec dh,time[6] ;see end of chapter
byte_to_dec dl,time[9] ;see end of chapter
display time ;see Function 09H
dir_console_io 0FFH ;see Function 06H
cmp al,00H ;was a char. typed?
jne stop ;yes, stop the timer
jmp read_clock ;no keep timer on
stop: read_kbd ;see Function 08H
jmp begin ;keep displaying time
Set/Reset Verify Flag (Function 2EH)
Call:
AH = 2EH
AL
0 = Do not verify
1 = Verify
Return:
None
Comments:
Function 2EH tells MS-DOS whether to verify each disk write. If AL is 1,
verify is on; if AL is 0, verify is off. MS-DOS checks this flag each time
it writes to a disk.
The flag is normally off; you may wish to turn it on when writing
critical data to disk. Because disk errors are rare and verification slows
writing, you will probably want to leave it off at other times. You can
check the setting with Function 54H (Get Verify State).
Macro Definition:
verify macro switch
mov al,switch
mov ah,2EH
int 21H
endm
Example:
The following program copies the contents of a single-sided disk in drive A
to the disk in drive B, verifying each write. It uses a buffer of
32K bytes.
on equ 1
off equ 0
;
prompt db "Source in A, target in B",0DH,0AH
db "Any key to start. $"
first dw 0
buffer db 60 dup (512 dup(?)) ;60 sectors
;
begin: display prompt ;see Function 09H
read_kbd ;see Function 08H
verify on ;THIS FUNCTION
mov cx,6 ;copy 60 sectors
;6 times
copy: push cx ;save counter
abs_disk_read 0,buffer,60,first ;see Int 25H
abs_disk_write 1,buffer,64,first ;see Int 26H
add first,60 ;do next 60 sectors
pop cx ;restore counter
loop copy ;do it again
verify off ;THIS FUNCTION
Get Disk Transfer Address (Function 2FH)
Call:
AH = 2FH
Return:
ES:BX
Pointer to Disk Transfer Address
Comments:
Function 2FH returns the segment address of the current Disk Transfer
Address in ES and the offset in BX.
Macro Definition:
get_dta macro
mov ah,2fH
int 21H
endm
Example:
The following program displays the current Disk Transfer Address in the
form: segment:offset.
message db "DTA -- : ",0DH,0AH,"$"
sixteen db 10H
temp db 2 dup (?)
;
begin: get_dta ;THIS FUNCTION
mov word ptr temp,ex ;To access each byte
convert temp[1],sixteen,message[07H] ;See end of
convert temp,sixteen,message[09H] ;chapter for
convert bh,sixteen,message[0CH] ;description
convert bl,sixteen,message[0EH] ;of CONVERT
display message ;See Function 09H
Get MS-DOS Version Number (Function 30H)
Call:
AH = 30H
Return:
AL
Major version number
AH
Minor version number
BH
OEM serial number
BL:CX
24-bit user (serial) number
Comments:
Function 30H returns the MS-DOS version number. AL returns the major
version number; AH returns the minor version number. (For example,
MS-DOS 3.0 returns 3 in AL and 0 in AH.)
If AL returns 0, the MS-DOS version is earlier than 2.0.
Macro Definition:
get_version macro
mov ah,30H
int 21H
endm
Example:
The following program displays the MS-DOS version if it is 1.28 or greater.
message db "MS-DOS Version . ",0DH,0AH,"$"
ten db 0AH ;For CONVERT
;
begin: get_version ;THIS FUNCTION
cmp al,0 ;1.28 or later?
jng return ;No, go home
convert al,ten,message[0FH] ;See end of chapter
convert ah,ten,message[12H] ;for description
display message ;See Function 09H
Keep Process (Function 31H)
Call:
AH = 31H
AL
Return code
DX
Memory size, in paragraphs
Return:
None
Comments:
Function 31H makes a program remain resident after it terminates. You can
use it to install device-specific interrupt handlers. But unlike Interrupt
27H (Terminate But Stay Resident), this function request allows more than
64K bytes to remain resident and does not require CS to contain the segment
address of the Program Segment Prefix. You should use Function 31H to
install a resident program unless your program must be compatible with
MS-DOS versions earlier than 2.0.
DX must contain the number of paragraphs of memory required by the
program (one paragraph = 16 bytes). AL contains an exit code.
Be careful when using this function with .exe programs. The value in
DX must be the total size to remain resident, not just the size of the code
segment which is to remain resident. A typical error is to forget about
the 100H-byte program-header-prefix and give a value in DX that is 10H
too small.
MS-DOS terminates the current process and tries to set the memory
allocation to the number of paragraphs in DX. No other allocation blocks
belonging to the process are released.
By using Function 4DH (Get Return Code of Child Process), the parent
process can retrieve the process's exit code from AL. (You can test this
exit code by using the if command with errorlevel.)
Macro Definition:
keep_process macro return_code,last_byte
mov al,return_code
mov dx,offset last_byte
mov cl,4
shr dx,cl
inc dx
mov ah,31H
int 21H
endm
Example:
Because the most common use of this call is to install a machine-specific
routine, an example is not shown. The macro definition, however, shows the
calling syntax.
CONTROL-C Check (Function 33H)
Call:
AH = 33H
AL
0 = Get state
1 = Set state
DL (if AL=1)
0 = Off
1 = On
Return:
DL (if AL=0)
0 = Off
1 = On
AL
FFH = error (AL was neither 0 nor 1
when call was made)
Comments:
Function 33H gets or sets the state of CONTROL-C (or CONTROL-BREAK for IBM
compatibles) checking in MS-DOS. AL must contain a code that specifies the
requested action:
Code Meaning
───────────────────────────────────────────────────────────────────────────
0 Current state of CONTROL-C checking in DL
1 Set state of CONTROL-C checking to the value in DL
If AL is 0, DL returns the current state (0=off, 1=on). If AL is 1, the
value in DL specifies the state to be set (0=off, 1=on). If AL is neither 0
nor 1, AL returns FFH and the state of CONTROL-C checking is unaffected.
MS-DOS normally checks for CONTROL-C only when carrying out certain
function requests in the 01H through 0CH group (see the description of
specific calls for details). When CONTROL-C checking is on, MS-DOS checks
for CONTROL-C when carrying out any function request. For example, if
CONTROL-C checking is off, all disk I/O proceeds without interruption, but
if it is on, the CONTROL-C interrupt is issued at the function request that
initiates the disk operation.
───────────────────────────────────────────────────────────────────────────
Note
Programs that use Function 06H (Direct Console I/O) or 07H (Direct
Console Input) to read CONTROL-C as data must ensure that the CONTROL-C
checking is off.
───────────────────────────────────────────────────────────────────────────
Macro Definition:
ctrl_c_ck macro action,state
mov al,action
mov dl,state
mov ah,33H
int 21H
endm
Example:
The following program displays a message that tells whether CONTROL-C
checking is on or off:
message db "CONTROL-C checking ","$"
on db "on","$",0DH,0AH,"$"
off db "off","$",0DH,0AH,"$"
;
begin: display message ;See Function 09H
ctrl_c_ck 0 ;THIS FUNCTION
cmp dl,0 ;Is checking off?
jg ck_on ;No
display off ;See Function 09H
jmp return ;Go home
ck_on: display on ;See Function 09H
Get Interrupt Vector (Function 35H)
Call:
AH = 35H
AL
Interrupt number
Return:
ES:BX
Pointer to interrupt routine
Comments:
Function 35H gets the address from the interrupt-vector table for the
specified interrupt. AL must contain the number of an interrupt.
ES returns the segment address of the interrupt handler; BX returns
the offset.
To avoid compatibility problems, programs should never read an
interrupt vector directly from memory, nor set an interrupt vector by
writing it into memory. Use this function request to get a vector and
Function 25H (Set Interrupt Vector) to set a vector, unless your program
must be compatible with MS-DOS versions earlier than 2.0.
Macro Definition:
get_vector macro interrupt
mov al,interrupt
mov ah,35H
int 21H
endm
Example:
The following program displays the segment and offset (CS:IP) for the
handler for Interrupt 25H (Absolute Disk Read).
message db "Interrupt 25H -- CS:0000 IP:0000"
db 0DH,0AH,"$"
vec_seg db 2 dup (?)
vec_off db 2 dup (?)
;
begin: push es ;save ES
get_vector 25H ;THIS FUNCTION
mov ax,es ;INT25H segment in AX
pop es ;save ES
convert ax,16,message[20] ;see end of chapter
convert bx,16,message[28] ;see end of chapter
display message ;See Function 09H
Get Disk Free Space (Function 36H)
Call:
AH = 36H
DL
Drive (0=default, 1=A, etc.)
Return:
AX
0FFFFH if drive number is invalid;
otherwise, sectors per cluster
BX
Available clusters
CX
Bytes per sector
DX
Clusters per drive
Comments:
Function 36H returns the number of clusters available on the disk in the
specified drive, and the information necessary to calculate the number of
bytes available on the disk. DL must contain a drive number (0=default,
1=A, etc.). If the drive number is valid, MS-DOS returns the information
in the following registers:
Register Contents
───────────────────────────────────────────────────────────────────────────
AX Sectors per cluster
BX Available clusters
CX Bytes per sector
DX Total clusters
If the drive number is invalid, AX returns 0FFFFH.
This call supersedes Functions 1BH and 1CH in earlier MS-DOS versions.
Macro Definition:
get_disk_space macro drive
mov dl,drive
mov ah,36H
int 21H
endm
Example:
The following program displays the space information for the disk in
drive B.
message db " clusters on drive B.",0DH,0AH ;DX
db " clusters available.",0DH,0AH ;BX
db " sectors per cluster.",0DH,0AH ;AX
db " bytes per sector,",0DH,0AH,"$" ;CX
;
begin: get_disk_space 2 ;THIS FUNCTION
convert ax,10,message[55] ;see end of chapter
convert bx,10,message[28] ;see end of chapter
convert cx,10,message[83] ;see end of chapter
convert dx,10,message ;see end of chapter
display message ;See Function 09H
Get Country Data (Function 38H)
Call:
AH = 38H
AL
00H = Current country
1-0FEH = Country code
0FFH = BX contains country code
BX (if AL = 0FFH)
Country code 255 or higher
DS:DX
Pointer to 32-byte memory area
Return:
Carry set:
AX
2 = Invalid country code
Carry not set:
BX
Country code
Comments:
Function 38H gets the country-dependent information that MS-DOS uses to
control the keyboard and display, or it sets the currently defined country
(to set the country code, see the next function request description, Set
Country Data). To get the information, DX must contain the offset (from the
segment address in DS) of a 32-byte memory area to which the country data
returns. AL specifies the country code:
Value in AL Meaning
───────────────────────────────────────────────────────────────────────────
00H Retrieve information about the country currently set.
1 to 0FEH Retrieve information about the country identified by
this code.
0FFH Retrieve information about the country identified by the
code in BX.
BX must contain the country code if the code is 255 or greater. The
country code is usually the international telephone-prefix code.
The country-dependent information returns in the following form:
Offset
Hex Decimal Field Name Length in bytes
───────────────────────────────────────────────────────────────────────────
00H 0 Date format 2 (word)
02H 2 Currency symbol 5 (ASCIZ string)
07H 7 Thousands separator 2 (ASCIZ string)
09H 9 Decimal separator 2 (ASCIZ string)
0BH 11 Date separator 2 (ASCIZ string)
0DH 13 Time separator 2 (ASCIZ string)
0FH 15 Bit field 1
10H 16 Currency places 1
11H 17 Time format 1
12H 18 Case-map call address 4 (DWORD)
16H 22 Data-list separator 2 (ASCIZ string)
18H 24 Reserved 10
Date Format:
0 = USA (month/day/year)
1 = Europe (day/month/year)
2 = Japan (year/month/day)
Bit Field:
Bit Value Meaning
───────────────────────────────────────────────────────────────────────────
0 0 Currency symbol precedes amount
1 Currency symbol follows amount
1 0 No space between symbol and amount
1 One space between symbol and amount
All other bits are undefined.
Time format:
0 = 12-hour clock
1 = 24-hour clock
Currency Places:
Specifies the number of places that appear after the decimal point on
currency amounts.
Case-Mapping Call Address:
Specifies the segment and offset of a FAR procedure that performs
country-specific lowercase-to-uppercase mapping on character values from
80H to 0FFH. You call it with the character to be mapped in AL. If there is
an uppercase code for the character, it is returned in AL; if there is not,
or if you call it with a value less than 80H in AL, AL returns unchanged.
AL and the FLAGS are the only altered registers.
If there is an error, the carry flag (CF) is set and the error code
returns in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
2 Invalid country code (no table for it).
Macro Definition:
get_country macro country,buffer
local gc_01
mov dx,offset buffer
mov ax,country
cmp ax,OFFH
jl gc_01
mov al,OFFh
mov bx,country
gc_01: mov ah,38h
int 21H
endm
Example:
The following program displays the time and date in the format appropriate
to the current country code, and the number 999,999 and 99/100 as a
currency amount with the proper currency symbol and separators.
time db " : : ",5 dup (20H),"$"
date db " / / ",5 dup (20H),"$"
number db "999?999?99",0DH,0AH,"$"
data_area db 32 dup (?)
;
begin: get_country 0,data_area ;THIS FUNCTION
get_time ;See Function 2CH
byte_to_dec ch,time ;See end of chapter
byte_to_dec cl,time[03H] ;for description of
byte_to_dec dh,time[06H] ;CONVERT macro
get_date ;See Function 2AH
sub cx,1900 ;Want last 2 digits
byte_to_dec cl,date[06H] ;See end of chapter
cmp word ptr data_area,0 ;Check country code
jne not_usa ;It's not USA
byte_to_dec dh,date ;See end of chapter
byte_to_dec dl,date[03H] ;See end of chapter
jmp all_done ;Display data
not_usa: byte_to_dec dl,date ;See end of chapter
byte_to_dec dh,date[03H] ;See end of chapter
all_done: mov al,data_area[07H] ;Thousand separator
mov number[03H],al ;Put in NUMBER
mov al,data_area[09H] ;Decimal separator
mov number[07H],al ;Put in AMOUNT
display time ;See Function 09H
display date ;See Function 09H
display_char data_area[02H] ;See Function 02H
display number ;See Function 09H
Set Country Data (Function 38H)
Call:
AH = 38H
DX = -1 (0FFFFH)
AL
Country code less than 255, or
0FFH if the country code is in BX
BX (if AL=0FFH)
Country code 255 or higher
Return:
Carry set:
AX
2 = Invalid country code
Carry not set:
No error
Comments:
Function 38H sets the country code that MS-DOS uses to control the keyboard
and the display, or it retrieves the country-dependent information (to get
the country data, see the previous function request description, "Get
Country Data"). To set the information, DX must contain 0FFFFH. AL must
contain either the country code, if it is less than 255, or 255 to indicate
that the country code is in BX. If AL contains 0FFH, BX must contain the
country code.
The country code is usually the international telephone prefix-code.
See "Get Country Data" for a description of the country data and how
it is used.
If there is an error, the carry flag (CF) is set and the error code
returns in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
2 Invalid country code (no table for it).
Macro Definition:
set_country macro country
local sc_01
mov dx,0FFFFH
mov ax,country
cmp ax,0FFH
jl sc_01
mov bx,country
mov al,0ffh
sc_01: mov ah,38H
int 21H
endm
Example:
The following program sets the country code to the United Kingdom (44).
uk equ 44
;
begin: set_country uk ;THIS FUNCTION
jc error ;routine not shown
Create Directory (Function 39H)
Call:
AH = 39H
DS:DX
Pointer to pathname
Return:
Carry set:
AX
2 = File not found
3 = Path not found
5 = Access denied
Carry not set:
No error
Comments:
Function 39H creates a new subdirectory. DX must contain the offset (from
the segment address in DS) of an ASCIZ string that specifies the pathname
of the new subdirectory.
If there is an error, the carry flag (CF) is set and the error code
returns in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
2 File not found
3 Path not found
5 No room in the parent directory, a file with the same name exists in
the current directory, or the path specifies a device
Macro Definition:
make_dir macro path
mov dx,offset path
mov ah,39H
int 21H
endm
Example:
The following program adds a subdirectory named new_dir to the root
directory on the disk in drive B and changes the current directory to
new_dir. The program then changes the current directory back to the
original directory and then deletes new_dir. It displays the current
directory after each step to confirm the changes.
old_path db "b:
new_path db "b:\new_dir",0
buffer db "b:
;
begin: get_dir 2,old_path[03H] ;See Function 47H
jc error_get ;Routine not shown
display_asciz old_path ;See end of chapter
make_dir new_path ;THIS FUNCTION
jc error_make ;Routine not shown
change_dir new_path ;See Function 3BH
jc error_change ;Routine not shown
get_dir 2,buffer[03H] ;See Function 47H
jc error_get ;Routine not shown
display_asciz buffer ;See end of chapter
change_dir old_path ;See Function 3BH
jc error_change ;Routine not shown
rem_dir new_path ;See Function 3AH
jc error_rem ;Routine not shown
get_dir 2,buffer[03H] ;See Function 47H
jc error_get ;Routine not shown
display_asciz buffer ;See end of chapter
Remove Directory (Function 3AH)
Call:
AH = 3AH
DS:DX
Pointer to pathname
Return:
Carry set:
AX
2 = File not found
3 = Path not found
5 = Access denied
16 = Current directory
Carry not set:
No error
Comments:
Function 3AH deletes a subdirectory. DX must contain the offset (from the
segment address in DS) of an ASCIZ string that specifies the pathname of
the subdirectory you want to delete.
The subdirectory must not contain any files. You cannot erase the current
directory. If there is an error, the carry flag (CF) is set and the error
code returns in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
2 File not found
3 Path not found
5 Directory not empty, or path doesn't specify a directory,
or it specifies the root directory, or it is invalid
16 Path specifies current directory
Macro Definition:
rem_dir macro path
mov dx,offset path
mov ah,3AH
int 21H
endm
Example:
The following program adds a subdirectory named new_dir to the root
directory on the disk in drive B and changes the current directory to
new_dir. The program then changes the current directory back to the
original directory and deletes new_dir. It displays the current directory
after each step to confirm the changes.
old_path db "b:
new_path db "b:\new_dir",0
buffer db "b:
;
begin: get_dir 2,old_path[03H] ;See Function 47H
jc error_get ;Routine not shown
display_asciz old_path ;See end of chapter
make_dir new_path ;See Function 39H
jc error_make ;Routine not shown
change_dir new_path ;See Function 3BH
jc error_change ;Routine not shown
get_dir 2,buffer[03H] ;See Function 47H
jc error_get ;Routine not shown
display_asciz buffer ;See end of chapter
change_dir old_path ;See Function 3BH
jc error_change ;Routine not shown
rem_dir new_path ;THIS FUNCTION
jc error_rem ;Routine not shown
get_dir 2,buffer[03H] ;See Function 47H
jc error_get ;Routine not shown
display_asciz buffer ;See end of chapter
Change Current Directory (Function 3BH)
Call:
AH = 3BH
DS:DX
Pointer to pathname
Return:
Carry set:
AX
2 = File not found
3 = Path not found
Carry not set:
No error
Comments:
Function 3BH changes the current directory. DX must contain the offset
(from the segment address in DS) of an ASCIZ string that specifies the
pathname of the new current directory.
The directory string is limited to 64 characters.
If any member of the path doesn't exist, the path is unchanged.
If there is an error, the carry flag (CF) is set and the error code returns
in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
2 File not found
3 Path either doesn't exist or it specifies a file instead of a
directory
Macro Definition:
change_dir macro path
mov dx,offset path
mov ah,3BH
int 21H
endm
Example:
The following program adds a subdirectory named new_dir to the root
directory that is on the disk in drive B and changes the current directory
to new_dir. The program then changes the current directory back to the
original directory and deletes new_dir. It displays the current directory
after each step to confirm the changes.
old_path db "b:
new_path db "b:\new_dir",0
buffer db "b:
;
begin: get_dir 2,old_path[03H] ;See Function 47H
jc error_get ;Routine not shown
display_asciz old_path ;See end of chapter
make_dir new_path ;See Function 39H
jc error_make ;Routine not shown
change_dir new_path ;THIS FUNCTION
jc error_change ;Routine not shown
get_dir 2,buffer[03H] ;See Function 47H
jc error_get ;Routine not shown
display_asciz buffer ;See end of chapter
change_dir old_path ;See Function 3BH
jc error_change ;Routine not shown
rem_dir new_path ;See Function 3AH
jc error_rem ;Routine not shown
get_dir 2,buffer[03H] ;See Function 47H
jc error_get ;Routine not shown
display_asciz buffer ;See end of chapter
Create Handle (Function 3CH)
Call:
AH = 3CH
DS:DX
Pointer to pathname
CX
File attribute
Return:
Carry set:
AX
2 = File not found
3 = Path not found
4 = Too many open files
5 = Access denied
Carry not set:
AX
Handle
Comments:
Function 3CH creates a file and assigns it the first available handle. DX
must contain the offset (from the segment address in DS) of an ASCIZ string
that specifies the pathname of the file to be created. CX must contain the
attribute to be assigned to the file, as described under "File Attributes"
earlier in this chapter.
If the specified file does not exist, this function creates it. But
if the file already exists, it is truncated to a length of 0. Function 3CH
then assigns the attribute in CX to the file and opens it for read/write.
AX returns the file handle.
If there is an error, the carry flag (CF) is set and the error code
returns in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
2 File not found
3 Path is invalid
4 Too many open files (no handle available)
5 Directory is full, a directory with the same name exists, or a file
with the same name exists with more restrictive attributes
Macro Definition:
create_handle macro path,attrib
mov dx,offset path
mov cx,attrib
mov ah,3CH
int 21H
endm
Example:
The following program creates a file named dir.tmp, containing the name and
extension of each file in the current directory, on the disk in drive B.
srch_file db "b:*.*",0
tmp_file db "b:dir.tmp",0
buffer db 43 dup (?)
handle dw ?
;
begin: set_dta buffer ;See Function 1AH
find_first_file srch_file,16H ;See Function 4EH
cmp ax,12H ;Directory empty?
je all_done ;Yes, go home
create_handle tmp_file,0 ;THIS FUNCTION
jc error ;Routine not shown
mov handle,ax ;Save handle
write_it: write_handle handle,buffer[1EH],12 ;Function 40H
find_next_file ;See Function 4FH
cmp ax,12H ;Another entry?
je all_done ;No, go home
jmp write_it ;Yes, write record
all_done: close_handle handle ;See Function 3EH
Open Handle (Function 3DH)
Call:
AH = 3DH
AL
Access code (see text)
DS:DX
Pointer to pathname
Return:
Carry set:
AX
2 = File not found
3 = Path not found
4 = Too many open files
5 = Access denied
12 = Invalid access
Carry not set:
No error
Comments:
Function 3DH opens any file, including hidden and system files, for input
or output. DX contains the offset (from the segment address in DS) of an
ASCIZ string that specifies the pathname of the file to be opened. AL
contains a code that specifies how the file is to be opened. This code
is described later under "Controlling Access to the File."
If there is no error, AX returns the file handle. MS-DOS sets the
read/write pointer to the first byte of the file.
Controlling Access to the File
The value in AL is made up of three parts that specify whether the file
is to be opened for read, write, or both (access code); what access other
processes have to the file (sharing mode); and whether a child process
inherits the file (inherit bit).
|---|-----------|---------------|
Bit | 7 | 6 5 4 | 3 2 1 0 |
|---|---|---|---|---|---|---|---|
\/ \________/ \____________/
| | |
| | |--------> Access code
| |
| |-----------------------> Sharing mode
|
|-------------------------------> Inherit bit
Inherit Bit
The high-order bit (bit 7) specifies whether the file is inherited by a
child process created with Function 4BH (Load and Execute Program). If the
bit is 0, the child process inherits the file; if the bit is 1, it doesn't.
Sharing Mode
The sharing mode bits (bits 4-6) specify what access, if any, other
processes have to the open file. It can have the following values:
Table 1.21
Sharing Mode Bit Values
╓┌───────────────┌───────────────┌───────────────────────────────────────────╖
Bits 4-6 Sharing Mode Description
────────────────────────────────────────────────────────────────────
000 Compatibility On a given machine, any process
can open the file any number of
times with this mode. Fails if
the file has been opened with
any of the other sharing modes.
001 Deny both Fails if the file has been
opened in compatibility mode or
for read or write access, even
if by the current process.
010 Deny write Fails if the file has been
opened in compatibility mode or
for write access by any other
process.
011 Deny read Fails if the file has been
opened in compatibility mode or
Bits 4-6 Sharing Mode Description
opened in compatibility mode or
for read access by any other
process.
100 Deny none Fails if the file has been
opened in compatibility mode by
any other process.
Access Code
The access code (bits 0-3) specifies how the file is to be used. It can
have the following values:
Table 1.22
Access Code Bit Values
╓┌───────────────┌─────────┌─────────────────────────────────────────────────╖
Access
Bit 0-3 Allowed Description
Access
Bit 0-3 Allowed Description
────────────────────────────────────────────────────────────────────
0000 Read Fails if the file has been opened in
deny read or deny both sharing mode.
0001 Write Fails if the file has been opened in
deny write or deny both sharing
mode.
0010 Both Fails if the file has been opened in
deny read, deny write, or deny both
sharing mode.
If there is an error, the carry flag (CF) is set and the error code is
returned in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
2 Specified file is invalid or doesn't exist
3 Specified path is invalid or doesn't exist
4 No handles are available in the current process or the internal
system tables are full
5 Program attempted to open a directory or VolumeID, or tried to open
a read-only file for writing
12 Access code (bits 0-3 of AL) not 0, 1, or 2
If this system call fails because of a file-sharing error, MS-DOS
issues Interrupt 24H with error code 2 (Drive Not Ready). A subsequent
Function 59H (Get Extended Error) returns the extended error code that
specifies a sharing violation.
When opening a file, it is important to inform MS-DOS of any operations
that other processes may perform on this file (sharing mode). The default
(compatibility mode) denies all other processes access to the file, unless
they also attempt to open the file in compatibility mode.
The following table shows the effect of opening a file with compatibility
mode set:
Type of File Opening Read-Only File Not Read-Only
───────────────────────────────────────────────────────────────────────────
First open for read, Succeeds Succeeds
write, or both by
machine/process "N"
Subsequent opens by Succeeds Succeeds
machine or process "N"
An open by another Succeeds Fails
machine or process
Files may be read-only with the MS-DOS attrib command or by a read-only
share over the network.
It may be all right for other processes to continue to read the file
while your process is operating on it. In this case, you should specify
"Deny Write," which inhibits other processes from writing to your files
but allows them to read from these files.
Similarly, it is important for you to specify what operations your process
will perform ("Access" mode). If another process has the file open with any
sharing mode other than "Deny" mode, then the default mode ("Read/write")
causes the open request to fail. If you only want to read the file, your
open request succeeds unless all other processes have specified "Deny"
mode or "Deny write."
Macro Definition:
open_handle macro path,access
mov dx, offset path
mov al, access
mov ah, 3DH
int 21H
endm
Example:
The following program prints a file named textfile.asc that is on the disk
in drive B.
file db "b:textfile.asc",0
buffer db ?
handle dw ?
;
begin: open_handle file,0 ;THIS FUNCTION
mov handle,ax ;Save handle
read_char: read_handle handle,buffer,1 ;Read 1 character
jc error_read ;Routine not shown
cmp ax,0 ;End of file?
je return ;Yes, go home
print_char buffer ;See Function 05H
jmp read_char ;Read another
Close Handle (Function 3EH)
Call:
AH = 3EH
BX
Handle
Return:
Carry set:
AX
6 = Invalid handle
Carry not set:
No error
Comments:
Function 3EH closes a file opened with Function 3DH (Open Handle) or 3CH
(Create Handle). BX must contain the handle of the open file that you want
to close.
If there is no error, MS-DOS closes the file and flushes all internal
buffers. If there is an error, the carry flag (CF) is set and the error
code returns in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
6 Handle not open or invalid
Macro Definition:
close_handle macro handle
mov bx,handle
mov ah,3EH
int 21H
endm
Example:
The following program creates a file named dir.tmp, containing the filename
and extension of each file in the current directory, in the current
directory on the disk in drive B.
srch_file db "b:*.*",0
tmp_file db "b:dir.tmp",0
buffer db 43 dup (?)
handle dw ?
;
begin: set_dta buffer ;See Function 1AH
find_first_file srch_file,16H ;See Function 4EH
cmp ax,12H ;Directory empty?
je all_done ;Yes, go home
create_handle tmp_file,0 ;See Function 3CH
jc error_create ;Routine not shown
mov handle,ax ;Save handle
write_it: write_handle handle,buffer[1EH],12 ;See Function 40H
find_next_file ;See Function 4FH
cmp ax,12H ;Another entry?
je all_done ;No, go home
jmp write_it ;Yes, write record
all_done: close_handle handle ;See Function 3EH
jc error_close ;Routine not shown
Read Handle (Function 3FH)
Call:
AH = 3FH
BX
Handle
CX
Bytes to read
DS:DX
Pointer to buffer
Return:
Carry set:
AX
5 = Access denied
6 = Invalid handle
Carry not set:
AX
Bytes read
Comments:
Function 3FH reads from the file or device associated with the specified
handle. BX must contain the handle. CX must contain the number of bytes
to be read. DX must contain the offset (to the segment address in DS)
of the buffer.
If there is no error, AX returns the number of bytes read; if you
attempt to read starting at end of file, AX returns 0. The number of bytes
specified in CX is not necessarily transferred to the buffer; if you use
this call to read from the keyboard, for example, it reads only up to the
first carriage-return.
If you use this function request to read from standard input, you can
redirect the input.
If there is an error, the carry flag (CF) is set and the error code
returns in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
5 Handle not open for reading
6 Handle not open or invalid
Macro Definition:
read_handle macro handle,buffer,bytes
mov bx,handle
mov dx,offset buffer
mov cx,bytes
mov ah,3FH
int 21H
endm
Example:
The following program displays a file named textfile.asc that is on the
disk in drive B.
filename db "b:\textfile.asc",0
buffer db 129 dup (?)
handle dw ?
;
begin: open_handle filename,0 ;See Function 3DH
jc error_open ;Routine not shown
mov handle,ax ;Save handle
read_file: read_handle buffer,file_handle,128
jc error_open ;Routine not shown
cmp ax,0 ;End of file?
je return ;Yes, go home
mov bx,ax ;# of bytes read
mov buffer[bx],"$" ;Make a string
display buffer ;See Function 09H
jmp read_file ;Read more
Write Handle (Function 40H)
Call:
AH = 40H
BX
Handle
CX
Bytes to write
DS:DX
Pointer to buffer
Return:
Carry set:
AX
5 = Access denied
6 = Invalid handle
Carry not set:
AX
Bytes written
Comments:
Function 40H writes to the file or device associated with the specified
handle. BX must contain the handle. CX must contain the number of bytes to
be written. DX must contain the offset (to the segment address in DS) of
the data to be written.
If you set CX to zero, the file will be truncated at the current
position of the file pointer. MS-DOS will not perform the write if the
handle is read-only.
If there is no error, AX returns the number of bytes written. Be sure
to check AX after performing a write. If its value is less than the number
in CX when the call was made, it indicates an error, even though the carry
flag isn't set. If AX contains 0, and if the target is a disk file, the
disk is full.
If you use this function request to write to standard output, you can
redirect the output. If you call this request with CX=0, the file size is
set to the value of the read/write pointer. To satisfy the new file size,
allocation units are allocated or released, as required.
If there is an error, the carry flag (CF) is set and the error code
returns in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
5 Handle not open for writing
6 Handle not open or invalid
Macro Definition:
write_handle macro handle,buffer,bytes
mov bx,handle
mov dx,offset buffer
mov cx,bytes
mov ah,40H
int 21H
endm
Example:
The following program creates a file named dir.tmp, containing the filename
and extension of each file in the current directory, in the current
directory on the disk in drive B.
srch_file db "b:*.*",0
tmp_file db "b:dir.tmp",0
buffer db 43 dup (?)
handle dw ?
;
begin: set_dta buffer ;See Function 1AH
find_first_file srch_file,16H ;Check directory
cmp ax,12H ;Directory empty?
je return ;Yes, go home
create_handle tmp_file,0 ;See Function 3CH
jc error_create ;Routine not shown
mov handle,ax ;Save handle
write_it: write_handle handle,buffer[1EH],12 ;THIS FUNCTION
jc error_write ;Routine not shown
find_next_file ;Check directory
cmp ax,12H ;Another entry?
je all_done ;No, go home
jmp write_it ;Yes, write record
all_done: close_handle handle ;See Function 3EH
jc error_close ;Routine not shown
Delete Directory Entry [Unlink] (Function 41H)
Call:
AH = 41H
DS:DX
Pointer to pathname
Return:
Carry set:
AX
2 = File not found
3 = Path not found
5 = Access denied
Carry not set:
No error
Comments:
Function 41H erases a file by deleting its directory entry. DX must
contain the offset (from the segment address in DS) of an ASCIZ string that
specifies the pathname of the file that you want to delete. You cannot use
wildcard characters.
If the file exists and is not read-only, the call deletes it. If there
is an error, the call sets the carry flag (CF) and the error code returns
in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
2 File doesn't exist, or specifies a directory
3 Path is invalid
5 File is read-only
To delete a file with the read-only attribute, first change its
attribute to 0 with Function 43H (Get/Set File Attribute).
Macro Definition:
delete_entry macro path
mov dx,offset path
mov ah,41H
int 21H
endm
Example:
The following program deletes all files, dated before December 31, 1986,
from the disk in drive B.
year db 1986
month db 12
day db 31
files db ?
message db "NO FILES DELETED.",0DH,0AH,"$"
path db "b:*.*", 0
buffer db 43 dup (?)
;
begin: set_dta buffer ;See Function 1AH
select_disk "B" ;See Function 0EH
find_first_file path,0 ;See Function 4EH
jnc compare ;got one
jmp all_done ;no match, go home
compare: convert_date buffer[-1] ;See end of chapter
cmp cx,year ;After 1986?
jg next ;Yes, don't delete
cmp dl,month ;After December?
jg next ;Yes, don't delete
cmp dh,day ;31st or after?
jge next ;Yes, don't delete
delete_entry buffer[1EH] ;THIS FUNCTION
jc error_delete ;Routine not shown
inc files ;Bump file counter
next: find_next_file ;Check directory
jnc compare ;Go home if done
how_many: cmp files,0 ;Was directory empty?
je all_done ;Yes, go home
convert files,10,message ;See end of chapter
all_done: display message ;See Function 09H
select_disk "A" ;See Function 0EH
Move File Pointer (Function 42H)
Call:
AH = 42H
AL
Method of moving
BX
Handle
CX:DX
Distance in bytes (offset)
Return:
Carry set:
AX
1 = Invalid function
6 = Invalid handle
Carry not set:
DX:AX
New read/write pointer location
Comments:
Function 42H moves the read/write pointer of the file associated with the
specified handle. BX must contain the handle. CX and DX must contain a 32-
bit offset (CX contains the most significant byte). AL must contain a code
that specifies how to move the pointer:
Code Cursor Moved to
───────────────────────────────────────────────────────────────────────────
0 Beginning of file plus the offset
1 Current pointer location plus the offset
2 End of file plus the offset
DX and AX return the new location of the read/write pointer (a 32-bit
integer; DX contains the most significant byte). You can determine the
length of a file by setting CX:DX to 0, AL to 2, and calling this function.
DX:AX returns the offset of the byte following the last byte in the file
(size of the file in bytes).
If there is an error, the carry flag (CF) is set and the error code
returns in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
1 AL not 0, 1, or 2
6 Handle not open
Macro Definition:
move_ptr macro handle,high,low,method
mov bx,handle
mov cx,high
mov dx,low
mov al,method
mov ah,42H
int 21H
endm
Example:
The following program prompts for a letter, converts it to its alphabetic
sequence (A=1, B=2, etc.), then reads and displays the corresponding record
from the file named alphabet.dat that is in the current directory on the
disk in drive B. The file contains 26 records, each 28 bytes long.
file db "b:alphabet.dat",0
buffer db 28 dup (?),"$"
prompt db "Enter letter: $"
crlf db 0DH,0AH,"$"
handle db ?
record_length dw 28
;
begin: open_handle file,0 ;See Function 3DH
jc error_open ;Routine not shown
mov handle,ax ;Save handle
get_char: display prompt ;See Function 09H
read_kbd_and_echo ;See Function 01H
sub al,41h ;Convert to sequence
mul byte ptr record_length ;Calculate offset
move_ptr handle,0,ax,0 ;THIS FUNCTION
jc error_move ;Routine not shown
read_handle handle,buffer,record_length
jc error_read ;Routine not shown
cmp ax,0 ;End of file?
je return ;Yes, go home
display crlf ;See Function 09H
display buffer ;See Function 09H
display crlf ;See Function 09H
jmp get_char ;Get another character
Get/Set File Attributes (Function 43H)
Call:
AH = 43H
AL
0 = Get attributes
1 = Set attributes
CX (if AL=1)
Attributes to be set
DS:DX
Pointer to pathname
Return:
Carry set:
AX
1 = Invalid function
2 = File not found
3 = Path not found
5 = Access denied
Carry not set:
CX
Attribute byte (if AL=0)
Comments:
Function 43H gets or sets the attributes of a file. DX must contain the
offset (from the segment address in DS) of an ASCIZ string that specifies
the pathname of a file. AL must specify whether to get or set the attribute
(0=get, 1=set).
If AL is 0 (get the attribute), the attribute byte returns in CX. If AL
is 1 (set the attribute), CX must contain the attributes to be set. The
attributes are described under "File Attributes" earlier in this chapter.
You cannot change the VolumeID bit (08H) or the Subdirectory bit (10H)
of the attribute byte with this function.
If there is an error, the carry flag (CF) is set and the error code
returns in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
1 AL not 0 or 1
2 File doesn't exist
3 Path invalid
5 Attribute in CX cannot be changed (Subdirectory or VolumeID).
Macro Definition:
change_attr macro path,action,attrib
mov dx,offset path
mov al,action
mov cx,attrib
mov ah,43H
int 21H
endm
Example:
The following program displays the attributes assigned to the file named
report.asm that is in the current directory on the disk in drive B.
header db 15 dup (20h),"Read-",0DH,0AH
db "Filename Only Hidden "
db "System Volume Sub-Dir Archive"
db 0DH,0AH,0DH,0AH,"$"
path db "b:report.asm",3 dup (0),"$"
attribute dw ?
blanks db 9 dup (20h),"$"
;
begin: change_attr path,0,0 ;THIS FUNCTION
jc error_mode ;Routine not shown
mov attribute,cx ;Save attribute byte
display header ;See Function 09H
display path ;See Function 09H
mov cx,6 ;Check 6 bits (0-5)
mov bx,1 ;Start with bit 0
chk_bit: test attribute,bx ;Is the bit set?
jz no_attr ;No
display_char "X" ;See Function 02H
jmp short next_bit ;Done with this bit
no_attr: display_char 20h ;See Function 02H
next_bit: display blanks ;See Function 09H
shl bx,1 ;Move to next bit
loop chk_bit ;Check it
IOCtl Data (Function 44H, Codes 0 and 1)
Call:
AH = 44H
AL
0 = Get device data
1 = Set device data
BX
Handle
DX
Device data (see text)
Return:
Carry set:
AX
1 = Invalid function
6 = Invalid handle
Carry not set:
DX
Device data
Comments:
Function 44H, Codes 0 and 1, either gets or sets the data MS-DOS uses to
control the device. AL must contain 0 to get the data or 1 to set it. BX
must contain the handle. If AL is 1, DH must contain 0.
The device-data word is specified or returned in DX. If bit 7 of the
data is 1, the handle refers to a device and the other bits have the
following meanings:
Table 1.23
MS-DOS Data Bit Values
╓┌───────────┌───────┌───────────────────────────────────────────────────────╖
Bit Value Meaning
────────────────────────────────────────────────────────────────────
Bit Value Meaning
────────────────────────────────────────────────────────────────────
0 1 Console input device
1 1 Console output device
2 1 Null device
3 1 Clock device
4 1 Reserved
5 1 Don't check for control characters
0 Check for control characters
6 0 End of file on input
8-10 Reserved
11 1 Device understands open/close
Bit Value Meaning
12 Reserved
13 1 Device supports output until busy
14 1 Device can process control strings sent
with Function 44H, Codes 2 and 3 (IOCtl
character); bit can be read only, but
not set
15 Reserved
You must set the reserved bits to zero.
The control characters referred to in the description of bit 5 are
CONTROL-C, CONTROL-P, CONTROL-S, and CONTROL-Z. To read these characters as
data, instead of as control characters, you must set bit 5 and use either
Function 33H, CONTROL-C Check, or the MS-DOS break command to turn off
CONTROL-C checking.
If bit 7 of DX is 0, the handle refers to a file and the other bits
have the following meanings:
Bit Value Meaning
───────────────────────────────────────────────────────────────────────────
0-5 Drive number (0=A, 1=B, etc.)
6 0 The file has been written
8-15 Reserved
If there is an error, the carry flag (CF) is set and the error code returns
in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
1 AL not 0 or 1, or AL is 1 but DH is not 0
6 Handle in BX not open or is invalid
Macro Definition:
ioctl_data macro code,handle
mov bx,handle
mov al,code
mov ah,44H
int 21H
endm
Example:
The following program gets the device data for standard output, sets the
bit that specifies not to check for control characters (bit 5), and then
clears the bit.
get equ 0
set equ 1
stdout equ 1
;
begin: ioctl_data get,stdout ;THIS FUNCTION
jc error ;routine not shown
mov dh,0 ;clear DH
or dl,20H ;set bit 5
ioctl_data set,stdout ;THIS FUNCTION
jc error ;routine not shown
;
; <control characters now treated as data, or "raw mode">
;
ioctl_data get,stdout ;THIS FUNCTION
jc error ;routine not shown
mov dh,0 ;clear DH
and dl,0DFH ;clear bit 5
ioctl_data set,stdout ;THIS FUNCTION
;
; <control characters now interpreted, or "cooked mode">
;
IOCtl Character (Function 44H, Codes 2 and 3)
Call:
AH = 44H
AL
2 = Send control data
3 = Receive control data
BX
Handle
CX
Bytes to read or write
DS:DX
Pointer to buffer
Return:
Carry set:
AX
1 = Invalid function
6 = Invalid handle
Carry not set:
AX
Bytes transferred
Comments:
Function 44H, Codes 2 and 3, sends or receives control data to or from a
character device. AL must contain 2 to send data or 3 to receive. BX must
contain the handle of a character device, such as a printer or serial port.
CX must contain the number of bytes to be read or written. DX must contain
the offset (to the segment address in DS) of the data buffer.
AX returns the number of bytes transferred. The device driver must
support the IOCtl interface.
If there is an error, the carry flag (CF) is set and the error code
returns in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
1 AL not 2 or 3, or device cannot perform the specified function
6 Handle in BX not open or doesn't exist
Macro Definition:
ioctl_char macro code,handle,buffer
mov bx,handle
mov dx,offset buffer
mov al,code
mov ah,44H
int 21H
endm
Example:
No general example is applicable, since processing of IOCtl control data
depends on the device being used, as well as the device driver.
IOCtl Block (Function 44H, Codes 4 and 5)
Call:
AH = 44H
AL
4 = Send control data
5 = Receive control data
BL
Drive number (0=default, 1=A, etc.)
CX
Bytes to read or write
DS:DX
Pointer to buffer
Return:
Carry set:
AX
1 = Invalid function
5 = Invalid drive
Carry not set:
AX
Bytes transferred
Comments:
Function 44H, Codes 4 and 5, sends or receives control data to or from
a block device. AL must contain 4 to send data or 5 to receive. BL must
contain the drive number (0=default, 1=A, etc.). CX must contain the number
of bytes to be read or written. DX must contain the offset (to the segment
address in DS) of the data buffer.
AX returns the number of bytes transferred. The device driver must
support the IOCtl interface. To determine whether it does, use Function
44H, Code 0, to get the device data, and test bit 14; if the bit is set,
the driver supports IOCtl.
If there is an error, the carry flag (CF) is set and the error code
returns in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
1 AL not 4 or 5, or device cannot perform the specified function
5 Number in BL not a valid drive number
Macro Definition:
ioctl_status macro code,drive,buffer
mov bl,drive
mov dx,offset buffer
mov al,code
mov ah,44H
int 21H
endm
Example:
No general example is applicable, since processing of IOCtl control data
depends on the device being used, as well as the device driver.
IOCtl Status (Function 44H, Codes 6 and 7)
Call:
AH = 44H
AL
6 = Check input status
7 = Check output status
BX
Handle
Return:
Carry set:
AX
1 = Invalid function
5 = Access denied
6 = Invalid handle
13 = Invalid data
Carry not set:
AL
00H = Not ready
0FFH = Ready
Comments:
Function 44H, Codes 6 and 7, checks whether the file or device associated
with a handle is ready. AL must contain 6 to check whether the handle
is ready for input or 7 to check whether the handle is ready for output.
BX must contain the handle.
AL returns the status:
Meaning for Meaning for Meaning for
Value Device Input File Output File
───────────────────────────────────────────────────────────────────────────
00H Not ready Pointer is at EOF Ready
0FFH Ready Ready Ready
An output file always returns ready, even if the disk is full.
If there is an error, the carry flag (CF) is set and the error code
returns in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
1 AL not 6 or 7
5 Access denied
6 Number in BX not a valid, open handle
13 Invalid data
Macro Definition:
ioctl_status macro code,handle
mov bx,handle
mov al,code
mov ah,44H
int 21H
endm
Example:
The following program displays a message that tells whether the file
associated with handle 6 is ready for input or whether it is at
end-of-file.
stdout equ 1
;
message db "File is "
ready db "ready."
at_eof db "at EOF."
crlf db ODH,OAH
;
begin: write_handle stdout,message,8 ;display message
jc write_error ;routine not shown
ioctl_status 6 ;THIS FUNCTION
jc ioctl_error ;routine not shown
cmp al,0 ;check status code
jne not_eof ;file is ready
write_handle stdout,at_eof,7 ;see Function 40H
jc write_error ;routine not shown
jmp all_done ;clean up & go home
not_eof: write_handle stdout,ready,6 ;see Function 40H
all_done: write_handle stdout,crlf,2 ;see Function 40H
jc write_error ;routine not shown
IOCtl Is Changeable (Function 44H, Code 08H)
Call:
AH = 44H
AL = 08H
BL
Drive number (0=default, 1=A, etc.)
Return:
Carry set:
AX
1 = Invalid function
15 = Invalid drive
Carry not set:
AX
0 = Changeable
1 = Not changeable
Comments:
Function 44H, Code 08H, checks whether a drive contains a removable or
nonremovable disk. BL must contain the drive number (0=default, 1=A, etc.).
AX returns 0 if the disk can be changed, 1 if it cannot.
This call lets a program determine whether to issue a message to
change disks.
If there is an error, the carry flag (CF) is set and the error code
returns in AX.
Code Meaning
───────────────────────────────────────────────────────────────────────────
1 Device does not support this call
15 Number in BL not a valid drive number
When the call returns error 1 (because the driver doesn't support it),
the caller asssumes that the driver cannot be changed.
Macro Definition:
ioctl_change macro drive
mov bl, drive
mov al, 08H
mov ah, 44H
int 21H
endm
Example:
The following program checks whether the current drive contains a removable
disk. If not, processing continues; if so, the program prompts the user
to replace the disk in the current drive.
stdout equ 1
;
message db "Please replace disk in drive "
drives db "ABCD"
crlf db 0DH,0AH
;
begin: ioctl_change 0 ;THIS FUNCTION
jc ioctl_error ;routine not shown
cmp ax,0 ;current drive changeable?
jne continue ;no, continue processing
write_handle stdout,message,29 ;see Function 40H
jc write_error ;routine not shown
current_disk ;see Function 19H
xor bx,bx ;clear index
mov bl,al ;get current drive
display_char drives[bx] ;see Function 02H
write_handle stdout,crlf,2 ;see Function 40H
jc write_error ;routine not shown
continue:
; (Further processing here)
IOCtl Is Redirected Block (Function 44H, Code 09H)
Call:
AH = 44H
AL = 09H
BL
Drive number (0=default, 1=A, etc.)
Return:
Carry set:
AX
1 = Invalid function code
15 = Invalid drive number
Carry not set:
DX
Device-attribute bits
Comments:
Function 44H, Code 09H, checks whether a drive letter refers to a drive
on a Microsoft Networks workstation (local) or is redirected to a server
(remote). BL must contain the drive number (0=default, 1=A, etc.).
If the block device is local, DX returns the attribute word from the
device header. If the block device is remote, only bit 12 (1000H) is set;
the other bits are 0 (reserved).
An application program should not test bit 12, because applications
should not make distinctions between local and remote files (or devices).
Programs should be written so that they will be independent of the location
of a device that has been removed.
If there is an error, the carry flag (CF) is set and the error code
returns in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
1 File sharing must be loaded to use this system call
15 Number in BL not a valid drive number
Macro Definition:
ioctl_rblock macro drive
mov bl, drive
mov al, 09H
mov ah, 44H
int 21H
endm
Example:
The following program checks whether drive B is local or remote and
displays the appropriate message.
stdout equ 1
;
message db "Drive B: is "
loc db "local."
rem db "remote."
crlf db 0DH,0AH
;
begin: write_handle stdout,message,12 ;display message
jc write_error ;routine not shown
ioctl_rblock 2 ;THIS FUNCTION
jc ioctl_error ;routine not shown
test dx,1000h ;bit 12 set?
jnz not_loc ;yes, it's remote
write_handle stdout,loc,6 ;see Function 40H
jc write_error ;routine not shown
jmp done
not_loc: write_handle stdout,rem,7 ;see Function 40H
jc write_error ;routine not shown
done: write_handle stdout,crlf,2 ;see Function 40H
jc write_error ;routine not shown
IOCtl Is Redirected Handle (Function 44H, Code 0AH)
Call:
AH = 44H
AL = 0AH
BX
Handle
Return:
Carry set:
AX
1 = Invalid function code
6 = Invalid handle
Carry not set:
DX
IOCtl bit field
Comments:
Function 44H, Code 0AH, checks whether a handle refers to a file or a
device on a Microsoft Networks workstation (local) or is redirected to a
server (remote). BX must contain the file handle. DX returns the IOCtl bit
field; bit 15 is set if the handle refers to a remote file or device.
An application program should not test bit 15, because applications
should not make distinctions between local and remote files (or devices).
Programs should be written so that they will be independent of the location
of a device that has been removed.
If there is an error, the carry flag (CF) is set and the error code
returns in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
1 Network must be loaded to use this system call
6 Handle in BX not a valid, open handle
Macro Definition:
ioctl_rhandle macro handle
mov bx, handle
mov al, 0AH
mov ah, 44H
int 21H
endm
Example:
The following program checks whether handle 5 refers to a local or remote
file or a device and displays the appropriate message.
stdout equ 1
;
message db "Handle 5 is "
loc db "local."
rem db "remote."
crlf db 0DH,0AH
;
begin: write_handle stdout,message,12 ;display message
jc write_error ;routine not shown
ioctl_rhandle 5 ;THIS FUNCTION
jc ioctl_error ;routine not shown
test dx,8000h ;bit 15 set?
jnz not_loc ;yes, it's remote
write_handle stdout,loc,6 ;see Function 40H
jc write_error ;routine not shown
jmp done
not_loc: write_handle stdout,rem,7 ;see Function 40H
jc write_error ;routine not shown
done: write_handle stdout,crlf,2 ;see Function 40H
jc write_error ;routine not shown
IOCtl Retry (Function 44H, Code 0BH)
Call:
AH = 44H
AL = 0BH
DX
Number of retries
CX
Wait time
Return:
Carry set:
AX
1 = Invalid function code
Carry not set:
No error
Comments:
Function 44H, Code 0BH, specifies how many times MS-DOS should retry a disk
operation that fails because of a file-sharing violation. DX must contain
the number of retries. CX controls the pause between retries.
MS-DOS retries this type of disk operation three times, unless you use
this system call to specify a different number. After the specified number
of retries, MS-DOS issues Interrupt 24H (Critical-Error-Handler Address)
for the requesting process.
The effect of the delay parameter in CX is machine-dependent because
it specifies how many times MS-DOS should execute an empty loop. The actual
time varies, depending on the processor and clock speed. You can determine
the effect on your machine by using debug. Set the number of retries to 1
and then time several values of CX.
If there is an error, the carry flag (CF) is set and the error code
returns in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
1 File sharing must be loaded to use this system call
Macro Definition:
ioctl_retry macro retries, wait
mov dx, retries
mov cx, wait
mov al, 0BH
mov ah, 44H
int 21H
endm
Example:
The following program sets the number of sharing retries to 10 and
specifies a delay of 1000 between retries.
begin: ioctl_retry 10,1000 ;THIS FUNCTION
jc error ;routine not shown
Generic IOCtl (for Handles) (Function 44H, Code 0CH)
Call:
AH = 44H
AL = 0CH
BX
Handle
CH = 05H
Category code (printer device)
CL
Function (minor) code
DS:DX
Pointer to data buffer
Return:
Carry set:
AX
1 = Invalid function code
Carry not set:
No error
Comments:
This call loads and selects code pages for devices on a per-device basis.
It also sets or gets the output iteration count for a printer that supports
"PRINT 'TIL BUSY."
The category code may be one of the following:
Code Meaning
───────────────────────────────────────────────────────────────────────────
00 Unknown device
01 Serial printer
03 Console device
05 Parallel printer
The function code may be one of the following:
Code Meaning
───────────────────────────────────────────────────────────────────────────
45H Sets iteration count for printer
4AH Select code page
4CH Start prepare list
4DH End prepare list
65H Gets iteration count for printer
6AH Query code page selected
6BH Query code page prepare list
───────────────────────────────────────────────────────────────────────────
Note
DS:DX points to a word that contains the new value for the total number
of output iterations performed before proceeding. Thus, DS:DX points to
a word that contains the character iteration count for the "PRINT 'TIL
BUSY" loop. This is the number of times the device driver will wait for
the device to signal "ready" before acknowledging "Device busy."
───────────────────────────────────────────────────────────────────────────
Macro Definition:
ioctl_handles macro handle,function,category,buffer
mov ch,05H
mov cl,function
mov dx,offset buffer
mov bx,handle
mov ah,44H
mov al,0CH
int 21H
endm
Generic IOCtl (for Devices) (Function 44H, Code 0DH)
Call:
AH = 44H
AL = 0DH
BL
Drive number
(0 = default, 1 = A, etc.)
CH = 08H
Category (major) code
CL
Function (minor) code
DS:DX
Pointer to parameter block -1
Return:
Carry set:
AX
1 = Invalid function code
2 = Invalid drive
Carry not set:
No error
Comments:
The function code may be one of the following:
Code Meaning
───────────────────────────────────────────────────────────────────────────
40 Set device parameters
41 Write track on logical device
42 Format track on logical device
60 Get device parameters
61 Read track on logical device
62 Verify track on logical device
───────────────────────────────────────────────────────────────────────────
Note
You must issue "Set Device Parameters" before you can read, write,
format, or verify a logical drive.
───────────────────────────────────────────────────────────────────────────
You should use the following procedure when you want to read, write,
format, or verify a logical drive:
1. Save drive parameters using "Get Device Parameters."
2. Set desired drive parameters using "Set Device Parameters."
3. Perform the I/O operation.
4. Restore the original drive parameters using "Set Device Parameters."
Set Device Parameters (Function 44 0DH, CL=40H)
When CL=40H, the parameter block has the following field format:
--------------------------------------
| BYTE Special Functions |
|------------------------------------|
| BYTE Device Type |
|------------------------------------|
| WORD Device Attributes |
|------------------------------------|
| WORD Number of Cylinders |
|------------------------------------|
| BYTE Media Type |
|------------------------------------|
| Device BPB |
|------------------------------------|
| Track Layout |
--------------------------------------
These fields have the following meanings:
Special Functions
╓┌───────┌────────┌──────────────────────────────────────────────────────────╖
Bit Value Meaning
Bit Value Meaning
───────────────────────────────────────────────────────────────────────────
0 0 The Device BPB (BIOS Parameter Block)
field contains the new default BPB for
this device. If a previous "Set
Parameter Device" call set this bit,
Build BPB returns the actual media BPB;
otherwise, it returns the default BPB
for the device.
1 All subsequent Build BPB requests
return the device BPB.
1 0 Read all fields of the parameter block.
1 Ignore all fields of the parameter
block except for the Track Layout
field.
2 0 The sectors in the track may not all
be the same size. (You should not use
Bit Value Meaning
be the same size. (You should not use
this setting.)
1 The sectors in the track are all the
same size and the sector numbers range
between 1 and the total number of
sectors actually in the track. You
should always set this bit.
3-7 0 These bits must be zero.
Device Type
This byte describes the physical device and is set by the device.
When set, it has the following meanings:
Value Meaning
───────────────────────────────────────────────────────────────────────────
0 320/360 KB
1 1.2 MB
2 720 KB
3 8-inch, single-density
4 8-inch, double-density
5 Hard disk
6 Tape drive
7 Other
Device Attributes
Bit Value Meaning
───────────────────────────────────────────────────────────────────────────
0 The media is removable.
0 1 The media is not removable.
1 0 Disk change-line is not
supported; (no door lock
support).
1 Disk change-line is
supported; (door lock
support).
2-7 0 These bits must be zero.
Number of Cylinders
This field indicates the maximum number of cylinders that the physical
device can support. This information is set by the device.
Media Type
For drives that may contain different media, this field (which is
device-dependent) indicates which media the drive expects.
For a 1.2 MB disk, bit zero has the following meaning:
Bit Value Meaning
───────────────────────────────────────────────────────────────────────────
0 0 Quad-density, 1.2 MB disk
1 Double-density, 320/360 KB disk
The default media type is a quad-density 1.2 MB disk.
Device BPB
If bit 0 of the Special Functions field is clear, the BPB in this
field is the new default BPB for the device.
If bit 0 of the Special Functions field is set, the device driver
returns the BPB from this field for subsequent Build BPB requests.
Track Layout
This field contains a table of variable length for each logical device
and indicates the expected layout of the sectors on the media track.
The field has the following format:
------------------------------------------------
| WORD Sector Count -- total # of sectors |
|----------------------------------------------|
| WORD Sector Number -- sector #1 |
|----------------------------------------------|
| WORD Sector Size -- sector #1 |
|----------------------------------------------|
| WORD Sector Number -- sector #2 |
|----------------------------------------------|
| WORD Sector Size -- sector #2 |
------------------------------------------------
|
|
|
------------------------------------------------
| WORD Sector Number -- sector #n |
|----------------------------------------------|
| WORD Sector Size -- sector #n |
------------------------------------------------
The Sector Count field indicates the total number of sectors. Each sector
number must be unique and in the range of 1 to sector count (n).
If bit 2 of the Special Functions field is set, all sector sizes must
be the same.
Get Device Parameters (Function 440DH, CL=60H)
When CL=60H, the parameter block has the same field layout as for CL=40H.
However, some of the fields have different meanings. These are described
as follows:
Special Functions
Bit Value Meaning
───────────────────────────────────────────────────────────────────────────
0 0 Returns the default BPB for the device.
1 Returns the BPB that Build BPB would return.
1-7 0 These bits must be zero.
Track Layout
The "Get Device Parameters" call does not use this field.
Read/Write Track on Logical Drive (Function 440D, CL=61H/CL=41H)
To write to a track on a logical drive, set CL=41H. To read a track on a
logical drive, set CL=61H.
When CL=41H or 61H, the parameter block has the following format:
--------------------------------
| BYTE Special Functions |
|------------------------------|
| WORD Head |
|------------------------------|
| WORD Cylinder |
|------------------------------|
| WORD First Sector |
|------------------------------|
| WORD Number of Sectors |
|------------------------------|
| DWORD Transfer Address |
--------------------------------
These fields are described as follows:
Special Functions
This byte must be zero.
Head
This field contains the number of the head on which you perform the
write or read.
Cylinder
This field contains the number of the cylinder on which you perform
the write or read.
First Sector
This field contains the number of the first sector on which you perform
the write or read. Sectors are numbered starting with zero, so the fourth
sector is numbered 3.
Number of Sectors
This field contains the total number of sectors.
Transfer Address
This field contains the address for storing the data to be written or
the data just read.
Format/Verify Track on Logical Drive (Function 440DH, CL=42/CL=62)
To format and verify a track on a logical drive, set CL=42H. To verify a
track on a logical drive, set CL=62H.
When CL=42H or 62H, the parameter block has the following format:
--------------------------------
| BYTE Special Functions |
|------------------------------|
| WORD Head |
|------------------------------|
| WORD Cylinder |
--------------------------------
These fields are described as follows:
Special Functions
This byte must be zero.
Head
This field contains the number of the head on which you perform the
format or verify.
Cylinder
This field contains the number of the cylinder on which you perform
the format or verify.
Get/Set IOCtl Drive Map (Function 44H, Codes 0EH and 0FH)
Call:
AH = 44H
AL
OEH = Get logical drive map
OFH = Set logical drive map
BX
Drive number
(0 = default, 1 = A, etc.)
Return:
Carry set:
AX
1 = Invalid function code
5 = Invalid drive
Carry not set:
AL = Logical drive mapped onto physical drive
(= 0 if only one drive is
assigned to this physical drive)
Comments:
MS-DOS 3.3 supports the mapping of multiple logical drives onto a single
physical block device. Get IOCtl Drive Map lets you query the DOS about
which logical drive is currently mapped onto the corresponding physical
device. Set IOCtl Drive Map alters the device that is currently mapped
onto the physical device. These functions are only useful if there is
more than one logical block device mapped onto a single physical device.
A possible use for these functions is with applications that want to
disable the DOS prompt in order to place the correct floppy disk in the
drive when accessing the other logical drive.
To detect whether a logical device currently owns the physical device
it is mapped to, a program needs to check the value in AL after calling
Function 440EH or 440FH (Get/Set IOCtl Drive Map).
Duplicate File Handle (Function 45H)
Call:
AH = 45H
BX
Handle
Return:
Carry set:
AX
4 = Too many open files
6 = Invalid handle
Carry not set:
AX
New handle
Comments:
Function 45H creates an additional handle for a file. BX must contain the
handle of an open file.
MS-DOS returns the new handle in AX. The new handle refers to the same
file as the handle in BX, with the file pointer at the same position.
After you use this function request, moving the read/write pointer of
either handle also moves the pointer for the other handle. You usually use
this function request to redirect standard input (handle 0) and standard
output (handle 1). For a description of standard input, standard output,
and the advantages and techniques of manipulating them, see Software Tools
by Brian W. Kernighan and P.J. Plauger (Addison-Wesley Publishing Co.,
1976).
If there is an error, the carry flag (CF) is set and the error code
returns in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
4 Too many open files (no handle available)
6 Handle not open or is invalid
Macro Definition:
xdup macro handle
mov bx,handle
mov ah,45H
int 21H
endm
Example:
The following program redirects standard output (handle 1) to a file named
dirfile, invokes a second copy of command.com to list the directory (which
writes the directory to dirfile), and then restores standard input to
handle 1.
pgm_file db "command.com",0
cmd_line db 9,"/c dir /w",0dH
parm_blk db 14 dup (0)
path db "dirfile",0
dir_file dw ? ; For handle
sav_stdout dw ? ; For handle
;
begin: set_block last_inst ; See Function 4AH
jc error_setblk ; Routine not shown
create_handle path,0 ; See Function 3CH
jc error_create ; Routine not shown
mov dir_file,ax ; Save handle
xdup 1 ; THIS FUNCTION
jc error_xdup ; Routine not shown
mov sav_stdout,ax ; Save handle
xdup2 dir_file,1 ; See Function 46H
jc error_xdup2 ; Routine not shown
exec pgm_file,cmd_line,parm_blk ; See Function 4BH
jc error_exec ; Routine not shown
xdup2 sav_stdout,1 ; See Function 46H
jc error_xdup2 ; Routine not shown
close_handle sav_stdout ; See Function 3EH
jc error_close ; Routine not shown
close_handle dir_file ; See Function 3EH
jc error_close ; Routine not shown
Force Duplicate File Handle (Function 46H)
Call:
AH = 46H
BX
Handle
CX
Second handle
Return:
Carry set:
AX
4 = Too many open files
6 = Invalid handle
Carry not set:
No error
Comments:
Function 46H forces a specified handle to refer to the same file as
a second handle already associated with an open file. BX must contain
the handle of the open file; CX must contain the second handle.
On return, the handle in CX now refers to the same file at the same
position as the handle in BX. If the file referred to by the handle in
CX was open at the time of the call, this function closes it.
After you use this call, moving the read/write pointer of either handle
also moves the pointer for the other handle. Normally, you would use this
function request to redirect standard input (handle 0) and standard output
(handle 1). For a description of standard input, standard output, and the
advantages and techniques of manipulating them, see Software Tools by
Brian W. Kernighan and P.J. Plauger (Addison-Wesley Publishing Co., 1976).
If there is an error, the carry flag (CF) is set and the error code
returns in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
4 Too many open files (no handle available)
6 Handle not open or is invalid
Macro Definition:
xdup2 macro handle1,handle2
mov bx,handle1
mov cx,handle2
mov ah,46H
int 21H
endm
Example:
The following program redirects standard output (handle 1) to a file named
dirfile, invokes a second copy of command.com to list the directory (which
writes the directory to dirfile), and then restores standard input to
handle 1.
pgm_file db "command.com",0
cmd_line db 9,"/c dir /w",0dH
parm_blk db 14 dup (0)
path db "dirfile",0
dir_file dw ? ; For handle
sav_stdout dw ? ; For handle
;
begin: set_block last_inst ; See Function 4AH
jc error_setblk ; Routine not shown
create_handle path,0 ; See Function 3CH
jc error_create ; Routine not shown
mov dir_file,ax ; Save handle
xdup 1 ; See Function 45H
jc error_xdup ; Routine not shown
mov sav_stdout,ax ; Save handle
xdup2 dir_file,1 ;
jc error_xdup2 ; Routine not shown
exec pgm_file,cmd_line,parm_blk ; See Function 4BH
jc error_exec ; Routine not shown
xdup2 sav_stdout,1 ; THIS FUNCTION
jc error_xdup2 ; Routine not shown
close_handle sav_stdout ; See Function 3EH
jc error_close ; Routine not shown
close_handle dir_file ; See Function 3EH
jc error_close ; Routine not shown
Get Current Directory (Function 47H)
Call:
AH = 47H
DS:SI
Pointer to 64-byte memory area
DL
Drive number
(0 = default, 1 = A)
Return:
Carry set:
AX
15 = Invalid drive number
Carry not set:
No error
Comments:
Function 47H returns the pathname of the current directory on a specified
drive. DL must contain a drive number (0=default, 1=A, etc.). SI must
contain the offset (from the segment address in DS) of a 64-byte memory
area.
MS-DOS places an ASCIZ string in the memory area, consisting of the path
(starting from the root directory) of the current directory for the drive
specified in DL. The string does not begin with a backslash and does not
include the drive letter.
If there is an error, the carry flag (CF) is set and the error code
returns in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
15 Number in DL not a valid drive number
Macro Definition:
get_dir macro drive,buffer
mov dl,drive
mov si,offset buffer
mov ah,47H
int 21H
endm
Example:
The following program displays the current directory that is on the disk in
drive B.
disk db "b:
buffer db 64 dup (?)
;
begin: get_dir 2,buffer ;THIS FUNCTION
jc error_dir ;Routine not shown
display disk ;See Function 09H
display_asciz buffer ;See end of chapter
Allocate Memory (Function 48H)
Call:
AH = 48H
BX
Paragraphs of memory requested
Return:
Carry set:
AX
7 = Memory-control blocks damaged
8 = Insufficient memory
BX
Paragraphs of memory available
Carry not set:
AX
Segment address of allocated memory
Comments:
Function 48H tries to allocate the specified amount of memory to the
current process. BX must contain the number of paragraphs of memory
(one paragraph is 16 bytes).
If sufficient memory is available to satisfy the request, AX returns
the segment address of the allocated memory (the offset is 0). If
sufficient memory is not available, BX returns the number of paragraphs
of memory in the largest available block.
If there is an error, the carry flag (CF) is set and the error code
returns in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
7 Memory-control blocks damaged (a user program changed memory
that doesn't belong to it)
8 Not enough free memory to satisfy the request
Macro Definition:
allocate_memory macro bytes
mov bx,bytes
mov cl,4
shr bx,cl
inc bx
mov ah,48H
int 21H
endm
Example:
The following program opens the file named textfile.asc, calculates its
size with Function 42H (Move File Pointer), allocates a block of memory the
size of the file, reads the file into the allocated memory block, and then
frees the allocated memory.
path db "textfile.asc",0
msg1 db "File loaded into allocated memory block.",
0DH,0AH
msg2 db "Allocated memory now being freed
(deallocated).",0DH,0AH
handle dw ?
mem_seg dw ?
file_len dw ?
;
begin: open_handle path,0
jc error_open ;Routine not shown
mov handle,ax ;Save handle
move_ptr handle,0,0,2 ;See Function 42H
jc error_move ;Routine not shown
mov file_len,ax ;Save file length
set_block last_inst ;See Function 4AH
jc error_setblk ;Routine not shown
allocate_memory file_len ;THIS FUNCTION
jc error_alloc ;Routine not shown
mov mem_seg,ax ;Save address of new memory
move_ptr handle,0,0,0 ;See Function 42H
jc error_move ;Routine not shown
push ds ;Save DS
mov ax,mem_seg ;Get segment of new memory
mov ds,ax ;Point DS at new memory
read_handle cs:handle,0,cs:file_len ;Read file into new memory
pop ds ;Restore DS
jc error_read ;Routine not shown
; (CODE TO PROCESS FILE GOES HERE)
write_handle stdout,msg1,42 ;See Function 40H
jc write_error ;Routine not shown
free_memory mem_seg ;See Function 49H
jc error_freemem ;Routine not shown
write_handle stdout,msg2,49 ;See Function 40H
jc write_error ;Routine not shown
Free Allocated Memory (Function 49H)
Call:
AH = 49H
ES
Segment address of memory to be
freed
Return:
Carry set:
AX
7 = Memory-control blocks damaged
9 = Incorrect segment
Carry not set:
No error
Comments:
Function 49H frees (makes available) a block of memory previously allocated
with Function 48H (Allocate Memory). ES must contain the segment address of
the memory block to be freed.
If there is an error, the carry flag (CF) is set and the error code
returns in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
7 Memory-control blocks damaged (a user program changed memory
that didn't belong to it)
9 Memory pointed to by ES was not allocated with Function 48H
Macro Definition:
free_memory macro seg_addr
mov ax,seg_addr
mov es,ax
mov ah,49H
int 21H
endm
Example:
The following program opens a file named textfile.asc, calculates its size
with Function 42H (Move File Pointer), allocates a block of memory the size
of the file, reads the file into the allocated memory block, and then frees
the allocated memory.
path db "textfile.asc",0
msg1 db "File loaded into allocated memory block.",
0DH,0AH
msg2 db "Allocated memory now being freed
(deallocated).",0DH,0AH
handle dw ?
mem_seg dw ?
file_len dw ?
;
begin: open_handle path,0
jc error_open ;Routine not shown
mov handle,ax ;Save handle
move_ptr handle,0,0,2 ;See Function 42H
jc error_move ;Routine not shown
mov file_len,ax ;Save file length
set_block last_inst ;See Function 4AH
jc error_setblk ;Routine not shown
allocate_memory file_len ;See Function 48H
jc error_alloc ;Routine not shown
mov mem_seg,ax ;Save address of new memory
mov_ptr handle,0,0,0 ;See Function 42H
jc error_move ;Routine not shown
push ds ;Save DS
mov ax,mem_seg ;Get segment of new memory
mov ds,ax ;Point DS at new memory
read_handle handle,code,file_len ;Read file into new memory
;
pop ds ;Restore DS
jc error_read ;Routine not shown
; (CODE TO PROCESS FILE GOES HERE)
write_handle stdout,msg1,42 ;See Function 40H
jc write_error ;Routine not shown
free_memory mem_seg ;THIS FUNCTION
jc error_freemem ;Routine not shown
write_handle stdout,msg2,49 ;See Function 40H
jc write_error ;Routine not shown
Set Block (Function 4AH)
Call:
AH = 4AH
BX
Paragraphs of memory
ES
Segment address of memory area
Return:
Carry set:
AX
7 = Memory-control blocks damaged
8 = Insufficient memory
9 = Incorrect segment
BX
Paragraphs of memory available
Carry not set:
No error
Comments:
Function 4AH changes the size of a memory-allocation block. ES must
contain the segment address of the memory block. BX must contain the
new size of the memory block, in paragraphs (one paragraph is 16 bytes).
MS-DOS attempts to change the size of the memory block. If the call
fails on a request to increase memory, BX returns the maximum size
(in paragraphs) to which the block can be increased.
Since MS-DOS allocates all available memory to a .com program, you would
use this call most often to reduce the size of a program's initial memory-
allocation block.
If there is an error, the carry flag (CF) is set and the error code
returns in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
7 Memory-control blocks destroyed (a user program changed memory
that didn't belong to it)
8 Not enough free memory to satisfy the request
9 Wrong address in ES (the memory block it points to cannot
be modified with Set Block)
The following macro shrinks the initial memory-allocation block of a
.com program. It takes as a parameter the offset of the first byte
following the last instruction of a program (LAST_INST in the sample
programs), uses it to calculate the number of paragraphs in the program,
and then adds 17 to the result: one to round up and 16 to set aside 256
bytes for a stack. It then sets up SP and BP to point to this stack.
Macro Definition:
set_block macro last_byte
mov bx,offset last_byte
mov cl,4
shr bx,cl
add bx,17
mov ah,4AH
int 21H
mov ax,bx
shl ax,cl
dec ax
mov sp,ax
mov bp,sp
endm
Example:
The following program invokes a second copy of command.com and executes a
dir (directory) command.
pgm_file db "command.com",0
cmd_line db 9,"/c dir /w",0DH
parm_blk db 14 dup (?)
reg_save db 10 dup (?)
;
begin: set_block last_inst ;THIS FUNCTION
exec pgm_file,cmd_line,parm_blk,0 ;See Function 4BH
Load and Execute Program (Function 4BH, Code 00H)
Call:
AH = 4BH
AL = 00H
DS:DX
Pointer to pathname
ES:BX
Pointer to parameter block
Return:
Carry set:
AX
1 = Invalid function
2 = File not found
3 = Path not found
4 = Too many open files
5 = Access denied
8 = Insufficient memory
10 = Bad environment
11 = Bad format
Carry not set:
No error
Comments:
Function 4BH, Code 00H, loads and executes a program. DX must contain the
offset (from the segment address in DS) of an ASCIZ string that specifies
the drive and pathname of an executable program file. BX must contain the
offset (from the segment address in ES) of a parameter block. AL must
contain 0.
There must be enough free memory for MS-DOS to load the program file.
MS-DOS allocates all available memory to a program when it loads it, so
you must free some memory with Function 4AH (Set Block) before using this
function request to load and execute another program. Unless you or MS-DOS
needs the memory for some other purpose, you should shrink the memory to
the minimum amount required by the current process before issuing
this request.
MS-DOS creates a Program Segment Prefix for the program being loaded
and sets the terminate and CONTROL-C addresses to the instruction that
immediately follows the call to Function 4BH in the invoking program.
The parameter block consists of four addresses:
Table 1.24
Contents of the Parameter Block
╓┌─────────────┌───────────┌─────────────────────────────────────────────────╖
Offset Length
(Hex) (Bytes) Description
──────────────────────────────────────────────────────────────────────
Offset Length
(Hex) (Bytes) Description
──────────────────────────────────────────────────────────────────────
00 2 (word) Segment address of the environment
to be passed; 00H means copy the
parent program's environment.
02 4 (dword) Segment: Offset of command line to
be placed at offset 80H of the new
Program Segment Prefix. Must be a
correctly-formed command line no
longer than 128 bytes.
06 4 (dword) Segment: Offset of FCB to be placed
at offset 5CH of the new Program
Segment Prefix (the Program Segment
Prefix is described in Chapter 4
"MS-DOS Control Blocks and Work Areas")
0A 4 (dword) Segment: Offset of FCB to be placed
at offset 6CH of the new Program
Offset Length
(Hex) (Bytes) Description
at offset 6CH of the new Program
Segment Prefix
All open files of a program are available to the newly loaded program,
giving the parent program control over the definition of standard input,
output, auxiliary, and printer devices. For example, a program could write
a series of records to a file, open the file as standard input, open a
second file as standard output, and then use Function 4BH, Code 00H (Load
and Execute Program) to load and execute a program that takes its input
from standard input, sorts records, and writes to standard output.
The loaded program also receives an environment, a series of ASCIZ
strings of the form parameter=value (for example, verify = on). The
environment must begin on a paragraph boundary, be less than 32K bytes
long, and end with a byte of 00H (that is, the final entry consists of an
ASCIZ string followed by two bytes of 00H). Following the last byte of
zeros is a set of initial arguments passed to a program containing a word
count followed by an ASCIZ string. If the call finds the file in the
current directory, the ASCIZ string contains the drive and pathname of the
executable program as passed to Function 4BH. If the call finds the file
in the path, it concatenates the filename with the path information. (A
program may use this area to determine whence it was loaded.) If the word-
environment address is 0, the loaded program either inherits a copy of the
parent program's environment or receives a new environment built for it
by the parent.
Place the segment address of the environment at offset 2CH of the new
Program Segment Prefix. To build an environment for the loaded program, put
it on a paragraph boundary and place the segment address of the environment
in the first word of the parameter block. To pass a copy of the parent's
environment to the loaded program, put 00H in the first word of the
parameter block.
If there is an error, the carry flag (CF) is set and the error code
returns in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
1 AL not 0 or 3
2 Program file not found
3 Path invalid or not found
4 Too many open files (no handle available)
5 Directory full, a directory with the same name exists,
or a file with the same name exists
8 Not enough memory to load the program
10 Environment appears longer than 32K
11 Program file is an .exe file that contains internally
inconsistent information
Executing Another Copy of Command.com
Since command.com builds pathnames, searches command paths for program
files, and relocates .exe files, the simplest way to load and execute
another program is to load and execute an additional copy of command.com,
passing it a command line that includes the /c switch, which invokes the
.com or .exe file.
This action requires 17K bytes of available memory, so a program that
does it should be sure to shrink its initial memory-allocation block with
Function 4AH (Set Block). The format of a command line that contains the
/c switch:
length,/c command,0DH
Length is the length of the command line, counting the length byte but
not the ending carriage-return (0DH).
Command is any valid MS-DOS command.
0DH is a carriage-return character.
If a program executes another program directly--naming it as the program
file to Function 4BH instead of command.com--it must perform all the
processing normally done by command.com.
Macro Definition:
exec macro path,command,parms
mov dx,offset path
mov bx,offset parms
mov word ptr parms[02H],offset command
mov word ptr parms[04H],cs
mov word ptr parms[06H],5CH
mov word ptr parms[08H],es
mov word ptr parms[0AH],6CH
mov word ptr parms[0CH],es
mov al,0
mov ah,4BH
int 21H
endm
Example:
The following program invokes a second copy of command.com and executes a
dir (directory) command by using the /w (wide) switch:
pgm_file db "command.com",0
cmd_line db 9,"/c dir /w",0DH
parm_blk db 14 dup (?)
reg_save db 10 dup (?)
;
begin:
set_block last_inst ;See Function 4AH
exec pgm_file,cmd_line,parm_blk,0 ;THIS FUNCTION
Load Overlay (Function 4BH, Code 03H)
Call:
AH = 4BH
AL = 03H
DS:DX
Pointer to pathname
ES:BX
Pointer to parameter block
Return:
Carry set:
AX
1 = Invalid function
2 = File not found
3 = Path not found
4 = Too many open files
5 = Access denied
8 = Insufficient memory
10 = Bad environment
Carry not set:
No error
Comments:
Function 4BH, Code 03H, loads a program segment (overlay). DX must contain
the offset (from the segment address in DS) of an ASCIZ string that
specifies the drive and pathname of the program file. BX must contain the
offset (from the segment address in ES) of a parameter block. AL must
contain 3.
MS-DOS assumes that since the invoking program is loading into its own
address space, it requires no free memory. This call does not create a
Program Segment Prefix.
The parameter block is four bytes long:
Table 1.25
Contents of the Parameter Block
╓┌─────────────┌──────────┌──────────────────────────────────────────────────╖
Offset Length
(Hex) (Bytes) Description
───────────────────────────────────────────────────────────────────────────
Offset Length
(Hex) (Bytes) Description
───────────────────────────────────────────────────────────────────────────
00 2 (word) Segment address where program is to be loaded
02 2 (word) Relocation factor; usually the same as the
first word of the parameter block (for a
description of an .exe file and of
relocation, see Chapter 6, ".Exe File
Structure and Loading.")
If there is an error, the carry flag (CF) is set and the error code returns
in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
1 AL not 00H or 03H
2 Program file not found
3 Path invalid or not found
4 Too many open files (no handle available)
5 Directory is full, a directory with the same name exists,
or a file with the same name exists
8 Not enough memory to load the program
10 Environment appears longer than 32K
Macro Definition:
exec_ovl macro path,parms,seg_addr
mov dx,offset path
mov bx,offset parms
mov parms,seg_addr
mov parms[02H],seg_addr
mov al,3
mov ah,4BH
int 21H
endm
Example:
The following program opens a file named textfile.asc, redirects standard
input to that file, loads more.com as an overlay, and calls an overlay
named bit.com, which reads textfile.asc as standard input. The overlay
must establish its own addressability and end with a FAR return.
stdin equ 0
;
file db "TEXTFILE.ASC",0
cmd_file db "\bit.com",0
parm_blk dw 4 dup (?)
overlay label dword
dw 0
handle dw ?
new_mem dw ?
;
begin: set_block last_inst ;see Function 4AH
jc setblock_error ;routine not shown
allocate_memory 2000 ;see Function 48H
jc allocate_error ;routine not shown
mov new_mem,ax ;save seg of memory
open_handle file,0 ;see Function 3DH
jc open_error ;routine not shown
mov handle,ax ;save handle
xdup2 handle,stdin ;see Function 45H
jc dup2_error ;routine not shown
close_handle handle ;see Function 3EH
jc close_error ;routine not shown
mov ax,new_mem ;addr of new memory
exec_ovl cmd_file,parm_blk,ax ;THIS FUNCTION
jc exec_error ;routine not shown
call overlay ;call the overlay
free_memory new_mem ;see Function 49H
jc free_error ;routine not shown
;
End Process (Function 4CH)
Call:
AH = 4CH
AL
Return code
Return:
None
Comments:
Function 4CH terminates a process and returns to MS-DOS. AL contains a
return code that can be retrieved by the parent process with Function 4DH
(Get Return Code of Child Process) or the if command, using errorlevel.
MS-DOS closes all open handles, ends the current process, and returns
control to the invoking process.
This function request doesn't require CS to contain the segment address
of the Program Segment Prefix. You should use it to end a program (rather
than Interrupt 20H or a jump to location 0) unless your program must be
compatible with MS-DOS versions before 2.0.
───────────────────────────────────────────────────────────────────────────
Note
If you use file sharing, you must remove all locks issued by this
process or the DOS will be in an uncertain state.
───────────────────────────────────────────────────────────────────────────
Macro Definition:
end_process macro return_code
mov al,return_code
mov ah,4CH
int 21H
endm
Example:
The following program displays a message and returns to MS-DOS with a
return code of 8. It uses only the opening portion of the sample program
skeleton shown at the beginning of this chapter.
message db "Displayed by FUNC_4CH example",0DH,0AH,"$"
;
begin: display message ;See Function 09H
end_process 8 ;THIS FUNCTION
code ends
end code
Get Return Code of Child Process (Function 4DH)
Call:
AH = 4DH
Return:
AX
Return code
Comments:
Function 4DH retrieves the return code specified when a child process
terminates via either Function 31H (Keep Process) or Function 4CH (End
Process). The code returns in AL. AH returns a code that specifies why
the program ended:
Code Meaning
───────────────────────────────────────────────────────────────────────────
0 Normal termination
1 Terminated by CONTROL-C
2 Critical device error
3 Function 31H (Keep Process)
This call can retrieve the exit code only once.
Macro Definition:
ret_code macro
mov ah,4DH
int 21H
endm
Example:
No example is included for this function request, because the meaning of
a return code varies.
Find First File (Function 4EH)
Call:
AH = 4EH
DS:DX
Pointer to pathname
CX
Attributes to match
Return:
Carry set:
AX
2 = File not found
3 = Path not found
18 = No more files
Carry not set:
No error
Comments:
Function 4EH searches the current or specified directory for the first
entry that matches the specified pathname. DX must contain the offset (from
the segment address in DS) of an ASCIZ string that specifies the pathname,
which can contain wildcard characters. CX must contain the attribute to
be used in searching for the file, as described in Section 1.5.5, "File
Attributes."
If the attribute field is hidden file, system file, or subdirectory
entry (02H, 04H, or 10H), or any combination of these values, all normal
file entries are also searched. To search all directory entries except
the volume label, set the attribute byte to 16H (hidden file, system file,
and directory entry).
If this function finds a directory entry that matches the name and
attribute, it fills the current DTA as follows:
Table 1.26
╓┌─────────────┌────────┌────────────────────────────────────────────────────╖
Offset Length Description
──────────────────────────────────────────────────────────────────────
00H 21 Reserved for subsequent Function 4FH (Find
Next File)
15H 1 Attribute found
16H 2 Time file was last written
18H 2 Date file was last written
1AH 2 Low word of file size
1CH 2 High word of file size
1EH 13 Name and extension of the file, followed by 00H.
All blanks are removed; if there is an extension,
it is preceded by a period. (Volume labels include
a period after the eighth character.)
If there is an error, the carry flag (CF) is set and the error code returns
in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
2 Specified file invalid or doesn't exist
3 Specified path invalid or doesn't exist
18 No matching directory entry found
Macro Definition:
find_first_file macro path,attrib
mov dx,offset path
mov cx,attrib
mov ah,4EH
int 21H
endm
Example:
The following program displays a message that specifies whether a file
named report.asm exists in the current directory on the disk in drive B.
yes db "File exists.",0DH,0AH,"$"
no db "File does not exist.",0DH,0AH,"$"
path db "b:report.asm",0
buffer db 43 dup (?)
;
begin: set_dta buffer ;See Function 1AH
find_first_file path,0 ;THIS FUNCTION
jc error_findfirst ;Routine not shown
cmp al,12H ;File found?
je not_there ;No
display yes ;See Function 09H
jmp return ;All done
not_there: display no ;See Function 09H
Find Next File (Function 4FH)
Call:
AH = 4FH
Return:
Carry set:
AX
18 = No more files
Carry not set:
No error
Comments:
Function 4FH searches for the next directory entry that matches the name
and attributes specified in a previous Function 4EH (Find First File).
The current DTA must contain the information filled in by Function 4EH
(Find First File).
If the function finds a matching entry, it fills the current DTA just
as it did for Find First File (see Function 4EH (Find First File)).
If there is an error, the carry flag (CF) is set and the error code
returns in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
2 Specified path invalid or doesn't exist
18 No matching directory entry found
Macro Definition:
find_next_file macro
mov ah,4FH
int 21H
endm
Example:
The following program displays the number of files contained in the current
directory on the disk in drive B.
message db "No files",0DH,0AH,"$"
files dw ?
path db "b:*.*",0
buffer db 43 dup (?)
;
begin: set_dta buffer ;See Function 1AH
find_first_file path,0 ;See Function 4EH
jc error_findfirst ;Routine not shown
cmp al,12H ;Directory empty?
je all_done ;Yes, go home
inc files ;No, bump file counter
search_dir: find_next_file ;THIS FUNCTION
jc error_findnext ;Routine not shown
cmp al,12H ;Any more entries?
je done ;No, go home
inc files ;Yes, bump file counter
jmp search_dir ;And check again
done: convert files,10,message ;See end of chapter
all_done: display message ;See Function 09H
Get Verify State (Function 54H)
Call:
AH = 54H
Return:
AL
0 = No verify after write
1 = Verify after write
Comments:
Function 54H checks whether MS-DOS verifies write operations to disk files.
The status returns in AL: 0 if verify is off, 1 if verify is on.
You can set the verify status with Function 2EH (Set/Reset Verify Flag).
Macro Definition:
get_verify macro
mov ah,54H
int 21H
endm
Example:
The following program displays the verify status:
message db "Verify ","$"
on db "on.",0DH,0AH,"$"
off db "off.",0DH,0AH,"$"
;
begin: display message ;See Function 09H
get_verify ;THIS FUNCTION
cmp al,0 ;Is flag off?
jg ver_on ;No, it's on
display off ;See Function 09H
jmp return ;Go home
ver_on: display on ;See Function 09H
Change Directory Entry (Function 56H)
Call:
AH = 56H
DS:DX
Pointer to pathname
ES:DI
Pointer to second pathname
Return:
Carry set:
AX
2 = File not found
3 = Path not found
5 = Access denied
17 = Not same device
Carry not set:
No error
Comments:
Function 56H renames a file by changing its directory entry. DX must
contain the offset (from the segment address in DS) of an ASCIZ string
that contains the pathname of the entry to be changed. DI must contain
the offset (from the segment address in ES) of an ASCIZ string that
contains a second pathname to which the first is to be changed.
If a directory entry for the first pathname exists, it is changed to
the second pathname.
The directory paths need not be the same; in effect, you can move the
file to another directory by renaming it. You cannot use this function
request to copy a file to another drive, however; if the second pathname
specifies a drive, the first pathname must specify or default to the
same drive.
You cannot use this function request to rename an open file, a hidden
file, a system file, or a subdirectory, because it may corrupt your disk.
If there is an error, the carry flag (CF) is set and the error code
returns in AX.
Code Meaning
───────────────────────────────────────────────────────────────────────────
2 One of files is invalid or not open
3 One of paths is invalid or not open
5 First pathname specifies a directory, second pathname specifies
an existing file; or second directory entry could not be opened
17 Both files not on the same drive
Macro Definition:
rename_file macro old_path,new_path
mov dx,offset old_path
push ds
pop es
mov di,offset new_path
mov ah,56H
int 21H
endm
Example:
The following program prompts for the name of a file and a new name,
then renames the file.
prompt1 db "Filename: $"
prompt2 db "New name: $"
old_path db 15,?,15 dup (?)
new_path db 15,?,15 dup (?)
crlf db 0DH,0AH,"$"
;
begin: display prompt1 ;See Function 09H
get_string 15,old_path ;See Function 0AH
xor bx,bx ;To use BL as index
mov bl,old_path[1] ;Get string length
mov old_path[bx+2],0 ;Make an ASCIZ string
display crlf ;See Function 09H
display prompt2 ;See Function 09H
get_string 15,new_path ;See Function 0AH
xor bx,bx ;To use BL as index
mov bl,new_path[1] ;Get string length
mov new_path[bx+2],0 ;Make an ASCIZ string
display crlf ;See Function 09H
rename_file old_path[2],new_path[2] ;THIS FUNCTION
jc error_rename ;Routine not shown
Get/Set Date/Time of File(Function 57H)
Call:
AH = 57H
AL = Function code
0 = Get date and time
1 = Set date and time
BX
Handle
CX (if AL = 1)
Time to be set
DX (if AL = 1)
Date to be set
Return:
Carry set:
AX
1 = Invalid function
6 = Invalid handle
Carry not set:
CX (if AL = 0)
Time file last written
DX (if AL = 0)
Date file last written
Comments:
Function 57H gets or sets the time and date when a file was last written.
To get the time and date, AL must contain 0; the time and date return in CX
and DX. To set the time and date, AL must contain 1; CX and DX must contain
the time and date. BX must contain the file handle. The time and date are
in the form described in "Fields of the FCB" in Section 1.9.1.
If there is an error, the carry flag (CF) is set and the error code
returns in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
1 AL not 0 or 1
6 Handle in BX invalid or not open
Macro Definition:
get_set_date_time macro handle,action,time,date
mov bx,handle
mov al,action
mov cx,word ptr time
mov dx,word ptr date
mov ah,57H
int 21H
endm
Example:
The following program gets the date of a file named report.asm in the
current directory on the disk in drive B, increments the day, increments
the month and/or year, if necessary, and sets the new date of the file.
month db 31,28,31,30,31,30,31,31,30,31,30,31
path db "b:report.asm",0
handle dw ?
time db 2 dup (?)
date db 2 dup (?)
;
begin: open_handle path,0 ;See Function 3DH
mov handle,ax ;Save handle
get_set_date_time handle,0,time,date ;THIS FUNCTION
jc error_time ;Routine not shown
mov word ptr time,cx ;Save time
mov word ptr date,dx ;Save date
convert_date date[-24] ;See end of chapter
inc dh ;Increment day
xor bx,bx ;To use BL as index
mov bl,dl ;Get month
cmp dh,month[bx-1] ;Past last day?
jle month_ok ;No, go home
mov dh,1 ;Yes, set day to 1
inc dl ;Increment month
cmp dl,12 ;Is it past December?
jle month_ok ;No, go home
mov dl,1 ;Yes, set month to 1
inc cx ;Increment year
month_ok: pack_date date ;See end of chapter
get_set_date_time handle,1,time,date ;THIS FUNCTION
jc error_time ;Routine not shown
close_handle handle ;See Function 3EH
jc error_close ;Routine not shown
Get/Set Allocation Strategy (Function 58H)
Call:
AH = 58H
AL
0 = Get strategy
1 = Set strategy
BX (AL = 1)
0 = First fit
1 = Best fit
2 = Last fit
Return:
Carry set:
AX
1 = Invalid function code
Carry not set:
AX (AL = 0)
0 = First fit
1 = Best fit
2 = Last fit
Comments:
Function 58H gets or sets the strategy that MS-DOS uses to allocate memory
when a process requests it. If AL contains 0, the strategy is returned in
AX. If AL contains 1, BX must contain the strategy. The three possible
strategies are:
Table 1.27
Allocation Strategy
╓┌────────────┌───────────┌──────────────────────────────────────────────────╖
Value Name Description
──────────────────────────────────────────────────────────────────────
0 First fit MS-DOS starts searching at the lowest
available block and allocates the
first block it finds (the allocated
memory is the lowest available block).
This is the default strategy.
Value Name Description
1 Best fit MS-DOS searches each available block
and allocates the smallest available
block that satisfies the request.
2 Last fit MS-DOS starts searching at the
highest available block and allocates
the first block it finds (the
allocated memory is the highest
available block).
You can use this function request to control how MS-DOS uses its memory
resources.
If there is an error, the carry flag (CF) is set and the error code
returns in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
1 AL doesn't contain 0 or 1, or BX doesn't contain 0, 1, or 2.
Macro Definition:
alloc_strat macro code,strategy
mov bx,strategy
mov al,code
mov ah,58H
int 21H
endm
Example:
The following program displays the memory-allocation strategy in effect,
then forces subsequent memory allocations to the top of memory by setting
the strategy to last fit (code 2).
get equ 0
set equ 1
stdout equ 1
last_fit equ 2
;
first db "First fit ",0DH,0AH
best db "Best fit ",0DH,0AH
last db "Last fit ",0DH,0AH
;
begin: alloc_strat get ;THIS FUNCTION
jc alloc_error ;routine not shown
mov cl,4 ;multiply code by 16
shl ax,cl ;to calculate offset
mov dx,offset first ;point to first msg
add dx,ax ;add to base address
mov bx,stdout ;handle for write
mov cs,16 ;write 16 bytes
mov ah,40h ;write handle
int 21H ;system call
; jc write_error ;routine not shown
alloc_strat set,last_fit ;THIS FUNCTION
; jc alloc_error ;routine not shown
Get Extended Error (Function 59H)
Call:
AH = 59H
BX = 0
Return:
AX
Extended-error code
BH
Error class (see text)
BL
Suggested action (see text)
CH
Locus (see text)
CL, DX, SI, DI, DS, ES destroyed
Comments:
Function 59H retrieves an extended-error code for the preceding system
call. Each release of MS-DOS extends the error codes to cover new
capabilities. These new codes are mapped to a simpler set of error codes
based on MS-DOS Version 2.0, so that existing programs can continue to
operate correctly. Note that this call destroys all registers except CS:IP
and SS:SP.
A user-written Interrupt 24H (Critical-Error Handler Address) can use
Function 59H to get detailed information about the error that caused the
interrupt to be issued.
The input BX is a version indicator that specifies for what level of
error handling the application was written. The current level is 0.
The extended-error code consists of four separate codes in AX, BH, BL,
and CH that give as much detail as possible about the error and suggest
how the issuing program should respond.
BH--Error Class
BH returns a code that describes the class of error that occurred:
╓┌──────┌────────────────────────────────────────────────────────────────────╖
Class Description
───────────────────────────────────────────────────────────────────────────
1 Out of a resource, such as storage or channels
2 Not an error, but a temporary situation (such as a locked region
in a file) that is expected to end
3 Authorization problem
4 Internal error in system software
5 Hardware failure
Class Description
6 System software failure not the fault of the active process (could
be caused by missing or incorrect configuration files, for example)
7 Application program error
8 File or item not found
9 File or item of invalid format or type, or that is otherwise
invalid or unsuitable
10 Interlocked file or item
11 Wrong disk in drive, bad spot on disk, or other problem
with storage medium
12 Other error
BL--Suggested Action
BL returns a code that suggests how the issuing program can respond to
the error:
Action Description
───────────────────────────────────────────────────────────────────────────
1 Retry, then prompt user
2 Retry after a Pause
3 If user entered data such as drive letter or filename,
prompt for it again
4 Terminate with cleanup
5 Terminate immediately; system so unhealthy that program should
exit as soon as possible without taking time to close files
and update indexes
6 Error is informational
7 Prompt user to perform some action, such as changing disks,
then retry operation
CH--Locus
CH returns a code that provides additional information to help locate the
area involved in the failure. This code is particularly useful for hardware
failures (BH=5).
Locus Description
───────────────────────────────────────────────────────────────────────────
1 Unknown
2 Related to random-access block devices, such as a disk drive
3 Related to Network
4 Related to serial-access character devices, such as a printer
5 Related to random-access memory
Your programs should handle errors by noting the error return from the
original system call and then issuing this system call to get the extended-
error code. If the program does not recognize the extended-error code, it
should respond to the original error code.
This system call is available during Interrupt 24H and may be used to
return network-related errors.
Macro Definition:
get_error macro
mov ah, 59H
int 21H
endm
Example:
Since this function request provides such detailed information, a general
example is not practical. User programs can interpret the various codes to
determine what sort of messages or prompts should be displayed, what action
to take, and whether to terminate the program if recovery from the errors
isn't possible.
Create Temporary File (Function 5AH)
Call:
AH = 5AH
CX
Attribute
DS:DX
Pointer to pathname, followed by a
byte of 0, and then by 13 bytes of memory
Return:
Carry set:
AX
2 = File not found
3 = Path not found
4 = Too many open files
5 = Access denied
Carry not set:
AX
Handle
Comments:
Function 5AH creates a file with a unique name. DX must contain the offset
(from the segment address in DS) of an ASCIZ string that specifies a
pathname and 13 bytes of memory (to hold the filename). CX must contain
the attribute to be assigned to the file, as described in Section 1.5.5,
"File Attributes," earlier in this chapter.
MS-DOS creates a unique filename and appends it to the pathname pointed
to by DS:DX, creates the file and opens it in compatibility mode, then
returns the file handle in AX. A program that needs a temporary file should
use this function request to avoid name conflicts.
When the creating process exits, MS-DOS does not automatically delete
a file created with Function 5AH. When you no longer need the file you
should delete it.
If there is an error, the carry flag (CF) is set and the error code
returns in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
2 File is invalid or doesn't exist
3 Directory pointed to by DS:DX is invalid or doesn't exist
4 Too many open files (no handle available)
5 Access denied
Macro Definition:
create_temp macro pathname,attrib
mov cx,attrib
mov dx,offset pathname
mov ah,5AH
int 21H
endm
Example:
The following program creates a temporary file in the directory named
\wp\docs, copies a file named textfile.asc that is in the current directory
into the temporary file, and then closes both files.
stdout equ 1
;
file db "TEXTFILE.ASC",0
path db "\WP\DOCS",0
temp db 13 dup (0)
open_msg db " opened.",0DH,0AH
crl_msg db " created.",0DH,0AH
rd_msg db " read into buffer.",0DH,0AH
wr_msg db "Buffer written to "
cl_msg db "Files closed.",0DH,0AH
crlf db 0DH,0AH
handle1 dw ?
handle2 dw ?
buffer db 512 dup (?)
;
begin: open_handle file,0 ;see Function 3DH
jc open_error ;routine not shown
mov handle1,ax ;save handle
write_handle stdout,file,12 ;see Function 40H
jc write_error ;routine not shown
write_handle stdout,open_msg,10 ;see Function 40H
jc write_error ;routine not shown
create_temp path,0 ;THIS FUNCTION
jc create_error ;routine not shown
mov handle2,ax ;save handle
write_handle stdout,path,8 ;see Function 40H
jc write_error ;routine not shown
display_char "
write_handle stdout,temp,12 ;see Function 40H
jc write_error ;routine not shown
write_handle stdout,crl_msg,11 ;See Function 40H
jc write_error ;routine not shown
read_handle handle1,buffer,512 ;see Function 3FH
jc read_error ;routine not shown
write_handle stdout,file,12 ;see Function 40H
jc write_error ;routine not shown
write_handle stdout,rd_msg,20 ;see Function 40H
jc write_error ;routine not shown
write_handle handle2,buffer,512 ;see Function 40H
jc write_error ;routine not shown
write_handle stdout,wr_msg,18 ;see Function 40H
jc write_error ;routine not shown
write_handle stdout,temp,12 ;see Function 40H
jc write_error ;routine not shown
write_handle stdout,crlf,2 ;see Function 40H
jc write_error ;routine not shown
close_handle handle1 ;see Function 3EH
jc close_error ;routine not shown
close_handle handle2 ;see Function 3EH
jc close_error ;routine not shown
write_handle stdout,cl_msg,15 ;see Function 40H
jc write_error ;routine not shown
Create New File (Function 5BH)
Call:
AH = 5BH
CX
Attribute
DS:DX
Pointer to pathname
Return:
Carry set:
AX
2 = File not found
3 = Path not found
4 = Too many open files
5 = Access denied
80 = File already exists
Carry not set:
AX
Handle
Comments:
Function 5BH creates a new file. DX must contain the offset (from the
segment address in DS) of an ASCIZ string that specifies a pathname.
CX contains the attribute to be assigned to the file, as described in
Section 1.5.5, "File Attributes."
If there is no existing file with the same filename, MS-DOS creates
the file, opens it in compatibility mode, and returns the file handle
in AX.
This function request fails if the specified file exists, unlike
Function 3CH (Create Handle), which, under the same circumstances,
truncates the file to a length of 0. In a multitasking system, the
existence of a file is used as a semaphore; you can use this system
call as a test-and-set semaphore.
If there is an error, the carry flag (CF) is set and the error code
returns in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
2 File is invalid or doesn't exist
3 Directory pointed to by DS:DX is invalid or doesn't exist
4 No free handles are available in the current process,
or internal system tables are full
5 Access denied
80 File with the same specification pointed to by DS:DX
already exists
Macro Definition:
create_new macro pathname,attrib
mov cx, attrib
mov dx, offset pathname
mov ah, 5BH
int 21H
endm
Example:
The following program attempts to create a new file named report.asm in
the current directory. If the file already exists, the program displays an
error message and returns to MS-DOS. If the file doesn't exist and there
are no other errors, the program saves the handle and continues processing.
err_msg db "FILE ALREADY EXISTS",0DH,0AH,"$"
path db "report.asm",0
handle dw ?
;
begin: create_new path,0 ;THIS FUNCTION
jnc continue ;further processing
cmp ax,80 ;file already exist?
jne error ;routine not shown
display err_msg ;see Function 09H
jmp return ;return to MS-DOS
continue: mov handle,ax ;save handle
;
; (further processing here)
Lock (Function 5CH, Code 00H)
Call:
AH = 5CH
AL = 00H
BX
Handle
CX:DX
Offset of region to be locked
SI:DI
Length of region to be locked
Return:
Carry set:
AX
1 = Invalid function code
6 = Invalid handle
33 = Lock violation
36 = Sharing buffer exceeded
Carry not set:
No error
Comments:
Function 5CH, Code 00H, denies all access (read or write) by any other
process to the specified region of the file. BX must contain the handle of
the file that contains the region to be locked. CX:DX (a four-byte integer)
must contain the offset in the file of the beginning of the region. SI:DI
(a four-byte integer) must contain the length of the region.
If another process attempts to use (read or write) a locked region,
MS-DOS retries three times; if the retries fail, MS-DOS issues Interrupt
24H for the requesting process. You can change the number of retries with
Function 44H, Code 0BH (IOCtl Retry).
The locked region can be anywhere in the file. For instance, locking
beyond the end of the file is not an error. A region should be locked for
only a brief period, so if it is locked for more than ten seconds you
should consider it to be an error.
Function 45H (Duplicate File Handle) and Function 46H (Force Duplicate
File Handle) duplicate access to any locked region. Passing an open file to
a child process with Function 4BH, Code 00H (Load and Execute Program) does
not duplicate access to locked regions.
───────────────────────────────────────────────────────────────────────────
Warning
If a program closes a file that contains a locked region or terminates
with an open file that contains a locked region, the result is undefined.
───────────────────────────────────────────────────────────────────────────
Programs that might be terminated by Interrupt 23H (CONTROL-C Handler
Address) or Interrupt 24H (Critical-Error-Handler Address) should trap
these interrupts and unlock any locked regions before exiting.
Programs should not rely on being denied access to a locked region.
A program can determine the status of a region (locked or unlocked)
by attempting to lock the region and examining the error code.
If there is an error, the carry flag (CF) is set and the error code is
returned in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
1 File sharing must be loaded to use this function request.
6 The handle in BX is not a valid, open handle.
33 All or part of the specified region is already locked.
36 There is no more room for lock entries in the buffer. Refer to
the share command in the MS-DOS User's Reference for information
on allocating more lock entries.
Macro Definition:
lock macro handle,start,bytes
mov bx, handle
mov cx, word ptr start
mov dx, word ptr start+2
mov si, word ptr bytes
mov di, word ptr bytes+2
mov al, 0
mov ah, 5CH
int 21H
endm
Example:
The following program opens a file named finalrpt in "Deny None" mode and
locks two portions of it: the first 128 bytes and bytes 1024 through 5119.
After some (unspecified) processing, it unlocks the same portions and
closes the file.
stdout equ 1
;
start1 dd 0
lgth1 dd 128
start2 dd 1023
lgth2 dd 4096
file db "FINALRPT",0
op_msg db " opened.",0DH,0AH
11_msg db "First 128 bytes locked.",0DH,0AH
12_msg db "Bytes 1024-5119 locked.",0DH,0AH
u1_msg db "First 128 bytes unlocked.",0DH,0AH
u2_msg db "Bytes 1024-5119 unlocked.",0DH,0AH
cl_msg db " closed.:,0DH,0AH
handle dw ?
;
begin: open_handle file,01000010b ;see Function 3DH
jc open_error ;routine not shown
write_handle stdout,file,8 ;see Function 40H
jc write_error ;routine not shown
write_handle stdout,op_msg,10 ;see Function 40H
jc write_error ;routine not shown
mov handle,ax ;save handle
lock handle,start1,lgth1 ;THIS FUNCTION
jc lock_error ;routine not shown
write_handle stdout,11_msg,25 ;see Function 40H
jc write_error ;routine not shown
lock handle,start2,lgth2 ;THIS FUNCTION
jc lock_error ;routine not shown
write_handle stdout,12_msg,25 ;see Function 40H
jc write_error ;routine not shown
;
; ( Further processing here )
;
unlock handle,start1,lgth1 ;See Function 5C01H
jc unlock_error ;routine not shown
write_handle stdout,ul_msg,27 ;see Function 40H
jc write_error ;routine not shown
unlock handle,start2,lgth2 ;See Function 5C01H
jc unlock_error ;routine not shown
write_handle stdout,u2_msg,27 ;See Function 40H
jc write_error ;routine not shown
close_handle handle ;See Function 3EH
jc close_error ;routine not shown
write_handle stdout,file,8 ;see Function 40H
jc write_error ;routine not shown
write_handle stdout,cl_msg,10 ;see Function 40H
jc write_error ;routine not shown
Unlock (Function 5CH, Code 01H)
Call:
AH = 5CH
AL = 01H
BX
Handle
CX:DX
Offset of area to be unlocked
SI:DI
Length of area to be unlocked
Return:
Carry set:
AX
1 = Invalid function code
6 = Invalid handle
33 = Lock violation
36 = Sharing buffer exceeded
Carry not set:
No error
Comments:
Function 5CH, Code 01H, unlocks a region previously locked by the same
process. BX must contain the handle of the file that contains the region
to be unlocked. CX:DX (a four-byte integer) must contain the offset in
the file of the beginning of the region. SI:DI (a four-byte integer) must
contain the length of the region. The offset and length must be exactly
the same as the offset and length specified in the previous Function 5CH,
Code 00H (Lock).
The description of Function 5CH, Code 00H (Lock) describes how to use
locked regions.
If there is an error, the carry flag (CF) is set and the error code
returns in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
1 File sharing must be loaded to use this function request.
6 The handle in BX is not a valid, open handle.
33 The region specified is not identical to one that was
previously locked by the same process.
36 There is no more room for lock entries in the buffer. Refer
to the share command in the MS-DOS User's Reference for
information on allocating more lock entries.
You should issue Function 59H (Get Extended Error) to list the possible
errors returned by this function.
Macro Definition:
unlock macro handle,start,bytes
mov bx, handle
mov cx, word ptr start
mov dx, word ptr start+2
mov si, word ptr bytes
mov di, word ptr bytes+2
mov al, 1
mov ah, 5CH
int 21H
endm
Example:
The following program opens a file named finalrpt in "Deny None" mode and
locks two portions of it: the first 128 bytes and bytes 1024 through 5119.
After some (unspecified) processing, it unlocks the same portions and
closes the file.
stdout equ 1
;
start1 dd 0
lgth1 dd 128
start2 dd 1023
lgth2 dd 4096
file db "FINALRPT",0
op_msg db " opened.",0DH,0AH
11_msg db "First 128 bytes locked.",0DH,0AH
12_msg db "Bytes 1024-5119 locked.",0DH,0AH
u1_msg db "First 128 bytes unlocked.",0DH,0AH
u2_msg db "Bytes 1024-5119 unlocked.",0DH,0AH
cl_msg db " closed.",0DH,0AH
handle dw ?
;
begin: open_handle file,01000010b ;see Function 3DH
jc open_error ;routine not shown
write_handle stdout,file,8 ;see Function 40H
jc write_error ;routine not shown
write_handle stdout,op_msg,10 ;see Function 40H
jc write_error ;routine not shown
mov handle,ax ;save handle
lock handle,start1,lgth1 ;See Function 5C00H
jc lock_error ;routine not shown
write_handle stdout,11_msg,25 ;see Function 40H
jc write_error ;routine not shown
lock handle,start2,lgth2 ;See Function 5C00H
jc lock_error ;routine not shown
write_handle stdout,12_msg,25 ;see Function 40H
jc write_error ;routine not shown
;
; ( Further processing here )
;
unlock handle,start1,lgth1 ;THIS FUNCTION
jc unlock_error ;routine not shown
write_handle stdout,u1_msg,27 ;see Function 40H
jc write_error ;routine not shown
unlock handle,start2,lgth2 ;THIS FUNCTION
jc unlock_error ;routine not shown
write_handle stdout,u2_msg,27 ;see Function 40H
jc write_error ;routine not shown
close_handle handle ;See Function 3EH
jc close_error ;routine not shown
write_handle stdout,file,8 ;see Function 40H
jc write_error ;routine not shown
write_handle stdout,cl_msg,10 ;see Function 40H
jc write_error ;routine not shown
Get Machine Name (Function 5EH, Code 00H)
Call:
AH = 5EH
AL = 0
DS:DX
Pointer to 16-byte buffer
Return:
Carry set:
AX
1 = Invalid function code
Carry not set:
CX
Identification number of local
computer
Comments:
Function 5EH, Code 0, retrieves the net name of the local computer. DX
must contain the offset (to the segment address in DS) of a 16-byte buffer.
Microsoft Networks must be running.
MS-DOS returns the local computer name (a 16-byte ASCIZ string,
padded with blanks) in the buffer pointed to by DS:DX. CX returns the
identification number of the local computer. If the network was never
installed, the CH register returns with zero and the value in the CL
register is invalid.
If there is an error, the carry flag (CF) is set and the error code
returns in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
1 Microsoft Networks must be running to use this function request.
Macro Definition:
get_machine_name macro buffer
mov dx,offset buffer
mov al,0
mov ah,5EH
int 21H
endm
Example:
The following program displays the name of a Microsoft Networks work-
station.
stdout equ 1
;
msg db "Netname: "
mac_name db 16 dup (?),0DH,0AH
;
begin: get_machine_name mac_name ;THIS FUNCTION
jc name_error ;routine not shown
write_handle stdout,msg,27 ;see Function 40H
jc write_error ;routine not shown
Printer Setup (Function 5EH, Code 02H)
Call:
AH = 5EH
AL = 02H
BX
Assign-list index
CX
Length of setup string
DS:SI
Pointer to setup string
Return:
Carry set:
AX
1 = Invalid function code
Carry not set:
No error
Comments:
Function 5EH, Code 02H, defines a string of control characters that MS-DOS
adds to the beginning of each file sent to the network printer. BX must
contain the index into the assign list that identifies the printer (entry 0
is the first entry). CX must contain the length of the string. SI must
contain the offset (to the segment address in DS) of the string itself.
Microsoft Networks must be running.
MS-DOS adds the setup string to the beginning of each file sent to the
printer, which is specified by the assign-list index in BX. This function
request lets each program that shares a printer have its own printer
configuration. You can use Function 5F02H (Get Assign-List Entry) to
determine which entry in the assign list refers to the printer.
If there is an error, the carry flag (CF) is set and the error code
returns in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
1 Microsoft Networks must be running to use this function request.
Macro Definition:
printer_setup macro index,lgth,string
mov bx, index
mov cx, lgth
mov dx, offset string
mov al, 2
mov ah, 5EH
int 21H
endm
Example:
The following program defines a printer-setup string that consists of
the control character to print expanded type on Epson-compatible printers.
The printer cancels this mode at the first carriage return, so the effect
is to print the first line of each file sent to the network printer as a
title in expanded characters. The setup string is one character. This
example assumes that the printer is the entry number 3 (the fourth entry)
in the assign list. Use Function 5F02H (Get Assign-List Entry) to determine
this value.
setup db 0EH
;
begin: printer_setup 3,1,setup ;THIS FUNCTION
jc error ;routine not shown
Get Assign-List Entry (Function 5FH, Code 02H)
Call:
AH = 5FH
AL = 02H
BX
Assign-list index
DS:SI
Pointer to buffer for local name
ES:DI
Pointer to buffer for remote name
Return:
Carry set:
AX
1 = Invalid function code
18 = No more files
Carry not set:
BL
3 = Printer
4 = Drive
CX
Stored user value
Comments:
Function 5FH, Code 02H, retrieves the specified entry from the network list
of assignments. BX must contain the assign-list index (entry 0 is the first
entry). SI must contain the offset (to the segment address in DS) of a 16-
byte buffer for the local name. DI must contain the offset (to the segment
address in ES) of a 128-byte buffer for the remote name. Microsoft Networks
must be running.
MS-DOS puts the local name in the buffer pointed to by DS:SI and the
remote name in the buffer pointed to by ES:DI. The local name can be a null
ASCIZ string. BL returns 3 if the local device is a printer or 4 if the
local device is a drive. CX returns the stored user value set with
Function 5F03H (Make Assign-List Entry). The contents of the assign list
can change between calls.
You can use this function request to retrieve any entry, or to make a
copy of the complete list by stepping through the table. To detect the end
of the assign list, check for error code 18 (no more files), as you would
when stepping through a directory by using Functions 4EH (Find First File)
and 4FH (Find Next File).
If there is an error, the carry flag (CF) is set and the error code
returns in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
1 Microsoft Networks must be running to use this function request.
18 The index passed in BX is greater than the number of entries
in the assign list.
Macro Definition:
get_list macro index,local,remote
mov bx, index
mov si, offset local
mov di, offset remote
mov al,2
mov ah, 5FH
int 21H
endm
Example:
The following program displays the assign list on a Microsoft Networks
workstation, showing the local name, remote name, and device type (drive
or printer) for each entry.
stdout equ 1
printer equ 3
;
local_nm db 16 dup (?),2 dup (20h)
remote_nm db 128 dup (?),2 dup (20h)
header db "Local name",8 dup (20h)
db "Remote name",7 dup (20h)
db "Device Type"
crlf db 0dh,0ah,0dh,0ah
drive_msg db "drive"
print_msg db "printer"
index dw ?
;
begin: write_handle stdout,header,51 ;see Function 40H
jc write_error ;routine not shown
mov index,0 ;assign list index
ck_list: get_list index,local_nm,remote_nm ;THIS FUNCTION
jnc got_one ;got an entry
error: cmp ax,18
je last_one ;yes
jmp error ;routine not shown
got_one: push bx ;save device type
write_handle stdout,local_nm,148 ;see Function 40H
jc write_error ;routine not shown
pop bx ;get device type
cmp bl,printer ;is it a printer?
je prntr ;yes
write_handle stdout,drive_msg,5 ;see Function 40H
jc write_error ;routine not shown
jmp get_next ;finish message
prntr: write_handle stdout,print_msg,7 ;see Function 40H
jc write_error ;routine not shown
get_next: write_handle stdout,crlf,2 ;see Function 40H
jc write_error ;routine not shown
inc index ;bump index
jmp ck_list ;get next entry
last_one: write_handle stdout,crlf,4 ;see Function 40H
jc write_error ;routine not shown
;
Make Assign-List Entry (Function 5FH, Code 03H)
Call:
AH = 5FH
AL = 03H
BL
3 = Printer
4 = Drive
CX
User value
DS:SI
Pointer to name of source device
ES:DI
Pointer to name of destination
device
Return:
Carry set:
AX
1 = Invalid function code
5 = Access denied
3 = Path not found
8 = Insufficient memory
(Other errors particular to the
network may occur.)
Carry not set:
No error
Comments:
Function 5FH, Code 03H, redirects a printer or disk drive (source device)
to a network directory (destination device). BL must contain 3 if the
source device is a printer or 4 if it is a disk drive. SI must contain
the offset (to the segment address in DS) of an ASCIZ string that specifies
the name of the printer, or a drive letter followed by a colon, or a null
string (one byte of 00H). DI must contain the offset (to the segment
address in ES) of an ASCIZ string that specifies the name of a network
directory. CX contains a user-specified 16-bit value that MS-DOS maintains.
Microsoft Networks must be running.
The destination string must be an ASCIZ string of the following form:
machine-name pathname 00H password 00H
where:
Machine-name is the net name of the server that contains the network
directory;
Pathname is the alias of the network directory (not the directory
path) to which the source device is to be redirected;
00H is a null byte; and
Password is the password for access to the network directory. If no
password is specified, both null bytes must immediately follow the
pathname.
If BL=3, the source string must be PRN, LPT1, LPT2, or LPT3. This
function buffers and sends all output for the named printer to the remote-
printer spooler named in the destination string.
If BL=4, the source string can be either a drive letter followed by a
colon, or a null string. If the source string contains a valid drive letter
and colon, this call redirects all subsequent drive-letter references to
the network directory named in the destination string. If the source string
is a null string, MS-DOS attempts to grant access to the network directory
with the specified password.
The maximum length of the destination string is 128 bytes. You can
retrieve the value in CX by using Function 5FH, Code 02H (Get Assign-List
Entry).
If there is an error, the carry flag (CF) is set and the error code
returns in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
1 Microsoft Networks must be running to use this function request;
the value in BX is not 1 to 4, the source string is in the wrong
format; the destination string is in the wrong format; or the
source device is already redirected.
3 The network directory path is invalid or doesn't exist.
5 The network directory/password combination is not valid. This
does not mean that the password itself was invalid; the directory
might not exist on the server.
8 There is not enough memory for string substitutions.
Macro Definition:
redir macro device,value,source,destination
mov bl, device
mov cx, value
mov si, offset source
mov es, seg destination
mov di, offset destination
mov al, 03H
mov ah, 5FH
int 21H
endm
Example:
The following program redirects two drives and a printer from a workstation
to a server named harold. It assumes the machine name, directory names,
and driver letters shown:
Local drive Netname
or printer on server Password
E: WORD none
F: COMM fred
PRN: PRINTER quick
printer equ 3
drive equ 4
;
local_1 db "e:",0
local_2 db "f:",0
local_3 db "prn",0
remote_1 db "\harold\word",0,0
remote_2 db "\harold\comm",0,"fred",0
remote_3 db "\harold\printer",0,"quick",0
;
begin: redir local_1,remote_1,drive,0 ;THIS FUNCTION
jc error ;routine not shown
redir local_2,remote_2,drive,0 ;THIS FUNCTION
jc error ;routine not shown
redir local_3,remote_3,printer,0 ;THIS FUNCTION
jc error ;routine not shown
Cancel Assign-List Entry (Function 5FH, Code 04H)
Call:
AH = 5FH
AL = 04H
DS:SI
Pointer to name of source device
Return:
Carry set:
AX
1 = Invalid function code
15 = Redirection paused on server
(Other errors particular to the network
may occur.)
Carry not set:
No error
Comments:
Function 5FH, Code 04H, cancels the redirection of a printer or disk drive
(source device) to a network directory (destination device) made with
Function 5FH, Code 03H (Make Assign-List Entry). SI must contain the offset
(to the segment address in DS) of an ASCIZ string that specifies the name
of the printer or drive whose redirection is to be canceled. Microsoft
Networks must be running.
The ASCIZ string pointed to by DS:SI can contain one of three values:
■ The letter of a redirected drive, followed by a colon. Cancels the
redirection and restores the drive to its physical meaning.
■ The name of a redirected printer (PRN, LPT1, LPT2, LPT3, or their
machine-specific equivalents). Cancels the redirection and restores
the printer name to its physical meaning.
■ A string starting with \\ (2 backslashes). Terminates the connection
between the local machine and the network directory.
If there is an error, the carry flag (CF) is set and the error code
returns in AX:
Code Meaning
───────────────────────────────────────────────────────────────────────────
1 Microsoft Networks must be running to use this function request;
or the ASCIZ string names a nonexistent source device.
15 Disk or printer redirection on the network server is paused.
Macro Definition:
cancel_redir macro local
mov si, offset local
mov al, 4
mov ah, 5FH
int 21H
endm
Example:
The following program cancels the redirection of drives E and F and the
printer (PRN) of a Microsoft Networks workstation. It assumes that these
local devices were redirected previously.
local_1 db "e:",0
local_2 db "f:",0
local_3 db "prn",0
;
begin: cancel_redir local_1 ;THIS FUNCTION
jc error ;routine not shown
cancel_redir local_2 ;THIS FUNCTION
jc error ;routine not shown
cancel_redir local_3 ;THIS FUNCTION
jc error ;routine not shown
Get PSP (Function 62H)
Call:
AH = 62H
Return:
BX
Segment address of the Program
Segment Prefix of the current process
Comments:
Function 62H retrieves the segment address of the currently active process
(the start of the Program Segment Prefix). The address returns in BX.
Macro Definition:
get_psp macro
mov ah, 62H
int 21H
endm
Example:
The following program displays the segment address of its Program Segment
Prefix (PSP) in hexadecimal.
msg db "PSP segment address: H",0DH,0AH,"$"
;
begin: get_psp ;THIS FUNCTION
convert bx,16,msg[21] ;see end of chapter
display msg ;see Function 09H
Get Extended Country Information (Function 65H)
Call:
AH = 65H
AL
Function (minor) code
BX
Code page (-1 = active CON device)
CX
Amount of data to return
DX
Country ID for which information is to be returned
(-1=default country)
ES:DI
Address of country information buffer
Return:
1 = Buffer has been filled
2 = File not found
Comments:
Function 65H retrieves standard country information. This information
includes country ID, code page, date and time format, currency symbol,
separators (for thousands, decimals, data list, date and time) currency
format flags, digits in currency, and case-mapping information.
The function code passed in AL may be one of the following:
Code Description
───────────────────────────────────────────────────────────────────────────
1 Return standard information
2 Return pointer to uppercase table
3 Return pointer to filename uppercase table
4 Return pointer to collating table
5 Reserved (no entry)
6 Return pointer to collating sequence
MS-DOS 3.3 provides more country-dependent information than previous
versions of MS-DOS. Only the information for the default country is kept
in the kernel. Country-dependent information for all other countries is
contained in the country.sys file. The MS-DOS nlsfunc command is used to
access the country-dependent information in country.sys using this call.
If the country code and code page number do not match, or if either is
invalid, error code 2 is returned to AX. If CX is less than 5, error code
1 is returned. If the amount of information requested is greater than the
value of CX, only CX bytes are returned and no error is reported.
If AL = 1, the buffer is filled with the following information:
db 1 ; Information ID
dw ? ; Size (<=38)
dw ? ; Country ID
dw ? ; Code page
If AL = 2, the buffer is filled with the following information:
db 2 ; Information ID
dd ? ; Double-word pointer to uppercase table
If AL = 4, the buffer is filled with the following information:
db 4 ; Information ID
dd ? ; Double-word pointer to filename uppercase table
Both of these tables consist of a length field (two bytes) followed by 128
uppercase values for the upper 128 ASCII characters. The following formula
is used to compute the address of an uppercase equivalent in the table:
Address of outchar = inchar - (256-table_len) = table_start
where:
Parameter Meaning
───────────────────────────────────────────────────────────────────────────
inchar Character to be generated
table_len Length of list of uppercase values (two bytes)
table_start Starting address of uppercase table
outchar Uppercase value for inchar
If inchar is greater than or equal to (256 - table_len), there is an
uppercase equivalent in the table; otherwise, there is not.
If AL = 6, the buffer is filled with the following information:
db 6 ; Information ID
dd ? ; Double-word pointer to collating sequence
The table is 258 bytes long. The first word is the length of the table.
The rest of the table is 256 ASCII values in the appropriate order.
Get/Set Global Code Page (Function 66H)
Call:
AH = 66H
AL
Function (minor) code
BX
Code page to set (AL = 2)
Return:
Carry set:
AX
02 = File not found
65 = Device not selected
Carry not set:
No error
Comments:
Function 66H gets or sets the code page used by the kernel and all devices.
If no other code page has been set, this function gets the default code
page from DX. If another code page is set, this function retrieves the
active code page from BX.
The MS-DOS nlsfunc command and country.sys must be on the system if
this function is to be used to change the global code page.
The function code may be one of the following:
Code Description
───────────────────────────────────────────────────────────────────────────
1 Get code page
2 Set code page
MS-DOS gets the new code page from the country.sys file. Devices must
be prepared for code page switching before a code page can be selected.
To prepare a device, a device driver that supports code page switching
must be installed by using the device command in the config.sys file.
The user must also use the prepare keyword with the MS-DOS mode command
to prepare the device for code page switching.
The code page selected must be compatible with the country code specified
in the config.sys file. If MS-DOS cannot read country.sys or other
specified country information file, error code 02 is returned to AX.
Set Handle Count (Function 67H)
Call:
AH = 67H
BX
Number of allowed handles
Return:
Carry set:
AX
Carry not set:
No error
Comments:
Function 67H increases or decreases the number of files a program can
have open at one time. The maximum number of files handles is 64K. If less
than 20 are specified, the minimum handle number, 20, is assumed. If this
call is used to reduce the number of allowed handles, the new limit does
not take affect until any handles above the new limit are closed.
The user should use Call 4AH (Set Block) to allocate memory for the
extended handle list if BX is greater than 255. The maximum number for
the value of the config.sys command files is 255.
Commit File (Function 68H)
Call:
AH = 68H
BX
File handle
Return:
Carry set:
AX = error
Carry not set
No error
Comments:
Function 68H flushes all buffered data for a file without closing it.
Using this call is more efficient than using the traditional close-open
sequence, and is more effective for network environments. This call makes
sure that the disk image of a file is current.
; Macro Definitions for MS-DOS System Call Examples
;
;*******************
; Interrupts
;*******************
; Interrupt 25H
ABS_DISK_READ macro disk,buffer,num_sectors,first_sector
mov al,disk
mov bx,offset buffer
mov cx,num_sectors
mov dx,first_sector
int 25H
popf
endm
; Interrupt 26H
ABS_DISK_WRITE macro disk,buffer,num_sectors,first_sector
mov al,disk
mov bx,offset buffer
mov cx,num_sectors
mov dx,first_sector
int 26H
popf
endm
; Interrupt 27H
STAY_RESIDENT macro last_instruc
mov dx,offset last_instruc
inc dx
int 27H
endm
;
;
;*******************
; Function Requests
;*******************
; Function Request 00H
TERMINATE_PROGRAM macro
xor ah,ah
int 21H
endm
; Function Request 01H
READ_KBD_AND_ECHO macro
mov ah,01H
int 21H
endm
; Function Request 02H
DISPLAY_CHAR macro character
mov dl,character
mov ah,02H
int 21H
endm
; Function Request 03H
AUX_INPUT macro
mov ah,03H
int 21H
endm
; Function Request 04H
AUX_OUTPUT macro
mov ah,04H
int 21H
endm
; Function Request 05H
PRINT_CHAR macro character
mov dl,character
mov ah,05H
int 21H
endm
; Function Request 06H
DIR_CONSOLE_IO macro switch
mov dl,switch
mov ah,06H
int 21H
endm
; Function Request 07H
DIR_CONSOLE_INPUT macro
mov ah,07H
int 21H
endm
; Function Request 08H
READ_KBD macro
mov ah,08H
int 21H
endm
; Function Request 09H
DISPLAY macro string
mov dx,offset string
mov ah,09H
int 21H
endm
; Function Request 0AH
GET_STRING macro limit,string
mov dx,offset string
mov string,limit
mov ah,0AH
int 21H
endm
; Function Request 0BH
CHECK_KBD_STATUS macro
mov ah,0BH
int 21H
endm
; Function Request 0CH
FLUSH_AND_READ_KBD macro switch
mov al,switch
mov ah,0CH
int 21H
endm
; Function Request 0DH
RESET_DISK macro
mov ah,0DH
int 21H
endm
; Function Request 0EH
SELECT_DISK macro disk
mov dl,disk[-65]
mov ah,0EH
int 21H
endm
; Function Request 0FH
OPEN macro fcb
mov dx,offset fcb
mov ah,0FH
int 21H
endm
; Function Request 10H
CLOSE macro fcb
mov dx,offset fcb
mov ah,10H
int 21H
endm
; Function Request 11H
SEARCH_FIRST macro fcb
mov dx,offset fcb
mov ah,11H
int 21H
endm
; Function Request 12H
SEARCH_NEXT macro fcb
mov dx,offset fcb
mov ah,12H
int 21H
endm
; Function Request 13H
DELETE macro fcb
mov dx,offset fcb
mov ah,13H
int 21H
endm
; Function Request 14H
READ_SEQ macro fcb
mov dx,offset fcb
mov ah,14H
int 21H
endm
; Function Request 15H
WRITE_SEQ macro fcb
mov dx,offset fcb
mov ah,15H
int 21H
endm
; Function Request 16H
CREATE macro fcb
mov dx,offset fcb
mov ah,16H
int 21H
endm
; Function Request 17H
RENAME macro fcb,newname
mov dx,offset fcb
mov ah,17H
int 21H
endm
; Function Request 19H
CURRENT_DISK macro
mov ah,19H
int 21H
endm
; Function Request 1AH
SET_DTA macro buffer
mov dx,offset buffer
mov ah,1AH
endm
; Function Request 1BH
DEF_DRIVE_DATA macro
mov ah,1BH
int 21H
endm
; Function Request 1CH
DRIVE_DATA macro drive
mov dl,drive
mov ah,1CH
int 21H
endm
; Function Request 21H
READ_RAN macro fcb
mov dx,offset fcb
mov ah,21H
int 21H
endm
; Function Request 22H
WRITE_RAN macro fcb
mov dx,offset fcb
mov ah,22H
int 21H
endm
; Function Request 23H
FILE_SIZE macro fcb
mov dx,offset fcb
mov ah,23H
int 21H
endm
; Function Request 24H
SET_RELATIVE_RECORD macro fcb
mov dx,offset fcb
mov ah,24H
int 21H
endm
; Function Request 25H
SET_VECTOR macro interrupt,handler_start
mov al,interrupt
mov dx,offset handler_start
mov ah,25H
int 21H
endm
; Function Request 26H
CREATE_PSP macro seg_addr
mov dx,offset seg_addr
mov ah,26H
int 21H
endm
; Function Request 27H
RAN_BLOCK_READ macro fcb,count,rec_size
mov dx,offset fcb
mov cx,count
mov word ptr fcb[14],rec_size
mov ah,27H
int 21H
endm
; Function Request 28H
RAN_BLOCK_WRITE macro fcb,count,rec_size
mov dx,offset fcb
mov cx,count
mov word ptr fcb[14],rec_size
mov ah,28H
int 21H
endm
; Function Request 29H
PARSE macro string,fcb
mov si,offset string
mov di,offset fcb
push es
push ds
pop es
mov al,0FH
mov ah,29H
int 21H
pop es
endm
; Function Request 2AH
GET_DATE macro
mov ah,2AH
int 21H
endm
; Function Request 2BH
SET_DATE macro year,month,day
mov cx,year
mov dh,month
mov dl,day
mov ah,2BH
int 21H
endm
; Function Request 2CH
GET_TIME macro
mov ah,2CH
int 21H
endm
; Function Request 2DH
SET_TIME macro hour,minutes,seconds,hundredths
mov ch,hour
mov cl,minutes
mov dh,seconds
mov dl,hundredths
mov ah,2DH
int 21H
endm
; Function Request 2EH
VERIFY macro switch
mov al,switch
mov ah,2EH
int 21H
endm
; Function Request 2FH
GET_DTA macro
mov ah,2FH
int 21H
endm
; Function Request 30H
GET_VERSION macro
mov ah,30H
int 21H
endm
; Function Request 31H
KEEP_PROCESS macro return_code,last_byte
mov al,return_code
mov dx,offset last_byte
mov cl,4
shr dx,cl
inc dx
mov ah,31H
int 21H
endm
; Function Request 33H
CTRL_C_CK macro action,state
mov al,action
mov dl,state
mov ah,33H
int 21H
endm
; Function Request 35H
GET_VECTOR macro interrupt
mov al,interrupt
mov ah,35H
int 21H
endm
; Function Request 36H
GET_DISK_SPACE macro drive
mov dl,drive
mov ah,36H
int 21H
endm
; Function Request 38H
GET_COUNTRY macro country,buffer
local gc_01
mov dx,offset buffer
mov ax,country
cmp ax,0FFH
jl gc_01
mov al,0ffh
mov bx,country
gc_01: mov ah,38H
int 21H
endm
; Function Request 38H
SET_COUNTRY macro country
local sc_01
mov dx,0FFFFH
mov ax,country
cmp ax,0FFH
jl sc_01
mov al,0ffh
mov bx,country
sc_01: mov ah,38H
int 21H
endm
; Function Request 39H
MAKE_DIR macro path
mov dx,offset path
mov ah,39H
int 21H
endm
; Function Request 3AH
REM_DIR macro path
mov dx,offset path
mov ah,3AH
int 21H
endm
; Function Request 3BH
CHANGE_DIR macro path
mov dx,offset path
mov ah,3BH
int 21H
endm
; Function Request 3CH
CREATE_HANDLE macro path,attrib
mov dx,offset path
mov cx,attrib
mov ah,3CH
int 21H
endm
; Function Request 3DH
OPEN_HANDLE macro path,access
mov dx,offset path
mov al,access
mov ah,3DH
int 21H
endm
; Function Request 3EH
CLOSE_HANDLE macro handle
mov bx,handle
mov ah,3EH
int 21H
endm
; Function Request 3FH
READ_HANDLE macro handle,buffer,bytes
mov bx,handle
mov dx,offset buffer
mov cx,bytes
mov ah,3FH
int 21H
endm
; Function Request 40H
WRITE_HANDLE macro handle,buffer,bytes
mov bx,handle
mov dx,offset buffer
mov cx,bytes
mov ah,40H
int 21H
endm
; Function Request 41H
DELETE_ENTRY macro path
mov dx,offset path
mov ah,41H
int 21H
endm
; Function Request 42H
MOVE_PTR macro handle,high,low,method
mov bx,handle
mov cx,high
mov dx,low
mov al,method
mov ah,42H
int 21H
endm
; Function Request 43H
CHANGE_MODE macro path,action,attrib
mov dx,offset path
mov al,action
mov cx,attrib
mov ah,43H
int 21H
endm
; Function Request 4400H,01H
IOCTL_DATA macro code,handle
mov bx,handle
mov al,code
mov ah,44H
int 21H
endm
; Function Request 4402H,03H
IOCTL_CHAR macro code,handle,buffer
mov bx,handle
mov dx,offset buffer
mov al,code
mov ah,44H
int 21H
endm
; Function Request 4404H,05H
IOCTL_STATUS macro code,drive,buffer
mov bl,drive
mov dx,offset buffer
mov al,code
mov ah,44H
int 21H
endm
; Function Request 4406H,07H
IOCTL_STATUS macro code,handle
mov bx,handle
mov al,code
mov ah,44H
int 21H
endm
; Function Request 4408H
IOCTL_CHANGE macro drive
mov bl,drive
mov al,08H
mov ah,44H
int 21H
endm
; Function Request 4409H
IOCTL_RBLOCK macro drive
mov bl,drive
mov al,09H
mov ah,44H
int 21H
endm
; Function Request 440AH
IOCTL_RHANDLE macro handle
mov bx,handle
mov al,0AH
mov ah,44H
int 21H
endm
; Function Request 440BH
IOCTL_RETRY macro retries,wait
mov dx,retries
mov cx,wait
mov al,0BH
mov ah,44H
int 21H
endm
; Function Request 440CH
GENERIC_IOCTL_HANDLES macro handle,function,category,buffer
mov ch,05H
mov cl,function
mov dx,offset buffer
mov bx,handle
mov ah,44H
mov al,0CH
int 21H
endm
; Function Request 440DH
GENERIC_IOCTL_BLOCK macro drive_num,function,category,parm_blk
mov ch,08H
mov cl,function
mov dx,offset parm_blk - 1
mov bx,drive_num
mov ah,44H
mov al,0DH
int 21H
endm
; Function Request 440EH
IOCTL_GET_DRIVE_MAP macro logical_drv
mov bx,logical_drv
mov ah,44H
mov al,0EH
int 21H
endm
; Function Request 440FH
IOCTL_SET_DRIVE_MAP macro logical_drv
mov bx,logical_drv
mov ah,44H
mov al,0FH
int 21H
endm
; Function Request 45H
XDUP macro handle
mov bx,handle
mov ah,45H
int 21H
endm
; Function Request 46H
XDUP2 macro handle1,handle2
mov bx,handle1
mov cx,handle2
mov ah,46H
int 21H
endm
; Function Request 47H
GET_DIR macro drive,buffer
mov dl,drive
mov si,offset buffer
mov ah,47H
int 21H
endm
; Function Request 48H
ALLOCATE_MEMORY macro bytes
mov bx,bytes
mov cl,4
shr bx,cl
inc bx
mov ah,48H
int 21H
endm
; Function Request 49H
FREE_MEMORY macro seg_addr
mov ax,seg_addr
mov es,ax
mov ah,49H
int 21H
endm
; Function Request 4AH
SET_BLOCK macro last_byte
mov bx,offset last_byte
mov cl,4
shr bx,cl
add bx,17
mov ah,4AH
int 21H
mov ax,bx
shl ax,cl
dec ax
mov sp,ax
mov bp,sp
endm
; Function Request 4B00H
EXEC macro path,command,parms
mov dx,offset path
mov bx,offset parms
mov word ptr parms[02h],offset command
mov word ptr parms[04h],cs
mov word ptr parms[06h],5ch
mov word ptr parms[08h],es
mov word ptr parms[0ah],6ch
mov word ptr parms[0ch],es
mov al,0
mov ah,4BH
int 21H
endm
; Function Request 4B03H
EXEC_OVL macro path,parms,seg_addr
mov dx,offset path
mov bx,offset parms
mov parms,seg_addr
mov parms[02H],seg_addr
mov al,3
mov ah,4BH
int 21H
endm
; Function Request 4CH
END_PROCESS macro return_code
mov al,return_code
mov ah,4CH
int 21H
endm
; Function Request 4DH
RET_CODE macro
mov ah,4DH
int 21H
endm
; Function Request 4EH
FIND_FIRST_FILE macro path,attrib
mov dx,offset path
mov cx,attrib
mov ah,4EH
int 21H
endm
; Function Request 4FH
FIND_NEXT_FILE macro
mov ah,4FH
int 21H
endm
; Function Request 54H
GET_VERIFY macro
mov ah,54H
int 21H
endm
; Function Request 56H
RENAME_FILE macro old_path,new_path
mov dx,offset old_path
push ds
pop es
mov di,offset new_path
mov ah,56H
int 21H
endm
; Function Request 57H
GET_SET_DATE_TIME macro handle,action,time,date
mov bx,handle
mov al,action
mov cx,word ptr time
mov dx,word ptr date
mov ah,57H
int 21H
endm
; Function Request 58H
ALLOC_STRAT macro code,strategy
mov bx,strategy
mov al,code
mov ah,58H
int 21H
endm
; Function Request 59H
GET_ERROR macro
mov ah,59
int 21H
endm
; Function Request 5AH
CREATE_TEMP macro pathname,attrib
mov cx,attrib
mov dx,offset pathname
mov ah,5AH
int 21H
endm
; Function Request 5BH
CREATE_NEW macro pathname,attrib
mov cx,attrib
mov dx,offset pathname
mov ah,5BH
int 21H
endm
; Function Request 5C00H
LOCK macro handle,start,bytes
mov bx,handle
mov cx,word ptr start
mov dx,word ptr start+2
mov si,word ptr bytes
mov di,word ptr bytes+2
mov al,0
mov ah,5CH
int 21H
endm
; Function Request 5C01H
UNLOCK macro handle,start,bytes
mov bx,handle
mov cx,word ptr start
mov dx,word ptr start+2
mov si,word ptr bytes
mov di,word ptr bytes+2
mov al,1
mov ah,5CH
int 21H
endm
; Function Request 5E00H
GET_MACHINE_NAME macro buffer
mov dx,offset buffer
mov al,0
mov ah,5EH
int 21H
endm
; Function Request 5E02H
PRINTER_SETUP macro index,lgth,string
mov bx,index
mov cx,lgth
mov dx,offset string
mov al,2
mov ah,5EH
int 21H
endm
; Function Request 5F02H
GET_LIST macro index,local,remote
mov bx,index
mov si,offset local
mov di,offset remote
mov al,2
mov ah,5FH
int 21H
endm
; Function Request 5F03H
REDIR macro device,value,source,destination
mov bl,device
mov cx,value
mov si,offset source
mov es,seg destination
mov di,offset destination
mov al,03H
mov ah,5FH
int 21H
endm
; Function Request 5F04H
CANCEL_REDIR macro local
mov si,offset local
mov al,4
mov ah,5FH
int 21H
endm
; Function Request 62H
GET_PSP macro
mov ah,62H
int 21H
endm
;
;
;*******************
; General
;*******************
;
DISPLAY_ASCIIZ macro asciiz_string
local search,found_it
mov bx,offset asciiz_string
search:
cmp byte ptr [bx],0
je found_it
inc bx
jmp short search
found_it:
mov byte ptr [bx],"$"
display asciiz_string
mov byte ptr [bx],0
display_char 0DH
display_char 0AH
endm
;
MOVE_STRING macro source,destination,count
push es
push ds
pop es
assume es:code
mov si,offset source
mov di,offset destination
mov cx,count
rep movs es:destination,source
assume es:nothing
pop es
endm
;
CONVERT macro value,base,destination
local table,start
jmp start
table db "0123456789ABCDEF"
start:
push ax
push bx
push dx
mov al,value
xor ah,ah
xor bx,bx
div base
mov bl,al
mov al,cs:table[bx]
mov destination,al
mov bl,ah
mov al,cs:table[bx]
mov destination[1],al
pop dx
pop bx
pop ax
endm
;
CONVERT_TO_BINARY macro string,number,value
local ten,start,calc,mult,no_mult
jmp start
ten db 10
start:
mov value,0
xor cx,cx
mov cl,number
xor si,si
calc:
xor ax,ax
mov al,string[si]
sub al,48
cmp cx,2
jl no_mult
push cx
dec cx
mult:
mul cs:ten
loop mult
pop cx
no_mult:
add value,ax
inc si
loop calc
endm
;
CONVERT_DATE macro dir_entry
mov dx,word ptr dir_entry[24]
mov cl,5
shr dl,cl
mov dh,dir_entry[24]
and dh,1FH
xor cx,cx
mov cl,dir_entry[25]
shr cl,1
add cx,1980
endm
;
PACK_DATE macro date
local set_bit
;
; On entry: DH=day, DL=month, CX=(year-1980)
;
sub cx,1980
push cx
mov date,dh
mov cl,5
shl dl,cl
pop cx
jnc set_bit
or cl,80h
set_bit:
or date,dl
rol cl,1
mov date[1],cl
endm
;
Chapter 2 MS-DOS Device Drivers
───────────────────────────────────────────────────────────────────────────
2.1 Introduction
2.2 Format of a Device Driver
2.3 How to Create a Device Driver
2.3.1 Device Strategy Routine
2.3.2 Device Interrupt Routine
2.4 Installing Device Drivers
2.5 Device Headers
2.5.1 Pointer to Next Device Field
2.5.2 Attribute Field
2.5.3 Strategy and Interrupt Routines
2.5.4 Name Field
2.6 Request Header
2.6.1 Length of Record
2.6.2 Unit Code Field
2.6.3 Command Code Field
2.6.4 Status Field
2.7 Device Driver Functions
2.7.1 The Init Function
2.7.2 The Media Check Function
2.7.3 The Build BPB Function
2.7.4 The Read or Write Function
2.7.5 The Non-destructive Read, No Wait Function
2.7.6 The Open or Close Function
2.7.7 The Removable Media Function
2.7.8 The Status Function
2.7.9 The Flush Function
2.7.10 The Generic IOCtl Function
2.7.11 The Get/Set Logical Drive Map Function
2.8 The Media Descriptor Byte
2.9 Format of a Media Descriptor Table
2.10 The CLOCK Device
2.11 Anatomy of a Device Call
2.12 Two Sample Device Drivers
2.1 Introduction
The io.sys file comprises the "resident" device drivers, which form the
MS-DOS BIOS. These drivers are called upon by MS-DOS to handle input/output
(I/O) requests initiated by application programs.
One of the most powerful features of MS-DOS is the ability to add new
devices such as printers, plotters, and mouse input devices without
rewriting the BIOS. The MS-DOS BIOS is configurable; that is, new drivers
can be added and existing drivers can be preempted. Nonresident, or
installable, device drivers may be easily added at boot time by including
a device command line in the config.sys file.
At boot time, a minimum of five resident device drivers must be present.
These drivers are in a linked list: the header of each one contains a DWORD
pointer to the next. The last driver in the chain has an end-of-list marker
of -1, -1 (all bits on).
Each driver in the chain has two entry points: the strategy entry point
and the interrupt entry point. MS-DOS does not take advantage of the two
entry points: it calls the strategy routine, then immediately calls the
interrupt routine.
The dual entry points will accomodate future multitasking versions of
MS-DOS and MS OS/2 operating systems. In multitasking environments,
I/O must be asynchronous; to accomplish this, the strategy routine will be
called to (internally) queue a request and return quickly. It is then the
responsibility of the interrupt routine to perform the I/O at interrupt
time by getting requests from the internal queue and processing them. When
a request is completed, it is flagged as "done" by the interrupt routine.
MS-DOS periodically scans the list of requests looking for those that are
flagged as done, and "wakes up" the process waiting for the completion
of the request.
When requests are queued in this manner, it is no longer sufficient to
pass I/O information in registers, since many requests may be pending at
any time. Therefore, the MS-DOS device interface uses "packets" to pass
request information. These request packets are of variable size and
format, and are composed of two parts:
1. The static request header section, which has the same format for
all requests
2. A section which has information specific to the type of request
A driver is called with a pointer to a packet. In multitasking versions,
this packet will be linked into a global chain of all pending I/O requests
maintained by MS-DOS.
MS-DOS does not implement a global or local queue. Only one request is
pending at any one time. The strategy routine must store the address of
the packet at a fixed location, and the interrupt routine, which is called
immediately after the strategy routine, should process the packet by
completing the request and returning. It is assumed that the request
is completed when the interrupt routine returns.
To make a device driver that sysinit can install, a .bin (core
image) or .exe format file must be created with the device driver header
at the beginning of the file. The link field should be initialized to -1
(sysinit fills it in). Device drivers which are part of the BIOS should
have their headers point to the next device in the list and the last header
should be initialized to -1,-1. The BIOS must be a .bin (core image)
format file.
The .exe format installable device drivers may be used in non-IBM
versions of MS-DOS. On the IBM Personal Computer, the .exe loader is
located in command.com which is not present at the time that installable
devices are being loaded.
2.2 Format of a Device Driver
A device driver is a program segment responsible for communication between
DOS and the system hardware. It has a special header at the beginning
identifying it as a device driver, defining entry points, and describing
various attributes of the device.
───────────────────────────────────────────────────────────────────────────
Note
For device drivers, the file must not use the ORG 100H (like .com files).
Because it does not use the Program Segment Prefix (PSP), the device
driver is simply loaded; therefore, the file must have an origin of zero
(ORG 0 or no ORG statement).
───────────────────────────────────────────────────────────────────────────
There are two kinds of device drivers:
■ Character device drivers
■ Block device drivers
Character devices perform serial character I/O. Examples are the console,
communications port and printer. These devices are named (i.e., CON, AUX,
CLOCK, etc.), and programs may open channels (handles or file control
blocks) to do I/O to them.
Block devices include all the disk drives on the system. They can perform
random I/O in structured pieces called blocks (usually the physical sector
size). These devices are not named as the character devices are, and
therefore cannot be opened directly. Instead they have unit numbers and
are identified by drive letters such as A, B, and C.
A single block device driver may be responsible for one or more logically
contiguous disk drives. For example, block device driver ALPHA may be
responsible for drives A, B, C, and D. This means that it has four units
defined (0-3), and therefore, takes up four drive letters. The position of
the driver in the list of all drivers determines which units correspond to
which driver letters. If driver ALPHA is the first block driver in the
device list, and it defines four 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. The theoretical limit is 63,
but it should be noted that the device installation code will not allow
the installation of a device if it would result in a drive letter greater
than Z (5AH). All block device drivers present in the standard resident
BIOS will be placed ahead of installable block device drivers in the list.
───────────────────────────────────────────────────────────────────────────
Note
Because they have only one name, character devices cannot define
multiple units.
───────────────────────────────────────────────────────────────────────────
2.3 How to Create a Device Driver
To create a device driver that MS-DOS can install, you must create a
binary file (.com or .exe format) with a device header at the beginning of
the file. Note that for device drivers, the code should not be originated
at 100H, but at 0. The device header contains a link field (a pointer to
the next device header) which should be -1, unless there is more than one
device driver in the file. The attribute field and entry points must be
set correctly.
If it is a character device, the name field should be filled in with
the name of that character device. The name can be any legal eight-
character filename. If the name is less than eight characters, it should
be padded out to eight characters with spaces (20H). Note that device
names do not include colons (:). The fact that CON is the same as CON: is a
property of the default MS-DOS command interpreter (command.com) and not of
the device driver or the MS-DOS interface. All character device names are
handled in this way.
MS-DOS always processes installable device drivers before handling the
default devices, so to install a new CON device, simply name the device
CON. Remember to set the standard input device and standard output device
bits in the attribute word on a new CON device. The scan of the device
list stops on the first match, so the installable device driver takes
precedence.
It is not possible to replace the resident disk block device driver
with an installable device driver the same way you can replace the other
device drivers in the BIOS. Block drivers can be used only for devices
not directly supported by the default disk drivers in the io.sys file.
───────────────────────────────────────────────────────────────────────────
Note
Because MS-DOS can install the driver anywhere in memory, care must be
taken when making far memory references. You should not expect that your
driver will always be loaded in the same place every time.
───────────────────────────────────────────────────────────────────────────
2.3.1 Device Strategy Routine
The device strategy routine, which is called by MS-DOS for each device
driver service request, is primarily responsible for queuing these requests
in the order in which they are to be processed by the device interrupt
routine. Such queuing can be a very important performance feature in a
multitasking environment, or where asynchronous I/O is supported. As MS-DOS
does not currently support these facilities, only one request can be
serviced at a time, and this routine is usually very short. In the coding
examples in Section 2.12, "Two Sample Device Drivers," each request is
simply stored in a single pointer area.
2.3.2 Device Interrupt Routine
The device interrupt routine contains the code necessary to process
the service request. It may interface to the hardware, or it may use
ROM BIOS calls. It usually consists of a series of procedures that handle
the specific command codes to be supported as well as some exit and error-
handling routines. See the coding examples in Section 2.12, "Two Sample
Device Drivers."
2.4 Installing Device Drivers
MS-DOS allows new device drivers to be installed dynamically at boot
time. This is accomplished by initialization code in the io.sys file
that reads and processes the config.sys file.
MS-DOS calls upon the device drivers to perform their function in the
following manner:
1. MS-DOS makes a FAR call to the strategy entry.
2. MS-DOS passes device driver information in a request header to the
strategy routine.
3. MS-DOS makes a FAR call to the interrupt entry.
This calling structure is designed to be easily upgraded to support
any future multitasking environment.
2.5 Device Headers
A device header is required at the beginning of a device driver. A device
header looks like this:
+--------------------------------------+
| DWORD Pointer to next device |
| (Usually set to -1 if this driver |
| is the last or only driver in the |
| file) |
+--------------------------------------+
| WORD Attributes |
+--------------------------------------+
| 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. |
+--------------------------------------+
Figure 2.1 Sample Device Header
Note that the device entry points are words. They must be offsets from the
same segment number used to point to this table. For example, if xxx:yyy
points to the start of this table, then xxx:strategy and xxx:interrupt are
the entry points.
The device header fields are described in the following section.
2.5.1 Pointer to Next Device Field
The pointer to the next device header field is a double-word field
(offset followed by segment) that is set by MS-DOS to point at the next
driver in the system list at the time the device driver is loaded. It is
important that this field be set to -1 prior to load (when it is on the
disk as a file) unless there is more than one device driver in the file.
If there is more than one driver in the file, the first word of the
double-word pointer should be the offset of the next driver's device
header.
───────────────────────────────────────────────────────────────────────────
Note
If there is more than one device driver in the file, the last driver in
the file must have the pointer to the next device header field set to -1.
───────────────────────────────────────────────────────────────────────────
2.5.2 Attribute Field
The attribute field is used to identify the type of device for which
this driver is responsible. In addition to distinguishing between block
and character devices, these bits are used to give selected character
devices special treatment. (Note that if a bit in the attribute word is
defined only for one type of device, a driver for the other type of device
must set that bit to 0.)
Table 2.1
For Character Devices:
╓┌───────────┌───────┌───────────────────────────────────────────────────────╖
Bit Value Meaning
──────────────────────────────────────────────────────────────────────
Bit Value Meaning
──────────────────────────────────────────────────────────────────────
0 1 Device is console input (sti) device
1 1 Device is console output (sto) device
2 1 Device is nul device
3 1 Device is clock device
4-5 Reserved (must be 0)
6 1 Device supports 3.2 functions
7-10 Reserved (must be 0)
11 1 Device understands Open/Close
12 Reserved (must be 0)
13 1 Device supports Output Until Busy (OUB)
14 1 Device supports IOCtl control strings
15 1 Character device
Table 2.2
For Block Devices:
╓┌───────────┌───────┌───────────────────────────────────────────────────────╖
Bit Value Meaning
──────────────────────────────────────────────────────────────────────
Bit Value Meaning
──────────────────────────────────────────────────────────────────────
0-5 Reserved (must be 0)
6 1 Device supports 3.2 functions and Generic IOCtl
function calls
7-10 Reserved (must be 0)
11 1 Device understands Open/Close/Removable Media
12 Reserved (must be 0)
13 1 Device determines the media by examining the FATID byte
14 1 Device supports IOCtl control strings
15 0 Block device
For example, assume that you have a new device driver that you want to use
as the standard input and output. In addition to installing the driver,
you must tell MS-DOS that you want the new driver to override the current
standard input and standard output (the CON device). This is accomplished
by setting the attributes to the desired characteristics, so you 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. (Refer to Section
2.10, "The Clock Device," in this chapter for more information.)
Although there is a NUL device attribute, the NUL device cannot be
reassigned. This attribute exists so that MS-DOS can determine if the
NUL device is being used.
Bit 13 for block devices affects the operation of the Build BPB (BIOS
Parameter Block) device call. If set, it requires the first sector of the
FAT always to reside in the same place. This bit has a different meaning
on character devices. It indicates that the device implements the Output
Until Busy device call.
The IOCtl bit (bit 14) has meaning on character and block devices. The
IOCtl functions allow data to be sent and received by the device for
its own use (to set baud rate, stop bits, form length, 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 be treated as normal I/O. This bit tells MS-DOS whether
the device can handle control strings by using the IOCtl system call,
Function 44H.
If a driver cannot process control strings, it should initially set
this bit to 0. This tells MS-DOS to return an error if an attempt is made
(via Function 44H) to send or receive control strings to this device. A
device which can process control strings should initialize the IOCtl bit
to 1. For drivers of this type, MS-DOS will make calls to the IOCtl input
and output device functions to send and receive IOCtl strings.
The IOCtl functions allow data to be sent and received by the device
for its own use (for example, to set baud rate, stop bits, and form
length), instead of passing data over the device channel as does a normal
read or write. The interpretation of the passed information is up to the
device, but it must not be treated as a normal I/O request.
The Open/Close/Removable Media bit (bit 11) signals to MS-DOS 3.x
and later versions whether this driver supports additional MS-DOS 3.x
functionality. To support these old drivers, it is necessary to detect
them. This bit was reserved in MS-DOS 2.x, and is 0. All new devices
should support the Open, Close, and Removable Media calls and set this
bit to 1. Since MS-DOS 2.x never makes these calls, the driver will
be backward-compatible.
The MS-DOS 3.2 bit (bit 6) signals whether the device supports logical
drive mapping via Function 440EH (Get Logical Drive Map) and Function 440FH
(Set Logical Drive Map). This bit also supports generic IOCtl functions via
Function 440CH (Generic IOCtl for Handles) and Function 440DH (Generic
IOCtl for Block Devices).
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+---------------------------------------------------------------+
| C | I | | | O | | | | | 3 | | | C | N | S | S |
| H | O | | | P | | | | | . | | | L | U | T | T |
| R | C | | | N | | | | | 2 | | | K | L | O | I |
+---------------------------------------------------------------+
Figure 2.2 Attribute Word for Character Devices
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+---------------------------------------------------------------+
| | I | F | | O | | | | | 3 | | | | | | |
| | O | A | | P | | | | | . | | | | | | |
| | C | T | | N | | | | | 2 | | | | | | |
+---------------------------------------------------------------+
Figure 2.3 Attribute Word for Block Devices
2.5.3 Strategy and Interrupt Routines
These two fields are the pointers to the entry points of the strategy
and interrupt routines. They are word values, so they must be in the same
segment as the device header.
2.5.4 Name Field
This is an eight-byte field that contains the name of a character
device or the number of units of a block device. If the field refers
to a block device, the number of units can be put in the first byte. This
is optional, because MS-DOS will fill in this location with the value
returned by the driver's Init code. For more information, see Section 2.4,
"Installing Device Drivers."
2.6 Request Header
When MS-DOS calls a device driver to perform a function, it passes a
request header in ES:BX to the strategy entry point. This is a fixed
length header, followed by data pertinent to the operation being performed.
Note that it is the device driver's responsibility to preserve the machine
state (for example, save all registers, including flags, on entry, and
restore them on exit). There is enough room on the stack when the strategy
or interrupt routine is called to do about 20 pushes. If more room on the
stack is needed, the driver should set up its own stack.
The following figure illustrates a request header.
REQUEST HEADER ->
+-----------------------------+
| BYTE Length of record |
| Length in bytes of this |
| request header |
+-----------------------------+
| BYTE Unit code |
| The subunit the operation |
| is for (minor device) |
| (no meaning on character |
| devices) |
+-----------------------------+
| BYTE Command code |
+-----------------------------+
| WORD Status |
+-----------------------------+
| 8 BYTES Reserved |
| |
|-----------------------------|
Figure 2.4 Request Header
The request header fields are described below.
2.6.1 Length of Record
This field contains the length (in bytes) of the request header.
2.6.2 Unit Code Field
The unit code field identifies which unit in your device driver the
request is for. For example, if your device driver has three units defined,
then the possible values of the unit code field would be 0, 1, and 2.
2.6.3 Command Code Field
The command code field in the request header can have the following
values:
╓┌───────┌───────────────────────────────────────────────────────────────────╖
Code Function
──────────────────────────────────────────────────────────────────────────
0 Init
1 Media Check (Block devices only)
2 Build BPB (Block devices only)
3 IOCtl Input (Only called if device has IOCtl)
4 Input (Read)
5 Non-destructive Read, No Wait (Character devices only)
6 Input Status (Character devices only)
7 Input Flush (Character devices only)
8 Output (Write)
Code Function
8 Output (Write)
9 Output (Write) with Verify
10 Output Status (Character devices only)
11 Output Flush (Character devices only)
12 IOCtl Output (Only called if device has IOCtl)
13 Device Open (Only called if Open/Close/Removable Media bit set)
14 Device Close (Only called if Open/Close/Removable Media bit set)
15 Removable Media (Only called if Open/Close/Removable Media bit
set and device is block)
16 Output Until Busy (Only called if bit 13 is set on character
devices)
Code Function
19 Generic IOCtl Request
23 Get Logical Device
24 Set Logical Device
2.6.4 Status Field
The following figure illustrates the status field in the request header.
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 | | S | N | |
| | | Y | E | |
+---+---+--+--+--+--+---+---+--+--+--+--+--+--+--+--+
Figure 2.5 Status Field
The status word is zero on entry and is set by the driver interrupt routine
on return.
Bit 8 is the done bit. When set, it means the operation has
completed. The driver sets it to 1 when it exits.
Bit 15 is the error bit. If it is set, then the low eight bits
indicate the error. The errors are as follows:
Error Meaning
───────────────────────────────────────────────────────────────────────────
0 Write protect violation
1 Unknown unit
2 Drive not ready
3 Unknown command
4 CRC error
5 Bad drive request structure length
6 Seek error
7 Unknown media
8 Sector not found
9 Printer out of paper
A Write fault
B Read fault
C General failure
D Reserved
E Reserved
F Invalid disk change
Bit 9 is the busy bit, which is set only by Status calls and the
Removable Media call.
2.7 Device Driver Functions
Device drivers may perform all or some of these general functions. In some
cases, these functions break down into several command codes, for specific
cases. Each of the following general functions is described in this
section.
■ Init
■ Media Check
■ Build BPB
■ Read, or Write, or Write Until Busy, or Write with Verify,
or Read IOCtl, or Write IOCtl
■ Non-destructive Read, No Wait
■ Open or Close (3.x)
■ Removable Media (3.x)
■ Status
■ Flush
■ Generic IOCtl
■ Get or Set Logical Device
All strategy routines are called with ES:BX pointing to the request header.
The interrupt routines get the pointers to the request header from the
queue that the strategy routines store them in. The command code in the
request header tells the driver which function to perform and what data
follows the request header.
───────────────────────────────────────────────────────────────────────────
Note
All DWORD pointers are stored offset first, then segment.
───────────────────────────────────────────────────────────────────────────
2.7.1 The Init Function
Command code = 0
INIT - ES:BX ->
+------------------------------------+
| 13-BYTE Request header |
+------------------------------------+
| BYTE Number of units |
+------------------------------------+
| DWORD End Address |
+------------------------------------+
| DWORD Pointer to BPB array |
| (Not set by character devices) |
+------------------------------------+
| BYTE Block device number |
+------------------------------------+
One of the functions defined for each device driver is Init. This routine
is called only once when the device is installed. The Init routine must
return the end address, which is a DWORD pointer to the end of the portion
of the device driver to remain resident. To save space, you can use this
pointer method to delete initialization code that is needed only once.
The number of units, end address, and BPB pointer are to be set by the
driver. However, on entry for installable device drivers, the DWORD that
is to be set by the driver to the BPB array (on block devices) points to
the character after the "=" on the line in config.sys that caused this
device driver to be loaded. This allows drivers to scan the config.sys
invocation line for parameters that might be passed to the driver. This
line is terminated by a RETURN or a linefeed character. This data is
read-only and allows the device to scan the config.sys command line
for arguments.
device=\dev\vt52.sys /l
|
|_____BPB address points here
Also, for block devices only, the drive number assigned to the first unit
defined by this driver (A=0) as contained in the block device number field.
This is also read-only.
───────────────────────────────────────────────────────────────────────────
Note
The Init routine can issue only Functions 01H-0CH, 25H, 30H, and 35H.
───────────────────────────────────────────────────────────────────────────
For installable character devices, the end address parameter must be
returned. This is a pointer to the first available byte of memory above
the driver and may be used to throw away initialization code.
Block devices must return the following information:
1. The number of units must be returned. MS-DOS uses this number
to determine 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 the
position of the driver in the device list, and by the number of
units on the device (stored in the first byte of the device
name field).
2. A DWORD pointer to an array of word offsets (pointers) to BPBs
(BIOS Parameter Blocks) must be returned. The BPBs passed
by the device driver are used by MS-DOS to create an internal
structure. There must be one entry in this array for each unit
defined by the device driver. In this way, if all units are the
same, all the pointers can point to the same BPB, saving space. If
the device driver defines two units, then the DWORD pointer points
to the first of two one-word offsets which in turn point to BPBs.
The format of the BPB is described later in this chapter in Section
2.7.3, "The Build BPB Function."
Note that this array of word offsets must be protected (below the
free pointer set by the return), since an internal DOS structure
will be built starting at the byte pointed to by the free pointer.
The defined sector size must be less than or equal to the maximum
sector size defined by the resident device drivers (BIOS) during
initialization. If it isn't, the installation will fail.
3. The last thing that the Init function of a block device must pass
back is the media descriptor byte. This byte means nothing to
MS-DOS, but is passed to devices so that they know what parameters
MS-DOS is currently using for a particular drive.
───────────────────────────────────────────────────────────────────────────
Note
If there are multiple device drivers in a single file, MS-DOS uses the
ending address returned by the last Init function called. All device
drivers in a single file should return the same ending address. All
devices in a single file should be grouped together low in memory with
the initialization code for all devices following it in memory.
───────────────────────────────────────────────────────────────────────────
2.7.2 The Media Check Function
Command Code = 1
MEDIA CHECK - ES:BX ->
+------------------------------------+
| 13-BYTE Request header |
+------------------------------------+
| BYTE Media descriptor from BPB |
+------------------------------------+
| BYTE Returned |
+------------------------------------+
| Returned DWORD pointer to previous |
| Volume ID if bit 11 set and |
| Disk Changed is returned |
+------------------------------------+
The Media Check function is used only with block devices. It is called
when there is a pending drive-access call other than a file read or write,
such as Open, Close, delete, and rename. Its purpose is to determine
whether the media in the drive has been changed. If the driver can assure
that the media has not been changed (through a door-lock or other interlock
mechanism), MS-DOS performance is enhanced, because MS-DOS does not need to
reread the FAT and invalidate in-memory buffers for each directory access.
When a disk-access call to the DOS occurs (other than a file read or
write), the following sequence of events takes place:
1. The DOS converts the drive letter into a unit number
of a particular block device.
2. The device driver is then called to request a media check on that
subunit to see if the disk might have been changed. MS-DOS passes
the old media descriptor byte. The driver returns one of the
following:
Return Meaning
───────────────────────────────────────────────────────────────────
(1) Media not changed
(0) Don't know if changed
(-1) Media changed
value Error (value is a standard error code value)
If the media has not been changed, MS-DOS proceeds with the
disk access.
If the value returned is -1, then if there are any disk sectors
that have been modified and not written back out to the disk for
this unit, MS-DOS assumes that the disk has not been changed and
proceeds. MS-DOS invalidates any other buffers for the unit and
does a Build BPB call (see Step 3, following).
If the media has been changed, MS-DOS invalidates all buffers
associated with this unit including buffers with modified data that
are waiting to be written, and requests a new BIOS Parameter Block
via the Build BPB call (see Step 3).
3. Once the BPB has been returned, MS-DOS corrects its internal
structure for the drive from the new BPB and proceeds with the
access after reading the directory and the FAT.
Note that the previous media ID byte is passed to the device driver.
If the old media ID byte is the same as the new one, the disk might have
been changed and a new disk may be in the drive; therefore, all FAT,
directory, and data sectors that are buffered in memory for the drive
are considered invalid.
If the driver has bit 11 of the device attribute word set to 1, and
the driver returns -1 (Media Changed) the driver must set the DWORD pointer
to the previous Volume ID field. If the DOS determines that "Media changed"
is an error based on the state of the DOS buffer cache, the DOS will
generate a 0FH error on behalf of the device. If the driver does not
implement volume ID support, but has bit 11 set, (it should set a static
pointer to the string "NO NAME" ,0.)
It is not possible for a user to change a disk in less than two
seconds. So when Media Check occurs within two seconds of a disk access,
the driver reports "Media not changed (1)." This improves performance
tremendously.
───────────────────────────────────────────────────────────────────────────
Note
If the media ID byte in the returned BPB is the same as the previous
media ID byte, MS-DOS will assume that the format of the disk is the same
(even though the disk may have been changed) and will skip the step of
updating its internal structure. Therefore, all BPBs must have unique
media bytes regardless of FAT ID bytes.
───────────────────────────────────────────────────────────────────────────
2.7.3 The Build BPB Function
Command code = 2
BUILD BPB - ES:BX ->
+------------------------------------+
| 13-BYTE Request header |
+------------------------------------+
| BYTE Media descriptor from BPB |
+------------------------------------+
| DWORD Transfer address |
| (Points to one sector worth of |
| scratch space or first sector |
| of FAT depending on the value |
| of Bit 13 in the device attribute |
| word.) |
+------------------------------------+
| DWORD Pointer to BPB |
+------------------------------------+
The Build BPB function is used with block devices only. As described in
the Media Check function, the Build BPB function will be called any time
that a preceding Media Check call indicates that the disk has been or might
have been changed. The device driver must return a pointer to a BPB. This
is different from the Init call where the device driver returns a pointer
to an array of word offsets to BPBs.
The Build BPB call gets a DWORD pointer to a one-sector buffer. The
contents of this buffer are determined by the non-FAT ID bit (bit 13)
in the attribute field. If the bit is zero, then the buffer contains the
first sector of the first FAT. The FAT ID byte is the first byte of this
buffer. In this case, the driver must not alter this buffer. Note that
the location of the FAT must be the same for all possible media because
this first FAT sector must be read before the actualBPB is returned.
If the non-FAT ID bit is set, the pointer points to one sector of scratch
space (which may be used for anything). For information on how to construct
the BPB, see Section 2.8, "The Media Descriptor Byte," and Section 2.9,
"Format of a Media Descriptor Table."
MS-DOS 3.x includes additional support for devices that have door-locks
or some other means of telling when a disk has been changed. There is a new
error that can be returned from the device driver (error 15). The error
means "the disk has been changed when it shouldn't have been," and the user
is prompted for the correct disk using a volume ID. The driver may generate
this error on read or write. The DOS may generate the error on Media Check
calls if the driver reports media changed, and there are buffers in the DOS
buffer cache that need to be flushed to the previous disk.
For drivers that support this error, the Build BPB function is a trigger
that causes a new volume ID to be read off the disk. This action indicates
that the disk has been legally changed. A volume ID is placed on a disk by
the format command, and is simply an entry in the root directory of the
disk that has the Volume ID attribute. It is stored by the driver as an
ASCIZ string.
The requirement that the driver return a volume ID does not exclude
some other volume identifier scheme as long as the scheme uses ASCIZ
strings. A NUL (nonexistent or unsupported) volume ID is by convention
the following string:
DB "NO NAME ",0
2.7.4 The Read or Write Function
Command codes = 3,4,8,9,12, and 16
READ OR WRITE (Including IOCtl) or
OUTPUT UNTIL BUSY - ES:BX ->
+------------------------------------+
| 13-BYTE Request header |
+------------------------------------+
| BYTE Media descriptor from BPB |
+------------------------------------+
| DWORD Transfer address |
+------------------------------------+
| WORD Byte/sector count |
+------------------------------------+
| WORD Starting sector number |
| (Ignored on character devices) |
+------------------------------------+
| Returned DWORD pointer to requested|
| Volume ID if error 0FH |
+------------------------------------+
Code Request
───────────────────────────────────────────────────────────────────────────
3 IOCtl read
4 Read (block or character device)
8 Write (block or character device)
9 Write with Verify
12 IOCtl Write
16 Output Until Busy (character device only)
The driver must perform the Read or Write call depending on which command
code is set. Block devices read or write sectors; character devices read or
write bytes.
When I/O completes, the device driver must set the status word and report
the number of sectors or bytes successfully transferred. This should be
done even if an error prevented the transfer from being completed. Setting
the error bit and error code alone is not sufficient.
In addition to setting the status word, the driver must set the sector
count to the actual number of sectors (or bytes) transferred. No error
check is performed on an IOCtl I/O call. The device driver must always
set the return byte/sector count to the actual number of bytes/sectors
successfully transferred.
If the verify switch is on, the device driver will be called with command
code 9 (Write with Verify). Your device driver will be responsible for
verifying the write.
If the driver returns error code 0FH (Invalid disk change), it must
return a DWORD pointer to an ASCIZ string (which is the correct volume ID).
Returning this error code triggers the DOS to prompt the user to re-insert
the disk. The device driver should have read the volume ID as a result of
the Build BPB function.
Drivers may maintain a reference count of open files on the disk
by monitoring the Open and Close functions. This allows the driver to
determine when to return error 0FH. If there are no open files (reference
count = 0), and the disk has been changed, the I/O is okay. If there are
open files, however, an 0FH error may exist.
The Output Until Busy call is a speed optimization on character devices
only for print spoolers. The device driver is expected to output all the
characters possible until the device returns busy. Under no circumstances
should the device driver block during this function. Note that it is not an
error for the device driver to return the number of bytes output as being
less than the number of bytes requested (or = 0).
The Output Until Busy call allows spooler programs to take advantage
of the "burst" behavior of most printers. Many printers have on-board
RAM buffers that typically hold a line or a fixed amount of characters.
These buffers fill up without the printer going busy, or going busy for
a short period (less than ten instructions) between characters. A line of
characters can be quickly output to the printer, after which the printer
is busy for a long time while the characters are being printed. This new
device call allows background spooling programs to use this burst behavior
efficiently. Rather than take the overhead of a device driver call for
each character, or risk getting stuck in the device driver outputting a
block of characters, this call allows a burst of characters to be output
without the device driver having to wait for the device to be ready.
The Following Applies to Block Device Drivers:
Under certain circumstances, the BIOS may be asked to perform a write
operation of 64K bytes, which seems to be a "wrap-around" of the transfer
address in the BIOS I/O packet. This request, which arises due to an
optimization added to the write code in MS-DOS, will manifest itself only
on user writes that are within a sector size of 64K bytes on files
"growing" past the current end-of-file (EOF) mark. It is allowable for
the BIOS to ignore the balance of the write that "wraps around" if it so
chooses. For example, a write of 10000H bytes worth of sectors with a
transfer address of xxx:1 could ignore the last two bytes. A user program
can never request an I/O of more than FFFFH bytes and cannot wrap around
(even to 0) in the transfer segment. Therefore, in this case, the last
two bytes can be ignored.
MS-DOS maintains two FATs. If the DOS has problems reading the first,
it automatically tries the second before reporting the error. The BIOS is
responsible for all retries.
Although the command.com handler does no automatic retries, there are
applications that have their own Interrupt 24H handlers that do automatic
retries on certain types of Interrupt 24H errors before reporting them.
2.7.5 The Non-destructive Read, No Wait Function
Command code = 5
NON-DESTRUCTIVE READ NO WAIT - ES:BX ->
+------------------------------------+
| 13-BYTE Request header |
+------------------------------------+
| BYTE Read from device |
+------------------------------------+
The Non-destructive Read, No Wait function allows MS-DOS to look ahead one
input character. The device sets the done bit in the status word.
If the character device returns busy bit = 0 (there are characters in
the 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"). If the character device returns busy bit = 1,
there are no characters in the buffer.
2.7.6 The Open or Close Function
Command codes = 13 and 14
OPEN or CLOSE - ES:BX ->
+------------------------------------+
| 13-BYTE Static request header |
+------------------------------------+
The Open and Close functions are called by MS-DOS 3.x only if the device
driver sets the Open/Close/Removable Media attribute bit in the device
header. They are designed to inform the device about current file activity
on the device. On block devices, they can be used to manage local
buffering. The device can keep a reference count. Every Open causes the
device to increment the count, every Close to decrement. When the count
goes to zero, it means there are no open files on the device, and the
device should flush any buffers that have been written to that may have
been used inside the device, because it is now "legal" for the user to
change the media on a removable media drive.
There are problems with this mechanism on block devices because programs
that use FCB calls can open files without closing them. It is therefore
advisable to reset the count to zero without flushing the buffers when the
answer to "Has the media been changed?" is yes, and the Build BPB call
is made to the device.
These calls are more useful on character devices. The Open call, for
instance, can be used to send a device initialization string. On a printer,
this could cause a string for setting font and page size characteristics to
be sent to the printer so that it would always be in a known state at the
start of an I/O stream. Using IOCtl to set these pre- and post- strings
provides a flexible mechanism of serial I/O device stream control. The
reference count mechanism can also be used to detect a simultaneous access
error. It may be desirable to disallow more than one Open on a device at
any given time. In this case, a second Open would result in an error.
Note that since all processes have access to stdin, stdout, stderr,
stdaux, and stdprn (handles 0,1,2,3,4), the CON, AUX, and PRN devices are
always open.
2.7.7 The Removable Media Function
Command code = 15
REMOVABLE MEDIA - ES:BX ->
+------------------------------------+
| 13-BYTE Static request header |
+------------------------------------+
The Removable Media function is called by MS-DOS 3.x only if the device
driver sets the Open/Close/Removable Media attribute bit in the device
header. This call is given only to block devices by a subfunction of the
IOCtl system call. It is sometimes desirable for a utility to know whether
it is dealing with a nonremovable media drive (such as a hard disk), or a
removable media drive (like a floppy). An example is the format command,
which prints different versions of some of the prompts.
The information is returned in the busy bit of the status word. If the
busy bit is 1, then the media is nonremovable. If the busy bit is 0,
then the media is removable. Note that the error bit is not checked.
It is assumed that this call always succeeds.
2.7.8 The Status Function
Command codes = 6 and 10
STATUS Calls ES:BX ->
+------------------------------------+
| 13-BYTE Request header |
+------------------------------------+
The Status function returns information to the DOS as to whether data is
waiting for input or output. All the driver must do is set the status word
and the busy bit as follows:
■ For output on character devices--if the driver sets bit 9 to 1 on
return, it informs the DOS that 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.
■ For input on character devices with a buffer--A return of 1 implies
that no characters are buffered and that a read request (if made)
would go to the physical device. If it is 0 on return, then there are
characters in the device buffer and a read would not be blocked. A
return of 0 implies that the user has typed something. MS-DOS assumes
that all character devices have an input type-ahead buffer.
Devices that do not have a type-ahead buffer should always return
busy = 0 so that the DOS will not "hang" waiting for something to get
into a nonexistent buffer.
2.7.9 The Flush Function
Command codes = 7 and 11
FLUSH Calls - ES:BX ->
+------------------------------------+
| 13-BYTE Request header |
+------------------------------------+
The Flush function tells the driver to flush (terminate) all pending
requests. This call is used to flush the input queue on character devices.
The device driver performs the flush function, sets the status word,
and returns.
2.7.10 The Generic IOCtl Function
Command code = 19
ES:BX ->
+------------------------------------+
| 13-BYTE Static request header |
+------------------------------------+
| BYTE Category (Major) code |
+------------------------------------+
| BYTE Function (Minor) code |
+------------------------------------+
| WORD (SI) Contents |
+------------------------------------+
| WORD (DI) Contents |
+------------------------------------+
| DWORD Pointer to data buffer |
+------------------------------------+
The Generic IOCtl function provides a generic, expandable IOCtl facility
that replaces and makes the Read IOCtl and Write IOCtl device driver
functions obsolete. The MS-DOS 2.0 IOCtl functions remain to support
existing uses of the IOCtl system call (Subfunctions 2, 3, 4, and 5),
but new device drivers should use this generic MS-DOS IOCtl facility.
The Generic IOCtl function contains both a category and function code.
The DOS examines the category field in order to intercept and obey device
commands that are actually serviced by the DOS code; all other command
categories are forwarded to the device driver for servicing.
For more information on these category and function codes, refer to
Function 440CH (Generic IOCtl for Handles) and Function 440DH (Generic
IOCtl for Block Devices) in Chapter 1, "System Calls."
2.7.11 The Get/Set Logical Drive Map Function
Command codes = 23 (Get) or 24 (Set)
+----------------------------------------+
| 13-BYTE Static request header |
+----------------------------------------+
| BYTE Input (unit code) |
+----------------------------------------+
| BYTE Output (last device referenced)|
+----------------------------------------+
| BYTE Command code |
+----------------------------------------+
| WORD Status |
+----------------------------------------+
| DWORD Reserved |
+----------------------------------------+
The Get/Set Logical Drive Map function is called by MS-DOS only if the
device driver sets the DOS 3.2 attribute bit in the device header. The
call is issued only to block devices by the subfunction of the IOCtl system
call. The logical drive to be mapped is passed in the Unit field of the
header to the device driver. The device driver returns the current logical
drive owner of the physical device that maps to the requested physical
drive. To detect whether a logical device currently owns the physical
device to which it is mapped, a program needs to verify that, after a call
of Function 440EH or 440FH (Get/Set Logical Drive Map), the value of the
Unit field is unchanged.
2.8 The Media Descriptor Byte
In MS-DOS, the media descriptor byte is used to inform the DOS that a
different type of media is present. The media descriptor byte can be any
value between 0 and FFH. It does not have to be the same as the FAT ID
byte. The FAT ID byte, which is the first byte of the FAT, was used in
MS-DOS 1.00 to distinguish between different types of disk media, and may
be used as well under 2.x and 3.x disk device drivers. However, FAT ID
bytes have significance only for block device drivers where the
non-FAT ID bit is not set (0).
Values of the media descriptor byte or the FAT ID byte have no
significance to MS-DOS. They are passed to the device driver so that
programs can determine the media type.
2.9 Format of a Media Descriptor Table
The MS-DOS file system uses a linked list of pointers (one for each cluster
or allocation unit) called the File Allocation Table (FAT). Unused clusters
are represented by zero and end-of-file by FFFH (or FFFFH on units with
16-bit FAT entries). No valid entry should ever point to a zero entry, but
if one does, the first FAT entry (which would be pointed to by a zero
entry) was reserved and set to end of chain. Eventually, several end of
chain values were defined ([F]FF8-[F]FFFH), and these were used to
distinguish different types of media.
A preferable technique is to write a complete media descriptor table
in the boot sector and use it for media identification. To ensure backward
compatibility for systems whose drivers do not set the non-FAT ID bit
(including the IBM PC implementation), it is necessary also to write the
FAT ID bytes during the format process.
To allow more flexibility for supporting many different disk formats
in the future, it is recommended that the information relating to the BPB
for a particular piece of media be kept in the boot sector. Figure 2.6
shows the format of such a boot sector.
+------------------------------------+
| 3 BYTE Near JUMP to boot code |
+------------------------------------+
| 8 BYTES OEM name and version |
---+------------------------------------+---
B | WORD Bytes per sector |
+------------------------------------+
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 |
+------------------------------------+
| WORD High order number of hidden |
| sectors |
+------------------------------------+
| DWORD Number of logical sectors |
+------------------------------------+
Figure 2.6 Format of a Boot Sector
Although MS-DOS does not use the five fields that follow the BPB, these
fields may be used by a device driver to help it understand the media.
The "Sectors per track" and "Number of heads" fields are useful for
supporting different media which may have the same logical layout, but a
different physical layout (for example, 40-track, double-sided versus
80-track, single-sided). "Sectors per track" tells the device driver how
the logical disk format is laid out on the physical disk.
The "Number of hidden sectors" and "High order number of hidden sectors"
fields may be used to support drive-partitioning schemes.
The "Number of logical sectors" field is not currently used, but will
tell the device driver how many sectors to reserve if the "Number of
sectors in logical image" field is zero. (Note that this is intended
for supporting devices that access more than 32 megabytes.)
The following procedure is recommended for media determination by
NON FAT ID format drivers:
1. Read the boot sector of the drive into the one-sector scratch
space pointed to by the DWORD transfer address.
2. Determine if the first byte of the boot sector is an E9H or EBIT
(the first byte of a 3-byte NEAR or 2-byte SHORT jump) or an EBH
(the first byte of a 2-byte jump followed by an NOP). If so, a BPB
is located beginning at offset 3. Return a pointer to it.
3. If the boot sector does not have a BPB table, it is probably a disk
formatted under a 1.x version of MS-DOS and probably uses a FAT ID
byte for determining media.
The driver may optionally attempt to read the first sector of the
FAT into the one-sector scratch area and read the first byte to
determine media type based upon whatever FAT ID bytes may have been
used on disks that are expected to be read by this system. Return
a pointer to a hard-coded BPB.
2.10 The CLOCK Device
MS-DOS assumes that some sort of clock is available in the system.
This may either be a CMOS real-time clock or an interval timer that
is initialized at boot time by the user. The CLOCK device defines and
performs functions like any other character device, except that it is
identified by a bit in the attribute word. The DOS uses this bit to
identify it; consequently, the CLOCK device may take any name. The IBM
implementation uses the name $CLOCK so as not to conflict with existing
files named clock.
The CLOCK device is unique in that MS-DOS will read or write a 6-byte
sequence that encodes the date and time. A write to this device will set
the date and time; a read will get the date and time.
Figure 2.7 illustrates the binary time format used by the CLOCK device:
byte 0 byte 1 byte 2 byte 3 byte 4 byte 5
+--------+--------+---------+--------+--------+---------+
| | | | | | |
|days since 1-1-80| minutes | hours | sec/100| seconds |
|low byte|hi byte | | | | |
+--------+--------+---------+--------+--------+---------+
Figure 2.7 Format of a Clock Device
2.11 Anatomy of a Device Call
The following steps illustrate what happens when MS-DOS calls on a block
device driver to perform a Write request:
1. MS-DOS writes a request packet in a reserved area of memory.
2. MS-DOS calls the strategy entry point of the block device driver.
3. The device driver saves the ES and BX registers (ES:BX points
to the request packet) and does a FAR return.
4. MS-DOS calls the interrupt entry point.
5. The device driver retrieves the pointer to the request packet and
reads the command code (offset 2) to determine that this is a Write
request. The device driver converts the command code to an index
into a dispatch table and control passes to the Write routine.
6. The device driver reads the unit code (offset 1) to determine which
disk drive it is supposed to write to.
7. Since the command is a disk Write, the device driver must get the
transfer address (offset 14), the sector count (offset 18), and
the start sector (offset 20) in the request packet.
8. The device driver translates the first logical sector number into
a track, head, and sector number.
9. The device driver writes the specified number of sectors, starting
at the beginning sector on the drive defined by the unit code (the
subunit defined by this device driver), and transfers data from
the transfer address indicated in the request packet. Note that
this may involve multiple Write commands to the disk controller.
10. After the transfer is complete, the device driver must report
the status of the request to MS-DOS by setting the done bit in the
status word (offset 3 in the request packet). It reports the number
of sectors actually transferred in the sector count area of the
request packet.
11. If an error occurs, the driver sets the done bit and the error
bit in the status word and fills in the error code in the lower
half of the status word. The number of sectors actually
transferred must be written in the request header. It is not
sufficient just to set the error bit of the status word.
12. The device driver does a FAR return to MS-DOS.
The device drivers should preserve the state of MS-DOS. This means
that all registers (including flags) should be preserved. The direction
flag and interrupt enable bits are critical. When the interrupt entry
point in the device driver is called, MS-DOS has room for about 40 to 50
bytes on its internal stack. Your device driver should switch to a local
stack if it uses extensive stack operations.
12.12 Two Sample Device Drivers
The following two examples illustrate a block device driver and a
character device driver program. These examples are provided as guides
for writing your own device drivers. However, since device drivers are
hardware-dependent, your device drivers will differ.
Block Device Driver
;********************* A Block Device *******************
Title 5.25-inch Disk Driver
;This driver is intended to drive up to four 5.25-inch
;drives hooked to a single disk controller. All standard
;IBM PC formats are supported.
FALSE EQU 0
TRUE EQU NOT FALSE
;The I/O port address of the disk controller
DISK EQU 0E0H
;DISK+0
; 1793 Command/Status
;DISK+1
; 1793 Track
;DISK+2
; 1793 Sector
;DISK+3
; 1793 Data
;DISK+4
; Aux Command/Status
;DISK+5
; Wait Sync
;Back side select bit
BACKBIT EQU 04H
;5 1/4" select bit
SMALBIT EQU 10H
;Double Density bit
DDBIT EQU 08H
;Done bit in status register
DONEBIT EQU 01H
;Use table below to select head step speed.
;Step times for 5" drives
;are double that shown in the table.
;
;Step value 1771 1793
;
; 0 6ms 3ms
; 1 6ms 6ms
; 2 10ms 10ms
; 3 20ms 15ms
;
STPSPD EQU 1
NUMERR EQU ERROUT-ERRIN
CR EQU 0DH
LF EQU 0AH
CODE SEGMENT
ASSUME CS:CODE,DS:NOTHING,ES:NOTHING,SS:NOTHING
;-----------------------------------------------------
;
; Device Header
;
DRVDEV LABEL WORD
DW -1,-1
DW 0000 ;IBM format-compatible, Block
DW STRATEGY
DW DRV$IN
DRVMAX DB 4
DRVTBL LABEL WORD
DW DRV$INIT
DW MEDIA$CHK
DW GET$BPB
DW CMDERR
DW DRV$READ
DW EXIT
DW EXIT
DW EXIT
DW DRV$WRIT
DW DRV$WRIT
DW EXIT
DW EXIT
DW EXIT
;------------------------------------
;
; Strategy
PTRSAV DD 0
STRATP PROC FAR
STRATEGY:
MOV WORD PTR [PTRSAV],BX
MOV WORD PTR [PTRSAV+2],ES
RET
STRATP ENDP
;--------------------------------------
;
; Main Entry
CMDLEN = 0 ;Length of this command
UNIT = 1 ;Subunit specified
CMDC = 2 ;Command Code
STATUS = 3 ;Status
MEDIA = 13 ;Media Descriptor
TRANS = 14 ;Transfer Address
COUNT = 18 ;Count of blocks or characters
START = 20 ;First block to transfer
DRV$IN:
PUSH SI
PUSH AX
PUSH CX
PUSH DX
PUSH DI
PUSH BP
PUSH DS
PUSH ES
PUSH BX
LDS BX,[PTRSAV] ;Get pointer to I/O packet
MOV AL,BYTE PTR [BX].UNIT ;AL = Unit Code
MOV AH,BYTE PTR [BX].MEDIA ;AH = Media Descrip
MOV CX,WORD PTR [BX].COUNT ;CX = Count
MOV DX,WORD PTR [BX].START ;DX = Start Sector
PUSH AX
MOV AL,BYTE PTR [BX].CMDC ;Command code
CMP AL,15
JA CMDERRP ;Bad command
CBW
SHL AX,1 ;2 times command =
;word table index
MOV SI,OFFSET DRVTBL
ADD SI,AX ;Index into table
POP AX ;Get back media
;and unit
LES DI,DWORD PTR [BX].TRANS ;ES:DI = Transfer
;Address
PUSH CS
POP DS
ASSUME DS:CODE
JMP WORD PTR [SI] ;GO DO COMMAND
;----------------------------------------------------------
;
; EXIT - All Routines return through this path
;
ASSUME DS:NOTHING
CMDERRP:
POP AX ;Clean stack
CMDERR:
MOV AL,3 ;Unknown command error
JMP SHORT ERR$EXIT
ERR$CNT:LDS BX,[PTRSAV]
SUB WORD PTR [BX].COUNT,CX ;# OF SUCCESS. I/Os
ERR$EXIT:
;AL has error code
MOV AH,10000001B ;Mark error return
JMP SHORT ERR1
EXITP PROC FAR
EXIT: MOV AH,00000001B
ERR1: LDS BX,[PTRSAV]
MOV WORD PTR [BX].STATUS,AX
;Mark Operation
CompleteE
POP BX
POP ES
POP DS
POP BP
POP DI
POP DX
POP CX
POP AX
POP SI
RET ;Restore REGS and return
EXITP ENDP
CURDRV DB -1
TRKTAB DB -1,-1,-1,-1
SECCNT DW 0
DRVLIM = 8 ;Number of sectors on device
SECLIM = 13 ;Maximum Sector
HDLIM = 15 ;Maximum Head
;WARNING - preserve order of drive and curhd!
DRIVE DB 0 ;Physical Drive Code
CURHD DB 0 ;Current Head
CURSEC DB 0 ;Current Sector
CURTRK DW 0 ;Current Track
;
MEDIA$CHK: ;Always indicates Don't know
ASSUME DS:CODE
TEST AH,00000100B ;Test if Media Removable
JZ MEDIA$EXT
XOR DI,DI ;Say I Don't know
MEDIA$EXT:
LDS BX,[PTRSAV]
MOV WORD PTR [BX].TRANS,DI
JMP EXIT
BUILD$BPB:
ASSUME DS:CODE
MOV AH,BYTE PTR ES:[DI] ;Get FAT ID Byte
CALL BUILDBP ;Translate
SETBPB: LDS BX,[PTRSAV]
MOV [BX].MEDIA,AH
MOV [BX].COUNT,DI
MOV [BX].COUNT+2,CS
JMP EXIT
BUILDBP:
ASSUME DS:NOTHING
;AH is media byte on entry
;DI points to correct BPB on return
PUSH AX
PUSH CX
PUSH DX
PUSH BX
MOV CL,AH ;Save Media
AND CL,0F8H ;Normalize
CMP CL,0F8H ;Compare with Good Media Byte
JZ GOODID
MOV AH,0FEH ;Default to 8-sector,
;Single-sided
GOODID:
MOV AL,1 ;Set number of FAT sectors
MOV BX,64*256+8 ;Set Dir Entries and Sector Max
MOV CX,40*8 ;Set Size of Drive
MOV DX,01*256+1 ;Set Head Limit & Sec/All Unit
MOV DI,OFFSET DRVBPB
TEST AH,00000010B ;Test for 8 OR 9 Sectors
JNZ HAS8 ;NZ = has 8 sectors
INC AL ;Inc Number of FAT sectors
INC BL ;Inc Sector Max
ADD CX,40 ;Increase Size
HAS8: TEST AH,00000001B ;Test for 1 or 2 Heads
JZ HAS1 ;Z = 1 Head
ADD CX,CX ;Double Size of Disk
MOV BH,112 ;Increase # of Dir Entries
INC DH ;Inc Sec/All Unit
INC DL ;Inc Head Limit
HAS1: MOV BYTE PTR [DI].2,DH
MOV BYTE PTR [DI].6,BH
MOV WORD PTR [DI].8,CX
MOV BYTE PTR [DI].10,AH
MOV BYTE PTR [DI].11,AL
MOV BYTE PTR [DI].13,BL
MOV BYTE PTR [DI].15,DL
POP BX
POP DX
POP CX
POP AX
RET
;----------------------------------------------------------
;
; Disk I/O Handlers
;
;ENTRY:
; AL = Drive Number (0-3)
; AH = Media Descriptor
; CX = Sector Count
; DX = First Sector
; DS = CS
; ES:DI = Transfer Address
;EXIT:
; IF Successful Carry Flag = 0
; ELSE CF=1 AND AL contains (MS-DOS) Error Code,
CX # sectors NOT transferred
DRV$READ:
ASSUME DS:CODE
JCXZ DSKOK
CALL SETUP
JC DSK$IO
CALL DISKRD
JMP SHORT DSK$IO
DRV$WRIT:
ASSUME DS:CODE
JCXZ DSKOK
CALL SETUP
JC DSK$IO
CALL DISKWRT
ASSUME DS:NOTHING
DSK$IO: JNC DSKOK
JMP ERR$CNT
DSKOK: JMP EXIT
SETUP:
ASSUME DS:CODE
;Input same as above
;On output
; ES:DI = Trans addr
; DS:BX Points to BPB
; Carry set if error (AL is error code (MS-DOS))
; else
; [DRIVE] = Drive number (0-3)
; [SECCNT] = Sectors to transfer
; [CURSEC] = Sector number of start of I/O
; [CURHD] = Head number of start of I/O ;Set
; [CURTRK] = Track # of start of I/O ;Seek performed
; All other registers destroyed
XCHG BX,DI ;ES:BX = Transfer Address
CALL BUILDBP ;DS:DI = PTR to B.P.B
MOV SI,CX
ADD SI,DX
CMP SI,WORD PTR [DI].DRVLIM
;Compare Against Drive Max
JBE INRANGE
MOV AL,8
STC
RET
INRANGE:
MOV [DRIVE],AL
MOV [SECCNT],CX ;Save Sector Count
XCHG AX,DX ;Set Up Logical Sector
;For Divide
XOR DX,DX
DIV WORD PTR [DI].SECLIM ;Divide by Sec per Track
INC DL
MOV [CURSEC],DL ;Save Current Sector
MOV CX,WORD PTR [DI].HDLIM ;Get Number of Heads
XOR DX,DX ;Divide Tracks by Heads per Cylinder
DIV CX
MOV [CURHD],DL ;Save Current Head
MOV [CURTRK],AX ;Save Current Track
SEEK:
PUSH BX ;Xaddr
PUSH DI ;BPB pointer
CALL CHKNEW ;Unload head if change drives
CALL DRIVESEL
MOV BL,[DRIVE]
XOR BH,BH ;BX drive index
ADD BX,OFFSET TRKTAB ;Get current track
MOV AX,[CURTRK]
MOV DL,AL ;Save desired track
XCHG AL,DS:[BX] ;Make desired track current
OUT DISK+1,AL ;Tell Controller current track
CMP AL,DL ;At correct track?
JZ SEEKRET ;Done if yes
MOV BH,2 ;Seek retry count
CMP AL,-1 ;Position Known?
JNZ NOHOME ;If not home head
TRYSK:
CALL HOME
JC SEEKERR
NOHOME:
MOV AL,DL
OUT DISK+3,AL ;Desired track
MOV AL,1CH+STPSPD ;Seek
CALL DCOM
AND AL,98H ;Accept not rdy, seek, & CRC errors
JZ SEEKRET
JS SEEKERR ;No retries if not ready
DEC BH
JNZ TRYSK
SEEKERR:
MOV BL,[DRIVE]
XOR BH,BH ;BX drive index
ADD BX,OFFSET TRKTAB ;Get current track
MOV BYTE PTR DS:[BX],-1 ;Make current track
;unknown
CALL GETERRCD
MOV CX,[SECCNT] ;Nothing transferred
POP BX ;BPB pointer
POP DI ;Xaddr
RET
SEEKRET:
POP BX ;BPB pointer
POP DI ;Xaddr
CLC
RET
;---------------------------------------------
;
; Read
;
DISKRD:
ASSUME DS:CODE
MOV CX,[SECCNT]
RDLP:
CALL PRESET
PUSH BX
MOV BL,10 ;Retry count
MOV DX,DISK+3 ;Data port
RDAGN:
MOV AL,80H ;Read command
CLI ;Disable for 1793
OUT DISK,AL ;Output read command
MOV BP,DI ;Save address for retry
JMP SHORT RLOOPENTRY
RLOOP:
STOSB
RLOOPENTRY:
IN AL,DISK+5 ;Wait for DRQ or INTRQ
SHR AL,1
IN AL,DX ;Read data
JNC RLOOP
STI ;Ints OK now
CALL GETSTAT
AND AL,9CH
JZ RDPOP ;Ok
MOV DI,BP ;Get back transfer
DEC BL
JNZ RDAGN
CMP AL,10H ;Record not found?
JNZ GOT_CODE ;No
MOV AL,1 ;Map it
GOT_CODE:
CALL GETERRCD
POP BX
RET
RDPOP:
POP BX
LOOP RDLP
CLC
RET
;---------------------------------------------
;
; Write
;
DISKWRT:
ASSUME DS:CODE
MOV CX,[SECCNT]
MOV SI,DI
PUSH ES
POP DS
ASSUME DS:NOTHING
WRLP:
CALL PRESET
PUSH BX
MOV BL,10 ;Retry count
MOV DX,DISK+3 ;Data port
WRAGN:
MOV AL,0A0H ;Write command
CLI ;Disable for 1793
OUT DISK,AL ;Output write command
MOV BP,SI ;Save address for retry
WRLOOP:
IN AL,DISK+5
SHR AL,1
LODSB ;Get data
OUT DX,AL ;Write data
JNC WRLOOP
STI ;Ints OK now
DEC SI
CALL GETSTAT
AND AL,0FCH
JZ WRPOP ;Ok
MOV SI,BP ;Get back transfer
DEC BL
JNZ WRAGN
CALL GETERRCD
POP BX
RET
WRPOP:
POP BX
LOOP WRLP
CLC
RET
PRESET:
ASSUME DS:NOTHING
MOV AL,[CURSEC]
CMP AL,CS:[BX].SECLIM
JBE GOTSEC
MOV DH,[CURHD]
INC DH
CMP DH,CS:[BX].HDLIM
JB SETHEAD ;Select new head
CALL STEP ;Go on to next track
XOR DH,DH ;Select head zero
SETHEAD:
MOV [CURHD],DH
CALL DRIVESEL
MOV AL,1 ;First sector
MOV [CURSEC],AL ;Reset CURSEC
GOTSEC:
OUT DISK+2,AL ;Tell controller which sector
INC [CURSEC] ;We go on to next sector
RET
STEP:
ASSUME DS:NOTHING
MOV AL,58H+STPSPD ;Step in w/ update, no verify
CALL DCOM
PUSH BX
MOV BL,[DRIVE]
XOR BH,BH ;BX drive index
ADD BX,OFFSET TRKTAB ;Get current track
INC BYTE PTR CS:[BX] ;Next track
POP BX
RET
HOME:
ASSUME DS:NOTHING
MOV BL,3
TRYHOM:
MOV AL,0CH+STPSPD ;Restore with verify
CALL DCOM
AND AL,98H
JZ RET3
JS HOMERR ;No retries if not ready
PUSH AX ;Save real error code
MOV AL,58H+STPSPD ;Step in w/ update no verify
CALL DCOM
DEC BL
POP AX ;Get back real error code
JNZ TRYHOM
HOMERR:
STC
RET3: RET
CHKNEW:
ASSUME DS:NOTHING
MOV AL,[DRIVE] ;Get disk drive number
MOV AH,AL
XCHG AL,[CURDRV] ;Make new drive current.
CMP AL,AH ;Changing drives?
JZ RET1 ;No
; If changing drives, unload head so the head load delay
;one-shot will fire again. Do it by seeking to the same
;track with the H bit reset.
;
IN AL,DISK+1 ;Get current track number
OUT DISK+3,AL ;Make it the track to seek
MOV AL,10H ;Seek and unload head
DCOM:
ASSUME DS:NOTHING
OUT DISK,AL
PUSH AX
AAM ;Delay 10 microseconds
POP AX
GETSTAT:
IN AL,DISK+4
TEST AL,DONEBIT
JZ GETSTAT
IN AL,DISK
RET1: RET
DRIVESEL:
ASSUME DS:NOTHING
;Select the drive based on current info
;Only AL altered
MOV AL,[DRIVE]
OR AL,SMALBIT + DDBIT ;5 1/4" IBM PC disks
CMP [CURHD],0
JZ GOTHEAD
OR AL,BACKBIT ;Select side 1
GOTHEAD:
OUT DISK+4,AL ;Select drive and side
RET
GETERRCD:
ASSUME DS:NOTHING
PUSH CX
PUSH ES
PUSH DI
PUSH CS
POP ES ;Make ES the local segment
MOV CS:[LSTERR],AL ;Terminate list w/ error code
MOV CX,NUMERR ;Number of error conditions
MOV DI,OFFSET ERRIN ;Point to error conditions
RECRE SCASB
MOV AL,NUMERR-1[DI] ;Get translation
STC ;Flag error condition
POP DI
POP ES
POP CX
RET ;and return
;*********************************************************
; BPB for an IBM floppy disk, Various parameters are
; patched by BUILDBP to reflect the type of Media
; inserted
; This is a 9-sector, single-side BPB
DRVBPB:
DW 512 ;Physical sector size in bytes
DB 1 ;Sectors/allocation unit
DW 1 ;Reserved sectors for DOS
DB 2 ;# of allocation tables
DW 64 ;Number directory entries
DW 9*40 ;Number 512-byte sectors
DB 11111100B ;Media descriptor
DW 2 ;Number of FAT sectors
DW 9 ;Sector limit
DW 1 ;Head limit
INITAB DW DRVBPB ;Up to four units
DW DRVBPB
DW DRVBPB
DW DRVBPB
ERRIN: ;Disk errors returned from the controller
DB 80H ;No response
DB 40H ;Write protect
DB 20H ;Write Fault
DB 10H ;SEEK error
DB 8 ;CRC error
DB 1 ;Mapped from 10H
;(record not found) on Read
LSTERR DB 0 ;All other errors
ERROUT: ;Returned error codes corresponding to above
DB 2 ;No response
DB 0 ;Write Attempt
;On Write-protected disk
DB 0AH ;Write fault
DB 6 ;SEEK Failure
DB 4 ;Bad CRC
DB 8 ;Sector not found
DB 12 ;General error
DRV$INIT:
;
; Determine number of physical drives by reading config.sys
;
ASSUME DS:CODE
PUSH DS
LDS SI,[PTRSAV]
ASSUME DS:NOTHING
LDS SI,DWORD PTR [SI.COUNT] ;DS:SI points to
;config.sys
SCAN_LOOP:
CALL SCAN_SWITCH
MOV AL,CL
OR AL,AL
JZ SCAN4
CMP AL,"s"
JZ SCAN4
WERROR: POP DS
ASSUME DS:CODE
MOV DX,OFFSET ERRMSG2
WERROR2: MOV AH,9
INT 21H
XOR AX,AX
PUSH AX ;No units
JMP SHORT ABORT
BADNDRV:
POP DS
MOV DX,OFFSET ERRMSG1
JMP WERROR2
SCAN4:
ASSUME DS:NOTHING
;BX is number of floppies
OR BX,BX
JZ BADNDRV ;User error
CMP BX,4
JA BADNDRV ;User error
POP DS
ASSUME DS:CODE
PUSH BX ;Save unit count
ABORT: LDS BX,[PTRSAV]
ASSUME DS:NOTHING
POP AX
MOV BYTE PTR [BX].MEDIA,AL ;Unit count
MOV [DRVMAX],AL
MOV WORD PTR [BX].TRANS,OFFSET DRV$INIT ;SET
;BREAK ADDRESS
MOV [BX].TRANS+2,CS
MOV WORD PTR [BX].COUNT,OFFSET INITAB
;SET POINTER TO BPB ARRAY
MOV [BX].ceOUNT+2,CS
JMP EXIT
;
; Put switch in CL, value in BX
;
SCAN_SWITCH:
XOR BX,BX
MOV CX,BX
LODSB
CMP AL,10
JZ NUMRET
CMP AL,"-"
JZ GOT_SWITCH
CMP AL,"/"
JNZ SCAN_SWITCH
GOT_SWITCH:
CMP BYTE PTR [SI+1],":"
JNZ TERROR
LODSB
OR AL,20H ; Convert to lowercase
MOV CL,AL ; Get switch
LODSB ; Skip ":"
;
; Get number pointed to by [SI]
;
; Wipes out AX,DX only BX returns number
;
GETNUM1:LODSB
SUB AL,"0"
JB CHKRET
CMP AL,9
JA CHKRET
CBW
XCHG AX,BX
MOV DX,10
MUL DX
ADD BX,AX
JMP GETNUM1
CHKRET: ADD AL,"0"
CMP AL," "
JBE NUMRET
CMP AL,"-"
JZ NUMRET
CMP AL,"/"
JZ NUMRET
TERROR:
POP DS ; Get rid of return address
JMP WERROR
NUMRET: DEC SI
RET
ERRMSG1 DB "SMLDRV: Bad number of drives",13,10,"$"
ERRMSG2 DB "SMLDRV: Invalid parameter",13,10,"$"
CODE ENDS
END
Character Device Driver
The following program illustrates a character device driver program.
;******************** A Character Device *******************
Title VT52 Console for 2.0 (IBM)
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;
; IBM Addresses for I/O
;
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
CR=13 ;Carriage-Return
BACKSP=8 ;BACKSPACE
ESC=1BH
BRKADR=6CH ;006C Break vector address
ASNMAX=200 ;Size of key assignment buffer
CODE SEGMENT BYTE
ASSUME CS:CODE,DS:NOTHING,ES:NOTHING
;----------------------------------------------------------
;
; C O N - Console Device Driver
;
CONDEV: ;Header for device "CON"
DW -1,-1
DW 1000000000010011B ;CON IN AND CON OUT
DW STRATEGY
DW ENTRY
DB 'CON '
;-----------------------------------------------------------
;
; Command JUMP Tables
CONTBL:
DW CON$INIT
DW EXIT
DW EXIT
DW CMDERR
DW CON$READ
DW CON$RDND
DW EXIT
DW CON$FLSH
DW CON$WRIT
DW CON$WRIT
DW EXIT
DW EXIT
CMDTABL DB 'A'
DW CUU ;cursor up
DB 'B'
DW CUD ;cursor down
DB 'C'
DW CUF ;cursor forward
DB 'D'
DW CUB ;cursor back
DB 'H'
DW CUH ;cursor position
DB 'J'
DW ED ;erase display
DB 'K'
DW EL ;erase line
DB 'Y'
DW CUP ;cursor position
DB 'j'
DW PSCP ;save cursor position
DB 'k'
DW PRCP ;restore cursor position
DB 'y'
DW RM ;reset mode
DB 'x'
DW SM ;set mode
DB 00
PAGE
;---------------------------------------------------
;
; Device entry point
;
CMDLEN = 0 ;Length of this command
UNIT = 1 ;Subunit Specified
CMD = 2 ;Command Code
STATUS = 3 ;Status
MEDIA = 13 ;Media Descriptor
TRANS = 14 ;Transfer Address
COUNT = 18 ;Count of blocks or characters
START = 20 ;First block to transfer
PTRSAV DD 0
STRATP PROC FAR
STRATEGY:
MOV WORD PTR CS:[PTRSAV],BX
MOV WORD PTR CS:[PTRSAV+2],ES
RET
STRATP ENDP
ENTRY:
PUSH SI
PUSH AX
PUSH CX
PUSH DX
PUSH DI
PUSH BP
PUSH DS
PUSH ES
PUSH BX
LDS BX,CS:[PTRSAV] ;GET POINTER TO I/O PACKET
MOV CX,WORD PTR DS:[BX].COUNT ;CX = COUNT
MOV AL,BYTE PTR DS:[BX].CMD
CBW
MOV SI,OFFSET CONTBL
ADD SI,AX
ADD SI,AX
CMP AL,11
JA CMDERR
LES DI,DWORD PTR DS:[BX].TRANS
PUSH CS
POP DS
ASSUME DS:CODE
JMP WORD PTR [SI] ;GO DO COMMAND
PAGE
;=====================================================
;=
;= Subroutines Shared by Multiple Devices
;=
;=====================================================
;-----------------------------------------------------
;
; EXIT - All routines return through this path
;
BUS$EXIT: ;Device Busy Exit
MOV AH,00000011B
JMP SHORT ERR1
CMDERR:
MOV AL,3 ;Unknown command error
ERR$EXIT:
MOV AH,10000001B ;Mark error Return
JMP SHORT ERR1
EXITP PROC FAR
EXIT: MOV AH,00000001B
ERR1: LDS BX,CS:[PTRSAV]
MOV WORD PTR [BX].STATUS,AX ;Mark
;Operation Complete
POP BX
POP ES
POP DS
POP BP
POP DI
POP DX
POP CX
POP AX
POP SI
RET ;Restore REGS and Return
EXITP ENDP
;-----------------------------------------------
;
; BREAK Key Handling
;
BREAK:
MOV CS:ALTAH,3 ;Indicate BREAK key Set
INTRET: IRET
PAGE
;
; WARNING - Variables are very order dependent,
so be careful when adding new ones!
;
WRAP DB 0 ; 0 = WRAP, 1 = NO WRAP
STATE DW S1
MODE DB 3
MAXCOL DB 79
COL DB 0
ROW DB 0
SAVCR DW 0
ALTAH DB 0 ;Special key handling
;-------------------------------------------------------
;
; CHROUT - Write out Char in AL using current attribute
;
ATTRW LABEL WORD
ATTR DB 00000111B ;Character Attribute
BPAGE DB 0 ;Base Page
base dw 0b800h
chrout: cmp al,13
jnz trylf
mov [col],0
jmp short setit
trylf: cmp al,10
jz lf
cmp al,7
jnz tryback
torom:
mov bx,[attrw]
and bl,7
mov ah,14
int 10h
ret5: ret
tryback:
cmp al,8
jnz outchr
cmp [col],0
jz ret5
dec [col]
jmp short setit
outchr:
mov bx,[attrw]
mov cx,1
mov ah,9
int 10h
inc [col]
mov al,[col]
cmp al,[maxcol]
jbe setit
cmp [wrap],0
jz outchr1
dec [col]
ret
outchr1:
mov [col],0
lf: inc [row]
cmp [row],24
jb setit
mov [row],23
call scroll
setit: mov dh,row
mov dl,col
xor bh,bh
mov ah,2
int 10h
ret
scroll: call getmod
cmp al,2
jz myscroll
cmp al,3
jz myscroll
mov al,10
jmp torom
myscroll:
mov bh,[attr]
mov bl,' '
mov bp,80
mov ax,[base]
mov es,ax
mov ds,ax
xor di,di
mov si,160
mov cx,23*80
cld
cmp ax,0b800h
jz colorcard
rep movsw
mov ax,bx
mov cx,bp
rep stosw
sret: push cs
pop ds
ret
colorcard:
mov dx,3dah
wait2: in al,dx
test al,8
jz wait2
mov al,25h
mov dx,3d8h
out dx,al ;turn off video
rep movsw
mov ax,bx
mov cx,bp
rep stosw
mov al,29h
mov dx,3d8h
out dx,al ;turn on video
jmp sret
GETMOD: MOV AH,15
INT 16 ;get column information
MOV BPAGE,BH
DEC AH
MOV WORD PTR MODE,AX
RET
;------------------------------------------------------
;
; Console Read Routine
;
CON$READ:
JCXZ CON$EXIT
CON$LOOP:
PUSH CX ;Save Count
CALL CHRIN ;Get Char in AL
POP CX
STOSB ;Store Char at ES:DI
LOOP CON$LOOP
CON$EXIT:
JMP EXIT
;---------------------------------------------------------
;
; Input Single Char into AL
;
CHRIN: XOR AX,AX
XCHG AL,ALTAH ;Get Character & Zero ALTAH
OR AL,AL
JNZ KEYRET
INAGN: XOR AH,AH
INT 22
ALT10:
OR AX,AX ;Check for non-key after BREAK
JZ INAGN
OR AL,AL ;Special case?
JNZ KEYRET
MOV ALTAH,AH ;Store special key
KEYRET: RET
;----------------------------------------------------------
;
; Keyboard Non-descructive Read, No Wait
;
CON$RDND:
MOV AL,[ALTAH]
OR AL,AL
JNZ RDEXIT
RD1: MOV AH,1
INT 22
JZ CONBUS
OR AX,AX
JNZ RDEXIT
MOV AH,0
INT 22
JMP CON$RDND
RDEXIT: LDS BX,[PTRSAV]
MOV [BX].MEDIA,AL
EXVEC: JMP EXIT
CONBUS: JMP BUS$EXIT
;----------------------------------------------------------
;
; Keyboard Flush Routine
;
CON$FLSH:
MOV [ALTAH],0 ;Clear out holding buffer
PUSH DS
XOR BP,BP
MOV DS,BP ;Select segment 0
MOV DS:BYTE PTR 41AH,1EH ;Reset KB queue head
;pointer
MOV DS:BYTE PTR 41CH,1EH ;Reset tail pointer
POP DS
JMP EXVEC
;----------------------------------------------------------
;
; Console Write Routine
;
CON$WRIT:
JCXZ EXVEC
PUSH CX
MOV AH,3 ;Set current cursor position
XOR BX,BX
INT 16
MOV WORD PTR [COL],DX
POP CX
CON$LP: MOV AL,ES:[DI] ;Get Char
INC DI
CALL OUTC ;Output Char
LOOP CON$LP ;Repeat until all through
JMP EXVEC
COUT: STI
PUSH DS
PUSH CS
POP DS
CALL OUTC
POP DS
IRET
OUTC: PUSH AX
PUSH CX
PUSH DX
PUSH SI
PUSH DI
PUSH ES
PUSH BP
CALL VIDEO
POP BP
POP ES
POP DI
POP SI
POP DX
POP CX
POP AX
RET
;----------------------------------------------------------
;
; Output Single Char in AL to Video Device
;
VIDEO: MOV SI,OFFSET STATE
JMP [SI]
S1: CMP AL,ESC ;Escape sequence?
JNZ S1B
MOV WORD PTR [SI],OFFSET S2
RET
S1B: CALL CHROUT
S1A: MOV WORD PTR [STATE],OFFSET S1
RET
S2: PUSH AX
CALL GETMOD
POP AX
MOV BX,OFFSET CMDTABL-3
S7A: ADD BX,3
CMP BYTE PTR [BX],0
JZ S1A
CMP BYTE PTR [BX],AL
JNZ S7A
JMP WORD PTR [BX+1]
MOVCUR: CMP BYTE PTR [BX],AH
JZ SETCUR
ADD BYTE PTR [BX],AL
SETCUR: MOV DX,WORD PTR COL
XOR BX,BX
MOV AH,2
INT 16
JMP S1A
CUP: MOV WORD PTR [SI],OFFSET CUP1
RET
CUP1: SUB AL,32
MOV BYTE PTR [ROW],AL
MOV WORD PTR [SI],OFFSET CUP2
RET
CUP2: SUB AL,32
MOV BYTE PTR [COL],AL
JMP SETCUR
SM: MOV WORD PTR [SI],OFFSET S1A
RET
CUH: MOV WORD PTR COL,0
JMP SETCUR
CUF: MOV AH,MAXCOL
MOV AL,1
CUF1: MOV BX,OFFSET COL
JMP MOVCUR
CUB: MOV AX,00FFH
JMP CUF1
CUU: MOV AX,00FFH
CUU1: MOV BX,OFFSET ROW
JMP MOVCUR
CUD: MOV AX,23*256+1
JMP CUU1
PSCP: MOV AX,WORD PTR COL
MOV SAVCR,AX
JMP SETCUR
PRCP: MOV AX,SAVCR
MOV WORD PTR COL,AX
JMP SETCUR
ED: CMP BYTE PTR [ROW],24
JAE EL1
MOV CX,WORD PTR COL
MOV DH,24
JMP ERASE
EL1: MOV BYTE PTR [COL],0
EL: MOV CX,WORD PTR [COL]
EL2: MOV DH,CH
ERASE: MOV DL,MAXCOL
MOV BH,ATTR
MOV AX,0600H
INT 16
ED3: JMP SETCUR
RM: MOV WORD PTR [SI],OFFSET RM1
RET
RM1: XOR CX,CX
MOV CH,24
JMP EL2
CON$INIT:
int 11h
and al,00110000b
cmp al,00110000b
jnz iscolor
mov [base],0b000h ;look for bw card
iscolor:
cmp al,00010000b ;look for 40 col mode
ja setbrk
mov [mode],0
mov [maxcol],39
setbrk:
XOR BX,BX
MOV DS,BX
MOV BX,BRKADR
MOV WORD PTR [BX],OFFSET BREAK
MOV WORD PTR [BX+2],CS
MOV BX,29H*4
MOV WORD PTR [BX],OFFSET COUT
MOV WORD PTR [BX+2],CS
LDS BX,CS:[PTRSAV]
MOV WORD PTR [BX].TRANS,OFFSET CON$INIT
;SET BREAK ADDRESS
MOV [BX].TRANS+2,CS
JMP EXIT
CODE ENDS
END
Chapter 3 MS-DOS Technical Information
───────────────────────────────────────────────────────────────────────────
3.1 Introduction
3.2 MS-DOS Initialization
3.3 The Command Processor
3.4 MS-DOS Disk Allocation
3.5 MS-DOS Disk Directory
3.6 File Allocation Table (FAT)
3.6.1 How to Use the FAT (12-Bit FAT Entries)
3.6.2 How to Use the FAT (16-Bit FAT Entries)
3.7 MS-DOS Standard Disk Formats
3.1 Introduction
This chapter describes how MS-DOS initializes and how it allocates disk
space for the root directory, the File Allocation Tables (FAT), and the
data area. For programmers writing installable device drivers, this chapter
explains MS-DOS disk directory entries and File Allocation Tables. At the
end of the chapter, Tables 3.1 and 3.2 describe MS-DOS standard formats
for floppy disks.
3.2 MS-DOS Initialization
MS-DOS initialization consists of several steps. When you reset your
computer or turn on its power, the ROM (Read Only Memory) BIOS is invoked
and performs hardware checks and initialization. The ROM BIOS then examines
drive A for the boot sector. If it locates a boot sector, the ROM BIOS
reads it into low memory and gives it control. If it doesn't find the boot
sector, the ROM BIOS then looks in the active partition of the hard disk.
If it still doesn't find the boot sector, the ROM BIOS then invokes
ROM BASIC.
On a removable disk (3.5-inch, 5.25-inch, or 8-inch disk), the boot
sector sector is always located on track 0, sector 1, side 0 of the disk.
On a hard disk, the boot sector begins on the first sector of the MS-DOS
partition. The hard disk boot sector also includes a partition table. This
table identifies the active MS-DOS partition and any other partitions,
such as an extended MS-DOS partition, on the hard disk. Note that extended
MS-DOS partitions are not bootable.
The boot sector then reads the following files, in the order listed:
io.sys
msdos.sys
───────────────────────────────────────────────────────────────────────────
Note
Versions of MS-DOS prior to 3.3 required the io.sys file to be
contiguous. This is no longer a requirement.
───────────────────────────────────────────────────────────────────────────
Next, the system initialization routine SYSINIT loads all of the resident
device drivers. Then, it searches for a config.sys file on the boot disk.
SYSINIT allocates memory for buffers and files, based on settings in the
config.sys file, or system default settings. If the config.sys file
specifies any installable device drivers, these are installed next.
Finally, SYSINIT executes the MS-DOS command processor, command.com.
3.3 The Command Processor
The command processor command.com consists of three parts:
■ A resident part resides in memory immediately following msdos.sys
and its data area. This part contains routines to process Interrupts
22H (Terminate Process Exit Address), 23H (CONTROL-C Exit Address),
and 24H (Critical-Error-Handler Addres