home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft_Programmers_Library.7z / MPL / msdos / dos33ref.txt next >
Encoding:
Text File  |  2013-11-08  |  632.9 KB  |  19,541 lines

  1.  TITLE PAGE
  2.  
  3.  
  4.  
  5.  ───────────────────────────────────────────────────────────────────────────
  6.  
  7.  
  8.  
  9.  Microsoft(R) MS-DOS(R)
  10.  
  11.  Version 3.3
  12.  
  13.  Programmer's Reference
  14.  
  15.  
  16.  
  17.  ───────────────────────────────────────────────────────────────────────────
  18.  
  19.  
  20.  
  21.  Information in this document is subject to change without notice and does
  22.  not represent a commitment on the part of Microsoft Corporation. The
  23.  software described in this document is furnished under a license agreement
  24.  or nondisclosure agreement. The software may be used or copied only in
  25.  accordance with the terms of the agreement. The purchaser may make one copy
  26.  of the software for backup purposes. No part of this manual may be
  27.  reproduced or transmitted in any form or by any means, electronic or
  28.  mechanical, including photocopying and recording, for any purpose other
  29.  than the purchaser's personal use without the written permission of
  30.  Microsoft Corporation.
  31.  
  32.  
  33.  
  34.  (c) Copyright Microsoft Corporation, 1988. All rights reserved.
  35.  Simultaneously published in the United States and Canada.
  36.  
  37.  
  38.  
  39.  Microsoft(R), the Microsoft logo, MS(R), MS-DOS(R), and XENIX(R) are
  40.  registered trademarks of Microsoft Corporation.
  41.  
  42.  IBM(R), IBM Personal Computer(R), IBM PC(R), and PC-DOS(R) are registered
  43.  trademarks of International Business Machines Corporation.
  44.  
  45.  INTEL(R) is a registered trademark of Intel Corporation.
  46.  
  47.  
  48.  
  49.  Contents
  50.  
  51.  ───────────────────────────────────────────────────────────────────────────
  52.  
  53.  1   System Calls
  54.  
  55.       1.1   Introduction
  56.       1.2   Standard Character Device I/O
  57.       1.3   Memory Management
  58.       1.4   Process Management
  59.       1.5   File and Directory Management
  60.       1.6   Microsoft Networks
  61.       1.7   National Language Support
  62.       1.8   Miscellaneous System-Management Functions
  63.       1.9   Old System Calls
  64.       1.10  Using the System Calls
  65.       1.11  Interupts
  66.       1.12  Function Requests
  67.  
  68.  
  69.  2   MS-DOS Device Drivers
  70.  
  71.       2.1   Introduction
  72.       2.2   Format of a Device Driver
  73.       2.3   How to Create a Device Driver
  74.       2.4   Installing Device Drivers
  75.       2.5   Device Headers
  76.       2.6   Request Header
  77.       2.7   Device Driver Functions
  78.       2.8   The Media Descriptor Byte
  79.       2.9   Format of a Media Descriptor Table
  80.       2.10  The CLOCK Device
  81.       2.11  Anatomy of a Device Call
  82.       2.12  Two Sample Device Drivers
  83.  
  84.  
  85.  3   MS-DOS Technical Information
  86.  
  87.       3.1   Introduction
  88.       3.2   MS-DOS Initialization
  89.       3.3   The Command Processor
  90.       3.4   MS-DOS Disk Allocation
  91.       3.5   MS-DOS Disk Directory
  92.       3.6   File Allocation Table (FAT)
  93.       3.7   MS-DOS Standard Disk Formats
  94.  
  95.  
  96.  4   MS-DOS Control Blocks and Work Areas
  97.  
  98.       4.1   Introduction
  99.       4.2   Typical Contents of an MS-DOS Memory Map
  100.       4.3   MS-DOS Program Segment
  101.  
  102.  
  103.  5   National Language Support
  104.  
  105.       5.1   Introduction
  106.       5.2   National Language Support Calls
  107.       5.3   Font Files
  108.  
  109.  
  110.  6   .Exe File Structure and Loading
  111.  
  112.       6.1   Format of a File Header
  113.       6.2   The Relocation Table
  114.  
  115.  
  116.  7   Relocatable Object Module Formats
  117.  
  118.       7.1   Introduction
  119.       7.2   Module Identification and Attributes
  120.       7.3   Conceptual Framework for Fixups
  121.       7.4   Record Sequence
  122.       7.5   Introducing the Record Formats
  123.       7.6   Microsoft Type Representations for Communal Variables
  124.  
  125.  
  126.  8   Programming Hints
  127.  
  128.       8.1   Introduction
  129.       8.2   Interrupts
  130.       8.3   System Calls
  131.       8.4   Device Management
  132.       8.5   Memory Management
  133.       8.6   Process Management
  134.       8.7   File and Directory Management
  135.       8.8   Miscellaneous
  136.  
  137.  
  138.  Figures
  139.  
  140.  Figure 1.1   Example of the 8088 Registers
  141.  
  142.  Figure 1.2   Sample Program with Common Skeleton
  143.  
  144.  Figure 2.1   Sample Device Header
  145.  
  146.  Figure 2.2   Attribute Word for Character Devices
  147.  
  148.  Figure 2.3   Attribute Word for Block Devices
  149.  
  150.  Figure 2.4   Request Header
  151.  
  152.  Figure 2.5   Status Field
  153.  
  154.  Figure 2.6   Format of a Boot Sector
  155.  
  156.  Figure 2.7   Format of a Clock Device
  157.  
  158.  Figure 4.1   Program Segment Prefix
  159.  
  160.  Figure 5.1   Font File Structure
  161.  
  162.  Figure 7.1   Location Types
  163.  
  164.  
  165.  Tables
  166.  
  167.  Table 1.1   Standard Character I/O Functions
  168.  
  169.  Table 1.2   Memory-Management Function Requests
  170.  
  171.  Table 1.3   Process-Management Function Requests
  172.  
  173.  Table 1.4   Predefined Device Handles
  174.  
  175.  Table 1.5   File-Related Function Requests
  176.  
  177.  Table 1.6   File-Sharing Function Requests
  178.  
  179.  Table 1.7   Device-Related Function Requests
  180.  
  181.  Table 1.8   Directory-Related Function Requests
  182.  
  183.  Table 1.9   File Attributes
  184.  
  185.  Table 1.10  Microsoft Networks Function Requests
  186.  
  187.  Table 1.11  National-Language-Support Function Requests
  188.  
  189.  Table 1.12  Miscellaneous System-Management Function Requests
  190.  
  191.  Table 1.13  Old System Calls and Their Replacements
  192.  
  193.  Table 1.14  Format of the File Control Block (FCB)
  194.  
  195.  Table 1.15  Error Codes Returned in AX
  196.  
  197.  Table 1.16  MS-DOS Interrupts, Numeric Order
  198.  
  199.  Table 1.17  MS-DOS Interrupts, Alphabetic Order
  200.  
  201.  Table 1.18  MS-DOS Function Requests, Numeric Order
  202.  
  203.  Table 1.19  MS-DOS Function Requests, Alphabetic Order
  204.  
  205.  Table 1.20  Bit Values for Function 29H
  206.  
  207.  Table 1.21  Sharing Mode Bit Values
  208.  
  209.  Table 1.22  Access Code Bit Values
  210.  
  211.  Table 1.23  MS-DOS Data Bit Values
  212.  
  213.  Table 1.24  Contents of the Parameter Block
  214.  
  215.  Table 1.25  Contents of the Parameter Block
  216.  
  217.  Table 1.26  DTA Values After Successful Find First File
  218.  
  219.  Table 1.27  Allocation Strategy
  220.  
  221.  Table 2.1   For Character Devices:
  222.  
  223.  Table 2.2   For Block Devices
  224.  
  225.  Table 3.1   MS-DOS Standard Removable-Disk Formats
  226.  
  227.  Table 3.2   MS-DOS Standard Removable-Disk Formats (High-Density)
  228.  
  229.  Table 7.1   Object Module Record Format
  230.  
  231.  Table 7.1   Combination Attribute Example
  232.  
  233.  
  234.  
  235.  
  236.  Chapter 1  System Calls
  237.  
  238.  ───────────────────────────────────────────────────────────────────────────
  239.  
  240.  1.1  Introduction
  241.  
  242.        1.1.1  System Calls That Have Been Superseded
  243.  
  244.  1.2  Standard Character Device I/O
  245.  
  246.  1.3  Memory Management
  247.  
  248.  1.4  Process Management
  249.  
  250.        1.4.1  Loading and Executing a Program
  251.  
  252.        1.4.2  Loading an Overlay
  253.  
  254.  1.5  File and Directory Management
  255.  
  256.        1.5.1  Handles
  257.  
  258.        1.5.2  File Related Function Requests
  259.  
  260.        1.5.3  Device-Related Function Requests
  261.  
  262.        1.5.4  Directory-Related Function Requests
  263.  
  264.        1.5.5  File Attributes
  265.  
  266.  1.6  Microsoft Networks
  267.  
  268.  1.7  National Language Support
  269.  
  270.  1.8  Miscellaneous System-Management Functions
  271.  
  272.  1.9  Old System Calls
  273.  
  274.        1.9.1  File Control Block (FCB)
  275.  
  276.  1.10 Using the System Calls
  277.  
  278.        1.10.1  Issuing an Interupt
  279.  
  280.        1.10.2  Calling a Function Request
  281.  
  282.        1.10.3  Using the Calls from a High-Level Language
  283.  
  284.        1.10.4  Treatment of Registers
  285.  
  286.        1.10.5  Handling Errors
  287.  
  288.        1.10.6  System Call Descriptions
  289.  
  290.                 1.10.6.1  Sample Programs
  291.  
  292.                 1.10.6.2  Error Handling in Sample Programs
  293.  
  294.  1.11 Interrupts
  295.  
  296.        1.11.1  Conditions upon Entry
  297.  
  298.        1.11.2  Requirements for an Interrupt 24H Handler
  299.  
  300.  
  301.  
  302.  1.1  Introduction
  303.  
  304.  
  305.  The routines that MS-DOS uses to manage system operation and resources can
  306.  be called by any application program. Using these system calls makes it
  307.  easier to write machine-independent programs and increases the likelihood
  308.  that a program will be compatible with future versions of MS-DOS. MS-DOS
  309.  system calls fall into several categories:
  310.  
  311.      ■ Standard character device I/O
  312.  
  313.      ■ Memory management
  314.  
  315.      ■ Process management
  316.  
  317.      ■ File and directory management
  318.  
  319.      ■ Microsoft Network calls
  320.  
  321.      ■ National Language Support calls
  322.  
  323.      ■ Miscellaneous system functions
  324.  
  325.  Applications invoke MS-DOS services by using software interrupts. The
  326.  current range of interrupts used for MS-DOS is 20H-27H; 28H-40H are
  327.  reserved. Interrupt 21H is the function request service; it provides
  328.  access to a wide variety of MS-DOS services. In some cases, the full AX
  329.  register is used to specify the requested function. Each interrupt or
  330.  function request uses values in various registers to receive or return
  331.  function-specific information.
  332.  
  333.  
  334.  1.1.1  System Calls That Have Been Superseded
  335.  
  336.  Many system calls introduced in versions of MS-DOS earlier than 2.0 have
  337.  been superseded by function requests that are more efficient and easier to
  338.  use. Although MS-DOS still includes these old system calls, they should
  339.  not be used unless it is imperative that a program maintain backward-
  340.  compatibility with versions of MS-DOS before 2.0.
  341.  
  342.  A table of the pre-2.0 system calls and a description of the File
  343.  Control Block (required by some of the old calls) appears in Section 1.8,
  344.  "Old System Calls."
  345.  
  346.  The first part of this chapter explains how DOS manages its resources--
  347.  such as memory, files, and processes--and briefly describes the purpose of
  348.  most of the system calls. The remainder of the chapter describes each
  349.  interrupt and function request in detail.
  350.  
  351.  The system-call descriptions are in numeric order, interrupts followed
  352.  by function requests. These descriptions include further detail on how
  353.  MS-DOS manages its resources.
  354.  
  355.  Chapter 2 of this manual describes how to write an MS-DOS device driver.
  356.  Chapters 3, 4, and 5 contain more detailed information about MS-DOS,
  357.  including how it manages disk space, the control blocks it uses, and how it
  358.  loads and executes relocatable programs (files with an extension of .exe).
  359.  Chapter 6 describes the Intel object module format. Chapter 7 gives some
  360.  programming hints.
  361.  
  362.  
  363.  1.2  Standard Character Device I/O
  364.  
  365.  
  366.  The standard character function requests handle all input and output to and
  367.  from character devices such as consoles, printers, and serial ports. If a
  368.  program uses these function requests, its input and output can be
  369.  redirected.
  370.  
  371.  Table 1.1 lists the MS-DOS function requests for managing standard
  372.  character input and output.
  373.  
  374.  
  375.       Table 1.1
  376.       Standard Character I/O Function Requests
  377. ╓┌──────────┌────────────────────┌───────────────────────────────────────────╖
  378.       Code  Request              Description
  379.      ───────────────────────────────────────────────────────────────────────
  380.       Code  Request              Description
  381.      ───────────────────────────────────────────────────────────────────────
  382.       01H   Read Keyboard and    Gets a character from standard input
  383.             Echo                 and echoes it to standard output
  384.  
  385.       02H   Display Character    Sends a character to standard output
  386.  
  387.       03H   Auxiliary Input      Gets a character from standard
  388.                                  auxiliary
  389.  
  390.       04H   Auxiliary Output     Sends a character to standard
  391.                                  auxiliary
  392.  
  393.       05H   Print Character      Sends a character to the standard
  394.                                  printer
  395.  
  396.       06H   Direct Console I/O   Gets a character from standard input
  397.                                  or sends a character to standard
  398.                                  output
  399.  
  400.       07H   Direct Console       Gets a character from standard input
  401.       Code  Request              Description
  402.      07H   Direct Console       Gets a character from standard input
  403.             Input
  404.  
  405.       08H   Read Keyboard        Gets a character from standard input
  406.  
  407.       09H   Display String       Sends a string to standard output
  408.  
  409.       0AH   Buffered Keyboard    Gets a string from standard input
  410.             Input
  411.  
  412.       0BH   Check Keyboard       Reports on the status of the
  413.             Status               standard input buffer
  414.  
  415.       0CH   Flush Buffer, Read   Empties the standard input buffer
  416.             Keyboard             and calls one of the other standard
  417.                                  character I/O function requests
  418.  
  419.  
  420.  Although several of these standard character I/O function requests seem to
  421.  do the same thing, they are distinguished by whether they check for control
  422.  characters or echo characters from standard input to standard output. The
  423.  detailed descriptions later in this chapter point out the differences.
  424.  
  425.  
  426.  1.3  Memory Management
  427.  
  428.  
  429.  MS-DOS keeps track of which areas of memory are allocated by writing a
  430.  memory control block at the beginning of each. This control block
  431.  specifies the size of the memory area; the name of the process, if any,
  432.  that owns the memory area; and a pointer to the next area of memory. If the
  433.  memory area is not owned, it is available.
  434.  
  435.  Table 1.2 lists the MS-DOS function requests for managing memory.
  436.  
  437.  
  438.       Table 1.2
  439.       Memory-Management Function Requests
  440. ╓┌──────────┌─────────────────┌──────────────────────────────────────────────╖
  441.       Code  Request           Description
  442.      ───────────────────────────────────────────────────────────────────────
  443.       Code  Request           Description
  444.      ───────────────────────────────────────────────────────────────────────
  445.       48H   Allocate Memory   Requests a block of memory
  446.  
  447.       49H   Free Allocated    Frees a block of memory
  448.             Memory            previously allocated with 48H
  449.  
  450.       4AH   Set Block         Changes the size of an allocated
  451.                               memory block
  452.  
  453.  
  454.  When a process requests additional memory with Function 48H (Allocate
  455.  Memory), MS-DOS searches for a block of available memory large enough to
  456.  satisfy the request. If it finds such a block of memory, it changes the
  457.  memory control block to show the owning process. If the block of memory is
  458.  larger than the requested amount, MS-DOS changes the size field of the
  459.  memory control block to the requested amount, writes a new memory control
  460.  block at the beginning of the unneeded portion showing that it is
  461.  available, and updates the pointers to add this memory to the chain of
  462.  memory control blocks. MS-DOS then returns the segment address of the
  463.  first byte of the allocated memory to the requesting process.
  464.  
  465.  When a process releases an allocated block of memory with Function 49H
  466.  (Free Allocated Memory), MS-DOS changes the memory control block to show
  467.  that it is available (not owned by any process).
  468.  
  469.  When a process uses Function 4AH (Set Block) to shrink an allocated
  470.  block of memory, MS-DOS builds a memory control block for the memory being
  471.  released and adds it to the chain of memory control blocks. When a process
  472.  tries to use Function 4AH (Set Block) to expand an allocated block of
  473.  memory, MS-DOS treats it as a request for additional memory rather than
  474.  returning the segment address of the additional memory to the requesting
  475.  process. However, MS-DOS simply chains the additional memory to the
  476.  existing memory block.
  477.  
  478.  If MS-DOS can't find a block of available memory large enough to satisfy a
  479.  request for additional memory made with either Function 48H (Allocate
  480.  Memory) or Function 4AH (Set Block), MS-DOS returns an error code to the
  481.  requesting process.
  482.  
  483.  When a program receives control, it should call Function 4AH (Set
  484.  Block) to shrink its initial memory-allocation block (the block that begins
  485.  with its Program Segment Prefix) to the minimum it requires. This frees
  486.  unneeded memory and makes the best application design for portability to
  487.  future multitasking environments.
  488.  
  489.  When a program exits, MS-DOS automatically frees its initial memory-
  490.  allocation block before returning control to the calling program
  491.  (command.com is usually the calling program for application programs). The
  492.  DOS frees any memory owned by the exiting process.
  493.  
  494.  Any program that changes memory that is not allocated to it will most
  495.  likely destroy at least one memory-management control block. This causes a
  496.  memory-allocation error the next time MS-DOS tries to use the chain of
  497.  memory control blocks; the only cure is to restart the system.
  498.  
  499.  
  500.  1.4  Process Management
  501.  
  502.  
  503.  MS-DOS uses several function requests to load, execute, and terminate
  504.  programs. Application programs can use these same function requests to
  505.  manage other programs.
  506.  
  507.  Table 1.3 lists the MS-DOS function requests for managing processes.
  508.  
  509.  
  510.       Table 1.3
  511.       Process-Management Function Requests
  512. ╓┌────────────┌──────────────────┌───────────────────────────────────────────╖
  513.       Code    Request            Description
  514.       ──────────────────────────────────────────────────────────────────────
  515.       31H     Keep Process       Terminates a process and
  516.                                  returns control to the
  517.                                  invoking process, but keeps
  518.                                  the terminated process in
  519.                                  memory
  520.  
  521.       4BH     Load and Execute   Loads and executes a program
  522.               Program
  523.  
  524.       4B03H   Load Overlay       Loads a program overlay
  525.                                  without executing it
  526.  
  527.       Code    Request            Description
  528. 
  529.       4CH     End Process        Returns control to the
  530.                                  invoking process
  531.  
  532.       4DH     Get Return Code    Returns a code passed by an
  533.               of Child Process   exiting child process
  534.  
  535.       62H     Get PSP            Returns the segment address of
  536.                                  the current process's Program
  537.                                  Segment Prefix
  538.  
  539.  
  540.  1.4.1  Loading and Executing a Program
  541.  
  542.  When a program uses Function 4BH (Load and Execute Program) to load and
  543.  execute another program, MS-DOS allocates memory, writes a Program Segment
  544.  Prefix (PSP) for the new program at offset 0 of the allocated memory, loads
  545.  the new program, and passes control to it. When the invoked program exits,
  546.  control returns to the calling program.
  547.  
  548.  Command.com uses Function 4BH to load and execute command files.
  549.  Application programs have the same degree of control over process
  550.  management as does command.com.
  551.  
  552.  In addition to these common features, there are some differences in the
  553.  way MS-DOS loads .com and .exe files.
  554.  
  555.  
  556.  Loading a .com Program
  557.  
  558.  When command.com loads and executes a .com program, it allocates all
  559.  available memory to the application and sets the stack pointer 100H bytes
  560.  from the end of available memory. A .com program should set up its own
  561.  stack before shrinking its initial memory-allocation block with Function
  562.  4AH (Set Block) because the default stack is in the memory to be released.
  563.  
  564.  If a newly loaded program is allocated all of memory--as a .com program
  565.  is--or requests all of available memory by using Function 48H (Allocate
  566.  Memory), MS-DOS allocates to it the memory occupied by the transient part
  567.  of command.com. If the program changes this memory, MS-DOS must reload the
  568.  transient portion of command.com before it can continue. If a program exits
  569.  (via Function 31H, Keep Process) without releasing enough memory, the
  570.  system halts and must be reset. To minimize this possibility, a .com
  571.  program should use Function 4AH (Set Block) to shrink its initial
  572.  allocation block before doing anything else, and before exiting, all
  573.  programs must release all memory they allocate by using Function 48H
  574.  (Allocate Memory).
  575.  
  576.  
  577.  Loading an .exe Program
  578.  
  579.  When command.com loads and executes an .exe program, it allocates the size
  580.  of the program's memory image plus either the value in the MAX_ALLOC field
  581.  (offset 0CH) of the file header (if that much memory is available) or the
  582.  value in the MIN_ALLOC field (offset 0AH). The linker sets these fields.
  583.  Before passing control to the .exe file, MS-DOS uses the relocation
  584.  information in the file header to calculate the correct relocation
  585.  addresses.
  586.  
  587.  For a more detailed description of how MS-DOS loads .com and .exe
  588.  files, see Chapter 3, "MS-DOS Technical Information," and Chapter 4,
  589.  "MS-DOS Control Blocks and Work Areas."
  590.  
  591.  
  592.  Executing a Program from Within Another Program
  593.  
  594.  Since command.com builds pathnames, searches directory paths for executable
  595.  files, and relocates .exe files, the simplest way to load and execute a
  596.  program is to load and execute an additional copy of command.com, passing
  597.  it a command line that includes the /C switch, which invokes the .com or
  598.  .exe file. The description of Function 4B00H (Load and Execute Program)
  599.  describes how to do this.
  600.  
  601.  
  602.  1.4.2  Loading an Overlay
  603.  
  604.  When a program uses Function 4B03H (Load Overlay) to load an overlay, it
  605.  must pass MS-DOS the segment address at which the overlay is to be loaded.
  606.  The program must call the overlay, which then returns directly to the
  607.  calling program. The calling program is in complete control: MS-DOS does
  608.  not write a PSP for the overlay or intervene in any other way.
  609.  
  610.  MS-DOS does not check to see if the calling program owns the memory
  611.  where the overlay is to be loaded. If the calling program does not own the
  612.  memory, loading the overlay will most likely destroy a memory-control
  613.  block, causing an eventual memory-allocation error.
  614.  
  615.  Therefore, a program that loads an overlay must either allow room for
  616.  the overlay when it calls Function 4AH (Set Block) to shrink its initial
  617.  memory-allocation block, or shrink its initial memory-allocation block to
  618.  the minimum and then use Function 48H (Allocate Memory) to allocate memory
  619.  for the overlay.
  620.  
  621.  
  622.  1.5  File and Directory Management
  623.  
  624.  
  625.  The MS-DOS hierarchical (multilevel) file system is similar to that of the
  626.  XENIX operating system. For a description of the multilevel directory
  627.  system and how to use it, see the MS-DOS User's Reference.
  628.  
  629.  
  630.  1.5.1  Handles
  631.  
  632.  To create or open a file, a program passes MS-DOS a pathname and the
  633.  attribute to be assigned to the file. MS-DOS returns a 16-bit number,
  634.  called a handle. For most subsequent actions, MS-DOS requires only this
  635.  handle to identify the file.
  636.  
  637.  A handle can refer to either a file or a device. MS-DOS predefines five
  638.  standard handles. These handles are always open, so you needn't open them
  639.  before you use them. Table 1.4 lists these predefined handles.
  640.  
  641.  
  642.       Table 1.4
  643.       Predefined Device Handles
  644. ╓┌─────────────┌─────────────────┌───────────────────────────────────────────╖
  645.       Handle   Standard device   Comment
  646.       ──────────────────────────────────────────────────────────────────────
  647.       0        Input             Can be redirected from command line
  648.       1        Output            Can be redirected from command line
  649.       2        Error
  650.       3        Auxiliary
  651.       4        Printer
  652.  
  653.  
  654.  When MS-DOS creates or opens a file, it assigns the first available handle.
  655.  Since a program can have 20 open handles, including the five predefined
  656.  handles, it typically can open 15 extra files. By using Function 46H
  657.  (Force Duplicate File Handle), MS-DOS can temporarily force any of the five
  658.  predefined handles to refer to an alternate file or device. For more
  659.  information about Function 46H, see its description later in this chapter.
  660.  
  661.  
  662.  1.5.2  File-Related Function Requests
  663.  
  664.  MS-DOS treats a file as a string of bytes; it assumes no record structure
  665.  or access technique. An application program imposes whatever record
  666.  structure it needs on this string of bytes. Reading from or writing to a
  667.  file requires only pointing to the data buffer and specifying the number of
  668.  bytes to read or write.
  669.  
  670.  Table 1.5 lists the MS-DOS function requests for managing files.
  671.  
  672.  
  673.       Table 1.5
  674.       File-Related Function Requests
  675. ╓┌──────────┌─────────────────────────────┌──────────────────────────────────╖
  676.       Code  Request                       Description
  677.       ──────────────────────────────────────────────────────────────────────
  678.       3CH   Create Handle                 Creates a file
  679.  
  680.       3DH   Open Handle                   Opens a file
  681.  
  682.       3EH   Close Handle                  Closes a file
  683.  
  684.       3FH   Read Handle                   Reads from a file
  685.  
  686.       40H   Write Handle                  Writes to a file
  687.  
  688.       42H   Move File Pointer             Sets the read/write pointer in a
  689.                                           file
  690.  
  691.       45H   Duplicate File Handle         Creates a new handle that refers
  692.                                           to the same file as an existing
  693.                                           handle
  694.  
  695.       Code  Request                       Description
  696. 
  697.       46H   Force Duplicate File Handle   Makes an existing handle refer to
  698.                                           the same file as another existing
  699.                                           handle
  700.  
  701.       5AH   Create Temporary File         Creates a file with a unique name
  702.  
  703.       5BH   Create New File               Attempts to create a file, but
  704.                                           fails if a file with the same name
  705.                                            exists
  706.  
  707.       67H   Set Handle Count              Increases or decreases the number
  708.                                           of files a program can have open
  709.                                           at one time
  710.  
  711.       68H   Commit File                   Flushes buffered data for a file
  712.                                           without closing it to ensure the
  713.                                           disk image of that file is current
  714.  
  715.  
  716.  File Sharing
  717.  
  718.  Version 3.1 of MS-DOS introduces file sharing, which lets more than one
  719.  process share access to a file. File sharing operates only after the share
  720.  command has been executed to load file-sharing support. That is, you must
  721.  use the share command to take advantage of file sharing.
  722.  
  723.  Table 1.6 lists the MS-DOS function requests for sharing files; if file
  724.  sharing is not in effect, these function requests cannot be used. Function
  725.  3DH (Open Handle) can operate in several modes. Here it is referred to in
  726.  the file-sharing modes, which require file sharing to be in effect.
  727.  (Compatibility mode is usable without file sharing in effect.)
  728.  
  729.  
  730.       Table 1.6
  731.       File-Sharing Function Requests
  732. ╓┌────────────┌─────────────┌────────────────────────────────────────────────╖
  733.       Code    Request       Description
  734.       ──────────────────────────────────────────────────────────────────────
  735.       3DH     Open Handle   Opens a file by using one of the
  736.                             file-sharing modes
  737.       Code    Request       Description
  738.                            file-sharing modes
  739.  
  740.       440BH   IOCtl Retry   (before Interrupt 24 is issued)
  741.                             Specifies how many times to retry
  742.                             an I/O operation that fails due
  743.                             to a file-sharing violation
  744.  
  745.       5C00H   Lock          Locks a region of a file
  746.  
  747.       5C01H   Unlock        Unlocks a region of a file
  748.  
  749.  
  750.  1.5.3  Device-Related Function Requests
  751.  
  752.  I/O Control for devices is implemented with Function 44H (IOCtl), which
  753.  includes several subfunctions necessary to perform device-related tasks.
  754.  Some forms of the IOCtl function request require that the device driver be
  755.  written to support the IOCtl interface. Table 1.7 lists the MS-DOS function
  756.  requests for managing devices.
  757.  
  758.  
  759.       Table 1.7
  760.       Device-Related Function Requests
  761. ╓┌────────────────┌─────────────────────────────┌────────────────────────────╖
  762.       Code        Request                       Description
  763.       ──────────────────────────────────────────────────────────────────────
  764.       4400H,01H   IOCtl Data                    Gets or sets device
  765.                                                 description
  766.  
  767.       4402H,03H   IOCtl Character               Gets or sets character-
  768.                                                 device control data
  769.  
  770.       4404H,05H   IOCtl Block                   Gets or sets block-device
  771.                                                 control data
  772.  
  773.       4406H,07H   IOCtl Status                  Checks device input or
  774.                                                 output status
  775.  
  776.       4408H       IOCtl Is Changeable           Checks whether block device
  777.                                                 contains removable medium
  778.  
  779.       Code        Request                       Description
  780. 
  781.       440CH       Generic IOCtl (for handles)   Sets Generic IOCtl for
  782.                                                 handles and supports code
  783.                                                 pages for devices
  784.  
  785.       440DH       Generic IOCtl (for devices)   Sets Generic IOCtl for
  786.                                                 devices
  787.       440E,0FH    Get/Set IOCtl Drive Map       Gets or sets logical
  788.                                                 drive map
  789.  
  790.  
  791.  Some forms of the IOCtl function request can be used only with Microsoft
  792.  Networks; these forms are listed in Section 1.6, "Microsoft Networks."
  793.  
  794.  
  795.  1.5.4  Directory-Related Function Requests
  796.  
  797.  A directory entry is a 32-byte record that includes the file's name,
  798.  extension, date and time of last change, and size. An entry in a
  799.  subdirectory is identical to an entry in the root directory. Directory
  800.  entries are described in detail in Chapter 3, "MS-DOS Technical
  801.  Information."
  802.  
  803.  The root directory on a disk has room for a fixed number of entries: 64
  804.  on a standard single-sided disk, 112 on a standard double-sided disk. For
  805.  hard disks, the number of directories depends on the DOS partition size. A
  806.  subdirectory is simply a file with a unique attribute; there can be as many
  807.  subdirectories on a disk as space allows. The depth of a directory
  808.  structure, therefore, is limited only by the amount of storage on a disk
  809.  and the maximum pathname length of 64 characters. Pre-2.0 disks appear to
  810.  have only a root directory that contains files but no subdirectories.
  811.  
  812.  Table 1.8 lists the MS-DOS function requests for managing directories.
  813.  
  814.  
  815.       Table 1.8
  816.       Directory-Related Function Requests
  817. ╓┌──────────┌─────────────────────────────────┌──────────────────────────────╖
  818.       Code  Request                           Description
  819.       ──────────────────────────────────────────────────────────────────────
  820.       39H   Create Directory                  Creates a subdirectory
  821.       Code  Request                           Description
  822.      39H   Create Directory                  Creates a subdirectory
  823.  
  824.       3AH   Remove Directory                  Deletes a subdirectory
  825.  
  826.       3BH   Change Current Directory          Changes the current directory
  827.  
  828.       41H   Delete Directory Entry (Unlink)   Deletes a file
  829.  
  830.       43H   Get/Set File Attributes (Chmod)   Retrieves or changes the
  831.                                               attributes of a file
  832.  
  833.       47H   Get Current Directory             Returns current directory for
  834.                                               a given drive
  835.  
  836.       4EH   Find First File                   Searches a directory for the
  837.                                               first entry that matches a
  838.                                               filename
  839.  
  840.       4FH   Find Next File                    Searches a directory for the
  841.                                               next entry that matches a
  842.       Code  Request                           Description
  843.                                              next entry that matches a
  844.                                               filename
  845.  
  846.       56H   Change Directory Entry            Renames a file
  847.  
  848.       57H   Get/Set Date/Time of File         Changes the time and date of
  849.                                               last change in a directory
  850.                                               entry
  851.  
  852.  
  853.  1.5.5  File Attributes
  854.  
  855.  Table 1.9 describes the file attributes and how they are represented in
  856.  the attribute byte of the directory entry (offset 0BH). The attributes can
  857.  be inspected or changed with Function 43H (Get/Set File Attributes
  858.  [Chmod]).
  859.  
  860.  
  861.       Table 1.9
  862.       File Attributes
  863. ╓┌───────────┌───────────────────────────────────────────────────────────────╖
  864.       Code   Description
  865.       ──────────────────────────────────────────────────────────────────────
  866.       00H    Normal; can be read or written without
  867.              restriction
  868.  
  869.       01H    Read-only; cannot be opened for write; a
  870.              file with the same name cannot be created
  871.  
  872.       02H    Hidden; not found by directory search
  873.  
  874.       04H    System; not found by directory search
  875.  
  876.       08H    VolumeID; only one file can have this
  877.              attribute; it must be in the root directory
  878.  
  879.       10H    Subdirectory
  880.  
  881.       20H    Archive; set whenever the file is changed,
  882.              or cleared by the Backup command
  883.  
  884.  
  885.  The VolumeID (08H) and Subdirectory (10H) attributes cannot be changed with
  886.  Function 43H (Get/Set File Attributes [Chmod]).
  887.  
  888.  
  889.  1.6  Microsoft Networks
  890.  
  891.  
  892.  Microsoft Networks consists of a server and one or more workstations.
  893.  MS-DOS maintains an assign list that keeps track of which workstation
  894.  drives and devices have been redirected to the server. For a description of
  895.  operation and use of the network, see the Microsoft Networks 1.0 Manager's
  896.  Guide and Microsoft Networks 1.0 User's Guide.
  897.  
  898.  Table 1.10 lists the MS-DOS function requests for managing a Microsoft
  899.  Networks workstation.
  900.  
  901.  
  902.       Table 1.10
  903.       Microsoft Networks Function Requests
  904. ╓┌────────────┌───────────────────┌──────────────────────────────────────────╖
  905.       Code    Request             Description
  906.       ──────────────────────────────────────────────────────────────────────
  907.       4409H   IOCtl Is            Checks whether a drive letter refers to
  908.               Redirected Block    a local or redirected drive
  909.  
  910.       440AH   IOCtl Is            Checks whether a device name refers to a
  911.               Redirected Handle   local or redirected device
  912.  
  913.       5E00H   Get Machine Name    Gets the network name of the workstation
  914.  
  915.       5E02H   Printer Setup       Defines a string of control characters
  916.                                   to be added at the beginning of each
  917.                                   file that is sent to a network
  918.                                   printer
  919.  
  920.       5F02H   Get Assign-List     Gets an entry from the assign list,
  921.               Entry               which shows the workstation drive letter
  922.                                   or device name and the net name of the
  923.                                   directory or device on the server to
  924.                                   which the entry is reassigned
  925.  
  926.       Code    Request             Description
  927. 
  928.       5F03H   Make Assign-List    Redirects a workstation drive or device
  929.               Entry               to a server directory or device
  930.  
  931.       5F04H   Cancel Assign-      Cancels the redirection of a workstation
  932.               List Entry          drive or device to a server directory or
  933.                                   device
  934.  
  935.  
  936.  1.7  National Language Support
  937.  
  938.  
  939.  National language support for this version of MS-DOS includes these
  940.  major features:
  941.  
  942.      ■ Country-dependent information
  943.  
  944.      ■ Support for national keyboard layouts
  945.  
  946.      ■ Programming interfaces for national language support
  947.  
  948.      ■ Utility commands
  949.  
  950.  Country-dependent information is available on a per-country basis and
  951.  includes the following:
  952.  
  953.      ■ Time, date, and currency
  954.  
  955.      ■ Lowercase-to-uppercase character-conversion tables
  956.  
  957.      ■ Collating sequence for character sorting
  958.  
  959.      ■ Valid single-byte characters used in filenames
  960.  
  961.  Keyboard support for different keyboard layouts is provided and
  962.  selectable.
  963.  
  964.  Table 1.11 lists the MS-DOS national-language-support system calls that
  965.  allow applications to use the country-dependent information just described.
  966.  
  967.  
  968.       Table 1.11
  969.       National Language-Support Function Requests
  970. ╓┌──────────┌──────────────────────────────────┌─────────────────────────────╖
  971.       Code  Request                            Description
  972.       ──────────────────────────────────────────────────────────────────────
  973.       65H   Get Extended Country Information   Returns standard
  974.                                                country information,
  975.                                                pointer to uppercase
  976.                                                table, pointer to
  977.                                                filename uppercasing
  978.                                                table, or pointer to
  979.                                                collating table
  980.  
  981.       66H   Get/Set Global Code Page           Gets or sets the code
  982.                                                page used by the
  983.                                                kernel and all
  984.                                                devices.
  985.  
  986.  
  987.  1.8  Miscellaneous System-Management Functions
  988.  
  989.  
  990.  The remaining system calls manage other system functions and resources such
  991.  as drives, addresses, and the clock. Table 1.12 lists the MS-DOS function
  992.  requests for managing miscellaneous system resources and operation.
  993.  
  994.  
  995.       Table 1.12
  996.       Miscellaneous System-Management Function Requests
  997. ╓┌──────────┌───────────────────────┌────────────────────────────────────────╖
  998.       Code  Request                 Description
  999.       ─────────────────────────────────────────────────────────────────────
  1000.       0DH   Reset Disk              Empties all file buffers
  1001.  
  1002.       0EH   Select Disk             Sets the default drive
  1003.  
  1004.       19H   Get Current Disk        Returns the default drive
  1005.  
  1006.       1AH   Set Disk Transfer       Establishes the disk I/O buffer
  1007.             Address
  1008.  
  1009.       1BH   Get Default Drive       Returns disk-format data
  1010.       Code  Request                 Description
  1011.      1BH   Get Default Drive       Returns disk-format data
  1012.             Data
  1013.  
  1014.       1CH   Get Drive Data          Returns disk-format data
  1015.  
  1016.       25H   Set Interrupt Vector    Sets interrupt-handler address
  1017.  
  1018.       29H   Parse File Name         Checks string for valid filename
  1019.  
  1020.       2AH   Get Date                Returns system date
  1021.  
  1022.       2BH   Set Date                Sets system date
  1023.  
  1024.       2CH   Get Time                Returns system time
  1025.  
  1026.       2DH   Set Time                Sets system time
  1027.  
  1028.       2EH   Set/Reset Verify Flag   Turns disk verify on or off
  1029.  
  1030.       2FH   Get Disk Transfer       Returns system-disk-I/O-buffer
  1031.       Code  Request                 Description
  1032.      2FH   Get Disk Transfer       Returns system-disk-I/O-buffer
  1033.             Address                 address
  1034.  
  1035.       30H   Get MS-DOS Version      Returns MS-DOS version number
  1036.             Number
  1037.  
  1038.       33H   CONTROL-C Check         Returns CONTROL-C check status
  1039.  
  1040.       35H   Get Interrupt Vector    Returns address of interrupt
  1041.                                     handler
  1042.  
  1043.       36H   Get Disk Free Space     Returns disk-space data
  1044.  
  1045.       38H   Get/Set Country Data    Sets current country or
  1046.                                     retrieves country information
  1047.  
  1048.       54H   Get Verify State        Returns status of disk verify
  1049.  
  1050.  
  1051.  1.9  Old System Calls
  1052.  
  1053.  
  1054.  Most of the superseded system calls deal with files. Table 1.13 lists
  1055.  these old calls and the function requests that have superseded them.
  1056.  
  1057.  Although MS-DOS still includes these old system calls, they should not
  1058.  be used unless a program must maintain backward-compatibility with earlier
  1059.  versions of MS-DOS.
  1060.  
  1061.  
  1062.       Table 1.13
  1063.       Old System Calls and Their Replacements
  1064. ╓┌─────────────────────────────────────────┌─────────────────────────────────╖
  1065.       Old System Call                      Has Been Superseded By
  1066.       Code   Function                      Code   Function
  1067.       ──────────────────────────────────────────────────────────────────────
  1068.       00H    Terminate Program             4CH    End Process
  1069.  
  1070.       0FH    Open File                     3DH    Open Handle
  1071.  
  1072.       10H    Close File                    3EH    Close Handle
  1073.       Old System Call                      Has Been Superseded By
  1074.       Code   Function                      Code   Function
  1075.      10H    Close File                    3EH    Close Handle
  1076.  
  1077.       11H    Search for First Entry        4EH    Find First File
  1078.  
  1079.       12H    Search for Next Entry         4FH    Find Next File
  1080.  
  1081.       13H    Delete File                   41H    Delete Directory Entry
  1082.  
  1083.       14H    Sequential Read               3FH    Read Handle
  1084.  
  1085.       15H    Sequential Write              40H    Write Handle
  1086.  
  1087.       16H    Create File                   3CH    Create Handle
  1088.                                            5AH    Create Temporary File
  1089.                                            5BH    Create New File
  1090.  
  1091.       17H    Rename File                   56H    Change Directory Entry
  1092.  
  1093.       21H    Random Read                   3FH    Read Handle
  1094.       Old System Call                      Has Been Superseded By
  1095.       Code   Function                      Code   Function
  1096.      21H    Random Read                   3FH    Read Handle
  1097.  
  1098.       22H    Random Write                  40H    Write Handle
  1099.  
  1100.       23H    Get File Size                 42H    Move File Pointer
  1101.  
  1102.       24H    Set Relative Record           42H    Move File Pointer
  1103.  
  1104.       26H    Create New PSP                4BH    Load and Execute Program
  1105.  
  1106.       27H    Random Block Read             42H    Move File Pointer
  1107.                                            3FH    Read Handle
  1108.  
  1109.       28H    Random Block Write            42H    Move File Pointer
  1110.                                            40H    Write Handle
  1111.  
  1112.       Code   Interrupt                     Code   Function
  1113.       ──────────────────────────────────────────────────────────────────────
  1114.       20H    Program Terminate             4CH    End Process
  1115.       Old System Call                      Has Been Superseded By
  1116.       Code   Function                      Code   Function
  1117.      20H    Program Terminate             4CH    End Process
  1118.  
  1119.       27H    Terminate But Stay Resident   31H    Keep Process
  1120.  
  1121.  
  1122.  1.9.1  File Control Block (FCB)
  1123.  
  1124.  The old file-related function requests require that a program maintain a
  1125.  File Control Block (FCB) for each file; this control block contains such
  1126.  information as a file's name, size, record length, and pointer to current
  1127.  record. MS-DOS does most of this housekeeping for the newer, handle-
  1128.  oriented function requests.
  1129.  
  1130.  Some descriptions of the old function requests refer to unopened and
  1131.  opened FCBs. An unopened FCB contains only a drive specifier and filename.
  1132.  An opened FCB contains all fields filled by Function 0FH (Open File).
  1133.  
  1134.  The Program Segment Prefix (PSP) includes room for two FCBs at
  1135.  offsets 5CH and 6CH. For a description of how to use the PSP and FCB
  1136.  calls, see Chapter 4, "MS-DOS Control Blocks and Work Areas," Table 1.14
  1137.  describes the FCB fields.
  1138.  
  1139.  
  1140.       Table 1.14
  1141.       Format of the File Control Block (FCB)
  1142. ╓┌────────────┌──────┌──────┌────────────────────────────────────────────────╖
  1143.       Offset
  1144.       Hex     Dec    Bytes  Field
  1145.       ──────────────────────────────────────────────────────────────────────
  1146.       00H      0     1      Drive Number
  1147.       01H      1     8      Filename
  1148.       09H      9     3      Extension
  1149.       0CH     12     2      Current Block
  1150.  
  1151.       0EH     14     2      Record Size
  1152.       10H     16     4      File Size
  1153.       14H     20     2      Date of Last Write
  1154.       16H     22     2      Time of Last Write
  1155.  
  1156.       18H     24     8      Reserved
  1157.       Offset
  1158.       Hex     Dec    Bytes  Field
  1159.      18H     24     8      Reserved
  1160.       20H     32     1      Current Record
  1161.       21H     33     4      Relative Record
  1162.  
  1163.  
  1164.  Fields of the FCB
  1165.  
  1166.  Drive Number (offset 00H): Specifies the disk drive; 1 means drive A and
  1167.  2 means drive B. If you use the FCB to create or open a file, you can set
  1168.  this field to 0 to specify the default drive; Function 0FH (Open File) sets
  1169.  the field to the number of the default drive.
  1170.  
  1171.  Filename (offset 01H): Eight characters, left-aligned and padded
  1172.  (if necessary) with blanks. If you specify a reserved device name (such
  1173.  as PRN), do not put a colon at the end.
  1174.  
  1175.  Extension (offset 09H): Three characters, left-aligned and padded (if
  1176.  necessary) with blanks. This field can be all blanks (no extension).
  1177.  
  1178.  Current Block (offset 0CH): Points to the block (group of 128 records)
  1179.  that contains the current record. This field and the Current Record field
  1180.  (offset 1FH) make up the record pointer. This field is set to zero by the
  1181.  Open File system call.
  1182.  
  1183.  Record Size (offset 0EH): The size of a logical record, in bytes. Set
  1184.  to 128 by the Open File system call. If the record size is not 128 bytes,
  1185.  you must set this field after opening the file.
  1186.  
  1187.  File Size (offset 0FH): The size of the file, in bytes. The first word
  1188.  of this 4-byte field is the low-order part of the size.
  1189.  
  1190.  Date of Last Write (offset 13H): The date the file was created or last
  1191.  updated. The year, month, and day are mapped into two bytes as follows:
  1192.  
  1193.  Off     set 14H          Offset 13H
  1194.  |Y|Y|Y|Y|Y|Y|Y|M|   |M|M|M|D|D|D|D|D|
  1195.  15              9   8    5 4        0
  1196.  
  1197.  Time of Last Write (offset 15H): The time the file was created or last
  1198.  updated. The hour, minutes, and seconds are mapped into two bytes as
  1199.  follows:
  1200.  
  1201.  Offset 16H          Offset 15H
  1202.  |H|H|H|H|H|M|M|M|   |M|M|M|S|S|S|S|S|
  1203.  15      11 10            5 4        0
  1204.  
  1205.  Reserved (offset 17H): These fields are reserved for use by MS-DOS.
  1206.  
  1207.  Current Record (offset 1FH): Points to one of the 128 records in the
  1208.  current block. This field and the Current Block field (offset 0CH) make up
  1209.  the record pointer. The Open File system call does not initialize this
  1210.  field. You must set it before doing a sequential read or write to the file.
  1211.  
  1212.  Relative Record (offset 20H): Points to the currently selected record,
  1213.  counting from the beginning of the file (starting with 0). The Open File
  1214.  system call does not initialize this field. You must set it before doing a
  1215.  random read or write to the file. If the record size is less than 64 bytes,
  1216.  both words of this field are used; if the record size is 64 bytes or more,
  1217.  only the first three bytes are used.
  1218.  
  1219.  ───────────────────────────────────────────────────────────────────────────
  1220.  Note
  1221.    If you use the FCB at offset 5CH of the Program Segment Prefix, the last
  1222.    byte of the Relative Record field is the first byte of the unformatted
  1223.    parameter area that starts at offset 80H. This is the default Disk
  1224.    Transfer Area.
  1225.  ───────────────────────────────────────────────────────────────────────────
  1226.  
  1227.  
  1228.  Extended FCB
  1229.  
  1230.  The Extended File Control Block is used to create or search for
  1231.  directory entries of files with special attributes. It adds the following
  1232.  7-byte prefix to the FCB:
  1233.  
  1234.  Name                Bytes   Offset
  1235.  ───────────────────────────────────────────────────────────────────────────
  1236.  Flag byte (FFH)     1       07H
  1237.  Reserved            5       06H
  1238.  Attribute byte      1       01H
  1239.  
  1240.  File attributes are described earlier in this chapter in Section 1.5.5,
  1241.  "File Attributes."
  1242.  
  1243.  ───────────────────────────────────────────────────────────────────────────
  1244.  Note
  1245.    You must remember to point to the beginning of the extended FCB if you
  1246.    are using Functions 0FH-16H with extended FCBs.
  1247.  ───────────────────────────────────────────────────────────────────────────
  1248.  
  1249.  
  1250.  1.10  Using the System Calls
  1251.  
  1252.  
  1253.  The remainder of this chapter describes how to use the system calls in
  1254.  application programs, and it lists the calls in numeric and alphabetic
  1255.  order, describing each call in detail.
  1256.  
  1257.  
  1258.  1.10.1  Issuing an Interrupt
  1259.  
  1260.  
  1261.  MS-DOS reserves Interrupts 28H through 3FH for its own use, and
  1262.  maintains the table of interrupt-handler addresses (the vector table) in
  1263.  locations 80H-FCH. Also, in case you need to write your own routines for
  1264.  three particular MS-DOS interrupt handlers (Program Terminate, CONTROL-C,
  1265.  and Critical Error), this chapter includes descriptions of each. Function
  1266.  requests have superseded most of these interrupts.
  1267.  
  1268.  To issue an interrupt, move any required data into the registers and
  1269.  give the INT instruction with the number of the interrupt you want.
  1270.  
  1271.  
  1272.  1.10.2  Calling a Function Request
  1273.  
  1274.  
  1275.  A function request is an MS-DOS routine for managing system resources. Use
  1276.  the following procedure to call a function request:
  1277.  
  1278.      1. Move any required data into the registers.
  1279.  
  1280.      2. Move the function number into AH.
  1281.  
  1282.      3. Move the action code, if required, into AL.
  1283.  
  1284.      4. Issue Interrupt 21H.
  1285.  
  1286.  
  1287.  1.10.3  Using the Calls from a High-Level Language
  1288.  
  1289.  
  1290.  The system calls can be executed from any high-level language whose
  1291.  modules can be linked with assembly-language modules. In addition to this
  1292.  linking technique, you can:
  1293.  
  1294.      ■ Use the DOSXQQ function of Pascal-86 to call a function request
  1295.        directly.
  1296.  
  1297.      ■ Use the CALL statement or USER function to execute the required
  1298.        assembly-language code from the BASIC interpreter.
  1299.  
  1300.  
  1301.  1.10.4  Treatment of Registers
  1302.  
  1303.  
  1304.  When MS-DOS takes control after a function request, it switches to an
  1305.  internal stack, and preserves any registers not used to return information
  1306.  (except AX). The calling program's stack must be large enough to
  1307.  accommodate the interrupt system--at least 128 bytes in addition to other
  1308.  needs.
  1309.  
  1310.  
  1311.  1.10.5  Handling Errors
  1312.  
  1313.  
  1314.  Most of the function requests introduced with version 2.0 or later set
  1315.  the Carry flag if there is an error, identifying the specific error by
  1316.  returning a number in the AX register. Table 1.15 lists these error codes
  1317.  and their meanings.
  1318.  
  1319.  
  1320.       Table 1.15
  1321.       Error Codes Returned in AX
  1322. ╓┌────────────┌──────────────────────────────────────────────────────────────╖
  1323.       Code    Meaning
  1324.       ──────────────────────────────────────────────────────────────────────
  1325.       Code    Meaning
  1326.       ──────────────────────────────────────────────────────────────────────
  1327.        1      Invalid function code
  1328.        2      File not found
  1329.        3      Path not found
  1330.        4      Too many open files (no open handles left)
  1331.        5      Access denied
  1332.        6      Invalid handle
  1333.        7      Memory control blocks destroyed
  1334.        8      Insufficient memory
  1335.        9      Invalid memory block address
  1336.  
  1337.       10      Invalid environment
  1338.       11      Invalid format
  1339.       12      Invalid access code
  1340.       13      Invalid data
  1341.       14      Reserved
  1342.       15      Invalid drive
  1343.       16      Attempt to remove the current directory
  1344.       17      Not same device
  1345.       18      No more files
  1346.       Code    Meaning
  1347.      18      No more files
  1348.       19      Disk is write-protected
  1349.  
  1350.       20      Bad disk unit
  1351.       21      Drive not ready
  1352.       22      Invalid disk command
  1353.       23      CRC error
  1354.       24      Invalid length (disk operation)
  1355.       25      Seek error
  1356.       26      Not an MS-DOS disk
  1357.       27      Sector not found
  1358.       28      Out of paper
  1359.       29      Write fault
  1360.  
  1361.       30      Read fault
  1362.       31      General failure
  1363.       32      Sharing violation
  1364.       33      Lock violation
  1365.       34      Wrong disk
  1366.       35      FCB unavailable
  1367.       Code    Meaning
  1368.      35      FCB unavailable
  1369.       36-49   Reserved
  1370.  
  1371.       50      Network request not supported
  1372.       51      Remote computer not listening
  1373.       52      Duplicate name on network
  1374.       53      Network name not found
  1375.       54      Network busy
  1376.       55      Network device no longer exists
  1377.       56      Net BIOS command limit exceeded
  1378.       57      Network adapter hardware error
  1379.       58      Incorrect response from network
  1380.       59      Unexpected network error
  1381.  
  1382.       60      Incompatible remote adapter
  1383.       61      Print queue full
  1384.       62      Queue not full
  1385.       63      Not enough space for print file
  1386.       64      Network name was deleted
  1387.       65      Access denied
  1388.       Code    Meaning
  1389.      65      Access denied
  1390.       66      Network device type incorrect
  1391.       67      Network name not found
  1392.       68      Network name limit exceeded
  1393.       69      Net BIOS session limit exceeded
  1394.  
  1395.       70      Temporarily paused
  1396.       71      Network request not accepted
  1397.       72      Print or disk redirection is paused
  1398.       73-79   Reserved
  1399.  
  1400.       80      File exists
  1401.       81      Reserved
  1402.       82      Cannot make
  1403.       83      Interrupt 24 failure
  1404.       84      Out of structures
  1405.       85      Already assigned
  1406.       86      Invalid password
  1407.       87      Invalid parameter
  1408.       88      Net write fault
  1409.       Code    Meaning
  1410.      88      Net write fault
  1411.  
  1412.  
  1413.  To handle error conditions, put the following statement immediately after
  1414.  calls that return errors:
  1415.  
  1416.  JC <error>
  1417.  
  1418.  <Error> represents the label of an error-handling routine that gets the
  1419.  specific error condition by checking the value in AX. This routine then
  1420.  takes appropriate action.
  1421.  
  1422.  Some of the older system calls return a value in a register that
  1423.  specifies whether the operation was successful. To handle such errors,
  1424.  check the error code and take the appropriate action.
  1425.  
  1426.  
  1427.  Extended Error Codes
  1428.  
  1429.  Versions of MS-DOS after 2.0 have added new error messages. Any
  1430.  programs that use the older system calls cannot use these new error
  1431.  messages. To avoid incompatibility, MS-DOS maps these new error codes
  1432.  to the old error code that most closely matches the new one.
  1433.  
  1434.  Function 59H (Get Extended Error) has been added so that these new
  1435.  calls can be used. It provides as much detail as possible about the most
  1436.  recent error code returned by MS-DOS. The description of Function 59H
  1437.  lists the new, more detailed error codes and shows how to use this function
  1438.  request.
  1439.  
  1440.  
  1441.  1.10.6  System Call Descriptions
  1442.  
  1443.  
  1444.  Most system calls require that you move information into one or more
  1445.  registers before issuing the call that returns information in the
  1446.  registers. The description of each system call in this chapter includes
  1447.  the following:
  1448.  
  1449.      ■ A diagram of the 8088 registers that shows their contents before and
  1450.        after the system call
  1451.  
  1452.      ■ A more complete description of the register contents required before
  1453.        the system call
  1454.  
  1455.      ■ A description of the processing performed
  1456.  
  1457.      ■ A more complete description of the register contents after the
  1458.        system call
  1459.  
  1460.      ■ An example of how to use the system call
  1461.  
  1462.  The following figure is a sample illustration of the 8088 registers,
  1463.  showing how the information is presented. Shaded areas indicate that the
  1464.  register receives or returns information used by the call.
  1465.  
  1466.  
  1467.  ┌──────────┬──────────┐
  1468.  │▒▒▒▒AH▒▒▒▒│▒▒▒▒AL▒▒▒▒│
  1469.  ├──────────┼──────────┤
  1470.  │    BH    │    BL    │
  1471.  ├──────────┼──────────┤
  1472.  │    CH    │    CL    │
  1473.  ├──────────┼──────────┤
  1474.  │▒▒▒▒DH▒▒▒▒│▒▒▒▒DL▒▒▒▒│
  1475.  └──────────┴──────────┘
  1476.  ┌─────────────────────┐
  1477.  │          SP         │
  1478.  ├─────────────────────┤
  1479.  │          BP         │
  1480.  ├─────────────────────┤
  1481.  │          SI         │
  1482.  ├─────────────────────┤
  1483.  │          DI         │
  1484.  └─────────────────────┘
  1485.  ┌─────────────────────┐
  1486.  │          IP         │
  1487.  ├──────────┬──────────┤
  1488.  │  FLAGSH  │▒▒FLAGSL▒▒│
  1489.  └──────────┴──────────┘
  1490.  ┌─────────────────────┐
  1491.  │          CS         │
  1492.  ├─────────────────────┤
  1493.  │▒▒▒▒▒▒▒▒▒▒DS▒▒▒▒▒▒▒▒▒│
  1494.  ├─────────────────────┤
  1495.  │          SS         │
  1496.  ├─────────────────────┤
  1497.  │          ES         │
  1498.  └─────────────────────┘
  1499.  
  1500.  Figure 1.1  Example of the 8088 Registers
  1501.  
  1502.  
  1503.  1.10.6.1  Sample Programs
  1504.  
  1505.  The sample programs show only data declarations and the code that you need
  1506.  to use the system calls. Unless stated otherwise, each example assumes a
  1507.  common program skeleton that defines the segments and returns control to
  1508.  MS-DOS. Each sample program is intended to be executed as a .com file.
  1509.  Figure 1.2 shows a complete sample program. The unshaded portion shows
  1510.  what appears in this chapter; the shaded portions are the common skeleton.
  1511.  
  1512.  ───────────────────────────────────────────────────────────────────────────
  1513.  code       segment
  1514.             assume  cs:code,ds:code,es:nothing,ss:nothing
  1515.             org     100H
  1516.  start:     jmp     begin
  1517.  ;
  1518.  filename   db      "b:\textfile.asc",0
  1519.  buffer     db      129 dup (?)
  1520.  handle     dw      ?
  1521.  ;
  1522.  begin:     open_handle filename,0        ; Open the file
  1523.             jc      error_open            ; Routine not shown
  1524.             mov     handle,ax             ; Save handle
  1525.  read_line: read_handle handle,buffer,128 ; Read 128 bytes
  1526.             jc      error_read            ; Routine not shown
  1527.             cmp     ax,0                  ; End of file?
  1528.             je      return                ;   Yes, go home
  1529.             mov     bx,ax                 ;   No, AX bytes read
  1530.             mov     buffer[bx],"$"        ; To terminate string
  1531.             display buffer                ; See Function 09H
  1532.             jmp     read_line             ; Get next 128 bytes
  1533.  
  1534.  return:    end_process 0                 ; Return to MS-DOS
  1535.  last_inst:                               ; To mark next byte
  1536.  ;
  1537.  code       ends
  1538.             end     start
  1539.  ───────────────────────────────────────────────────────────────────────────
  1540.  
  1541.  Figure 1.2  Sample Program with Common Skeleton
  1542.  
  1543.  
  1544.  A macro has been defined for each system call to allow the examples to
  1545.  be more complete programs, rather than isolated uses of the system calls.
  1546.  These macros, plus some general-purpose ones, are used in the sample
  1547.  programs.  For instance, the sample program in the preceding figure
  1548.  includes four such macros: open_handle, read_handle, display, and
  1549.  end_process.  All the macro definitions are listed at the end of this
  1550.  chapter.
  1551.  
  1552.  The macros assume the environment for a .com program as described in
  1553.  Chapter 4; in particular, they assume that all the segment registers
  1554.  contain the same value. To conserve space, the macros generally leave error
  1555.  checking to the main code and do not protect registers. This keeps the
  1556.  macros short, yet useful. You may find that such macros are a convenient
  1557.  way to include system calls in your assembly-language programs.
  1558.  
  1559.  
  1560.  1.10.6.2  Error Handling in Sample Programs
  1561.  
  1562.  Whenever a system call returns an error code, the sample program shows
  1563.  a test for the error condition and a jump to an error routine. To conserve
  1564.  space, the error routines themselves aren't shown. Some error routines
  1565.  might simply display a message and continue processing. For more serious
  1566.  errors, the routine might display a message and end the program (performing
  1567.  any required housekeeping, such as closing files).
  1568.  
  1569.  Tables 1.16 through 1.19 list the Interrupts and Function Requests in
  1570.  numeric and alphabetic order.
  1571.  
  1572.  
  1573.       Table 1.16
  1574.       MS-DOS Interrupts, Numeric Order
  1575. ╓┌────────────────┌──────────────────────────────────────────────────────────╖
  1576.       Interrupt   Description
  1577.       Interrupt   Description
  1578.       ──────────────────────────────────────────────────────────────────────
  1579.       20H         Program Terminate
  1580.       21H         Function Request
  1581.       22H         Terminate Process Exit Address
  1582.       23H         CONTROL-C Handler Address
  1583.       24H         Critical-Error-Handler Address
  1584.       25H         Absolute Disk Read
  1585.       26H         Absolute Disk Write
  1586.       27H         Terminate But Stay Resident
  1587.       28H-3FH     Reserved
  1588.  
  1589.  
  1590.  
  1591.       Table 1.17
  1592.       MS-DOS Interrupts, Alphabetic Order
  1593. ╓┌─────────────────────────────────────┌─────────────────────────────────────╖
  1594.       Description                      Interrupt
  1595.       ──────────────────────────────────────────────────────────────────────
  1596.       Absolute Disk Read               25H
  1597.       Absolute Disk Write              26H
  1598.       Description                      Interrupt
  1599.      Absolute Disk Write              26H
  1600.       CONTROL-C Handler Address        23H
  1601.       Critical-Error-Handler Address   24H
  1602.       Function Request                 21H
  1603.       Program Terminate                20H
  1604.       Reserved                         28H-3FH
  1605.       Terminate Process Exit Address   22H
  1606.       Terminate But Stay Resident      27H
  1607.  
  1608.  
  1609.  
  1610.       Table 1.18
  1611.       MS-DOS Function Requests, Numeric Order
  1612. ╓┌──────────────────┌────────────────────────────────────────────────────────╖
  1613.       Function      Description
  1614.       ──────────────────────────────────────────────────────────────────────
  1615.       00H           Terminate Program
  1616.       01H           Read Keyboard And Echo
  1617.       02H           Display Character
  1618.       03H           Auxiliary Input
  1619.       Function      Description
  1620.      03H           Auxiliary Input
  1621.       04H           Auxiliary Output
  1622.       05H           Print Character
  1623.       06H           Direct Console I/O
  1624.       07H           Direct Console Input
  1625.       08H           Read Keyboard
  1626.       09H           Display String
  1627.       0AH           Buffered Keyboard Input
  1628.       0BH           Check Keyboard Status
  1629.       0CH           Flush Buffer, Read Keyboard
  1630.       0DH           Reset Disk
  1631.       0EH           Select Disk
  1632.       0FH           Open File
  1633.       10H           Close File
  1634.       11H           Search For First Entry
  1635.       12H           Search For Next Entry
  1636.       13H           Delete File
  1637.       14H           Sequential Read
  1638.       15H           Sequential Write
  1639.       16H           Create File
  1640.       Function      Description
  1641.      16H           Create File
  1642.       17H           Rename File
  1643.       18H           Reserved
  1644.       19H           Get Current Disk
  1645.       1AH           Set Disk Transfer Address
  1646.       1BH           Get Default Drive Data
  1647.       1CH           Get Drive Data
  1648.       1DH-20H       Reserved
  1649.       21H           Random Read
  1650.       22H           Random Write
  1651.       23H           Get File Size
  1652.       24H           Set Relative Record
  1653.       25H           Set Interrupt Vector
  1654.       26H           Create New PSP
  1655.       27H           Random Block Read
  1656.       28H           Random Block Write
  1657.       29H           Parse File Name
  1658.       2AH           Get Date
  1659.       2BH           Set Date
  1660.       2CH           Get Time
  1661.       Function      Description
  1662.      2CH           Get Time
  1663.       2DH           Set Time
  1664.       2EH           Set/Reset Verify Flag
  1665.       2FH           Get Disk Transfer Address
  1666.       30H           Get MS-DOS Version Number
  1667.       31H           Keep Process
  1668.       32H           Reserved
  1669.       33H           CONTROL-C Check
  1670.       34H           Reserved
  1671.       35H           Get Interrupt Vector
  1672.       36H           Get Disk Free Space
  1673.       37H           Reserved
  1674.       38H           Get/Set Country Data
  1675.       39H           Create Directory
  1676.       3AH           Remove Directory
  1677.       3BH           Change Current Directory
  1678.       3CH           Create Handle
  1679.       3DH           Open Handle
  1680.       3EH           Close Handle
  1681.       3FH           Read Handle
  1682.       Function      Description
  1683.      3FH           Read Handle
  1684.       40H           Write Handle
  1685.       41H           Delete Directory Entry (Unlink)
  1686.       42H           Move File Pointer
  1687.       43H           Get/Set File Attributes (Chmod)
  1688.       4400H,4401H   IOCtl Data
  1689.       4402H,4403H   IOCtl Character
  1690.       4404H,4405H   IOCtl Block
  1691.       4406H,4407H   IOCtl Status
  1692.       4408H         IOCtl Is Changeable
  1693.       4409H         IOCtl Is Redirected Block
  1694.       440AH         IOCtl Is Redirected Handle
  1695.       440BH         IOCtl Retry
  1696.       440CH         Generic IOCtl (for code page functions)
  1697.       440DH         Generic IOCtl (for devices)
  1698.       440EH         Get IOCtl Drive Map
  1699.       440FH         Set IOCtl Drive Map
  1700.       45H           Duplicate File Handle
  1701.       46H           Force Duplicate File Handle
  1702.       47H           Get Current Directory
  1703.       Function      Description
  1704.      47H           Get Current Directory
  1705.       48H           Allocate Memory
  1706.       49H           Free Allocated Memory
  1707.       4AH           Set Block
  1708.       4BH           Load and Execute Program
  1709.       4B03H         Load Overlay
  1710.       4CH           End Process
  1711.       4DH           Get Return Code of Child Process
  1712.       4EH           Find First File
  1713.       4FH           Find Next File
  1714.       50H-53H       Reserved
  1715.       54H           Get Verify State
  1716.       55H           Reserved
  1717.       56H           Change Directory Entry
  1718.       57H           Get/Set Date/Time of File
  1719.       58H           Get/Set Allocation Strategy
  1720.       59H           Get Extended Error
  1721.       5AH           Create Temporary File
  1722.       5BH           Create New File
  1723.       5C00H         Lock
  1724.       Function      Description
  1725.      5C00H         Lock
  1726.       5C01H         Unlock
  1727.       5DH           Reserved
  1728.       5E00H         Get Machine Name
  1729.       5E02H         Printer Setup
  1730.       5F02H         Get Assign-List Entry
  1731.       5F03H         Make Assign-List Entry
  1732.       5F04H         Cancel Assign-List Entry
  1733.       60H-61H       Reserved
  1734.       62H           Get PSP
  1735.       63H,64H       Reserved
  1736.       65H           Get Extended Country Information
  1737.       66H           Get/Set Global Code Page
  1738.       67H           Set Handle Count
  1739.       68H           Commit File
  1740.       69H-7FH       Reserved
  1741.  
  1742.  
  1743.  
  1744.       Table 1.19
  1745.       MS-DOS Function Requests, Alphabetic Order
  1746. ╓┌──────────────────────────────────────────────┌────────────────────────────╖
  1747.       Description                               Interrupt
  1748.       ──────────────────────────────────────────────────────────────────────
  1749.       Allocate Memory                           48H
  1750.       Auxiliary Input                           03H
  1751.       Auxiliary Output                          04H
  1752.       Buffered Keyboard Input                   0AH
  1753.       Cancel Assign-List Entry                  5F04H
  1754.       Change Current Directory                  3BH
  1755.       Change Directory Entry                    56H
  1756.       Check Keyboard Status                     0BH
  1757.       Close File                                10H
  1758.       Close Handle                              3EH
  1759.       Commit FIle                               68H
  1760.       CONTROL-C Check                           33H
  1761.       Create Directory                          39H
  1762.       Create File                               16H
  1763.       Create Handle                             3CH
  1764.       Create New File                           5BH
  1765.       Create New PSP                            26H
  1766.       Description                               Interrupt
  1767.      Create New PSP                            26H
  1768.       Create Temporary File                     5AH
  1769.       Delete Directory Entry (Unlink)           41H
  1770.       Delete File                               13H
  1771.       Direct Console I/O                        06H
  1772.       Direct Console Input                      07H
  1773.       Display Character                         02H
  1774.       Display String                            09H
  1775.       Duplicate File Handle                     45H
  1776.       End Process                               4CH
  1777.       Find First File                           4EH
  1778.       Find Next File                            4FH
  1779.       Flush Buffer, Read Keyboard               0CH
  1780.       Force Duplicate File Handle               46H
  1781.       Free Allocated Memory                     49H
  1782.       Generic IOCtl (for devices)               440DH
  1783.       Generic IOCtl (for code page functions)   440CH
  1784.       Get Assign-List Entry                     5F02H
  1785.       Get Current Directory                     47H
  1786.       Get Current Disk                          19H
  1787.       Description                               Interrupt
  1788.      Get Current Disk                          19H
  1789.       Get Date                                  2AH
  1790.       Get Default Drive Data                    1BH
  1791.       Get Disk Free Space                       36H
  1792.       Get Disk Transfer Address                 2FH
  1793.       Get Drive Data                            1CH
  1794.       Get Extended Country Information          65H
  1795.       Get Extended Error                        59H
  1796.       Get File Size                             23H
  1797.       Get Interrupt Vector                      35H
  1798.       Get IOCtl Drive Map                       440EH
  1799.       Get Machine Name                          5E00H
  1800.       Get MS-DOS Version Number                 30H
  1801.       Get PSP                                   62H
  1802.       Get Return Code of Child Process          4DH
  1803.       Get Time                                  2CH
  1804.       Get Verify State                          54H
  1805.       Get/Set Allocation Strategy               58H
  1806.       Get/Set Country Data                      38H
  1807.       Get/Set Date/Time Of File                 57H
  1808.       Description                               Interrupt
  1809.      Get/Set Date/Time Of File                 57H
  1810.       Get/Set File Attributes (Chmod)           43H
  1811.       Get/Set Global Code Page                  66H
  1812.       IOCtl Block                               4404H,4405H
  1813.       IOCtl Character                           4402H,4403H
  1814.       IOCtl Data                                4400H,4401H
  1815.       IOCtl Is Changeable                       4408H
  1816.       IOCtl Is Redirected Block                 4409H
  1817.       IOCtl Is Redirected Handle                440AH
  1818.       IOCtl Retry                               440BH
  1819.       IOCtl Status                              4406H,4407H
  1820.       Keep Process                              31H
  1821.       Load and Execute Program                  4BH
  1822.       Load Overlay                              4B03H
  1823.       Lock                                      5C00H
  1824.       Make Assign-List Entry                    5F03H
  1825.       Move File Pointer                         42H
  1826.       Open File                                 0FH
  1827.       Open Handle                               3DH
  1828.       Parse File Name                           29H
  1829.       Description                               Interrupt
  1830.      Parse File Name                           29H
  1831.       Print Character                           05H
  1832.       Printer Setup                             5E02H
  1833.       Random Block Read                         27H
  1834.       Random Block Write                        28H
  1835.       Random Read                               21H
  1836.       Random Write                              22H
  1837.       Read Handle                               3FH
  1838.       Read Keyboard                             08H
  1839.       Read Keyboard And Echo                    01H
  1840.       Remove Directory                          3AH
  1841.       Rename File                               17H
  1842.       Reserved                                  18H
  1843.       Reserved                                  1DH-20H
  1844.       Reserved                                  32H
  1845.       Reserved                                  34H
  1846.       Reserved                                  37H
  1847.       Reserved                                  50H-53H
  1848.       Reserved                                  55H
  1849.       Reserved                                  5DH
  1850.       Description                               Interrupt
  1851.      Reserved                                  5DH
  1852.       Reserved                                  60H-61H
  1853.       Reserved                                  63H, 64H
  1854.       Reserved                                  69H-7FH
  1855.       Reset Disk                                0DH
  1856.       Search for First Entry                    11H
  1857.       Search for Next Entry                     12H
  1858.       Select Disk                               0EH
  1859.       Sequential Read                           14H
  1860.       Sequential Write                          15H
  1861.       Set Block                                 4AH
  1862.       Set Date                                  2BH
  1863.       Set Disk Transfer Address                 1AH
  1864.       Set Handle Count                          67H
  1865.       Set Interrupt Vector                      25H
  1866.       Set IOCtl Drive Map                       440FH
  1867.       Set Relative Record                       24H
  1868.       Set Time                                  2DH
  1869.       Set/Reset Verify Flag                     2EH
  1870.       Terminate Program                         00H
  1871.       Description                               Interrupt
  1872.      Terminate Program                         00H
  1873.       Unlock                                    5C01H
  1874.       Write Handle                              40H
  1875.  
  1876.  
  1877.  A detailed description of each system call follows. These calls are listed
  1878.  in numeric order, interrupts first, followed by function requests.
  1879.  
  1880.  ───────────────────────────────────────────────────────────────────────────
  1881.  Note
  1882.    Unless stated otherwise, in the system call descriptions--both text and
  1883.    code--all numbers are in hexadecimal.
  1884.  ───────────────────────────────────────────────────────────────────────────
  1885.  
  1886.  
  1887.  1.11  Interrupts
  1888.  
  1889.  
  1890.  The following pages describe Interrupts 20H-27H.
  1891.  
  1892.  
  1893.  Program Terminate (Interrupt 20H)
  1894.  
  1895.  
  1896.  Call:
  1897.  
  1898.  CS
  1899.    Segment address of Program Segment Prefix
  1900.  
  1901.  
  1902.  Return:
  1903.  
  1904.  None
  1905.  
  1906.  
  1907.  Comments:
  1908.  
  1909.  Interrupt 20H terminates the current process and returns control to its
  1910.  parent process. It also closes all open file handles and clears the disk
  1911.  cache. When this interrupt is issued, CS must contain the segment address
  1912.  of the Program Segment Prefix.
  1913.  
  1914.  Interrupt 20H is provided only for compatibility with MS-DOS versions
  1915.  prior to 2.0. New programs should use Function 4CH (End Process), which
  1916.  permits returning a completion code to the parent process and does not
  1917.  require CS to contain the segment address of the Program Segment Prefix.
  1918.  
  1919.  The following exit addresses are restored from the Program Segment
  1920.  Prefix:
  1921.  
  1922.  Offset       Exit Address
  1923.  ───────────────────────────────────────────────────────────────────────────
  1924.  0AH          Program terminate
  1925.  0EH          CONTROL-C
  1926.  12H          Critical error
  1927.  
  1928.  All file buffers are flushed to disk.
  1929.  
  1930.  ───────────────────────────────────────────────────────────────────────────
  1931.  Note
  1932.    You should close all files that have changed in length before issuing
  1933.    this interrupt. If you do not close a changed file, its length may not
  1934.    be recorded correctly in the directory. See Functions 10H and 3EH for
  1935.    a description of the Close File system calls. If sharing is loaded, you
  1936.    should remove all locks before using Interrupt 20H. See Function 5CH
  1937.    (Lock) for more information.
  1938.  ───────────────────────────────────────────────────────────────────────────
  1939.  
  1940.  
  1941.  Macro Definition:
  1942.  
  1943.  terminate  macro
  1944.             int 20H
  1945.             endm
  1946.  
  1947.  
  1948.  Example:
  1949.  
  1950.  The following program displays a message and returns to MS-DOS. It uses
  1951.  only the opening portion of the sample program skeleton shown in
  1952.  Figure 1.2:
  1953.  
  1954.  message db "displayed by INT20H example". 0DH, 0AH, "$"
  1955.  ;
  1956.  begin:  display message  ;see Function 09H
  1957.          terminate        ;THIS INTERRUPT
  1958.  code    ends
  1959.          end     start
  1960.  
  1961.  
  1962.  Function Request (Interrupt 21H)
  1963.  
  1964.  
  1965.  Call:
  1966.  
  1967.  AH
  1968.    Function number
  1969.  
  1970.  Other registers
  1971.    As specified in individual function
  1972.  
  1973.  
  1974.  Return:
  1975.  
  1976.  None.
  1977.  
  1978.  
  1979.  Comments:
  1980.  
  1981.  As specified in individual function. Interrupt 21H causes MS-DOS to
  1982.  carry out the function request whose number is in AH. See Section 1.12,
  1983.  "Function Requests," for a description of the MS-DOS functions.
  1984.  
  1985.  
  1986.  Example:
  1987.  
  1988.  To call the Get Time function:
  1989.  
  1990.  mov   ah,2CH           ;Get Time is Function 2CH
  1991.  int   21H              ;MS-DOS function request
  1992.  
  1993.  
  1994.  Terminate Process Exit Address (Interrupt 22H)
  1995.  
  1996.  
  1997.  This interrupt may be issued only by MS-DOS; user programs must never
  1998.  issue it. If you must write your own terminate interrupt handler, use
  1999.  Function 35H (Get Interrupt Vector) to get the address of the standard
  2000.  routine, save the address, then use Function 25H (Set Interrupt Vector)
  2001.  to change the Interrupt 22H entry in the vector table so that it points
  2002.  to your routine.
  2003.  
  2004.  When a program terminates, MS-DOS transfers control to the routine that
  2005.  starts at the address in the Interrupt 22H entry in the vector table.
  2006.  When MS-DOS creates a program segment, it copies this address into the
  2007.  Program Segment Prefix, starting at offset 0AH.
  2008.  
  2009.  
  2010.  CONTROL-C Handler Address (Interrupt 23H)
  2011.  
  2012.  
  2013.  When you type CONTROL-C or CONTROL-BREAK (on IBM-compatibles), MS-DOS
  2014.  transfers control as soon as possible to the routine that starts at the
  2015.  address in the Interrupt 23H entry in the vector table. When MS-DOS creates
  2016.  a program segment, it copies the address currently in the interrupt table
  2017.  into the Program Segment Prefix, starting at offset 0EH.
  2018.  
  2019.  This interrupt may be issued only by MS-DOS; user programs must never
  2020.  issue it. If you must write your own CONTROL-C interrupt handler, use
  2021.  Function Request 35H (Get Interrupt Vector) to get the address of the
  2022.  standard routine, save the address, then use Function Request 25H (Set
  2023.  Interrupt Vector) to change the Interrupt 23H entry in the vector table
  2024.  to point to your routine.
  2025.  
  2026.  If the CONTROL-C routine preserves all registers, it can end with an
  2027.  IRET instruction (return from interrupt) to continue program execution.
  2028.  If a user-written interrupt program returns with a long return, the program
  2029.  uses the carry flag to determine whether or not the program will abort.
  2030.  If the carry flag is set, it will abort; otherwise, execution will continue
  2031.  as with a return by IRET.
  2032.  
  2033.  If a user-written CONTROL-BREAK routine interrupts function calls 09H,
  2034.  0AH, or buffered I/O, and if it continues execution with an IRET, then I/O
  2035.  continues from the start of the line.  MS-DOS always outputs a CONTROL-C
  2036.  to the screen when it issues an Interrupt 23H.  There is no way to turn
  2037.  this off.
  2038.  
  2039.  When the interrupt occurs, all registers are set to the value they had
  2040.  when the original call to MS-DOS was made. There are no restrictions on
  2041.  what a CONTROL-C handler can do--including calling MS-DOS functions--
  2042.  as long as the program restores the registers.
  2043.  
  2044.  If a CONTROL-C interrupts Function 09H or 0AH (Display String or
  2045.  Buffered Keyboard Input), the three-byte sequence 03H-0DH-0AH (usually
  2046.  displayed as C followed by a carriage-return) is sent to the display and
  2047.  the function resumes at the beginning of the next line.
  2048.  
  2049.  Suppose a program uses Function 4BH (Load and Execute Program) to create
  2050.  a second Program Segment Prefix and execute a second program, which then
  2051.  changes the CONTROL-C address in the vector table. MS-DOS restores this
  2052.  CONTROL-C vector to its original value before returning control to the
  2053.  calling program.
  2054.  
  2055.  
  2056.  Critical-Error-Handler Address (Interrupt 24H)
  2057.  
  2058.  
  2059.  If a critical error occurs during execution of an I/O function request
  2060.  (this often means a fatal disk error), MS-DOS transfers control to the
  2061.  routine at the address in the Interrupt 24H entry in the vector table. When
  2062.  MS-DOS creates a program segment, it copies this address into the Program
  2063.  Segment Prefix, starting at offset 12H.
  2064.  
  2065.  This interrupt may be issued only by MS-DOS; user programs must never
  2066.  issue it. If you must write your own critical-error interrupt handler,
  2067.  use Function 35H (Get Interrupt Vector) to get the address of the standard
  2068.  routine, save the address, then use Function 25H (Set Interrupt Vector)
  2069.  to change the Interrupt 24H entry in the vector table to point to your
  2070.  routine.
  2071.  
  2072.  MS-DOS does not issue Interrupt 24H if a failure occurs during execution
  2073.  Interrupt 25H (Absolute Disk Read) or Interrupt 26H (Absolute Disk Write).
  2074.  A command.com error routines handles these errors. This routine retries
  2075.  the disk operation, then gives you the choice of aborting the operation,
  2076.  retrying it, allowing the system call to fail and the application process
  2077.  to continue, or ignoring the error.
  2078.  
  2079.  The following topics describe the requirements of an Interrupt 24H
  2080.  routine, including the error codes, registers, and stack.
  2081.  
  2082.  
  2083.  1.11.1  Conditions upon Entry
  2084.  
  2085.  After retrying an I/O error five times, MS-DOS issues Interrupt 24H, unless
  2086.  a File Allocation Table (FAT) or directory sector is involved. In those
  2087.  cases, DOS performs three retries. The interrupt handler receives control
  2088.  with interrupts disabled. AX and DI contain error codes, and BP contains
  2089.  the offset (to the segment address in SI) of a Device Header control block
  2090.  that describes the device on which the error occurred.
  2091.  
  2092.  
  2093.  1.11.2  Requirements for an Interrupt 24H Handler
  2094.  
  2095.  To issue the "Abort, Retry, Fail or Ignore" prompt to a user, a user-
  2096.  written critical-error handler should first push the flags and execute
  2097.  a FAR call to the address of the standard Interrupt 24H handler (the user
  2098.  program that changed the Interrupt 24H vector also should have saved this
  2099.  address).  After a user responds to the prompt, MS-DOS returns control
  2100.  to the user-written routine.
  2101.  
  2102.  ───────────────────────────────────────────────────────────────────────────
  2103.  Note
  2104.    There are source applications which will have trouble handling critical
  2105.    errors, since this changes the stack frame.
  2106.  ───────────────────────────────────────────────────────────────────────────
  2107.  
  2108.  The error handler can then do its processing, but before it does anything
  2109.  else it must preserve BX, CX, DX, DS, ES, SS, and SP. Also, the error
  2110.  handler may use only function calls 01-0CH (inclusive) and 59H (if it uses
  2111.  any others, the error handler destroys the MS-DOS stack and leaves MS-DOS
  2112.  in an unstable state). The contents of the Device Header should not be
  2113.  changed.
  2114.  
  2115.  It is recommended that Interrupt 24H routine fail critical errors and
  2116.  let the application test for an extended error code when the Interrupt 21H
  2117.  routine returns.
  2118.  
  2119.  
  2120.  User Stack
  2121.  
  2122.  This call uses the user stack that contains the following (starting
  2123.  with the top of the stack):
  2124.  
  2125.  IP     MS-DOS registers from issuing Interrupt 24H
  2126.  CS
  2127.  FLAGS
  2128.  
  2129.  AX     User registers at time of original
  2130.  BX     INT 21H
  2131.  CX
  2132.  DX
  2133.  SI
  2134.  DI
  2135.  BP
  2136.  DS
  2137.  ES
  2138.  
  2139.  IP     From the original INT 21H
  2140.  CS     from the user to MS-DOS
  2141.  FLAGS
  2142.  
  2143.  The registers are set such that if the user-written error handler issues an
  2144.  IRET, MS-DOS responds according to the value in AL:
  2145.  
  2146.  AL   Action
  2147.  ───────────────────────────────────────────────────────────────────────────
  2148.  0    Ignore the error.
  2149.  1    Retry the operation.
  2150.  2    Abort the program by issuing Interrupt 23H.
  2151.  3    Fail the system call that is in progress.
  2152.  
  2153.  Note that the ignore option may cause unexpected results, such as
  2154.  causing MS-DOS to behave as if an operation had completed successfully.
  2155.  
  2156.  
  2157.  Disk Error Code in AX
  2158.  
  2159.  If bit 7 of AH is 0, the error occurred on a disk drive. AL contains the
  2160.  failing drive (0=A, 1=B, etc.). Bit 0 of AH specifies whether the error
  2161.  occurred during a read or write operation (0=read, 1=write), and bits 1
  2162.  and 2 of AH identify the area of the disk where the error occurred:
  2163.  
  2164.  Bits 1-2   Location of error
  2165.  ───────────────────────────────────────────────────────────────────────────
  2166.  00         MS-DOS area
  2167.  01         File Allocation Table
  2168.  10         Directory
  2169.  11         Data area
  2170.  
  2171.  Bits 3-5 of AH specify valid responses to the error prompt:
  2172.  
  2173.  Bit   Value   Response
  2174.  ───────────────────────────────────────────────────────────────────────────
  2175.  3     0       Fail not allowed
  2176.        1       Fail allowed
  2177.  4     0       Retry not allowed
  2178.        1       Retry allowed
  2179.  5     0       Ignore not allowed
  2180.        1       Ignore allowed
  2181.  
  2182.  If you specify Retry but it isn't allowed, MS-DOS changes it to Fail. If
  2183.  you specify Ignore but it isn't allowed, MS-DOS changes it to Fail. If you
  2184.  specify Fail but it isn't allowed, MS-DOS changes it to Abort. The Abort
  2185.  response is always allowed.
  2186.  
  2187.  
  2188.  Other Device Error Code in AX
  2189.  
  2190.  If bit 7 of AH is 1, either the memory image of the File Allocation Table
  2191.  (FAT) is bad or an error occurred on a character device. The device header
  2192.  pointed to by BP:SI contains a WORD of attribute bits that identify the
  2193.  type of device and, therefore, the type of error.
  2194.  
  2195.  The word of attribute bits is at offset 04H of the Device Header. Bit 15
  2196.  specifies the type of device (0=block, 1=character).
  2197.  
  2198.  If bit 15 is 0 (block device), the error was a bad memory image of the FAT.
  2199.  
  2200.  If bit 15 is 1 (character device), the error was on a character device.
  2201.  DI contains the error code, the contents of AL are undefined, and bits 0-3
  2202.  of the attribute word have the following meaning:
  2203.  
  2204.  Bit  Meaning if Set
  2205.  ───────────────────────────────────────────────────────────────────────────
  2206.  0    Current standard input
  2207.  1    Current standard output
  2208.  2    Current null device
  2209.  3    Current clock device
  2210.  
  2211.  See Chapter 2, "MS-DOS Device Drivers," for a complete description of
  2212.  the Device Header control block.
  2213.  
  2214.  
  2215.  Error Code in DI
  2216.  
  2217.  The high byte of DI is undefined. The low byte contains the following
  2218.  error codes:
  2219.  
  2220.  Error code   Description
  2221.  ───────────────────────────────────────────────────────────────────────────
  2222.  0            Attempt to write on write-protected disk
  2223.  1            Unknown unit
  2224.  2            Drive not ready
  2225.  3            Unknown command
  2226.  4            CRC error in data
  2227.  5            Bad drive request structure length
  2228.  6            Seek error
  2229.  7            Unknown media type
  2230.  8            Sector not found
  2231.  9            Printer out of paper
  2232.  A            Write fault
  2233.  B            Read fault
  2234.  C            General failure
  2235.  
  2236.  A user-written Interrupt 24H handler can use Function 59H (Get Extended
  2237.  Error) to get detailed information about the error that caused the
  2238.  interrupt to be issued.
  2239.  
  2240.  
  2241.  Absolute Disk Read (Interrupt 25H)
  2242.  
  2243.  
  2244.  Call:
  2245.  
  2246.  AL
  2247.    Drive number
  2248.  DS:BX
  2249.    Disk Transfer Address
  2250.  CX
  2251.    Number of sectors
  2252.  DX
  2253.    Beginning relative sector
  2254.  
  2255.  
  2256.  Return:
  2257.  
  2258.  AL
  2259.    Error code if CF=1
  2260.  Flags
  2261.    CF      = 0 if successful
  2262.            = 1 if not successful
  2263.  
  2264.  
  2265.  Comments:
  2266.  
  2267.  The registers must contain the following:
  2268.  
  2269.  Register      Contents
  2270.  ───────────────────────────────────────────────────────────────────────────
  2271.  AL            Drive number (0=A, 1=B, etc.)
  2272.  BX            Offset of Disk Transfer Address (from segment address in DS)
  2273.  CX            Number of sectors to read
  2274.  DX            Beginning relative sector
  2275.  
  2276.  ───────────────────────────────────────────────────────────────────────────
  2277.  Warning
  2278.    Avoid using this function unless absolutely necessary. Instead, you
  2279.    should access files through normal MS-DOS function requests. There is no
  2280.    guarantee of upward compatibility for the Absolute Disk I/O in future
  2281.    releases of MS-DOS.
  2282.  ───────────────────────────────────────────────────────────────────────────
  2283.  
  2284.  Interrupt 25H transfers control to the device driver and reads from the
  2285.  disk to the Disk-Transfer Address the number of sectors specified in CX.
  2286.  The interrupt has the same requirements as and processes identically to
  2287.  Interrupt 26H (Absolute Disk Write), except that it reads data rather than
  2288.  writes it. Also, since this interrupt does not check your input parameters
  2289.  too closely, make sure they are reasonable. If you use unreasonable
  2290.  parameters, you may get strange results or cause your system to crash.
  2291.  
  2292.  ───────────────────────────────────────────────────────────────────────────
  2293.  Note
  2294.    This call destroys all registers except the segment registers. So before
  2295.    issuing the interrupt, save any registers that your program uses.
  2296.  ───────────────────────────────────────────────────────────────────────────
  2297.  
  2298.  The system pushes the flags at the time of the call; they are still
  2299.  there upon return. To prevent uncontrolled growth, be sure to pop the
  2300.  stack upon return.
  2301.  
  2302.  If the disk operation is successful, the Carry Flag (CF) is 0. If the
  2303.  disk operation is not successful, CF is 1 and AL contains the MS-DOS error
  2304.  code (see Interrupt 24H earlier in this section for the codes and their
  2305.  meanings).
  2306.  
  2307.  
  2308.  Macro Definition:
  2309.  
  2310.  abs_disk_read  macro  disk,buffer,num_sectors,first_sector
  2311.                 mov    al,disk
  2312.                 mov    bx,offset buffer
  2313.                 mov    cx,num_sectors
  2314.                 mov    dx,first_sector
  2315.                 int    25H
  2316.                 popf
  2317.                 endm
  2318.  
  2319.  
  2320.  Example:
  2321.  
  2322.  The following program copies the contents of a single-sided disk in drive A
  2323.  to the disk in drive B.
  2324.  
  2325.  prompt     db   "Source in A, target in B",0DH,0AH
  2326.             db   "Any key to start. $"
  2327.  first      dw    0
  2328.  buffer     db    60 dup (512 dup (?))  ;60 sectors
  2329.  ;
  2330.  begin:     display prompt         ;see Function 09H
  2331.             read_kbd               ;see Function 08H
  2332.             mov     cx,6           ;copy 6 groups of
  2333.                                    ;60 sectors
  2334.  copy:      push    cx             ;save the loop counter
  2335.             abs_disk_read  0,buffer,60,first  ;THIS INTERRUPT
  2336.             abs_disk_write 1,buffer,60,first  ;see INT 26H
  2337.             add  first,60          ;do the next 60 sectors
  2338.             pop  cx                ;restore the loop counter
  2339.             loop copy
  2340.  
  2341.  
  2342.  Absolute Disk Write (Interrupt 26H)
  2343.  
  2344.  
  2345.  Call:
  2346.  
  2347.  AL
  2348.    Drive number
  2349.  DS:BX
  2350.    Disk Transfer Address
  2351.  CX
  2352.    Number of sectors
  2353.  DX
  2354.    Beginning relative sector
  2355.  
  2356.  
  2357.  Return:
  2358.  
  2359.  AL
  2360.    Error code if CF = 1
  2361.  FLAGS
  2362.    CF      = 0 if successful
  2363.            = 1 if not successful
  2364.  
  2365.  
  2366.  Comments:
  2367.  
  2368.  ───────────────────────────────────────────────────────────────────────────
  2369.  Warning
  2370.    Avoid using this function unless absolutely necessary. Instead, you
  2371.    should access files through normal MS-DOS function requests. There is
  2372.    no guarantee of upward compatibility for the Absolute Disk I/O in future
  2373.    releases of MS-DOS.
  2374.  ───────────────────────────────────────────────────────────────────────────
  2375.  
  2376.  The registers must contain the following:
  2377.  
  2378.  Register       Contents
  2379.  ───────────────────────────────────────────────────────────────────────────
  2380.  AL             Drive number (0=A, 1=B, etc.)
  2381.  BX             Offset of Disk Transfer Address (from segment address in DS)
  2382.  CX             Number of sectors to write
  2383.  DX             Beginning relative sector
  2384.  
  2385.  This interrupt transfers control to MS-DOS. The number of sectors
  2386.  specified in CX is written from the Disk Transfer Address to the disk. Its
  2387.  requirements and processing are identical to Interrupt 25H (Absolute Disk
  2388.  Read), except data is written to the disk rather than read from it. Also,
  2389.  since Interrupt 26H does not check your input parameters too closely, make
  2390.  sure they are reasonable. If you use unreasonable parameters, you may get
  2391.  strange results or cause your system to crash.
  2392.  
  2393.  ───────────────────────────────────────────────────────────────────────────
  2394.  Note
  2395.    This call destroys all registers except the segment registers. So before
  2396.    issuing the interrupt, be sure to save any registers your program uses.
  2397.  ───────────────────────────────────────────────────────────────────────────
  2398.  
  2399.  The system pushes the flags at the time of the call; they are still there
  2400.  upon return. To prevent uncontrolled growth, be sure to pop the stack upon
  2401.  return.
  2402.  
  2403.  If the disk operation is successful, the Carry Flag (CF) is 0. If the
  2404.  disk operation is not successful, CF is 1 and AL contains the MS-DOS error
  2405.  code (see Interrupt 24H for the codes and their meanings).
  2406.  
  2407.  
  2408.  Macro Definition:
  2409.  
  2410.  abs_disk_write  macro  disk,buffer,num_sectors,first_sector
  2411.                  mov    al,disk
  2412.                  mov    bx,offset buffer
  2413.                  mov    cx,num_sectors
  2414.                  mov    dx,first_sector
  2415.                  int    26H
  2416.                  popf
  2417.                  endm
  2418.  
  2419.  
  2420.  Example:
  2421.  
  2422.  The following program copies the contents of a single-sided disk in drive A
  2423.  to the disk in drive B, verifying each write. It uses a buffer of 32K
  2424.  bytes.
  2425.  
  2426.  off        equ   0
  2427.  on         equ   1
  2428.  ;
  2429.  prompt     db   "Source in A, target in B",0DH,0AH
  2430.             db   "Any key to start. $"
  2431.  first      dw    0
  2432.  buffer     db    60 dup (512 dup (?))  ;60 sectors
  2433.  ;
  2434.  begin:     display prompt       ;see Function 09H
  2435.             read_kbd             ;see Function 08H
  2436.             verify  on           ;see Function 2EH
  2437.             mov     cx,6         ;copy 6 groups of 60 sectors
  2438.  copy:      push    cx           ;save the loop counter
  2439.             abs_disk_read  0,buffer,60,first  ;see INT 25H
  2440.             abs_disk_write 1,buffer,60,first  ;THIS INTERRUPT
  2441.             add  first,60        ;do the next 60 sectors
  2442.             pop  cx              ;restore the loop counter
  2443.             loop copy
  2444.             verify  off          ;see Function 2EH
  2445.  
  2446.  
  2447.  Terminate But Stay Resident (Interrupt 27H)
  2448.  
  2449.  
  2450.  Call:
  2451.  
  2452.  CS:DX
  2453.    Pointer to first byte following
  2454.    last byte of code.
  2455.  
  2456.  
  2457.  Return:
  2458.  
  2459.  None
  2460.  
  2461.  
  2462.  Comments:
  2463.  
  2464.  This interrupt is provided only for compatibility with MS-DOS versions
  2465.  prior to 2.0. Unless your resident program must be compatible with MS-DOS
  2466.  versions before 2.0, you should use Function 31H (Keep Process) to install
  2467.  it. Function 31H lets programs larger than 64K remain resident and allows
  2468.  return information to be passed.
  2469.  
  2470.  However, Interrupt 27H, which is often used to install device-specific
  2471.  interrupt handlers, forces programs that are up to 64K to remain resident
  2472.  after they terminate.
  2473.  
  2474.  DX must contain the offset (from the segment address in CS) of the first
  2475.  byte that follows the last byte of code in the program. When Interrupt 27H
  2476.  is executed, the program terminates and control returns to MS-DOS, but the
  2477.  program is not overlaid by other programs. Files left open are not closed.
  2478.  When the interrupt is called, CS must contain the segment address of the
  2479.  Program Segment Prefix (the value of DS and ES when execution started).
  2480.  
  2481.  .Exe programs that are loaded into high memory must not use this
  2482.  interrupt. Similarly, since it restores the Interrupt 22H, 23H, and
  2483.  24H vectors, you should not use Interrupt 27H to install new CONTROL-C
  2484.  or critical-error handlers.
  2485.  
  2486.  
  2487.  Macro Definition:
  2488.  
  2489.  stay_resident  macro last_instruc
  2490.                 mov   dx,offset last_instruc
  2491.                 inc   dx
  2492.                 int   27H
  2493.                 endm
  2494.  
  2495.  
  2496.  Example:
  2497.  
  2498.  Since the most common use of Interrupt 27H is to install a machine-specific
  2499.  routine, there is no general example that applies. The macro definition,
  2500.  however, shows the calling syntax.
  2501.  
  2502.  
  2503.  1.12  Function Requests
  2504.  
  2505.  
  2506.  The following pages describe function calls 00H-68H.
  2507.  
  2508.  
  2509.  Terminate Program (Function 00H)
  2510.  
  2511.  
  2512.  Call:
  2513.  
  2514.  AH = 00H
  2515.  CS
  2516.    Segment address of
  2517.    Program Segment Prefix
  2518.  
  2519.  
  2520.  Return:
  2521.  
  2522.  None
  2523.  
  2524.  
  2525.  Comments:
  2526.  
  2527.  
  2528.  Function 00H performs the same function as Interrupt 20H. It terminates
  2529.  the current process and returns control to its parent process. It also
  2530.  closes all open file handles and clears the disk cache. When this
  2531.  interrupt is issued, CS must contain the segment address of the Program
  2532.  Segment Prefix.
  2533.  
  2534.  The CS register must contain the segment address of the Program
  2535.  Segment Prefix before you call this interrupt.
  2536.  
  2537.  The following exit addresses are restored from the specified offsets
  2538.  in the Program Segment Prefix:
  2539.  
  2540.  Offset        Exit Address
  2541.  ───────────────────────────────────────────────────────────────────────────
  2542.  0AH     Program terminate
  2543.  0EH     CONTROL-C
  2544.  12H     Critical error
  2545.  
  2546.  All file buffers are flushed to disk.
  2547.  
  2548.  ───────────────────────────────────────────────────────────────────────────
  2549.  Warning
  2550.    Close all files that have changed in length before calling this function.
  2551.    If you do not close a changed file, its length is not correctly recorded
  2552.    in the directory. See Function 10H for a description of the Close File
  2553.    system call.
  2554.  ───────────────────────────────────────────────────────────────────────────
  2555.  
  2556.  
  2557.  Macro Definition:
  2558.  
  2559.  terminate_program  macro
  2560.                     xor    ah,ah
  2561.                     int    21H
  2562.                     endm
  2563.  
  2564.  
  2565.  Example:
  2566.  
  2567.  The following program displays a message and returns to MS-DOS. It uses
  2568.  only the opening portion of the sample program skeleton shown in Figure
  2569.  1.2.
  2570.  
  2571.  message db "Displayed by FUNC00H example", 0DH,0AH,"$"
  2572.  ;
  2573.  begin:  display message    ;see Function 09H
  2574.          terminate_program  ;THIS FUNCTION
  2575.  code    ends
  2576.          end    start
  2577.  
  2578.  
  2579.  Read Keyboard and Echo (Function 01H)
  2580.  
  2581.  
  2582.  Call:
  2583.  
  2584.  AH = 01H
  2585.  
  2586.  
  2587.  Return:
  2588.  
  2589.  AL
  2590.    Character typed
  2591.  
  2592.  
  2593.  Comments:
  2594.  
  2595.  Function 01H waits for a character to be read from standard input, then
  2596.  echoes the character to standard output and returns it in AL. If the
  2597.  character is CONTROL-C, it executes Interrupt 23H.
  2598.  
  2599.  
  2600.  Macro Definition:
  2601.  
  2602.  read_kbd_and_echo  macro
  2603.                     mov  ah, 01H
  2604.                     int  21H
  2605.                     endm
  2606.  
  2607.  
  2608.  Example:
  2609.  
  2610.  The following program displays and prints characters as you type them.
  2611.  If you press the RETURN key, the program sends a linefeed/carriage-return
  2612.  sequence to both the display and the printer.
  2613.  
  2614.  begin:     read_kbd_and_echo         ;THIS FUNCTION
  2615.             print_char   al           ;see Function 05H
  2616.             cmp          al,0DH       ;is it a CR?
  2617.             jne          begin        ;no, print it
  2618.             print_char   0AH          ;see Function 05H
  2619.             display_char 0AH          ;see Function 02H
  2620.             jmp          begin        ;get another character
  2621.  
  2622.  
  2623.  Display Character (Function 02H)
  2624.  
  2625.  
  2626.  Call:
  2627.  
  2628.  AH = 02H
  2629.  DL
  2630.    Character to be displayed
  2631.  
  2632.  
  2633.  Return:
  2634.  
  2635.  None
  2636.  
  2637.  
  2638.  Comments:
  2639.  
  2640.  Function 02H sends the character in DL to standard output. If you press
  2641.  CONTROL-C, it issues Interrupt 23H.
  2642.  
  2643.  
  2644.  Macro Definition:
  2645.  
  2646.  display_char macro   character
  2647.               mov     dl,character
  2648.               mov     ah,02H
  2649.               int     21H
  2650.               endm
  2651.  
  2652.  
  2653.  Example:
  2654.  
  2655.  The following program converts lowercase characters to uppercase before
  2656.  displaying them.
  2657.  
  2658.  begin:     read_kbd                 ;see Function 08H
  2659.             cmp     al,"a"
  2660.             jl      uppercase        ;don't convert
  2661.             cmp     al,"z"
  2662.             jg      uppercase        ;don't convert
  2663.             sub     al,20H           ;convert to ASCII code
  2664.                                      ;for uppercase
  2665.  uppercase: display_char al          ;THIS FUNCTION
  2666.             jmp     begin:           ;get another character
  2667.  
  2668.  
  2669.  Auxiliary Input (Function 03H)
  2670.  
  2671.  
  2672.  Call:
  2673.  
  2674.  AH = 03H
  2675.  
  2676.  
  2677.  Return:
  2678.  
  2679.  AL
  2680.    Character from auxiliary device
  2681.  
  2682.  
  2683.  Comments:
  2684.  
  2685.  Function 03H waits for a character from standard auxiliary devices (AUX,
  2686.  COM1, COM2, COM3, COM4), then returns the character in AL. This system
  2687.  call does not return a status or error code.
  2688.  
  2689.  If you press CONTROL-C, it issues Interrupt 23H.
  2690.  
  2691.  
  2692.  Macro Definition:
  2693.  
  2694.  aux_input  macro
  2695.             mov  ah,03H
  2696.             int  21H
  2697.             endm
  2698.  
  2699.  
  2700.  Example:
  2701.  
  2702.  The following program prints characters as soon as it receives them from
  2703.  the auxiliary device. It stops printing when it receives an end-of-file
  2704.  character (ASCII 26, or CONTROL-Z).
  2705.  
  2706.  begin:     aux_input        ;THIS FUNCTION
  2707.             cmp   al,1AH     ;end of file?
  2708.             je    return     ;yes, all done
  2709.             print_char  al   ;see Function 05H
  2710.             jmp   begin      ;get another character
  2711.  
  2712.  
  2713.  Auxiliary Output (Function 04H)
  2714.  
  2715.  
  2716.  Call:
  2717.  
  2718.  AH = 04H
  2719.  DL
  2720.    Character for auxiliary device
  2721.  
  2722.  
  2723.  Return:
  2724.  
  2725.  None
  2726.  
  2727.  
  2728.  Comments:
  2729.  
  2730.  Function 04H sends the character in DL to standard auxiliary. This system
  2731.  call does not return a status or error code.
  2732.  
  2733.  If you press CONTROL-C, it issues Interrupt 23H.
  2734.  
  2735.  
  2736.  Macro Definition:
  2737.  
  2738.  aux_output  macro  character
  2739.              mov  dl,character
  2740.              mov  ah,04H
  2741.              int  21H
  2742.              endm
  2743.  
  2744.  
  2745.  Example:
  2746.  
  2747.  The following program gets a series of strings of up to 80 bytes from the
  2748.  keyboard and sends each string to the auxiliary device. It stops when you
  2749.  type a null string (carriage-return only).
  2750.  
  2751.  string   db    81 dup(?) ;see Function 0AH
  2752.  ;
  2753.  begin:   get_string  80,string       ;see Function 0AH
  2754.           cmp  string[1],0            ;null string?
  2755.           je   return                 ;yes, all done
  2756.           mov  cx, word ptr string[1] ;get string length
  2757.           mov  bx,0                   ;set index to 0
  2758.  send_it: aux_output string[bx+2]     ;THIS FUNCTION
  2759.           inc  bx                     ;bump index
  2760.           loop  send_it               ;send another character
  2761.           jmp  begin                  ;get another string
  2762.  
  2763.  
  2764.  Print Character (Function 05H)
  2765.  
  2766.  
  2767.  Call:
  2768.  
  2769.  AH = 05H
  2770.  DL
  2771.    Character for printer
  2772.  
  2773.  
  2774.  Return:
  2775.  
  2776.  None
  2777.  
  2778.  
  2779.  Comments:
  2780.  
  2781.  Function 05H sends the character in DL to the standard printer. If you
  2782.  press CONTROL-C, it issues Interrupt 23H. This function does not return
  2783.  a status or error code.
  2784.  
  2785.  
  2786.  Macro Definition:
  2787.  
  2788.  print_char macro character
  2789.             mov   dl,character
  2790.             mov   ah,05H
  2791.             int   21H
  2792.             endm
  2793.  
  2794.  
  2795.  Example:
  2796.  
  2797.  The following program prints a walking test pattern on the printer. It
  2798.  stops if you press CONTROL-C.
  2799.  
  2800.  line_num    db    0
  2801.  ;
  2802.  begin:      mov   cx,60        ;print 60 lines
  2803.  start_line: mov   bl,33        ;first printable ASCII
  2804.                                 ;character (!)
  2805.              add   bl,line_num  ;to offset one character
  2806.              push  cx           ;save number-of-lines counter
  2807.              mov   cx,80        ;loop counter for line
  2808.  print_it:   print_char bl      ;THIS FUNCTION
  2809.              inc   bl           ;move to next ASCII character
  2810.              cmp   bl,126       ;last printable ASCII
  2811.                                 ;character (~)
  2812.              jl    no_reset     ;not there yet
  2813.              mov   bl,33        ;start over with (!)
  2814.  no_reset:   loop  print_it     ;print another character
  2815.              print_char 0DH     ;carriage return
  2816.              print_char 0AH     ;linefeed
  2817.              inc   line_num     ;to offset 1st char. of line
  2818.              pop   cx           ;restore #-of-lines counter
  2819.              loop  start_line   ;print another line
  2820.  
  2821.  
  2822.  Direct Console I/O (Function 06H)
  2823.  
  2824.  
  2825.  Call:
  2826.  
  2827.  AH = 06H
  2828.  DL
  2829.    See text
  2830.  
  2831.  
  2832.  Return:
  2833.  
  2834.  AL
  2835.    If DL = FFH  before call,
  2836.    then zero flag not set means AL
  2837.    has character from standard input.
  2838.    Zero flag set means there was not
  2839.    a character to get, and AL = 0.
  2840.  
  2841.  
  2842.  Comments:
  2843.  
  2844.  The action of Function 06H depends on the value in DL when the function
  2845.  is called:
  2846.  
  2847.  Value in DL  Action
  2848.  ───────────────────────────────────────────────────────────────────────────
  2849.  FFH          If a character has been read from standard input, it is
  2850.               returned in AL and the zero flag is cleared (0); if a
  2851.               character has not been read, the zero flag is set (1).
  2852.  
  2853.  Not FFH      The character in DL is sent to standard output.
  2854.  
  2855.  This function does not check for CONTROL-C.
  2856.  
  2857.  
  2858.  Macro Definition:
  2859.  
  2860.  dir_console_io  macro switch
  2861.                  mov  dl,switch
  2862.                  mov  ah,06H
  2863.                  int  21H
  2864.                  endm
  2865.  
  2866.  
  2867.  Example:
  2868.  
  2869.  The following program sets the system clock to 0 and displays the time
  2870.  continuously. When you type any character, the display freezes; when you
  2871.  type any character again, the clock is reset to 0 and the display starts
  2872.  again.
  2873.  
  2874.  time      db  "00:00:00.00",0DH,0AH,"$"  ;see Function 09H
  2875.  ;                                     ;for explanation of $
  2876.  ;
  2877.  begin:        set_time  0,0,0,0       ;see Function 2DH
  2878.  read_clock:   get_time                ;see Function 2CH
  2879.                CONVERT  ch,time        ;see end of chapter
  2880.                CONVERT  cl,time[3]     ;see end of chapter
  2881.                CONVERT  dh,time[6]     ;see end of chapter
  2882.                CONVERT  dl,time[9]     ;see end of chapter
  2883.                display  time           ;see Function 09H
  2884.                dir_console_io  FFH     ;THIS FUNCTION
  2885.                cmp      al,0           ;character typed?
  2886.                jne      stop           ;yes, stop timer
  2887.                jmp      read_clock     ;no, keep timer
  2888.                                        ;running
  2889.  stop:         read_kbd                ;see Function 08H
  2890.                jmp      begin          ;start over
  2891.  
  2892.  
  2893.  Direct Console Input (Function 07H)
  2894.  
  2895.  
  2896.  Call:
  2897.  
  2898.  AH = 07H
  2899.  
  2900.  
  2901.  Return:
  2902.  
  2903.  AL
  2904.    Character from keyboard
  2905.  
  2906.  
  2907.  Comments:
  2908.  
  2909.  Function 07H waits for a character to be read from standard input, then
  2910.  returns it in AL. This function does not echo the character or check
  2911.  for CONTROL-C. (For a keyboard input function that echoes or checks for
  2912.  CONTROL-C, see Function 01H or 08H.)
  2913.  
  2914.  
  2915.  Macro Definition:
  2916.  
  2917.  dir_console_input  macro
  2918.                     mov  ah,07H
  2919.                     int  21H
  2920.                     endm
  2921.  
  2922.  
  2923.  Example:
  2924.  
  2925.  The following program prompts for a password (eight characters maximum) and
  2926.  places the characters into a string without echoing them.
  2927.  
  2928.  password  db  8 dup(?)
  2929.  prompt    db "Password: $"       ;see Function 09H for
  2930.                                   ;explanation of $
  2931.  begin:    display prompt         ;see Function 09H
  2932.            mov  cx,8              ;maximum length of password
  2933.            xor  bx,bx             ;so BL can be used as index
  2934.  get_pass: dir_console_input      ;THIS FUNCTION
  2935.            cmp  al,0DH            ;was it a carriage return?
  2936.            je   return            ;yes, all done
  2937.            mov  password[bx],al   ;no, put character in string
  2938.            inc  bx                ;bump index
  2939.            loop get_pass          ;get another character
  2940.  
  2941.  
  2942.  Read Keyboard (Function 08H)
  2943.  
  2944.  
  2945.  Call:
  2946.  
  2947.  AH = 08H
  2948.  
  2949.  
  2950.  Return:
  2951.  
  2952.  AL
  2953.    Character from keyboard
  2954.  
  2955.  
  2956.  Comments:
  2957.  
  2958.  Function 08H waits for a character to be read from standard input, then
  2959.  returns it in AL. If you press CONTROL-C, it issues Interrupt 23H. This
  2960.  function does not echo the character. (For a keyboard input function
  2961.  that echoes the character or checks for CONTROL-C, see Function 01H.)
  2962.  
  2963.  
  2964.  Macro Definition:
  2965.  
  2966.  read_kbd  macro
  2967.            mov   ah,08H
  2968.            int   21H
  2969.            endm
  2970.  
  2971.  
  2972.  Example:
  2973.  
  2974.  The following program prompts for a password (eight characters maximum) and
  2975.  places the characters into a string without echoing them.
  2976.  
  2977.  password  db  8 dup(?)
  2978.  prompt    db "Password: $"      ;see Function 09H
  2979.                                  ;for explanation of $
  2980.  begin:    display prompt        ;see Function 09H
  2981.            mov  cx,8             ;maximum length of password
  2982.            xor  bx,bx            ;BL can be an index
  2983.  get_pass: read_kbd              ;THIS FUNCTION
  2984.            cmp  al,0DH           ;was it a carriage return?
  2985.            je   return           ;yes, all done
  2986.            mov  password[bx],al  ;no, put char. in string
  2987.            inc  bx               ;bump index
  2988.            loop get_pass         ;get another character
  2989.  
  2990.  
  2991.  Display String (Function 09H)
  2992.  
  2993.  
  2994.  Call:
  2995.  
  2996.  AH = 09H
  2997.  DS:DX
  2998.    Pointer to string to be displayed
  2999.  
  3000.  
  3001.  Return:
  3002.  
  3003.  None
  3004.  
  3005.  
  3006.  Comments:
  3007.  
  3008.  Function 09H sends to standard output a string that ends with "$" (the $ is
  3009.  not displayed).
  3010.  
  3011.  The DX register must contain the offset (from the segment address in
  3012.  DS) of the string.
  3013.  
  3014.  
  3015.  Macro Definition:
  3016.  
  3017.  display  macro string
  3018.           mov   dx,offset string
  3019.           mov   ah,09H
  3020.           int   21H
  3021.           endm
  3022.  
  3023.  
  3024.  Example:
  3025.  
  3026.  The following program displays the hexadecimal code of the key that
  3027.  is typed.
  3028.  
  3029.  table    db     "0123456789ABCDEF"
  3030.  result   db     " - 00H",0DH,0AH,"$"  ;see text for
  3031.                                        ;explanation of $
  3032.  begin:   read_kbd_and_echo            ;see Function 01H
  3033.           xor     ah,ah                ;clear upper byte
  3034.           convert ax,16,result[3]      ;see end of chapter
  3035.           display result               ;THIS FUNCTION
  3036.           jmp     begin                ;do it again
  3037.  
  3038.  
  3039.  Buffered Keyboard Input (Function 0AH)
  3040.  
  3041.  
  3042.  Call:
  3043.  
  3044.  AH = 0AH
  3045.  DS:DX
  3046.    Pointer to input buffer
  3047.  
  3048.  
  3049.  Return:
  3050.  
  3051.  None
  3052.  
  3053.  
  3054.  Comments:
  3055.  
  3056.  Function 0AH gets a string from standard input. DX must contain the offset
  3057.  (from the segment address in DS) of an input buffer of the following form:
  3058.  
  3059.  Byte     Contents
  3060.  ───────────────────────────────────────────────────────────────────────────
  3061.  1        Maximum number of characters in buffer, including the carriage
  3062.           return (you must set this value).
  3063.  
  3064.  2        Actual number of characters typed, not counting the carriage
  3065.           return (the function sets this value).
  3066.  
  3067.  3-n      Buffer; must be at least as long as the number in byte 1.
  3068.  
  3069.  Characters are read from standard input and placed in the buffer
  3070.  beginning at the third byte until a RETURN character (ASCII 0DH) is read.
  3071.  If the buffer fills to one less than the maximum, additional characters
  3072.  read are ignored and ASCII 07H (Bel) is sent to standard output until
  3073.  a RETURN character is read. If you type the string at the console, it
  3074.  can be edited as it is being entered. If you press CONTROL-C, it issues
  3075.  Interrupt 23H.
  3076.  
  3077.  MS-DOS sets the second byte of the buffer to the number of characters
  3078.  read (not counting the carriage return).
  3079.  
  3080.  
  3081.  Macro Definition:
  3082.  
  3083.  get_string  macro  limit,string
  3084.              mov    dx,offset string
  3085.              mov    string,limit
  3086.              mov    ah,0AH
  3087.              int    21H
  3088.              endm
  3089.  
  3090.  
  3091.  Example:
  3092.  
  3093.  The following program gets a 16-byte (maximum) string from the keyboard and
  3094.  fills a 24-line by 80-character screen with it.
  3095.  
  3096.  buffer           label byte
  3097.  max_length       db    ?                ;maximum length
  3098.  chars_entered    db    ?                ;number of chars.
  3099.  string           db    17 dup (?)       ;16 chars + CR
  3100.  strings_per_line dw    0                ;how many strings
  3101.                                          ;fit on line
  3102.  crlf             db    0DH,0AH
  3103.  ;
  3104.  begin:           get_string 17,buffer   ;THIS FUNCTION
  3105.                   xor  bx,bx             ;so byte can be
  3106.                                          ;used as index
  3107.                   mov  bl,chars_entered  ;get string length
  3108.                   mov  buffer[bx+2],"$"  ;see Function 09H
  3109.                   mov  al,50H            ;columns per line
  3110.                   cbw
  3111.                   div  chars_entered     ;times string fits
  3112.                                          ;on line
  3113.                   xor  ah,ah             ;clear remainder
  3114.                   mov  strings_per_line,ax ;save col. counter
  3115.                   mov  cx,24             ;row counter
  3116.  display_screen:  push cx                ;save it
  3117.                   mov  cx,strings_per_line ;get col. counter
  3118.  display_line:    display  string        ;see Function 09H
  3119.                   loop display_line
  3120.                   display crlf           ;see Function 09H
  3121.                   pop  cx                ;get line counter
  3122.                   loop display_screen    ;display 1 more line
  3123.  
  3124.  
  3125.  Check Keyboard Status (Function 0BH)
  3126.  
  3127.  
  3128.  Call:
  3129.  
  3130.  AH = 0BH
  3131.  
  3132.  
  3133.  Return:
  3134.  
  3135.  AL
  3136.    00H     = no characters in type-ahead buffer
  3137.    FFH     = characters in type-ahead buffer
  3138.  
  3139.  
  3140.  Comments:
  3141.  
  3142.  Function 0BH checks whether characters are available from standard input
  3143.  (if standard input has not been redirected, it checks the type-ahead
  3144.  buffer). If characters are available, AL returns FFH; if not, AL returns
  3145.  0. If CONTROL-C is in the buffer, it issues Interrupt 23H.
  3146.  
  3147.  
  3148.  Macro Definition:
  3149.  
  3150.  check_kbd_status  macro
  3151.                    mov   ah,0BH
  3152.                    int   21H
  3153.                    endm
  3154.  
  3155.  
  3156.  Example:
  3157.  
  3158.  The following program displays the time continuously until you press
  3159.  any key:
  3160.  
  3161.  time        db       "00:00:00.00",0DH,0AH,"$"
  3162.             .
  3163.             .
  3164.  begin:      get_time                  ;see Function 2CH
  3165.              byte_to_dec ch,time       ;see end of chapter
  3166.              byte_to_dec cl,time[3]    ;see end of chapter
  3167.              byte_to_dec dh,time[6]    ;see end of chapter
  3168.              byte_to_dec dl,time[9]    ;see end of chapter
  3169.              display time              ;see Function 09H
  3170.              check_kbd_status          ;THIS FUNCTION
  3171.              cmp     al,0FFH           ;has a key been typed?
  3172.              je      return            ;yes, go home
  3173.              jmp     begin             ;no, keep displaying
  3174.                                        ;time
  3175.  
  3176.  
  3177.  Flush Buffer, Read Keyboard (Function 0CH)
  3178.  
  3179.  
  3180.  Call:
  3181.  
  3182.  AH = 0CH
  3183.  AL
  3184.    1, 6, 7, 8, or 0AH = the
  3185.    corresponding function
  3186.    is called.
  3187.    Any other value = no
  3188.    further processing.
  3189.  
  3190.  
  3191.  Return:
  3192.  
  3193.  AL
  3194.    00H = Type-ahead buffer was
  3195.    flushed; no other
  3196.    processing performed.
  3197.  
  3198.  
  3199.  Comments:
  3200.  
  3201.  Function 0CH empties the standard input buffer (if standard input has not
  3202.  been redirected, Function 0CH empties the type-ahead buffer). Further
  3203.  processing depends on the value in AL when the function is called.
  3204.  
  3205.  AL                     Action
  3206.  ───────────────────────────────────────────────────────────────────────────
  3207.  1,6,7,8, or 0AH        The corresponding MS-DOS function is executed.
  3208.  Any other value        No further processing; AL returns 0.
  3209.  
  3210.  
  3211.  Macro Definition:
  3212.  
  3213.  flush_and_read_kbd  macro switch
  3214.                      mov   al,switch
  3215.                      mov   ah,0CH
  3216.                      int   21H
  3217.                      endm
  3218.  
  3219.  
  3220.  Example:
  3221.  
  3222.  The following program both displays and prints characters as you type them.
  3223.  If you press the RETURN key, the program sends a carriage-return/linefeed
  3224.  sequence to both the display and the printer.
  3225.  
  3226.  begin:     flush_and_read_kbd 1      ;THIS FUNCTION
  3227.             print_char   al           ;see Function 05H
  3228.             cmp          al,0DH       ;is it a carriage return?
  3229.             jne          begin        ;no, print it
  3230.             print_char   0AH          ;see Function 05H
  3231.             display_char 0AH          ;see Function 02H
  3232.             jmp          begin        ;get another character
  3233.  
  3234.  
  3235.  Reset Disk (Function 0DH)
  3236.  
  3237.  
  3238.  Call:
  3239.  
  3240.  AH = 0DH
  3241.  
  3242.  
  3243.  Return:
  3244.  
  3245.  None
  3246.  
  3247.  
  3248.  Comments:
  3249.  
  3250.  Function 0DH flushes all file buffers to ensure that the internal buffer
  3251.  cache matches the disks in the drives. It writes out buffers that have
  3252.  been modified, and marks all buffers in the internal cache as free. This
  3253.  function request is normally used to force a known state of the system;
  3254.  CONTROL-C interrupt handlers should call this function.
  3255.  
  3256.  This function does not update directory entries; you must close
  3257.  changed files to update their directory entries (see Function 10H,
  3258.  Close File).
  3259.  
  3260.  
  3261.  Macro Definition:
  3262.  
  3263.  reset_disk macro
  3264.             mov   ah,0DH
  3265.             int   21H
  3266.             endm
  3267.  
  3268.  
  3269.  Example:
  3270.  
  3271.  The following program flushes all file buffers and selects disk A.
  3272.  
  3273.  begin:  reset_disk
  3274.          select_disk "A"
  3275.  
  3276.  
  3277.  Select Disk (Function 0EH)
  3278.  
  3279.  
  3280.  Call:
  3281.  
  3282.  AH = 0EH
  3283.  DL
  3284.    Logical drive number
  3285.    (0 = A, 1 = B, etc.)
  3286.  
  3287.  
  3288.  Return:
  3289.  
  3290.  AL
  3291.    Number of logical drives
  3292.  
  3293.  
  3294.  Comments:
  3295.  
  3296.  Function 0EH selects the drive specified in DL (0=A, 1=B, etc.) as the
  3297.  current logical drive. AL returns the number of logical drives.
  3298.  
  3299.  ───────────────────────────────────────────────────────────────────────────
  3300.  Note
  3301.    For future compatibility, treat the value returned in AL with care. For
  3302.    example, if AL returns 5, it is not safe to assume that drives A, B, C,
  3303.    D, and E are all valid drive designators.
  3304.  ───────────────────────────────────────────────────────────────────────────
  3305.  
  3306.  
  3307.  Macro Definition:
  3308.  
  3309.  select_disk macro disk
  3310.              mov   dl,disk[-64]
  3311.              mov   ah,0EH
  3312.              int   21H
  3313.              endm
  3314.  
  3315.  
  3316.  Example:
  3317.  
  3318.  The following program toggles between drive A and drive B to select the
  3319.  current drive (in a two-drive system).
  3320.  
  3321.  begin:    current_disk       ;see Function 19H
  3322.            cmp    al,00H      ;drive A: selected?
  3323.            je     select_b    ;yes, select B
  3324.            select_disk "A"    ;THIS FUNCTION
  3325.            jmp    return
  3326.  select_b: select_disk "B"    ;THIS FUNCTION
  3327.  
  3328.  
  3329.  Open File (Function 0FH)
  3330.  
  3331.  
  3332.  Call:
  3333.  
  3334.  AH = 0FH
  3335.  DS:DX
  3336.    Pointer to unopened FCB
  3337.  
  3338.  
  3339.  Return:
  3340.  
  3341.  AL
  3342.    00H     = Directory entry found
  3343.    FFH     = No directory entry found
  3344.  
  3345.  
  3346.  Comments:
  3347.  
  3348.  Function 0FH opens a file. DX must contain the offset (from the segment
  3349.  address in DS) of an unopened File Control Block (FCB). This call searches
  3350.  the disk directory for the named file.
  3351.  
  3352.  If the call finds a directory entry for the file, AL returns 0 and the
  3353.  FCB is filled as follows:
  3354.  
  3355.      ■ If the drive code was 0 (current drive), it is changed to the actual
  3356.        drive used (1=A, 2=B, etc.). This lets you change the current drive
  3357.        without interfering with subsequent operations on this file.
  3358.  
  3359.      ■ Current Block (offset 0CH) is set to 0.
  3360.  
  3361.      ■ Record Size (offset 0EH) is set to the system default of 128.
  3362.  
  3363.      ■ File Size (offset 0FH), Date of Last Write (offset 13H), and Time of
  3364.        Last Write (offset 15H) are set from the directory entry.
  3365.  
  3366.  Before performing a sequential disk operation on the file, you must set
  3367.  the Current Record field (offset 1FH). Before performing a random disk
  3368.  operation on the file, you must set the Relative Record field (offset 20H).
  3369.  If the default record size (128 bytes) is not correct, set it to the
  3370.  correct length.
  3371.  
  3372.  If the call doesn't find a directory entry for the file, or if the
  3373.  file has the hidden or system attribute, AL returns 0FFH.
  3374.  
  3375.  
  3376.  Macro Definition:
  3377.  
  3378.  open  macro fcb
  3379.        mov   dx,offset fcb
  3380.        mov   ah,0FH
  3381.        int   21H
  3382.        endm
  3383.  
  3384.  
  3385.  Example:
  3386.  
  3387.  The following program prints a file named textfile.asc that is on the disk
  3388.  in drive B. If a partial record is in the buffer at end-of-file, the
  3389.  routine that prints the partial record prints characters until it
  3390.  encounters an end-of-file mark (ASCII 26, or CONTROL-Z).
  3391.  
  3392.  fcb            db    2,"TEXTFILEASC"
  3393.                 db    26 dup (?)
  3394.  buffer         db    128 dup (?)
  3395.  ;
  3396.  begin:         set_dta  buffer       ;see Function 1AH
  3397.                 open  fcb             ;THIS FUNCTION
  3398.  read_line:     read_seq  fcb         ;see Function 14H
  3399.                 cmp   al,02H          ;end of file?
  3400.                 je    all_done        ;yes, go home
  3401.                 cmp   al,00H          ;more to come?
  3402.                 jg    check_more      ;no, check for partial
  3403.                                       ;record
  3404.                 mov   cx,80H          ;yes, print the buffer
  3405.                 xor   si,si           ;set index to 0
  3406.  print_it:      print_char buffer[si] ;see Function 05H
  3407.                 inc   si              ;bump index
  3408.                 loop  print_it        ;print next character
  3409.                 jmp   read_line       ;read another record
  3410.  check_more:    cmp   al,03H          ;part. record to print?
  3411.                 jne   all_done        ;no
  3412.                 mov   cx,80H          ;yes, print it
  3413.                 xor   si,si           ;set index to 0
  3414.  find_eof:      cmp   buffer[si],26   ;end-of-file mark?
  3415.                 je    all_done        ;yes
  3416.                 print_char buffer[si] ;see Function 05H
  3417.                 inc   si              ;bump index to next
  3418.                                       ;character
  3419.                 loop  find_eof
  3420.  all_done:      close fcb             ;see Function 10H
  3421.  
  3422.  
  3423.  Close File (Function 10H)
  3424.  
  3425.  
  3426.  Call:
  3427.  
  3428.  AH = 10H
  3429.  DS:DX
  3430.    Pointer to opened FCB
  3431.  
  3432.  
  3433.  Return:
  3434.  
  3435.  AL
  3436.    00H     = Directory entry found
  3437.    FFH     = No directory entry found
  3438.  
  3439.  
  3440.  Comments:
  3441.  
  3442.  Function 10H closes a file. DX must contain the offset (to the segment
  3443.  address in DS) of an opened FCB. This call searches the disk directory for
  3444.  the file named in the FCB. If it finds a directory entry for the file, it
  3445.  compares the location of the file with the corresponding entries in the
  3446.  FCB. The call then updates the directory entry, if necessary, to match the
  3447.  FCB, and AL returns 0.
  3448.  
  3449.  After you change a file, you must call this function to update the
  3450.  directory entry. You should close any FCB (even one for a file that has
  3451.  not been changed) when you no longer need access to a file.
  3452.  
  3453.  If this call doesn't find a directory entry for the file, AL
  3454.  returns FFH.
  3455.  
  3456.  
  3457.  Macro Definition:
  3458.  
  3459.  close  macro fcb
  3460.         mov   dx,offset fcb
  3461.         mov   ah,10H
  3462.         int   21H
  3463.         endm
  3464.  
  3465.  
  3466.  Example:
  3467.  
  3468.  The following program checks the first byte of the file named mod1.bas in
  3469.  drive B to see if it is FFH and, if it is, prints a message.
  3470.  
  3471.  message        db   "Not saved in ASCII format",0DH,0AH,"$"
  3472.  fcb            db    2,"MOD1    BAS"
  3473.                 db    26  dup (?)
  3474.  buffer         db    128 dup (?)
  3475.  ;
  3476.  begin:         set_dta  buffer       ;see Function 1AH
  3477.                 open  fcb             ;see Function 0FH
  3478.                 read_seq  fcb         ;see Function 14H
  3479.  
  3480.                 cmp   buffer,0FFH     ;is first byte FFH?
  3481.                 jne   all_done        ;no
  3482.                 display  message      ;see Function 09H
  3483.  all_done:      close fcb             ;THIS FUNCTION
  3484.  
  3485.  
  3486.  Search for First Entry (Function 11H)
  3487.  
  3488.  
  3489.  Call:
  3490.  
  3491.  AH = 11H
  3492.  DS:DX
  3493.    Pointer to unopened FCB
  3494.  
  3495.  
  3496.  Return:
  3497.  
  3498.    AL
  3499.    00H     = Directory entry found
  3500.    FFH     = No directory entry found
  3501.  
  3502.  
  3503.  Comments:
  3504.  
  3505.  Function 11H searches the disk directory for the first matching filename.
  3506.  DX must contain the offset (from the segment address in DS) of an unopened
  3507.  FCB. The filename in the FCB can include wildcard characters. To search
  3508.  for hidden or system files, DX must point to the first byte of an
  3509.  extended FCB prefix.
  3510.  
  3511.  If this call does not find a directory entry for the filename in the
  3512.  FCB, AL returns FFH.
  3513.  
  3514.  But if the call does find a directory entry for the filename in the
  3515.  FCB, AL returns 0 and the call creates an unopened FCB of the same type
  3516.  (normal or extended) at the Disk Transfer Address as follows:
  3517.  
  3518.      1.  If the search FCB was normal, the first byte at the Disk Transfer
  3519.          Address is set to the drive number used in the search (1=A, 2=B,
  3520.          etc.) and the next 32 bytes contain the directory entry.
  3521.  
  3522.      2.  If the search FCB was extended, the first byte at the Disk Transfer
  3523.          Address is set to FFH, the next 5 bytes are set to 00H, and the
  3524.          following byte is set to the value of the attribute byte in the
  3525.          search FCB. The remaining 33 bytes are the same as the result of
  3526.          the normal FCB (drive number and 32 bytes of directory entry).
  3527.  
  3528.  If you use Function 12H (Search for Next Entry) to continue searching
  3529.  for matching filenames, you must not alter or open the original FCB
  3530.  at DS:DX.
  3531.  
  3532.  The attribute field is the last byte of the extended FCB fields that
  3533.  precede the FCB (see earlier in this chapter). If the attribute field is
  3534.  zero, Function 11H searches only normal file entries. It does not search
  3535.  directory entries for hidden files, system files, volume label, and
  3536.  subdirectories.
  3537.  
  3538.  If the attribute field is hidden file, system file, or subdirectory
  3539.  entry (02H, 04H, or 10H), or any combination of those values, this call
  3540.  also searches all normal file entries. To search all directory entries
  3541.  except the volume label, set the attribute byte to 16H (hidden file
  3542.  and system file and directory entry).
  3543.  
  3544.  If the attribute field is Volume ID (08H), the call searches only the
  3545.  volume label entry.
  3546.  
  3547.  
  3548.  Macro Definition:
  3549.  
  3550.  search_first  macro fcb
  3551.                mov   dx,offset fcb
  3552.                mov   ah,11H
  3553.                int   21H
  3554.                endm
  3555.  
  3556.  
  3557.  Example:
  3558.  
  3559.  The following program verifies the existence of a file named report.asm on
  3560.  the disk in drive B.
  3561.  
  3562.  yes        db   "FILE EXISTS.$"
  3563.  no         db   "FILE DOES NOT EXIST.$"
  3564.  crlf       db    0DH,0AH,"$"
  3565.  fcb        db    2,"REPORT  *ASM"
  3566.             db    26 dup (?)
  3567.  buffer     db    128 dup (?)
  3568.  ;
  3569.  begin:     set_dta  buffer           ;see Function 1AH
  3570.             search_first fcb          ;THIS FUNCTION
  3571.             cmp      al,0FFH          ;directory entry found?
  3572.             je       not_there        ;no
  3573.             display  yes              ;see Function 09H
  3574.             jmp      continue
  3575.  not_there: display  no               ;see Function 09H
  3576.  continue:  display  crlf             ;see Function 09H
  3577.  
  3578.  
  3579.  Search for Next Entry (Function 12H)
  3580.  
  3581.  
  3582.  Call:
  3583.  
  3584.  AH = 12H
  3585.  DS:DX
  3586.    Pointer to unopened FCB
  3587.  
  3588.  
  3589.  Return:
  3590.  
  3591.  AL
  3592.    00H     = Directory entry found
  3593.    FFH     = No directory entry found
  3594.  
  3595.  
  3596.  Comments:
  3597.  
  3598.  After you use Function 11H (Search for First Entry), you can use Function
  3599.  12H to find any additional directory entries that match a filename
  3600.  (containing wildcard characters). Function 12H searches the disk
  3601.  directory for the next matching name. DX must contain the offset (from the
  3602.  segment address in DS) of an FCB specified in a previous call to Function
  3603.  11H. To search for hidden or system files, DX must point to the first byte
  3604.  of an extended FCB prefix-one that includes the appropriate attribute
  3605.  value.
  3606.  
  3607.  If the call does not find a directory entry for the filename in the
  3608.  FCB, AL returns FFH.
  3609.  
  3610.  But if the call does find a directory entry for the filename in the
  3611.  FCB, AL returns 0 and the call creates an unopened FCB of the same type
  3612.  (normal or extended) at the Disk Transfer Address (see Function 11H for a
  3613.  description of how the unopened FCB is formed).
  3614.  
  3615.  
  3616.  Macro Definition:
  3617.  
  3618.  search_next  macro fcb
  3619.               mov   dx,offset fcb
  3620.               mov   ah,12H
  3621.               int   21H
  3622.               endm
  3623.  
  3624.  
  3625.  Example:
  3626.  
  3627.  The following program displays the number of files on the disk in drive B.
  3628.  
  3629.  message     db   "No files",0DH,0AH,"$"
  3630.  files       db    0
  3631.  fcb         db    2,"???????????"
  3632.              db    26  dup (?)
  3633.  buffer      db    128 dup (?)
  3634.  ;
  3635.  begin:      set_dta  buffer          ;see Function 1AH
  3636.              search_first  fcb        ;see Function 11H
  3637.              cmp  al,0FFH             ;directory entry found?
  3638.              je   all_done            ;no, no files on disk
  3639.              inc  files               ;yes, increment file
  3640.                                       ;counter
  3641.  search_dir: search_next  fcb         ;THIS FUNCTION
  3642.              cmp  al,0FFH             ;directory entry found?
  3643.              je   done                ;no
  3644.              inc  files               ;yes, increment file
  3645.                                       ;counter
  3646.              jmp  search_dir          ;check again
  3647.  done:       convert files,10,message ;see end of chapter
  3648.  all_done:   display  message         ;see Function 09H
  3649.  
  3650.  
  3651.  Delete File (Function 13H)
  3652.  
  3653.  
  3654.  Call:
  3655.  
  3656.  AH = 13H
  3657.  DS:DX
  3658.    Pointer to unopened FCB
  3659.  
  3660.  
  3661.  Return:
  3662.  
  3663.    AL
  3664.    00H     = Directory entry found
  3665.    FFH     = No directory entry found
  3666.  
  3667.  
  3668.  Comments:
  3669.  
  3670.  Function 13H deletes a file. DX must contain the offset (from the segment
  3671.  address in DS) of an unopened FCB. This call searches the directory for a
  3672.  matching filename. The filename in the FCB can contain wildcard characters.
  3673.  
  3674.  If the call does not find a matching directory entry, AL returns FFH.
  3675.  
  3676.  But if the call does find a matching directory entry, AL returns 0 and
  3677.  the call deletes the entry from the directory. If the filename contains a
  3678.  wildcard character, the call will delete all files which match.
  3679.  
  3680.  Do not delete open files.
  3681.  
  3682.  
  3683.  Macro Definition:
  3684.  
  3685.  delete  macro  fcb
  3686.          mov    dx,offset fcb
  3687.          mov    ah,13H
  3688.          int    21H
  3689.          endm
  3690.  
  3691.  
  3692.  Example:
  3693.  
  3694.  The following program deletes each file on the disk in drive B that was
  3695.  last written before December 31, 1982.
  3696.  
  3697.  year           dw    1982
  3698.  month          db    12
  3699.  day            db    31
  3700.  files          db    0
  3701.  message        db   "No files deleted.",0DH,0AH,"$"
  3702.  fcb            db    2,"???????????"
  3703.                 db    26 dup  (?)
  3704.  buffer         db    128 dup (?)
  3705.  ;
  3706.  begin:         set_dta  buffer      ;see Function 1AH
  3707.                 search_first fcb     ;see Function 11H
  3708.                 cmp   al,0FFH        ;directory entry found?
  3709.                 jne   compare        ;yes
  3710.                 jmp   all_done       ;no, no files on disk
  3711.  compare:       convert_date buffer  ;see end of chapter
  3712.                 cmp  cx,year         ;next several lines
  3713.                 jg   next            ;check date in directory
  3714.                 cmp  dl,month        ;entry against date
  3715.                 jg   next            ;above & check next file
  3716.                 cmp  dh,day          ;if date in directory
  3717.                 jge  next            ;entry isn't earlier.
  3718.                 delete  buffer       ;THIS FUNCTION
  3719.                 inc  files           ;bump deleted-files
  3720.                                      ;counter
  3721.  next:          search_next fcb      ;see Function 12H
  3722.                 cmp  al,00H          ;directory entry found?
  3723.                 je   compare         ;yes, check date
  3724.                 cmp  files,0         ;any files deleted?
  3725.                 je   all_done        ;no, display No files
  3726.                                      ;message.
  3727.                 convert files,10,message ;see end of chapter
  3728.  all_done:      display message      ;see Function 09H
  3729.  
  3730.  
  3731.  Sequential Read (Function 14H)
  3732.  
  3733.  
  3734.  Call:
  3735.  
  3736.  AH = 14H
  3737.  DS:DX
  3738.    Pointer to opened FCB
  3739.  
  3740.  
  3741.  Return:
  3742.  
  3743.  AL
  3744.    00H = Read completed successfully
  3745.    01H = EOF
  3746.    02H = DTA too small
  3747.    03H = EOF, partial record
  3748.  
  3749.  
  3750.  Comments:
  3751.  
  3752.  Function 14H reads a record from a specified file. DX must contain the
  3753.  offset (from the segment address in DS) of an opened FCB. This call loads
  3754.  the record pointed to by the Current Block field (offset 0CH) and Current
  3755.  Record (offset 1FH) field at the Disk Transfer Address, then increments the
  3756.  Current Block and Current Record fields.
  3757.  
  3758.  The length of the record is taken from the Record Size field (offset
  3759.  0EH) of the FCB.
  3760.  
  3761.  AL returns a code that describes the processing:
  3762.  
  3763.  Code  Meaning
  3764.  ───────────────────────────────────────────────────────────────────────────
  3765.  0     Read completed successfully
  3766.  
  3767.  1     End-of-file; no data in the record
  3768.  
  3769.  2     Not enough room at the Disk Transfer Address to read one record; read
  3770.        canceled
  3771.  
  3772.  3     End-of-file; a partial record was read and padded to the record
  3773.        length with zeros
  3774.  
  3775.  
  3776.  Macro Definition:
  3777.  
  3778.  read_seq  macro fcb
  3779.            mov   dx,offset fcb
  3780.            mov   ah,14H
  3781.            int   21H
  3782.            endm
  3783.  
  3784.  
  3785.  Example:
  3786.  
  3787.  The following program displays a file named textfile.asc that is on the
  3788.  disk in drive B; its function is similar to the MS-DOS type command. If a
  3789.  partial record is in the buffer at end-of-file, the routine that displays
  3790.  the partial record displays characters until it encounters an end-of-file
  3791.  mark (ASCII 26, or CONTROL-Z).
  3792.  
  3793.  fcb            db    2,"TEXTFILEASC"
  3794.                 db    26  dup (?)
  3795.  buffer         db    128 dup (?),"$"
  3796.  ;
  3797.  begin:         set_dta  buffer    ;see Function 1AH
  3798.                 open  fcb          ;see Function 0FH
  3799.  read_line:     read_seq  fcb      ;THIS FUNCTION
  3800.                 cmp   al,02H       ;DTA too small?
  3801.                 je    all_done     ;yes
  3802.                 cmp   al,00H       ;end-of-file?
  3803.                 jg    check_more   ;yes
  3804.                 display  buffer    ;see Function 09H
  3805.                 jmp   read_line    ;get another record
  3806.  check_more:    cmp   al,03H       ;partial record in buffer?
  3807.                 jne   all_done     ;no, go home
  3808.                 xor   si,si        ;set index to 0
  3809.  find_eof:      cmp   buffer[si],26 ;is character EOF?
  3810.                 je    all_done     ;yes, no more to display
  3811.                 display_char buffer[si]  ;see Function 02H
  3812.                 inc   si           ;bump index
  3813.                 jmp   find_eof     ;check next character
  3814.  all_done:      close fcb          ;see Function 10H
  3815.  
  3816.  
  3817.  Sequential Write (Function 15H)
  3818.  
  3819.  
  3820.  Call:
  3821.  
  3822.  AH = 15H
  3823.  DS:DX
  3824.    Pointer to opened FCB
  3825.  
  3826.  
  3827.  Return:
  3828.  
  3829.  AL
  3830.    00H = Write completed successfully
  3831.    01H = Disk full
  3832.    02H = DTA too small
  3833.  
  3834.  Function 15H writes a record to a specified file. DX must contain the
  3835.  offset (from the segment address in DS) of an opened FCB. This call
  3836.  writes the record pointed to by the Current Block field (offset 0CH) and
  3837.  Current Record field (offset 1FH) at the Disk Transfer Address, then
  3838.  increments the Current Block and Current Record fields.
  3839.  
  3840.  The record size is taken from the value of the Record Size field
  3841.  (offset 0EH) of the FCB. If the record size is less than a sector, the call
  3842.  writes the data at the Disk Transfer Address to an MS-DOS buffer; MS-DOS
  3843.  writes the buffer to disk when it contains a full sector of data, when the
  3844.  file is closed, or when Function 0DH (Reset Disk) is issued.
  3845.  
  3846.  AL returns a code that describes the processing:
  3847.  
  3848.  Code  Meaning
  3849.  ───────────────────────────────────────────────────────────────────────────
  3850.  0     Write completed successfully
  3851.  
  3852.  1     Disk full; write canceled
  3853.  
  3854.  2     Not enough room at the Disk Transfer Address to write one record;
  3855.        write canceled
  3856.  
  3857.  
  3858.  Macro Definition:
  3859.  
  3860.  write_seq  macro fcb
  3861.             mov   dx,offset fcb
  3862.             mov   ah,15H
  3863.             int   21H
  3864.             endm
  3865.  
  3866.  
  3867.  Example:
  3868.  
  3869.  The following program creates a file named dir.tmp on the disk in drive B,
  3870.  containing the disk number (0=A, 1=B, etc.) and filename from each
  3871.  directory entry on the disk.
  3872.  
  3873.  record_size    equ   0EH           ;offset of Record Size
  3874.  ;                                  field in FCB
  3875.  fcb1           db    2,"DIR     TMP"
  3876.                 db    26 dup (?)
  3877.  fcb2           db    2,"???????????"
  3878.                 db    26 dup (?)
  3879.  buffer         db    128 dup (?)
  3880.  ;
  3881.  begin:      set_dta      buffer     ;see Function 1AH
  3882.              search_first fcb2       ;see Function 11H
  3883.              cmp          al,0FFH    ;directory entry found?
  3884.              je           all_done   ;no, no files on disk
  3885.              create       fcb1       ;see Function 16H
  3886.              mov          fcb1[record_size],12
  3887.                                      ;set record size to 12
  3888.  write_it:   write_seq    fcb1       ;THIS FUNCTION
  3889.              cmp          al,0       ;write successful?
  3890.              jne          all_done   ;no, go home
  3891.              search_next  fcb2       ;see Function 12H
  3892.              cmp          al,FFH     ;directory entry found?
  3893.              je           all_done   ;no, go home
  3894.              jmp          write_it   ;yes, write the record
  3895.  all_done:   close        fcb1       ;see Function 10H
  3896.  
  3897.  
  3898.  Create File (Function 16H)
  3899.  
  3900.  
  3901.  Call:
  3902.  
  3903.  AH = 16H
  3904.  DS:DX
  3905.    Pointer to unopened FCB
  3906.  
  3907.  
  3908.  Return:
  3909.  
  3910.  AL
  3911.    00H     = Empty directory found
  3912.    FFH     = No empty directory available
  3913.  
  3914.  Function 16H creates a file. DX must contain the offset(from the segment
  3915.  address in DS) of an unopened FCB. MS-DOS searches the directory for an
  3916.  entry that matches the specified filename or, if there is no matching
  3917.  entry, an empty entry.
  3918.  
  3919.  If MS-DOS finds a matching entry, it opens the file and sets the
  3920.  length to zero (in other words, if you try to create a file that already
  3921.  exists, MS-DOS erases it and creates a new, empty file). If MS-DOS doesn't
  3922.  find a matching entry but does find an empty directory entry, it opens the
  3923.  file and sets its length to zero. In either case, the call creates the
  3924.  file, and AL returns 0. If MS-DOS doesn't find a matching entry and there
  3925.  is no empty entry, the call doesn't create the file, and AL returns FFH.
  3926.  
  3927.  You can assign an attribute to the file by using an extended FCB with
  3928.  the attribute byte set to the appropriate value (see Extended FCB in
  3929.  Section 1.9.1).
  3930.  
  3931.  
  3932.  Macro Definition:
  3933.  
  3934.  create  macro fcb
  3935.          mov   dx,offset fcb
  3936.          mov   ah,16H
  3937.          int   21H
  3938.          endm
  3939.  
  3940.  
  3941.  Example:
  3942.  
  3943.  The following program creates a file named dir.tmp on the disk in drive B,
  3944.  containing the disk number (0 = A, 1 = B, etc.) and filename from each
  3945.  directory entry on the disk.
  3946.  
  3947.  record_size    equ   0EH           ;offset of Record Size
  3948.  ;                                  field of FCB
  3949.  fcb1           db    2,"DIR     TMP"
  3950.                 db    26  dup (?)
  3951.  fcb2           db    2,"???????????"
  3952.                 db    26  dup (?)
  3953.  buffer         db    128 dup (?)
  3954.  ;
  3955.  begin:         set_dta   buffer     ;see Function 1AH
  3956.                 search_first  fcb2   ;see Function 11H
  3957.                 cmp       al,0FFH    ;directory entry found?
  3958.                 je        all_done   ;no, no files on disk
  3959.                 create    fcb1       ;THIS FUNCTION
  3960.                 mov       fcb1[record_size],12
  3961.                                      ;set record size to 12
  3962.  write_it:      write_seq fcb1       ;see Function 15H
  3963.                 cmp       al,0       ;write successful
  3964.                 jne       all_done   ;no, go home
  3965.                 search_next  fcb2    ;see Function 12H
  3966.                 cmp       al,FFH     ;directory entry found?
  3967.                 je        all_done   ;no, go home
  3968.                 jmp       write_it   ;yes, write the record
  3969.  all_done:      close     fcb1       ;see Function 10H
  3970.  
  3971.  
  3972.  Rename File (Function 17H)
  3973.  
  3974.  
  3975.  Call:
  3976.  
  3977.  AH = 17H
  3978.  DS:DX
  3979.    Pointer to modified FCB
  3980.  
  3981.  
  3982.  Return:
  3983.  
  3984.  AL
  3985.    00H     = Directory entry found
  3986.    FFH     = No directory entry found
  3987.              or destination already exists
  3988.  
  3989.  
  3990.  Comments:
  3991.  
  3992.  Function 17H changes the name of an existing file. DX must contain the
  3993.  offset (from the segment address in DS) of an FCB with the drive number
  3994.  and filename filled in, followed by a second filename at offset 11H. DOS
  3995.  searches the disk directory for an entry that matches the first filename.
  3996.  This filename can contain wildcard characters.
  3997.  
  3998.  If MS-DOS finds a matching directory entry and there is no directory
  3999.  entry that matches the second filename, it changes the filename in the
  4000.  directory entry to match the second filename in the modified FCB. AL then
  4001.  returns zero. If the second filename does contain a wildcard character,
  4002.  this call does not change the corresponding characters in the filename
  4003.  of the directory entry.
  4004.  
  4005.  You cannot use this function request to rename a hidden file, a system
  4006.  file, or a subdirectory. If MS-DOS does not find a matching directory entry
  4007.  or if it finds an entry for the second filename, AL returns FFH.
  4008.  
  4009.  
  4010.  Macro Definition:
  4011.  
  4012.  rename macro fcb,newname
  4013.         mov   dx,offset fcb
  4014.         mov   ah,17H
  4015.         int   21H
  4016.         endm
  4017.  
  4018.  
  4019.  Example:
  4020.  
  4021.  The following program prompts for the name of a file and a new name; it
  4022.  then renames the file.
  4023.  
  4024.  fcb               db    37 dup (?)
  4025.  prompt1           db   "Filename: $"
  4026.  prompt2           db   "New name: $"
  4027.  reply             db    15 dup(?)
  4028.  crlf              db    0DH,0AH,"$"
  4029.  ;
  4030.  begin:            display  prompt1       ;see Function 09H
  4031.                    get_string  15,reply   ;see Function 0AH
  4032.                    display  crlf          ;see Function 09H
  4033.                    parse    reply[2],fcb  ;see Function 29H
  4034.                    display  prompt2       ;see Function 09H
  4035.                    get_string  15,reply   ;see Function 0AH
  4036.                    display  crlf          ;see Function 09H
  4037.                    parse    reply[2],fcb[16]
  4038.                                           ;see Function 29H
  4039.                    rename   fcb           ;THIS FUNCTION
  4040.  
  4041.  
  4042.  Get Current Disk (Function 19H)
  4043.  
  4044.  
  4045.  Call:
  4046.  
  4047.  AH = 19H
  4048.  
  4049.  
  4050.  Return:
  4051.  
  4052.  AL
  4053.    Currently selected drive
  4054.    (0 = A, 1 = B, etc.)
  4055.  
  4056.  
  4057.  Comments:
  4058.  
  4059.  
  4060.  Function 19H returns the current drive in AL (0=A, 1=B, etc.).
  4061.  
  4062.  
  4063.  Macro Definition:
  4064.  
  4065.  current_disk  macro
  4066.                mov   ah,19H
  4067.                int   21H
  4068.                endm
  4069.  
  4070.  
  4071.  Example:
  4072.  
  4073.  The following program displays the default drive in a two-drive system.
  4074.  
  4075.  message    db  "Current disk is $"
  4076.  crlf       db   0DH,OAH,"$"
  4077.  ;
  4078.  begin:     display  message         ;see Function 09H
  4079.             current_disk             ;THIS FUNCTION
  4080.             cmp      al,00H          ;is it disk A?
  4081.             jne      disk_b          ;no, it's disk B:
  4082.             display_char "A"         ;see Function 02H
  4083.             jmp      all_done
  4084.  disk_b:    display_char "B"         ;see Function 02H
  4085.  all_done:  display  crlf            ;see Function 09H
  4086.  
  4087.  
  4088.  Set Disk Transfer Address (Function 1AH)set disk transfer address
  4089.  
  4090.  
  4091.  Call:
  4092.  
  4093.  AH = 1AH
  4094.  DS:DX
  4095.   Disk Transfer Address
  4096.  
  4097.  
  4098.  Return:
  4099.  
  4100.  None
  4101.  
  4102.  
  4103.  Comments:
  4104.  
  4105.  Function 1AH sets the Disk Transfer Address. DX must contain the offset
  4106.  (from the segment address in DS) of the Disk Transfer Address. Disk
  4107.  transfers cannot wrap around from the end of the segment to the beginning,
  4108.  nor can they overflow into another segment.
  4109.  
  4110.  If you do not set the Disk Transfer Address, MS-DOS defaults to offset
  4111.  80H in the Program Segment Prefix. You can check the current Disk Transfer
  4112.  Address with Function 2FH (Get Disk Transfer Address).
  4113.  
  4114.  
  4115.  Macro Definition:
  4116.  
  4117.  set_dta  macro  buffer
  4118.           mov    dx,offset buffer
  4119.           mov    ah,1AH
  4120.           int    21H
  4121.           endm
  4122.  
  4123.  
  4124.  Example:
  4125.  
  4126.  The following program prompts for a letter, converts it to its alphabetic
  4127.  sequence (A=1, B=2, etc.), then reads and displays the corresponding record
  4128.  from a file named alphabet.dat that is on the disk in drive B. The file
  4129.  contains 26 records, each 28 bytes long.
  4130.  
  4131.  record_size     equ   0EH      ;offset of Record Size
  4132.                                 ;field of FCB
  4133.  relative_record equ   21H      ;offset of Relative Record
  4134.  ;                              field of FCB
  4135.  fcb           db    2,"ALPHABETDAT"
  4136.                db    26  dup (?)
  4137.  buffer        db    28 dup(?),"$"
  4138.  prompt        db   "Enter letter: $"
  4139.  crlf          db    0DH,0AH,"$"
  4140.  ;
  4141.  begin:        set_dta  buffer       ;THIS FUNCTION
  4142.                open     fcb          ;see Function 0FH
  4143.                mov      fcb[record_size],28 ;set record size
  4144.  get_char:     display  prompt       ;see Function 09H
  4145.                read_kbd_and_echo     ;see Function 01H
  4146.                cmp      al,0DH       ;just a CR?
  4147.                je       all_done     ;yes, go home
  4148.                sub      al,41H       ;convert ASCII
  4149.                                      ;code to record #
  4150.                mov      fcb[relative_record],al
  4151.                                      ;set relative record
  4152.                display  crlf         ;see Function 09H
  4153.                read_ran fcb          ;see Function 21H
  4154.                display  buffer       ;see Function 09H
  4155.                display  crlf         ;see Function 09H
  4156.                jmp      get_char     ;get another character
  4157.  all_done:     close    fcb          ;see Function 10H
  4158.  
  4159.  
  4160.  Get Default Drive Data (Function 1BH)
  4161.  
  4162.  
  4163.  Call:
  4164.  
  4165.  AH = 1BH
  4166.  
  4167.  
  4168.  Return:
  4169.  
  4170.  AL
  4171.     Sectors per cluster
  4172.  CX
  4173.     Bytes per sector
  4174.  DX
  4175.     Clusters per drive
  4176.  DS:BX
  4177.     Pointer to FAT ID byte
  4178.  
  4179.  
  4180.  Comments
  4181.  
  4182.  Function 1BH retrieves data about the disk in the default drive.
  4183.  The data returns in the following registers:
  4184.  
  4185.  Register       Contents
  4186.  ───────────────────────────────────────────────────────────────────────────
  4187.  AL             Number of sectors in a cluster (allocation unit)
  4188.  CX             Number of bytes in a sector
  4189.  DX             Number of clusters on the disk
  4190.  
  4191.  BX returns the offset (to the segment address in DS) of the first
  4192.  byte of the File Allocation Table (FAT), which identifies the type of disk
  4193.  in the drive:
  4194.  
  4195.  Value   Type of Drive
  4196.  ───────────────────────────────────────────────────────────────────────────
  4197.  FF      Double-sided disk, 8 sectors per track, 40 tracks per side
  4198.  FE      Single-sided disk, 8 sectors per track, 40 tracks per side
  4199.  FD      Double-sided disk, 9 sectors per track, 40 tracks per side
  4200.  FC      Single-sided disk, 9 sectors per track, 40 tracks per side
  4201.  F9      Double-sided disk, 15 sectors per track, 40 tracks per side
  4202.  F9      Double-sided disk, 9 sectors per track, 80 tracks per side
  4203.  F8      Fixed disk
  4204.  
  4205.  This call is similar to Function 36H (Get Disk Free Space), except that it
  4206.  returns the address of the FAT ID byte in BX instead of the number of
  4207.  available clusters. It is also similar to Function 1CH (Get Drive Data),
  4208.  except that it returns data on the disk in the default drive instead of on
  4209.  the disk in a specified drive. For a description of how MS-DOS stores data
  4210.  on a disk, including a description of the File Allocation Table, see
  4211.  Chapter 3, "MS-DOS Technical Information."
  4212.  
  4213.  ───────────────────────────────────────────────────────────────────────────
  4214.  Warning
  4215.    The FAT ID byte is no longer adequate to identify the type of drive
  4216.    being used. See Chapter 2, "MS-DOS Device Drivers," for more details.
  4217.  ───────────────────────────────────────────────────────────────────────────
  4218.  
  4219.  
  4220.  Macro Definition:
  4221.  
  4222.  def_drive_data  macro
  4223.                  push   ds
  4224.                  mov    ah,1BH
  4225.                  int    21H
  4226.                  mov    al,byte ptr[bx]
  4227.                  pop    ds
  4228.                  endm
  4229.  
  4230.  
  4231.  Example:
  4232.  
  4233.  The following program displays a message that tells whether the default
  4234.  drive is a disk or a fixed disk drive.
  4235.  
  4236.  stdout      equ         1
  4237.  ;
  4238.  msg         db          "Default drive is "
  4239.  dskt        db          "disk."
  4240.  fixed       db          "fixed."
  4241.  crlf        db          ODH,OAH
  4242.  ;
  4243.  begin:      write_handle stdout,msg,17      ;display message
  4244.              jc           write_error        ;routine not shown
  4245.              def_drive_data                  ;THIS FUNCTION
  4246.              cmp          byte ptr [bx],0F8H ;check FAT ID byte
  4247.              jne          disk           ;it's a disk
  4248.              write_handle stdout,fixed,6     ;see Function 40H
  4249.              jc           write_error        ;see Function 40H
  4250.              jmp short    all_done           ;clean up & go home
  4251.  disk:   write_handle stdout,dskt,9          ;see Function 40H
  4252.  all_done:   write_handle stdout,crlf,2  ;see Function 40H
  4253.              jc           write_error        ;routine not shown
  4254.  
  4255.  
  4256.  Get Drive Data (Function 1CH)
  4257.  
  4258.  
  4259.  Call:
  4260.  
  4261.  AH = 1CH
  4262.  DL
  4263.     Drive (0=default, 1=A, etc.)
  4264.  
  4265.  
  4266.  Return:
  4267.  
  4268.  AL
  4269.     0FFH if drive number is invalid;
  4270.     otherwise, sectors per cluster
  4271.  CX
  4272.     Bytes per sector
  4273.  DX
  4274.     Clusters per drive
  4275.  DS:BX
  4276.     Pointer to FAT ID byte
  4277.  
  4278.  
  4279.  Comments:
  4280.  
  4281.  Function 1CH retrieves data about the disk in the specified drive. DL must
  4282.  contain the drive number (0=default, 1=A, etc.). The data returns in the
  4283.  following registers:
  4284.  
  4285.  Register       Contents
  4286.  ───────────────────────────────────────────────────────────────────────────
  4287.  AL             Number of sectors in a cluster (allocation unit)
  4288.  CX             Number of bytes in a sector
  4289.  DX             Number of clusters on the disk
  4290.  
  4291.  BX returns the offset (to the segment address in DS) of the first byte
  4292.  of the File Allocation Table (FAT), which identifies the type of disk in
  4293.  the drive:
  4294.  
  4295.  Value   Type of Drive
  4296.  ───────────────────────────────────────────────────────────────────────────
  4297.  FF      Double-sided disk, 8 sectors per track, 40 tracks per side
  4298.  FE      Single-sided disk, 8 sectors per track, 40 tracks per side
  4299.  FD      Double-sided disk, 9 sectors per track, 40 tracks per side
  4300.  FC      Single-sided disk, 9 sectors per track, 40 tracks per side
  4301.  F9      Double-sided disk, 15 sectors per track, 40 tracks per side
  4302.  F9      Double-sided disk, 9 sectors per track, 80 tracks per side
  4303.  F8      Fixed disk
  4304.  
  4305.  If the drive number in DL is invalid, AL returns 0FFH.
  4306.  
  4307.  ───────────────────────────────────────────────────────────────────────────
  4308.  Warning
  4309.    The FAT ID byte is no longer adequate to identify the type of drive being
  4310.    used. See Chapter 2, "MS-DOS Device Drivers" for more details.
  4311.  ───────────────────────────────────────────────────────────────────────────
  4312.  
  4313.  This call is similar to Function 36H (Get Disk Free Space), except that it
  4314.  returns the address of the FAT ID byte in BX instead of the number of
  4315.  available clusters. It is also similar to Function 1BH (Get Default Drive
  4316.  Data), except that it returns data on the disk in the drive specified in DL
  4317.  instead of the disk in the default drive. For a description of how MS-DOS
  4318.  stores data on a disk, including a description of the File Allocation
  4319.  Table, see Chapter 3, "MS-DOS Technical Information."
  4320.  
  4321.  
  4322.  Macro Definition:
  4323.  
  4324.  drive_data  macro  drive
  4325.              push   ds
  4326.              mov    dl,drive
  4327.              mov    ah,1BH
  4328.              int    21H
  4329.              mov    al, byte ptr[bx]
  4330.              pop    ds
  4331.              endm
  4332.  
  4333.  
  4334.  Example:
  4335.  
  4336.  The following program displays a message that tells whether drive B is a
  4337.  disk or a fixed disk drive.
  4338.  
  4339.  stdout      equ          1
  4340.  :
  4341.  msg         db           "Drive B is "
  4342.  dskt        db           "disk."
  4343.  fixed       db           "fixed."
  4344.  crlf        db           ODH,OAH
  4345.  ;
  4346.  begin:      write_handle stdout,msg,11      ;display message
  4347.              jc           write_error        ;routine not shown
  4348.              drive_data   2                  ;THIS FUNCTION
  4349.              cmp          byte ptr [bx],0F8H ;check FAT ID byte
  4350.              jne          disk           ;it's a disk
  4351.              write_handle stdout,fixed,6     ;see Function 40H
  4352.              jc           write_error        ;routine not shown
  4353.              jmp          all_done           ;clean up & go home
  4354.  disk:   write_handle stdout,dskt,9      ;see Function 40H
  4355.  all_done:   write_handle stdout,crlf,2      ;see Function 40H
  4356.              jc           write_error        ;routine not shown
  4357.  
  4358.  
  4359.  Random Read (Function 21H)
  4360.  
  4361.  
  4362.  Call:
  4363.  
  4364.  AH = 21H
  4365.  DS:DX
  4366.    Pointer to opened FCB
  4367.  
  4368.  
  4369.  Return:
  4370.  
  4371.  AL
  4372.    0 = Read completed successfully
  4373.    1 = End of file, record empty
  4374.    2 = DTA too small
  4375.    3 = End of file, partial record
  4376.  
  4377.  
  4378.  Comments:
  4379.  
  4380.  Function 21H reads (into the Disk Transfer Address) the record pointed to
  4381.  by the Relative Record field (offset 20H) of the FCB. DX must contain the
  4382.  offset (from the segment address in DS) of an opened FCB. The Current Block
  4383.  field (offset 0CH) and Current Record field (offset 1FH) are set to agree
  4384.  with the Relative Record field (offset 20H). The record is then loaded at
  4385.  the Disk Transfer Address. The record length is taken from the Record Size
  4386.  field (offset 0EH) of the FCB.
  4387.  
  4388.  AL returns a code that describes the processing:
  4389.  
  4390.  Code  Meaning
  4391.  ───────────────────────────────────────────────────────────────────────────
  4392.  0     Read completed successfully
  4393.  
  4394.  1     End-of-file; no data in the record
  4395.  
  4396.  2     Not enough room at the Disk Transfer Address to read one record;
  4397.        read canceled
  4398.  
  4399.  3     End-of-file; a partial record was read and padded to the record
  4400.        length with zeros
  4401.  
  4402.  
  4403.  Macro Definition:
  4404.  
  4405.  read_ran  macro  fcb
  4406.            mov    dx,offset fcb
  4407.            mov    ah,21H
  4408.            int    21H
  4409.            endm
  4410.  
  4411.  
  4412.  Example:
  4413.  
  4414.  The following program prompts for a letter, converts it to its alphabetic
  4415.  sequence (A = 1, B = 2, etc.), then reads and displays the corresponding
  4416.  record from a file named alphabet.dat that is on the disk in drive B. The
  4417.  file contains 26 records, each 28 bytes long.
  4418.  
  4419.  record_size     equ   0EH      ;offset of Record Size
  4420.                                 ;field of FCB
  4421.  relative_record equ   21H      ;offset of Relative Record
  4422.  ;                              field of FCB
  4423.  fcb           db    2,"ALPHABETDAT"
  4424.                db    26  dup (?)
  4425.  buffer        db    28 dup(?),"$"
  4426.  prompt        db   "Enter letter: $"
  4427.  crlf          db    0DH,0AH,"$"
  4428.  ;
  4429.  begin:        set_dta  buffer            ;see Function 1AH
  4430.                open     fcb               ;see Function 0FH
  4431.                mov      fcb[record_size],28 ;set record size
  4432.  get_char:     display  prompt            ;see Function 09H
  4433.                read_kbd_and_echo          ;see Function 01H
  4434.                cmp      al,0DH            ;just a CR?
  4435.                je       all_done          ;yes, go home
  4436.                sub      al,41H            ;convert ASCII code
  4437.                                           ;to record #
  4438.                mov      fcb[relative_record],al ;set relative
  4439.                                           ;record
  4440.                display  crlf              ;see Function 09H
  4441.                read_ran fcb               ;THIS FUNCTION
  4442.                display  buffer            ;see Function 09H
  4443.                display  crlf              ;see Function 09H
  4444.                jmp      get_char          ;get another char.
  4445.  all_done:     close    fcb               ;see Function 10H
  4446.  
  4447.  
  4448.  Random Write (Function 22H)
  4449.  
  4450.  
  4451.  Call:
  4452.  
  4453.  AH = 22H
  4454.  DS:DX
  4455.    Pointer to opened FCB
  4456.  
  4457.  
  4458.  Return:
  4459.  
  4460.  AL
  4461.    00H = Write completed successfully
  4462.    01H = Disk full
  4463.    02H = DTA too small
  4464.  
  4465.  
  4466.  Comments:
  4467.  
  4468.  Function 22H writes (from the Disk Transfer Address) the record pointed to
  4469.  by the Relative Record field (offset 20H) of the FCB. DX must contain the
  4470.  offset from the segment address in DS of an opened FCB. The Current Block
  4471.  (offset 0CH) and Current Record (offset 1FH) fields are set to agree with
  4472.  the Relative Record field (offset 20H). This record is then written from
  4473.  the Disk Transfer Address.
  4474.  
  4475.  The record length is taken from the Record Size field (offset 0EH) of
  4476.  the FCB. If the record size is less than a sector, the data at the Disk
  4477.  Transfer Address is written to a buffer, the buffer is written to disk when
  4478.  it contains a full sector of data; or when a program closes the file, or
  4479.  when it issues Function 0DH (Reset Disk).
  4480.  
  4481.  AL returns a code that describes the processing:
  4482.  
  4483.  Code  Meaning
  4484.  ───────────────────────────────────────────────────────────────────────────
  4485.  0     Write completed successfully
  4486.  
  4487.  1     Disk is full
  4488.  
  4489.  2     Not enough room at the Disk Transfer Address to write one record;
  4490.        write canceled
  4491.  
  4492.  
  4493.  Macro Definition:
  4494.  
  4495.  write_ran  macro  fcb
  4496.             mov    dx,offset fcb
  4497.             mov    ah,22H
  4498.             int    21H
  4499.             endm
  4500.  
  4501.  
  4502.  Example:
  4503.  
  4504.  The following program prompts for a letter, converts it to its alphabetic
  4505.  sequence (A = 1, B = 2, etc.), then reads and displays the corresponding
  4506.  record from a file named alphabet.dat that is on the disk in drive B.
  4507.  After displaying the record, it prompts you to enter a changed record. If
  4508.  you type a new record, it is written to the file, but if you just press the
  4509.  RETURN key, the record is not replaced. The file contains 26 records, each
  4510.  28 bytes long.
  4511.  
  4512.  record_size     equ   0EH      ;offset of Record Size
  4513.                                 ;field of FCB
  4514.  relative_record equ   21H      ;offset of Relative Record
  4515.  ;                              field of FCB
  4516.  fcb        db    2,"ALPHABETDAT"
  4517.             db    26  dup (?)
  4518.  buffer     db    28 dup(?),0DH,0AH,"$"
  4519.  prompt1    db   "Enter letter: $"
  4520.  prompt2    db   "New record (RETURN for no change): $"
  4521.  crlf       db    0DH,0AH,"$"
  4522.  reply      db    28 dup (32)
  4523.  blanks     db    26 dup (32)
  4524.  ;
  4525.  begin:     set_dta  buffer            ;see Function 1AH
  4526.             open     fcb               ;see Function 0FH
  4527.             mov      fcb[record_size],28 ;set record size
  4528.  get_char:  display  prompt1           ;see Function 09H
  4529.             read_kbd_and_echo          ;see Function 01H
  4530.             cmp      al,0DH            ;just a carriage return?
  4531.             je       all_done          ;yes, go home
  4532.             sub      al,41H            ;convert ASCII
  4533.                                        ;code to record #
  4534.             mov      fcb[relative_record],al
  4535.                                        ;set relative record
  4536.             display  crlf              ;see Function 09H
  4537.             read_ran fcb               ;THIS FUNCTION
  4538.             display  buffer            ;see Function 09H
  4539.             display  crlf              ;see Function 09H
  4540.             display  prompt2           ;see Function 09H
  4541.             get_string 27,reply        ;see Function 0AH
  4542.             display  crlf              ;see Function 09H
  4543.             cmp      reply[1],0        ;was anything typed
  4544.                                        ;besides CR?
  4545.             je       get_char          ;no
  4546.                                        ;get another char.
  4547.             xor      bx,bx             ;to load a byte
  4548.             mov      bl,reply[1]       ;use reply length as
  4549.                                        ;counter
  4550.             move_string blanks,buffer,26 ;see chapter end
  4551.             move_string reply[2],buffer,bx ;see chapter end
  4552.             write_ran fcb              ;THIS FUNCTION
  4553.             jmp      get_char          ;get another character
  4554.  all_done:  close    fcb               ;see Function 10H
  4555.  
  4556.  
  4557.  Get File Size (Function 23H)
  4558.  
  4559.  
  4560.  Call:
  4561.  
  4562.  AH = 23H
  4563.  DS:DX
  4564.    Pointer to unopened FCB
  4565.  
  4566.  
  4567.  Return:
  4568.  
  4569.  AL
  4570.    00H = Directory entry found
  4571.    FFH = No directory entry found
  4572.  
  4573.  
  4574.  Comments:
  4575.  
  4576.  Function 23H returns the size of a specified file. DX must contain the
  4577.  offset (from the segment address in DS) of an unopened FCB.
  4578.  
  4579.  If there is a directory entry that matches the specified file, MS-DOS
  4580.  divides the File Size field (offset 1CH) of the directory entry by the
  4581.  Record Size field (offset 0EH) of the FCB, puts the result in the Relative
  4582.  Record field (offset 20H) of the FCB, and returns 00 in AL.
  4583.  
  4584.  You must set the Record Size field of the FCB to the correct value
  4585.  before calling this function. If the Record Size field is not an even
  4586.  divisor of the File Size field, the value set in the Relative Record field
  4587.  is rounded up, yielding a value larger than the actual number of records.
  4588.  
  4589.  If this call does not find a matching directory, AL returns FFH.
  4590.  
  4591.  
  4592.  Macro Definition:
  4593.  
  4594.  file_size  macro  fcb
  4595.             mov    dx,offset fcb
  4596.             mov    ah,23H
  4597.             int    21H
  4598.             endm
  4599.  
  4600.  
  4601.  Example:
  4602.  
  4603.  The following program prompts for the name of a file, opens the file to
  4604.  fill in the Record Size field of the FCB, issues a File Size system call,
  4605.  and displays the record length and number of records.
  4606.  
  4607.  fcb           db      37 dup  (?)
  4608.  prompt        db     "File name: $"
  4609.  msg1          db     "Record length:     ",0DH,0AH,"$"
  4610.  msg2          db     "Records:      ",0DH,0AH,"$"
  4611.  crlf          db      0DH,0AH,"$"
  4612.  reply         db      17 dup(?)
  4613.  ;
  4614.  begin:        display prompt            ;see Function 09H
  4615.                get_string 17,reply       ;see Function 0AH
  4616.                cmp     reply[1],0        ;just a CR?
  4617.                jne     get_length        ;no, keep going
  4618.                jmp     all_done          ;yes, go home
  4619.  get_length:   display crlf              ;see Function 09H
  4620.                parse   reply[2],fcb      ;see Function 29H
  4621.                open    fcb               ;see Function 0FH
  4622.                file_size fcb             ;THIS FUNCTION
  4623.                mov     ax,word ptr fcb[33] ;get record length
  4624.                convert ax,10,msg2[9]     ;see end of chapter
  4625.                mov     ax,word ptr fcb[14] ; get record number
  4626.                convert ax,10,msg1[15]    ;see end of chapter
  4627.                display msg1              ;see Function 09H
  4628.                display msg2              ;see Function 09H
  4629.  all_done:     close   fcb               ;see Function 10H
  4630.  
  4631.  
  4632.  Set Relative Record (Function 24H)
  4633.  
  4634.  
  4635.  Call:
  4636.  
  4637.  AH = 24H
  4638.  DS:DX
  4639.    Pointer to opened FCB
  4640.  
  4641.  
  4642.  Return:
  4643.  
  4644.  None
  4645.  
  4646.  
  4647.  Comments:
  4648.  
  4649.  Function 24H sets the Relative Record field (offset 20H) to the file
  4650.  address specified by the Current Block field (offset 0CH) and Current
  4651.  Record field (offset 1FH). DX must contain the offset (from the segment
  4652.  address in DS) of an opened FCB. You use this call to set the file pointer
  4653.  before a Random Read or Write (Functions 21H, 22H, 27H, or 28H).
  4654.  
  4655.  
  4656.  Macro Definition:
  4657.  
  4658.  set_relative_record  macro  fcb
  4659.                       mov    dx,offset fcb
  4660.                       mov    ah,24H
  4661.                       int    21H
  4662.                       endm
  4663.  
  4664.  
  4665.  Example:
  4666.  
  4667.  The following program copies a file using the Random Block Read and Random
  4668.  Block Write system calls. It speeds the copy by setting the record length
  4669.  equal to the file size and the record count to 1, and by using a buffer of
  4670.  32K bytes. It positions the file pointer by setting the Current Record
  4671.  field (offset 1FH) to 1 and using Function 24H (Set Relative Record) to
  4672.  make the Relative Record field (offset 20H) point to the same record that
  4673.  the combination of the Current Block field (offset 0CH) and Current Record
  4674.  field (offset 1FH) points to.
  4675.  
  4676.  current_record  equ   20H        ;offset of Current Record
  4677.                                   ;field of FCB
  4678.  fil_size        equ   10H        ;offset of File Size
  4679.  ;                                field of FCB
  4680.  fcb       db      37 dup (?)
  4681.  filename  db      17 dup(?)
  4682.  prompt1   db     "File to copy: $"  ;see Function 09H for
  4683.  prompt2   db     "Name of copy: $"  ;explanation of $
  4684.  crlf      db      0DH,0AH,"$"
  4685.  file_length  dw   ?
  4686.  buffer    db      32767 dup(?)
  4687.  ;
  4688.  begin:    set_dta  buffer                    ;see Function 1AH
  4689.            display  prompt1                   ;see Function 09H
  4690.            get_string  15,filename            ;see Function 0AH
  4691.            display  crlf                      ;see Function 09H
  4692.            parse    filename[2],fcb           ;see Function 29H
  4693.            open     fcb                       ;see Function 0FH
  4694.            mov      fcb[current_record],0     ;set Current Record field
  4695.            set_relative_record  fcb           ;THIS FUNCTION
  4696.            mov      ax,word ptr fcb[fil_size] ;get file size
  4697.            mov      file_length,ax            ;save it for ran_block_write
  4698.            ran_block_read  fcb,1,ax           ;see Function 27H
  4699.            display  prompt2                   ;see Function 09H
  4700.            get_string  15,filename            ;see Function 0AH
  4701.            display  crlf                      ;see Function 09H
  4702.            parse    filename[2],fcb           ;see Function 29H
  4703.            create   fcb                       ;see Function 16H
  4704.            mov      fcb[current_record],0     ;set Current Record field
  4705.            set_relative_record  fcb           ;THIS FUNCTION
  4706.            mov      ax,file_length            ;get original file
  4707.            ran_block_write  fcb,1,ax          ;see Function 28H
  4708.            close    fcb                       ;see Function 10H
  4709.  
  4710.  
  4711.  Set Interrupt Vector (Function 25H)
  4712.  
  4713.  
  4714.  Call:
  4715.  
  4716.  AH = 25H
  4717.  AL
  4718.    Interrupt number
  4719.  DS:DX
  4720.    Pointer to interrupt-handling
  4721.    routine
  4722.  
  4723.  
  4724.  Return:
  4725.  
  4726.  None
  4727.  
  4728.  
  4729.  Comments:
  4730.  
  4731.  Function 25H sets the address in the interrupt vector table for the
  4732.  specified interrupt.
  4733.  
  4734.  AL must contain the number of the interrupt. DX must contain the
  4735.  offset (to the segment address in DS) of the interrupt-handling routine.
  4736.  
  4737.  To avoid compatibility problems, programs should never set an interrupt
  4738.  vector directly and should never use Interrupt 25H to read directly from
  4739.  memory. To get a vector, use Function 35H (Get Interrupt Vector), and to
  4740.  set a vector, use Function 25H, unless your program must be compatible with
  4741.  MS-DOS versions earlier than 2.0.
  4742.  
  4743.  
  4744.  Macro Definition:
  4745.  
  4746.  set_vector  macro  interrupt,handler_start
  4747.              mov    al,interrupt
  4748.              mov    dx,offset handler_start
  4749.              mov    ah,25H
  4750.              endm
  4751.  
  4752.  
  4753.  Example:
  4754.  
  4755.  Because interrupts tend to be machine-specific, no example is shown.
  4756.  
  4757.  
  4758.  Create New PSP (Function 26H)
  4759.  
  4760.  
  4761.  Call:
  4762.  
  4763.  AH = 26H
  4764.  DX
  4765.    Segment address of new PSP
  4766.  
  4767.  
  4768.  Return:
  4769.  
  4770.  None
  4771.  
  4772.  
  4773.  Comments:
  4774.  
  4775.  This function request has been superseded. Use Function 4BH (Load and
  4776.  Execute Program) to run a child process, unless your program must be
  4777.  compatible with MS-DOS versions earlier than 2.0.
  4778.  
  4779.  Function 26H creates a new Program Segment Prefix. DX must contain the
  4780.  segment address where the new PSP is to be created.
  4781.  
  4782.  
  4783.  Macro Definition:
  4784.  
  4785.  create_psp  macro  seg_addr
  4786.              mov    dx,seg_addr
  4787.              mov    ah,26H
  4788.              endm
  4789.  
  4790.  
  4791.  Example:
  4792.  
  4793.  Because Function 4BH (Load and Execute Program) and 4B03H (Load Overlay)
  4794.  have superseded this function request, no example is shown.
  4795.  
  4796.  
  4797.  Random Block Read (Function 27H)
  4798.  
  4799.  
  4800.  Call:
  4801.  
  4802.  AH = 27H
  4803.  DS:DX
  4804.    Pointer to opened FCB
  4805.  CX
  4806.    Number of blocks to read
  4807.  
  4808.  
  4809.  Return:
  4810.  
  4811.  AL
  4812.    0 = Read completed successfully
  4813.    1 = End of file, empty record
  4814.    2 = DTA too small
  4815.    3 = End of file, partial record
  4816.  CX
  4817.    Number of blocks read
  4818.  
  4819.  
  4820.  Comments:
  4821.  
  4822.  Function 27H reads one or more records from a specified file to the Disk
  4823.  Transfer Address. DX must contain the offset (to the segment address in DS)
  4824.  of an opened FCB. CX must contain the number of records to read. Reading
  4825.  starts at the record specified by the Relative Record field (offset 20H);
  4826.  you must set this field with Function 24H (Set Relative Record) before
  4827.  calling this function.
  4828.  
  4829.  DOS calculates the number of bytes to read by multiplying the value in
  4830.  CX by the Record Size field (offset 0EH) of the FCB.
  4831.  
  4832.  CX returns the number of records read. The Current Block field (offset
  4833.  0CH), Current Record field (offset 1FH), and Relative Record field (offset
  4834.  20H) are set to address the next record.
  4835.  
  4836.  If you call this function with CX=0, no records are read.
  4837.  
  4838.  AL returns a code that describes the processing:
  4839.  
  4840.  Code     Meaning
  4841.  ───────────────────────────────────────────────────────────────────────────
  4842.  0        Read completed successfully
  4843.  
  4844.  1        End-of-file; no data in the record
  4845.  
  4846.  2        Not enough room at the Disk Transfer Address to read one record;
  4847.           read canceled
  4848.  
  4849.  3        End-of-file; a partial record was read and padded to
  4850.           the record length with zeros
  4851.  
  4852.  
  4853.  Macro Definition:
  4854.  
  4855.  ran_block_read  macro  fcb,count,rec_size
  4856.                  mov    dx,offset fcb
  4857.                  mov    cx,count
  4858.                  mov    word ptr fcb[14],rec_size
  4859.                  mov    ah,27H
  4860.                  int    21H
  4861.                  endm
  4862.  
  4863.  
  4864.  Example:
  4865.  
  4866.  The following program copies a file by using Function 27H (Random Block
  4867.  Read). This program speeds the copy process by specifying a record count
  4868.  of 1 and a record length equal to the file size, and by using a buffer of
  4869.  32K bytes; the file is read as a single record (compare to the sample
  4870.  program for Function 28H that specifies a record length of 1 and a record
  4871.  count equal to the file size).
  4872.  
  4873.  current_record  equ  20H  ;offset of Current Record field
  4874.  fil_size        equ  10H  ;offset of File Size field
  4875.  ;
  4876.  fcb       db      37 dup (?)
  4877.  filename  db      17 dup(?)
  4878.  prompt1   db     "File to copy: $"         ;see Function 09H for
  4879.  prompt2   db     "Name of copy: $"         ;explanation of $
  4880.  crlf      db      0DH,0AH,"$"
  4881.  file_length  dw   ?
  4882.  buffer    db      32767 dup(?)
  4883.  ;
  4884.  begin:    set_dta    buffer                ;see Function 1AH
  4885.            display    prompt1               ;see Function 09H
  4886.            get_string 15,filename           ;see Function 0AH
  4887.            display    crlf                  ;see Function 09H
  4888.            parse      filename[2],fcb       ;see Function 29H
  4889.            open       fcb                   ;see Function 0FH
  4890.            mov        fcb[current_record],0 ;set Current Record field
  4891.            set_relative_record fcb          ;see Function 24H
  4892.            mov        ax, word ptr fcb[fil_size]
  4893.                                             ;get file size
  4894.            mov        file_length,ax        ;save it
  4895.            ran_block_read  fcb,1,ax         ;THIS FUNCTION
  4896.            display    prompt2               ;see Function 09H
  4897.            get_string 15,filename           ;see Function 0AH
  4898.            display    crlf                  ;see Function 09H
  4899.            parse      filename[2],fcb       ;see Function 29H
  4900.            create     fcb                   ;see Function 16H
  4901.            mov        fcb[current_record],0 ;set current Record field
  4902.            set_relative_record fcb          ;see Function 24H
  4903.            ran_block_write  fcb,1,ax        ;see Function 28H
  4904.            close      fcb                   ;see Function 10H
  4905.  
  4906.  
  4907.  Random Block Write (Function 28H)
  4908.  
  4909.  
  4910.  Call:
  4911.  
  4912.  AH = 28H
  4913.  DS:DX
  4914.    Pointer to opened FCB
  4915.  CX
  4916.    Number of blocks to write
  4917.    (0 = set File Size field)
  4918.  
  4919.  
  4920.  Return:
  4921.  
  4922.  AL
  4923.    00H = Write completed successfully
  4924.    01H = Disk full
  4925.    02H = End of segment
  4926.  CX
  4927.    Number of blocks written
  4928.  
  4929.  
  4930.  Comments:
  4931.  
  4932.  Function 28H writes one or more records to a specified file from the Disk
  4933.  Transfer Address. DX must contain the offset (to the segment address in DS)
  4934.  of an opened FCB; CX must contain either the number of records to write
  4935.  or 0.
  4936.  
  4937.  If CX is not 0, the specified number of records is written to the file,
  4938.  starting at the record specified in the Relative Record field (offset 20H)
  4939.  of the FCB. If CX is 0, no records are written, but MS-DOS sets the
  4940.  File Size field (offset 1CH) of the directory entry to the value in the
  4941.  Relative Record field (offset 20H) of the FCB. To satisfy this new file
  4942.  size, disk allocation units are allocated or released, as required.
  4943.  
  4944.  MS-DOS calculates the number of bytes to write by multiplying the
  4945.  value in CX by the Record Size field (offset 0EH) of the FCB. CX returns
  4946.  the number of records written; the Current Block field (offset 0CH),
  4947.  Current Record field (offset 1FH), and Relative Record (offset 20H) field
  4948.  are set to address the next record.
  4949.  
  4950.  AL returns a code that describes the processing:
  4951.  
  4952.  Code  Meaning
  4953.  ───────────────────────────────────────────────────────────────────────────
  4954.  0     Write completed successfully
  4955.  
  4956.  1     Disk full. No records written
  4957.  
  4958.  2     Not enough room at the Disk Transfer Address to write one record;
  4959.        write canceled
  4960.  
  4961.  
  4962.  Macro Definition:
  4963.  
  4964.  ran_block_write  macro  fcb,count,rec_size
  4965.                   mov    dx,offset fcb
  4966.                   mov    cx,count
  4967.                   mov    word ptr fcb[14],rec_size
  4968.                   mov    ah,28H
  4969.                   int    21H
  4970.                   endm
  4971.  
  4972.  
  4973.  Example:
  4974.  
  4975.  The following program copies a file using Function 27H (Random Block Read)
  4976.  and Function 28H (Random Block Write). This program speeds the copy process
  4977.  by specifying a record count equal to the file size and a record length of
  4978.  1, and by using a buffer of 32K bytes; the file is copied quickly with one
  4979.  disk access each to read and write (compare to the sample program of
  4980.  Function 27H, which specifies a record count of 1 and a record length
  4981.  equal to file size).
  4982.  
  4983.  current_record  equ  20H   ;offset of Current Record field
  4984.  fil_size        equ  10H   ;offset of File Size field
  4985.  ;
  4986.  fcb       db      37 dup (?)
  4987.  filename  db      17 dup(?)
  4988.  prompt1   db     "File to copy: $"   ;see Function 09H for
  4989.  prompt2   db     "Name of copy: $"   ;explanation of $
  4990.  crlf      db      0DH,0AH,"$"
  4991.  num_recs  dw      ?
  4992.  buffer    db      32767 dup(?)
  4993.  ;
  4994.  begin:    set_dta    buffer      ;see Function 1AH
  4995.            display    prompt1     ;see Function 09H
  4996.            get_string 15,filename ;see Function 0AH
  4997.            display    crlf        ;see Function 09H
  4998.            parse      filename[2],fcb  ;see Function 29H
  4999.            open       fcb              ;see Function 0FH
  5000.            mov        fcb[current_record],0;set Current Record field
  5001.            set_relative_record fcb     ;see Function 24H
  5002.            mov        ax, word ptr fcb[fil_size]
  5003.                                        ;get file size
  5004.            mov        num_recs,ax      ;save it
  5005.            ran_block_read  fcb,num_recs,1  ;THIS FUNCTION
  5006.            display    prompt2          ;see Function 09H
  5007.            get_string 15,filename      ;see Function 0AH
  5008.            display    crlf             ;see Function 09H
  5009.            parse      filename[2],fcb  ;see Function 29H
  5010.            create     fcb              ;see Function 16H
  5011.            mov        fcb[current_record],0  ;set Current Record field
  5012.            set_relative_record fcb     ;see Function 24H
  5013.            ran_block_write fcb,num_recs,1 ;see Function 28H
  5014.            close      fcb              ;see Function 10H
  5015.  
  5016.  
  5017.  Parse File Name (Function 29H)
  5018.  
  5019.  
  5020.  Call:
  5021.  
  5022.  AH = 29H
  5023.  AL
  5024.    Controls parsing (see text)
  5025.  DS:SI
  5026.    Pointer to string to parse
  5027.  ES:DI
  5028.    Pointer to buffer for unopened FCB
  5029.  
  5030.  
  5031.  Return:
  5032.  
  5033.  AL
  5034.    00H     = No wildcard characters
  5035.    01H     = Wildcard characters used
  5036.    FFH     = Drive letter invalid
  5037.  DS:SI
  5038.    Pointer to first byte past
  5039.    string that was parsed
  5040.  ES:DI
  5041.    Pointer to unopened FCB
  5042.  
  5043.  
  5044.  Comments:
  5045.  
  5046.  Function 29H parses a string for a filename of the form
  5047.  drive:filename.extension. SI must contain the offset (to the segment
  5048.  address in DS) of the string to parse; DI must contain the offset (to the
  5049.  segment address in ES) of an area of memory large enough to hold an
  5050.  unopened FCB. If the string contains a valid filename, this call creates
  5051.  a corresponding unopened FCB at ES:DI.
  5052.  
  5053.  AL controls the parsing. Bits 4-7 must be 0; bits 0-3 have the
  5054.  following meaning:
  5055.  
  5056.  
  5057.       Table 1.20
  5058.       Bit values for Function 29H
  5059. ╓┌──────────┌───────┌────────────────────────────────────────────────────────╖
  5060.       Bit   Value   Meaning
  5061.       ────────────────────────────────────────────────────────────────────
  5062.       0     0       Stop parsing if a file separator is encountered.
  5063.       Bit   Value   Meaning
  5064.      0     0       Stop parsing if a file separator is encountered.
  5065.  
  5066.             1       Ignore leading separators.
  5067.  
  5068.       1     0       Set the drive number in the FCB to 0 (current
  5069.                     drive) if the string does not contain a drive
  5070.                     number.
  5071.  
  5072.             1       Leave the drive number in the FCB unchanged if
  5073.                     the string does not contain a drive number.
  5074.  
  5075.       2     0       Set the filename in the FCB to eight blanks if
  5076.                     the string does not contain a filename.
  5077.  
  5078.             1       Leave the filename in the FCB unchanged if the
  5079.                     string does not contain a filename.
  5080.  
  5081.       3     1       Leave the extension in the FCB unchanged if the
  5082.                     string does not contain an extension.
  5083.  
  5084.       Bit   Value   Meaning
  5085. 
  5086.             0       Set the extension in the FCB to three blanks if
  5087.                     the string does not contain an extension.
  5088.  
  5089.  
  5090.  If the string contains a filename or extension that includes an asterisk
  5091.  (*), all remaining characters in the name or extension are set to question
  5092.  marks (?).
  5093.  
  5094.  
  5095.  Filename separators:
  5096.  
  5097.   :  ;  . ,  =  +  /  "  [  ]  \  <  >  |  space  tab
  5098.  
  5099.  Filename terminators include all the filename separators, plus any control
  5100.  character. A filename cannot contain a filename terminator, since if the
  5101.  call encounters one, parsing stops.
  5102.  
  5103.  If the string contains a valid filename:
  5104.  
  5105.      ■ AL returns 1 if the filename or extension contains a wildcard
  5106.        character (* or ?); AL returns 0 if neither the filename nor
  5107.        extension contains a wildcard character.
  5108.  
  5109.      ■ DS:SI points to the first character following the parsed string.
  5110.  
  5111.      ■ ES:DI points to the first byte of the unopened FCB.
  5112.  
  5113.  If the drive letter is invalid, AL returns FFH. If the string does not
  5114.  contain a valid filename, ES:DI+1 points to a blank.
  5115.  
  5116.  
  5117.  Macro Definition:
  5118.  
  5119.  parse macro string,fcb
  5120.        mov   si,offset string
  5121.        mov   di,offset fcb
  5122.        push  es
  5123.        push  ds
  5124.        pop   es
  5125.        mov   al,0FH        ;bits 0-3 on
  5126.        mov   ah,29H
  5127.        int   21H
  5128.        pop   es
  5129.        endm
  5130.  
  5131.  
  5132.  Example:
  5133.  
  5134.  The following program verifies the existence of the file named in reply to
  5135.  the prompt.
  5136.  
  5137.  fcb           db      37 dup (?)
  5138.  prompt        db     "Filename: $"
  5139.  reply         db      17 dup(?)
  5140.  yes           db     "File exists",0DH,0AH,"$"
  5141.  no            db     "File does not exist",0DH,0AH,"$"
  5142.                crlf    db 0DH,0AH,"$"
  5143.  ;
  5144.  begin:        display    prompt        ;see Function 09H
  5145.                get_string 15,reply      ;see Function 0AH
  5146.                parse      reply[2],fcb  ;THIS FUNCTION
  5147.                display    crlf          ;see Function 09H
  5148.                search_first  fcb        ;see Function 11H
  5149.                cmp        al,0FFH       ;dir. entry found?
  5150.                je         not_there     ;no
  5151.                display    yes           ;see Function 09H
  5152.                jmp        return
  5153.  not_there:    display    no
  5154.  
  5155.  
  5156.  Get Date (Function 2AH)
  5157.  
  5158.  
  5159.  Call:
  5160.  
  5161.  AH = 2AH
  5162.  
  5163.  
  5164.  Return:
  5165.  
  5166.  CX
  5167.    Year (1980-2099)
  5168.  DH
  5169.    Month (1-12)
  5170.  DL
  5171.    Day (1-31)
  5172.  AL
  5173.    Day of week (0=Sun., 6=Sat.)
  5174.  
  5175.  
  5176.  Comments:
  5177.  
  5178.  Function 2AH returns the current date set in the operating system as binary
  5179.  numbers in CX and DX:
  5180.  
  5181.  Register       Contents
  5182.  ───────────────────────────────────────────────────────────────────────────
  5183.  CX             Year (1980-2099)
  5184.  DH             Month (1=January, 2=February, etc.)
  5185.  DL             Day of month (1-31)
  5186.  AL             Day of week (0=Sunday, 1=Monday, etc.)
  5187.  
  5188.  
  5189.  Macro Definition:
  5190.  
  5191.  get_date  macro
  5192.            mov   ah,2AH
  5193.            int   21H
  5194.            endm
  5195.  
  5196.  
  5197.  Example:
  5198.  
  5199.  The following program gets the date, increments the day, increments the
  5200.  month or year, if necessary, and sets the new date.
  5201.  
  5202.  month      db      31,28,31,30,31,30,31,31,30,31,30,31
  5203.  ;
  5204.  begin:     get_date            ;THIS FUNCTION
  5205.             inc    dl           ;increment day
  5206.             xor    bx,bx        ;so BL can be used as index
  5207.             mov    bl,dh        ;move month to index register
  5208.             dec    bx           ;month table starts with 0
  5209.             cmp    dl,month[bx] ;past end of month?
  5210.             jle    month_ok     ;no, set new date
  5211.             mov    dl,1         ;yes, set day to 1
  5212.             inc    dh           ;and increment month
  5213.             cmp    dh,12        ;past end of year?
  5214.             jle    month_ok     ;no, set new date
  5215.             mov    dh,1         ;yes, set month to 1
  5216.             inc    cx           ;increment year
  5217.  month_ok:  set_date cx,dh,dl   ;see Function 2AH
  5218.  
  5219.  
  5220.  Set Date (Function 2BH)
  5221.  
  5222.  
  5223.  Call:
  5224.  
  5225.  AH = 2BH
  5226.  CX
  5227.    Year (1980-2099)
  5228.  DH
  5229.    Month (1-12)
  5230.  DL
  5231.    Day (1-31)
  5232.  
  5233.  
  5234.  Return:
  5235.  
  5236.  AL
  5237.    00H     = Date was valid
  5238.    FFH     = Date was invalid
  5239.  
  5240.  
  5241.  Comments:
  5242.  
  5243.  Function 2BH sets the date in the operating system (and in the CMOS clock,
  5244.  if one exists). Registers CX and DX must contain a valid date in binary:
  5245.  
  5246.  Register       Contents
  5247.  ───────────────────────────────────────────────────────────────────────────
  5248.  CX             Year (1980-2099)
  5249.  DH             Month (1=January, 2=February, etc.)
  5250.  DL             Day of month (1-31)
  5251.  
  5252.  If the date is valid, the call sets it and AL returns 0. If the date
  5253.  is not valid, the function aborts and AL returns FFH.
  5254.  
  5255.  
  5256.  Macro Definition:
  5257.  
  5258.  set_date  macro  year,month,day
  5259.            mov    cx,year
  5260.            mov    dh,month
  5261.            mov    dl,day
  5262.            mov    ah,2BH
  5263.            int    21H
  5264.            endm
  5265.  
  5266.  
  5267.  Example:
  5268.  
  5269.  The following program gets the date, increments the day, increments the
  5270.  month or year, if necessary, and sets the new date.
  5271.  
  5272.  month      db      31,28,31,30,31,30,31,31,30,31,30,31
  5273.  ;
  5274.  begin:     get_date            ;see Function 2AH
  5275.             inc    dl           ;increment day
  5276.             xor    bx,bx        ;so BL can be used as index
  5277.             mov    bl,dh        ;move month to index register
  5278.             dec    bx           ;month table starts with 0
  5279.             cmp    dl,month[bx] ;past end of month?
  5280.             jle    month_ok     ;no, set the new date
  5281.             mov    dl,1         ;yes, set day to 1
  5282.             inc    dh           ;and increment month
  5283.             cmp    dh,12        ;past end of year?
  5284.             jle    month_ok     ;no, set the new date
  5285.             mov    dh,1         ;yes, set the month to 1
  5286.             inc    cx           ;increment year
  5287.  month_ok:  set_date cx,dh,dl   ;THIS FUNCTION
  5288.  
  5289.  
  5290.  Get Time (Function 2CH)
  5291.  
  5292.  
  5293.  Call:
  5294.  
  5295.  AH = 2CH
  5296.  
  5297.  
  5298.  Return:
  5299.  
  5300.  CH
  5301.    Hour (0-23)
  5302.  CL
  5303.    Minutes (0-59)
  5304.  DH
  5305.    Seconds (0-59)
  5306.  DL
  5307.    Hundredths (0-99)
  5308.  
  5309.  
  5310.  Comments:
  5311.  
  5312.  Function 2CH returns the current time set in the operating system (and sets
  5313.  the CMOS clock, if one exists) as binary numbers in CX and DX:
  5314.  
  5315.  Register        Contents
  5316.  ───────────────────────────────────────────────────────────────────────────
  5317.  CH              Hour (0-23)
  5318.  CL              Minutes (0-59)
  5319.  DH              Seconds (0-59)
  5320.  DL              Hundredths of a second (0-99)
  5321.  
  5322.  Depending on how your hardware keeps time, some of these fields may be
  5323.  irrelevant. As an example, many CMOS clock chips do not resolve more than
  5324.  seconds. In such a case, the value in DL will probably always be 0.
  5325.  
  5326.  
  5327.  Macro Definition:
  5328.  
  5329.  get_time  macro
  5330.            mov   ah,2CH
  5331.            int   21H
  5332.            endm
  5333.  
  5334.  
  5335.  Example:
  5336.  
  5337.  The following program displays the time continuously until you press
  5338.  any key.
  5339.  
  5340.  time         db    "00:00:00.00",0DH,"$"
  5341.  ;
  5342.  begin:       get_time               ;THIS FUNCTION
  5343.               byte_to_dec ch,time    ;see end of chapter
  5344.               byte_to_dec cl,time[3] ;see end of chapter
  5345.               byte_to_dec dh,time[6] ;see end of chapter
  5346.               byte_to_dec dl,time[9] ;see end of chapter
  5347.               display time           ;see Function 09H
  5348.               check_kbd_status       ;see Function 0BH
  5349.               cmp     al,0FFH        ;has a key been pressed?
  5350.               je      return         ;yes, terminate
  5351.               jmp     begin          ;no, display time
  5352.  
  5353.  
  5354.  Set Time (Function 2DH)
  5355.  
  5356.  
  5357.  Call:
  5358.  
  5359.  AH = 2DH
  5360.  CH
  5361.    Hour (0-23)
  5362.  CL
  5363.    Minutes (0-59)
  5364.  DH
  5365.    Seconds (0-59)
  5366.  DL
  5367.    Hundredths (0-99)
  5368.  
  5369.  
  5370.  Return:
  5371.  
  5372.  AL
  5373.    00H     = Time was valid
  5374.    FFH     = Time was invalid
  5375.  
  5376.  
  5377.  Comments:
  5378.  
  5379.  Function 2DH sets the time in the operating system. Registers CX and DX
  5380.  must contain a valid time in binary:
  5381.  
  5382.  Register       Contents
  5383.  ───────────────────────────────────────────────────────────────────────────
  5384.  CH             Hour (0-23)
  5385.  CL             Minutes (0-59)
  5386.  DH             Seconds (0-59)
  5387.  DL             Hundredths of a second (0-9)
  5388.  
  5389.  Depending on how your hardware keeps time, some of these fields may be
  5390.  irrelevant. As an example, many CMOS clock chips do not resolve more than
  5391.  seconds. In such a case, the value in DL will not be relevant.
  5392.  
  5393.  If the time is valid, the call sets it and AL returns 0. If the time
  5394.  is not valid, the function aborts and AL returns FFH.
  5395.  
  5396.  
  5397.  Macro Definition:
  5398.  
  5399.  set_time  macro  hour,minutes,seconds,hundredths
  5400.            mov    ch,hour
  5401.            mov    cl,minutes
  5402.            mov    dh,seconds
  5403.            mov    dl,hundredths
  5404.            mov    ah,2DH
  5405.            int    21H
  5406.            endm
  5407.  
  5408.  
  5409.  Example:
  5410.  
  5411.  The following program sets the system clock to 0 and displays the time
  5412.  continuously. When you type a character, the display freezes; when you type
  5413.  another character, the clock is reset to 0 and the display starts again.
  5414.  
  5415.  time          db  "00:00:00.00",0DH,0AH,"$"
  5416.  ;
  5417.  begin:        set_time  0,0,0,0       ;THIS FUNCTION
  5418.  read_clock:   get_time                ;see Function 2CH
  5419.                byte_to_dec  ch,time    ;see end of chapter
  5420.                byte_to_dec  cl,time[3] ;see end of chapter
  5421.                byte_to_dec  dh,time[6] ;see end of chapter
  5422.                byte_to_dec  dl,time[9] ;see end of chapter
  5423.                display  time           ;see Function 09H
  5424.                dir_console_io 0FFH     ;see Function 06H
  5425.                cmp      al,00H         ;was a char. typed?
  5426.                jne      stop           ;yes, stop the timer
  5427.                jmp      read_clock     ;no keep timer on
  5428.  stop:         read_kbd                ;see Function 08H
  5429.                jmp      begin          ;keep displaying time
  5430.  
  5431.  
  5432.  Set/Reset Verify Flag (Function 2EH)
  5433.  
  5434.  
  5435.  Call:
  5436.  
  5437.  AH = 2EH
  5438.  AL
  5439.    0 = Do not verify
  5440.    1 = Verify
  5441.  
  5442.  
  5443.  Return:
  5444.  
  5445.  None
  5446.  
  5447.  
  5448.  Comments:
  5449.  
  5450.  Function 2EH tells MS-DOS whether to verify each disk write. If AL is 1,
  5451.  verify is on; if AL is 0, verify is off. MS-DOS checks this flag each time
  5452.  it writes to a disk.
  5453.  
  5454.  The flag is normally off; you may wish to turn it on when writing
  5455.  critical data to disk. Because disk errors are rare and verification slows
  5456.  writing, you will probably want to leave it off at other times. You can
  5457.  check the setting with Function 54H (Get Verify State).
  5458.  
  5459.  
  5460.  Macro Definition:
  5461.  
  5462.  verify  macro  switch
  5463.          mov    al,switch
  5464.          mov    ah,2EH
  5465.          int    21H
  5466.          endm
  5467.  
  5468.  
  5469.  Example:
  5470.  
  5471.  The following program copies the contents of a single-sided disk in drive A
  5472.  to the disk in drive B, verifying each write. It uses a buffer of
  5473.  32K bytes.
  5474.  
  5475.  on           equ   1
  5476.  off          equ   0
  5477.  ;
  5478.  prompt       db   "Source in A, target in B",0DH,0AH
  5479.               db   "Any key to start. $"
  5480.  first        dw    0
  5481.  buffer       db    60 dup (512 dup(?))   ;60 sectors
  5482.  ;
  5483.  begin:       display prompt              ;see Function 09H
  5484.               read_kbd                    ;see Function 08H
  5485.               verify on                   ;THIS FUNCTION
  5486.               mov    cx,6                 ;copy 60 sectors
  5487.                                           ;6 times
  5488.  copy:        push   cx                   ;save counter
  5489.               abs_disk_read  0,buffer,60,first ;see Int 25H
  5490.               abs_disk_write  1,buffer,64,first ;see Int 26H
  5491.               add    first,60             ;do next 60 sectors
  5492.               pop    cx                   ;restore counter
  5493.               loop   copy                 ;do it again
  5494.               verify off                  ;THIS FUNCTION
  5495.  
  5496.  
  5497.  Get Disk Transfer Address (Function 2FH)
  5498.  
  5499.  
  5500.  Call:
  5501.  
  5502.  AH = 2FH
  5503.  
  5504.  
  5505.  Return:
  5506.  
  5507.  ES:BX
  5508.    Pointer to Disk Transfer Address
  5509.  
  5510.  
  5511.  Comments:
  5512.  
  5513.  Function 2FH returns the segment address of the current Disk Transfer
  5514.  Address in ES and the offset in BX.
  5515.  
  5516.  
  5517.  Macro Definition:
  5518.  
  5519.  get_dta  macro
  5520.           mov    ah,2fH
  5521.           int    21H
  5522.           endm
  5523.  
  5524.  
  5525.  Example:
  5526.  
  5527.  The following program displays the current Disk Transfer Address in the
  5528.  form:  segment:offset.
  5529.  
  5530.  message   db      "DTA --        :    ",0DH,0AH,"$"
  5531.  sixteen   db       10H
  5532.  temp      db       2 dup (?)
  5533.  ;
  5534.  begin:    get_dta                      ;THIS FUNCTION
  5535.            mov    word ptr temp,ex      ;To access each byte
  5536.            convert temp[1],sixteen,message[07H]  ;See end of
  5537.            convert temp,sixteen,message[09H]    ;chapter for
  5538.            convert bh,sixteen,message[0CH]      ;description
  5539.            convert bl,sixteen,message[0EH]      ;of CONVERT
  5540.            display message              ;See Function 09H
  5541.  
  5542.  
  5543.  Get MS-DOS Version Number (Function 30H)
  5544.  
  5545.  
  5546.  Call:
  5547.  
  5548.  AH = 30H
  5549.  
  5550.  
  5551.  Return:
  5552.  
  5553.  AL
  5554.    Major version number
  5555.  AH
  5556.    Minor version number
  5557.  BH
  5558.    OEM serial number
  5559.  BL:CX
  5560.    24-bit user (serial) number
  5561.  
  5562.  
  5563.  Comments:
  5564.  
  5565.  Function 30H returns the MS-DOS version number. AL returns the major
  5566.  version number; AH returns the minor version number. (For example,
  5567.  MS-DOS 3.0 returns 3 in AL and 0 in AH.)
  5568.  
  5569.  If AL returns 0, the MS-DOS version is earlier than 2.0.
  5570.  
  5571.  
  5572.  Macro Definition:
  5573.  
  5574.  get_version  macro
  5575.               mov    ah,30H
  5576.               int    21H
  5577.               endm
  5578.  
  5579.  
  5580.  Example:
  5581.  
  5582.  The following program displays the MS-DOS version if it is 1.28 or greater.
  5583.  
  5584.  message   db      "MS-DOS Version  . ",0DH,0AH,"$"
  5585.  ten       db       0AH                 ;For CONVERT
  5586.  ;
  5587.  begin:    get_version                  ;THIS FUNCTION
  5588.            cmp     al,0                 ;1.28 or later?
  5589.            jng     return               ;No, go home
  5590.            convert al,ten,message[0FH]  ;See end of chapter
  5591.            convert ah,ten,message[12H]  ;for description
  5592.            display message              ;See Function 09H
  5593.  
  5594.  
  5595.  Keep Process (Function 31H)
  5596.  
  5597.  
  5598.  Call:
  5599.  
  5600.  AH = 31H
  5601.  AL
  5602.    Return code
  5603.  DX
  5604.    Memory size, in paragraphs
  5605.  
  5606.  
  5607.  Return:
  5608.  
  5609.  None
  5610.  
  5611.  
  5612.  Comments:
  5613.  
  5614.  Function 31H makes a program remain resident after it terminates. You can
  5615.  use it to install device-specific interrupt handlers. But unlike Interrupt
  5616.  27H (Terminate But Stay Resident), this function request allows more than
  5617.  64K bytes to remain resident and does not require CS to contain the segment
  5618.  address of the Program Segment Prefix. You should use Function 31H to
  5619.  install a resident program unless your program must be compatible with
  5620.  MS-DOS versions earlier than 2.0.
  5621.  
  5622.  DX must contain the number of paragraphs of memory required by the
  5623.  program (one paragraph = 16 bytes). AL contains an exit code.
  5624.  
  5625.  Be careful when using this function with .exe programs. The value in
  5626.  DX must be the total size to remain resident, not just the size of the code
  5627.  segment which is to remain resident. A typical error is to forget about
  5628.  the 100H-byte program-header-prefix and give a value in DX that is 10H
  5629.  too small.
  5630.  
  5631.  MS-DOS terminates the current process and tries to set the memory
  5632.  allocation to the number of paragraphs in DX. No other allocation blocks
  5633.  belonging to the process are released.
  5634.  
  5635.  By using Function 4DH (Get Return Code of Child Process), the parent
  5636.  process can retrieve the process's exit code from AL. (You can test this
  5637.  exit code by using the if command with errorlevel.)
  5638.  
  5639.  
  5640.  Macro Definition:
  5641.  
  5642.  keep_process  macro return_code,last_byte
  5643.                mov   al,return_code
  5644.                mov   dx,offset last_byte
  5645.                mov   cl,4
  5646.                shr   dx,cl
  5647.                inc   dx
  5648.                mov   ah,31H
  5649.                int   21H
  5650.                endm
  5651.  
  5652.  
  5653.  Example:
  5654.  
  5655.  Because the most common use of this call is to install a machine-specific
  5656.  routine, an example is not shown. The macro definition, however, shows the
  5657.  calling syntax.
  5658.  
  5659.  
  5660.  CONTROL-C Check (Function 33H)
  5661.  
  5662.  
  5663.  Call:
  5664.  
  5665.  AH = 33H
  5666.  AL
  5667.     0 = Get state
  5668.     1 = Set state
  5669.  DL (if AL=1)
  5670.     0 = Off
  5671.     1 = On
  5672.  
  5673.  
  5674.  Return:
  5675.  
  5676.  DL (if AL=0)
  5677.     0 = Off
  5678.     1 = On
  5679.  AL
  5680.     FFH = error (AL was neither 0 nor 1
  5681.           when call was made)
  5682.  
  5683.  
  5684.  Comments:
  5685.  
  5686.  Function 33H gets or sets the state of CONTROL-C (or CONTROL-BREAK for IBM
  5687.  compatibles) checking in MS-DOS. AL must contain a code that specifies the
  5688.  requested action:
  5689.  
  5690.  Code  Meaning
  5691.  ───────────────────────────────────────────────────────────────────────────
  5692.  0     Current state of CONTROL-C checking in DL
  5693.  1     Set state of CONTROL-C checking to the value in DL
  5694.  
  5695.  If AL is 0, DL returns the current state (0=off, 1=on). If AL is 1, the
  5696.  value in DL specifies the state to be set (0=off, 1=on). If AL is neither 0
  5697.  nor 1, AL returns FFH and the state of CONTROL-C checking is unaffected.
  5698.  
  5699.  MS-DOS normally checks for CONTROL-C only when carrying out certain
  5700.  function requests in the 01H through 0CH group (see the description of
  5701.  specific calls for details). When CONTROL-C checking is on, MS-DOS checks
  5702.  for CONTROL-C when carrying out any function request. For example, if
  5703.  CONTROL-C checking is off, all disk I/O proceeds without interruption, but
  5704.  if it is on, the CONTROL-C interrupt is issued at the function request that
  5705.  initiates the disk operation.
  5706.  
  5707.  ───────────────────────────────────────────────────────────────────────────
  5708.  Note
  5709.    Programs that use Function 06H (Direct Console I/O) or 07H (Direct
  5710.    Console Input) to read CONTROL-C as data must ensure that the CONTROL-C
  5711.    checking is off.
  5712.  ───────────────────────────────────────────────────────────────────────────
  5713.  
  5714.  
  5715.  Macro Definition:
  5716.  
  5717.  ctrl_c_ck  macro  action,state
  5718.             mov    al,action
  5719.             mov    dl,state
  5720.             mov    ah,33H
  5721.             int    21H
  5722.             endm
  5723.  
  5724.  
  5725.  Example:
  5726.  
  5727.  The following program displays a message that tells whether CONTROL-C
  5728.  checking is on or off:
  5729.  
  5730.  message   db       "CONTROL-C checking ","$"
  5731.  on        db       "on","$",0DH,0AH,"$"
  5732.  off       db       "off","$",0DH,0AH,"$"
  5733.  ;
  5734.  begin:    display   message          ;See Function 09H
  5735.            ctrl_c_ck 0                ;THIS FUNCTION
  5736.            cmp       dl,0             ;Is checking off?
  5737.            jg        ck_on            ;No
  5738.            display   off              ;See Function 09H
  5739.            jmp       return           ;Go home
  5740.  ck_on:    display   on               ;See Function 09H
  5741.  
  5742.  
  5743.  Get Interrupt Vector (Function 35H)
  5744.  
  5745.  
  5746.  Call:
  5747.  
  5748.  AH = 35H
  5749.  AL
  5750.     Interrupt number
  5751.  
  5752.  
  5753.  Return:
  5754.  
  5755.  ES:BX
  5756.     Pointer to interrupt routine
  5757.  
  5758.  
  5759.  Comments:
  5760.  
  5761.  Function 35H gets the address from the interrupt-vector table for the
  5762.  specified interrupt. AL must contain the number of an interrupt.
  5763.  
  5764.  ES returns the segment address of the interrupt handler; BX returns
  5765.  the offset.
  5766.  
  5767.  To avoid compatibility problems, programs should never read an
  5768.  interrupt vector directly from memory, nor set an interrupt vector by
  5769.  writing it into memory. Use this function request to get a vector and
  5770.  Function 25H (Set Interrupt Vector) to set a vector, unless your program
  5771.  must be compatible with MS-DOS versions earlier than 2.0.
  5772.  
  5773.  
  5774.  Macro Definition:
  5775.  
  5776.  get_vector  macro  interrupt
  5777.              mov    al,interrupt
  5778.              mov    ah,35H
  5779.              int    21H
  5780.              endm
  5781.  
  5782.  
  5783.  Example:
  5784.  
  5785.  The following program displays the segment and offset (CS:IP) for the
  5786.  handler for Interrupt 25H (Absolute Disk Read).
  5787.  
  5788.  message   db     "Interrupt 25H -- CS:0000 IP:0000"
  5789.            db      0DH,0AH,"$"
  5790.  vec_seg   db      2 dup (?)
  5791.  vec_off   db      2 dup (?)
  5792.  ;
  5793.  begin:    push    es                    ;save ES
  5794.            get_vector 25H                ;THIS FUNCTION
  5795.            mov     ax,es                 ;INT25H segment in AX
  5796.            pop     es                    ;save ES
  5797.            convert ax,16,message[20]     ;see end of chapter
  5798.            convert bx,16,message[28]     ;see end of chapter
  5799.            display message               ;See Function 09H
  5800.  
  5801.  
  5802.  Get Disk Free Space (Function 36H)
  5803.  
  5804.  
  5805.  Call:
  5806.  
  5807.  AH = 36H
  5808.  DL
  5809.     Drive (0=default, 1=A, etc.)
  5810.  
  5811.  
  5812.  Return:
  5813.  
  5814.  AX
  5815.     0FFFFH if drive number is invalid;
  5816.     otherwise, sectors per cluster
  5817.  BX
  5818.     Available clusters
  5819.  CX
  5820.     Bytes per sector
  5821.  DX
  5822.     Clusters per drive
  5823.  
  5824.  
  5825.  Comments:
  5826.  
  5827.  Function 36H returns the number of clusters available on the disk in the
  5828.  specified drive, and the information necessary to calculate the number of
  5829.  bytes available on the disk. DL must contain a drive number (0=default,
  5830.  1=A, etc.). If the drive number is valid, MS-DOS returns the information
  5831.  in the following registers:
  5832.  
  5833.  Register       Contents
  5834.  ───────────────────────────────────────────────────────────────────────────
  5835.  AX             Sectors per cluster
  5836.  BX             Available clusters
  5837.  CX             Bytes per sector
  5838.  DX             Total clusters
  5839.  
  5840.  If the drive number is invalid, AX returns 0FFFFH.
  5841.  
  5842.  This call supersedes Functions 1BH and 1CH in earlier MS-DOS versions.
  5843.  
  5844.  
  5845.  Macro Definition:
  5846.  
  5847.  get_disk_space  macro  drive
  5848.                  mov    dl,drive
  5849.                  mov    ah,36H
  5850.                  int    21H
  5851.                  endm
  5852.  
  5853.  
  5854.  Example:
  5855.  
  5856.  The following program displays the space information for the disk in
  5857.  drive B.
  5858.  
  5859.  message   db "      clusters on drive B.",0DH,0AH   ;DX
  5860.            db "      clusters available.",0DH,0AH    ;BX
  5861.            db "      sectors per cluster.",0DH,0AH   ;AX
  5862.            db "      bytes per sector,",0DH,0AH,"$"  ;CX
  5863.  ;
  5864.  begin:    get_disk_space 2                 ;THIS FUNCTION
  5865.            convert    ax,10,message[55]     ;see end of chapter
  5866.            convert    bx,10,message[28]     ;see end of chapter
  5867.            convert    cx,10,message[83]     ;see end of chapter
  5868.            convert    dx,10,message         ;see end of chapter
  5869.            display message                  ;See Function 09H
  5870.  
  5871.  
  5872.  Get Country Data (Function 38H)
  5873.  
  5874.  
  5875.  Call:
  5876.  
  5877.  AH = 38H
  5878.  AL
  5879.     00H    = Current country
  5880.     1-0FEH = Country code
  5881.     0FFH   = BX contains country code
  5882.  BX (if AL = 0FFH)
  5883.     Country code 255 or higher
  5884.  DS:DX
  5885.     Pointer to 32-byte memory area
  5886.  
  5887.  
  5888.  Return:
  5889.  
  5890.  Carry set:
  5891.  AX
  5892.     2 = Invalid country code
  5893.  Carry not set:
  5894.  BX
  5895.     Country code
  5896.  
  5897.  
  5898.  Comments:
  5899.  
  5900.  Function 38H gets the country-dependent information that MS-DOS uses to
  5901.  control the keyboard and display, or it sets the currently defined country
  5902.  (to set the country code, see the next function request description, Set
  5903.  Country Data). To get the information, DX must contain the offset (from the
  5904.  segment address in DS) of a 32-byte memory area to which the country data
  5905.  returns. AL specifies the country code:
  5906.  
  5907.  Value in AL  Meaning
  5908.  ───────────────────────────────────────────────────────────────────────────
  5909.  00H          Retrieve information about the country currently set.
  5910.  
  5911.  1 to 0FEH    Retrieve information about the country identified by
  5912.               this code.
  5913.  
  5914.  0FFH         Retrieve information about the country identified by the
  5915.               code in BX.
  5916.  
  5917.  BX must contain the country code if the code is 255 or greater. The
  5918.  country code is usually the international telephone-prefix code.
  5919.  
  5920.  The country-dependent information returns in the following form:
  5921.  
  5922.    Offset
  5923.  Hex   Decimal   Field Name              Length in bytes
  5924.  ───────────────────────────────────────────────────────────────────────────
  5925.  00H    0        Date format             2 (word)
  5926.  02H    2        Currency symbol         5 (ASCIZ string)
  5927.  07H    7        Thousands separator     2 (ASCIZ string)
  5928.  09H    9        Decimal separator       2 (ASCIZ string)
  5929.  0BH   11        Date separator          2 (ASCIZ string)
  5930.  0DH   13        Time separator          2 (ASCIZ string)
  5931.  0FH   15        Bit field               1
  5932.  10H   16        Currency places         1
  5933.  11H   17        Time format             1
  5934.  12H   18        Case-map call address   4 (DWORD)
  5935.  16H   22        Data-list separator     2 (ASCIZ string)
  5936.  18H   24        Reserved                10
  5937.  
  5938.  
  5939.  Date Format:
  5940.  
  5941.  0 = USA               (month/day/year)
  5942.  1 = Europe            (day/month/year)
  5943.  2 = Japan             (year/month/day)
  5944.  
  5945.  
  5946.  Bit Field:
  5947.  
  5948.  Bit   Value   Meaning
  5949.  ───────────────────────────────────────────────────────────────────────────
  5950.  0     0       Currency symbol precedes amount
  5951.        1       Currency symbol follows amount
  5952.  1     0       No space between symbol and amount
  5953.        1       One space between symbol and amount
  5954.  
  5955.  All other bits are undefined.
  5956.  
  5957.  
  5958.  Time format:
  5959.  
  5960.  0 = 12-hour clock
  5961.  1 = 24-hour clock
  5962.  
  5963.  
  5964.  Currency Places:
  5965.  
  5966.  Specifies the number of places that appear after the decimal point on
  5967.  currency amounts.
  5968.  
  5969.  
  5970.  Case-Mapping Call Address:
  5971.  
  5972.  Specifies the segment and offset of a FAR procedure that performs
  5973.  country-specific lowercase-to-uppercase mapping on character values from
  5974.  80H to 0FFH. You call it with the character to be mapped in AL. If there is
  5975.  an uppercase code for the character, it is returned in AL; if there is not,
  5976.  or if you call it with a value less than 80H in AL, AL returns unchanged.
  5977.  AL and the FLAGS are the only altered registers.
  5978.  
  5979.  If there is an error, the carry flag (CF) is set and the error code
  5980.  returns in AX:
  5981.  
  5982.  Code  Meaning
  5983.  ───────────────────────────────────────────────────────────────────────────
  5984.  2     Invalid country code (no table for it).
  5985.  
  5986.  
  5987.  Macro Definition:
  5988.  
  5989.  get_country   macro  country,buffer
  5990.                local     gc_01
  5991.                mov       dx,offset buffer
  5992.                mov       ax,country
  5993.                cmp       ax,OFFH
  5994.                jl        gc_01
  5995.                mov       al,OFFh
  5996.                mov       bx,country
  5997.  gc_01:        mov       ah,38h
  5998.                int       21H
  5999.                endm
  6000.  
  6001.  
  6002.  Example:
  6003.  
  6004.  The following program displays the time and date in the format appropriate
  6005.  to the current country code, and the number 999,999 and 99/100 as a
  6006.  currency amount with the proper currency symbol and separators.
  6007.  
  6008.  time       db     "  :  :  ",5 dup (20H),"$"
  6009.  date       db     "  /  /  ",5 dup (20H),"$"
  6010.  number     db     "999?999?99",0DH,0AH,"$"
  6011.  data_area  db      32 dup (?)
  6012.  ;
  6013.  begin:    get_country  0,data_area       ;THIS FUNCTION
  6014.            get_time                       ;See Function 2CH
  6015.            byte_to_dec  ch,time           ;See end of chapter
  6016.            byte_to_dec  cl,time[03H]      ;for description of
  6017.            byte_to_dec  dh,time[06H]      ;CONVERT macro
  6018.            get_date                       ;See Function 2AH
  6019.            sub      cx,1900               ;Want last 2 digits
  6020.            byte_to_dec  cl,date[06H]      ;See end of chapter
  6021.            cmp      word ptr data_area,0  ;Check country code
  6022.            jne      not_usa               ;It's not USA
  6023.            byte_to_dec  dh,date           ;See end of chapter
  6024.            byte_to_dec  dl,date[03H]      ;See end of chapter
  6025.            jmp      all_done              ;Display data
  6026.  not_usa:  byte_to_dec  dl,date           ;See end of chapter
  6027.            byte_to_dec  dh,date[03H]      ;See end of chapter
  6028.  all_done: mov      al,data_area[07H]     ;Thousand separator
  6029.            mov      number[03H],al        ;Put in NUMBER
  6030.            mov      al,data_area[09H]     ;Decimal separator
  6031.            mov      number[07H],al        ;Put in AMOUNT
  6032.            display  time                  ;See Function 09H
  6033.            display  date                  ;See Function 09H
  6034.            display_char  data_area[02H]   ;See Function 02H
  6035.            display  number                ;See Function 09H
  6036.  
  6037.  
  6038.  Set Country Data (Function 38H)
  6039.  
  6040.  
  6041.  Call:
  6042.  
  6043.  AH = 38H
  6044.  DX = -1 (0FFFFH)
  6045.  AL
  6046.     Country code less than 255, or
  6047.     0FFH if the country code is in BX
  6048.  BX (if AL=0FFH)
  6049.     Country code 255 or higher
  6050.  
  6051.  
  6052.  Return:
  6053.  
  6054.  Carry set:
  6055.  AX
  6056.     2 = Invalid country code
  6057.  Carry not set:
  6058.     No error
  6059.  
  6060.  
  6061.  Comments:
  6062.  
  6063.  Function 38H sets the country code that MS-DOS uses to control the keyboard
  6064.  and the display, or it retrieves the country-dependent information (to get
  6065.  the country data, see the previous function request description, "Get
  6066.  Country Data"). To set the information, DX must contain 0FFFFH. AL must
  6067.  contain either the country code, if it is less than 255, or 255 to indicate
  6068.  that the country code is in BX. If AL contains 0FFH, BX must contain the
  6069.  country code.
  6070.  
  6071.  The country code is usually the international telephone prefix-code.
  6072.  See "Get Country Data" for a description of the country data and how
  6073.  it is used.
  6074.  
  6075.  If there is an error, the carry flag (CF) is set and the error code
  6076.  returns in AX:
  6077.  
  6078.  Code  Meaning
  6079.  ───────────────────────────────────────────────────────────────────────────
  6080.  2     Invalid country code (no table for it).
  6081.  
  6082.  
  6083.  Macro Definition:
  6084.  
  6085.  set_country macro  country
  6086.              local  sc_01
  6087.              mov    dx,0FFFFH
  6088.              mov    ax,country
  6089.              cmp    ax,0FFH
  6090.              jl     sc_01
  6091.              mov    bx,country
  6092.              mov    al,0ffh
  6093.  sc_01:      mov    ah,38H
  6094.              int    21H
  6095.              endm
  6096.  
  6097.  
  6098.  Example:
  6099.  
  6100.  The following program sets the country code to the United Kingdom (44).
  6101.  
  6102.  uk        equ         44
  6103.  ;
  6104.  begin:    set_country uk     ;THIS FUNCTION
  6105.            jc          error  ;routine not shown
  6106.  
  6107.  
  6108.  Create Directory (Function 39H)
  6109.  
  6110.  
  6111.  Call:
  6112.  
  6113.  AH = 39H
  6114.  DS:DX
  6115.     Pointer to pathname
  6116.  
  6117.  
  6118.  Return:
  6119.  
  6120.  Carry set:
  6121.  AX
  6122.     2 = File not found
  6123.     3 = Path not found
  6124.     5 = Access denied
  6125.  Carry not set:
  6126.     No error
  6127.  
  6128.  
  6129.  Comments:
  6130.  
  6131.  Function 39H creates a new subdirectory. DX must contain the offset (from
  6132.  the segment address in DS) of an ASCIZ string that specifies the pathname
  6133.  of the new subdirectory.
  6134.  
  6135.  If there is an error, the carry flag (CF) is set and the error code
  6136.  returns in AX:
  6137.  
  6138.  Code  Meaning
  6139.  ───────────────────────────────────────────────────────────────────────────
  6140.  2     File not found
  6141.  
  6142.  3     Path not found
  6143.  
  6144.  5     No room in the parent directory, a file with the same name exists in
  6145.        the current directory, or the path specifies a device
  6146.  
  6147.  
  6148.  Macro Definition:
  6149.  
  6150.  make_dir  macro path
  6151.            mov    dx,offset path
  6152.            mov    ah,39H
  6153.            int    21H
  6154.            endm
  6155.  
  6156.  
  6157.  Example:
  6158.  
  6159.  The following program adds a subdirectory named new_dir to the root
  6160.  directory on the disk in drive B and changes the current directory to
  6161.  new_dir. The program then changes the current directory back to the
  6162.  original directory and then deletes new_dir. It displays the current
  6163.  directory after each step to confirm the changes.
  6164.  
  6165.  old_path  db        "b:
  6166.  new_path  db        "b:\new_dir",0
  6167.  buffer    db        "b:
  6168.  ;
  6169.  begin:    get_dir    2,old_path[03H]  ;See Function 47H
  6170.            jc         error_get        ;Routine not shown
  6171.            display_asciz  old_path     ;See end of chapter
  6172.            make_dir   new_path         ;THIS FUNCTION
  6173.            jc         error_make       ;Routine not shown
  6174.            change_dir new_path         ;See Function 3BH
  6175.            jc         error_change     ;Routine not shown
  6176.            get_dir    2,buffer[03H]    ;See Function 47H
  6177.            jc         error_get        ;Routine not shown
  6178.            display_asciz  buffer       ;See end of chapter
  6179.            change_dir old_path         ;See Function 3BH
  6180.            jc         error_change     ;Routine not shown
  6181.            rem_dir    new_path         ;See Function 3AH
  6182.            jc         error_rem        ;Routine not shown
  6183.            get_dir    2,buffer[03H]    ;See Function 47H
  6184.            jc         error_get        ;Routine not shown
  6185.            display_asciz  buffer       ;See end of chapter
  6186.  
  6187.  
  6188.  Remove Directory (Function 3AH)
  6189.  
  6190.  
  6191.  Call:
  6192.  
  6193.  AH = 3AH
  6194.  DS:DX
  6195.     Pointer to pathname
  6196.  
  6197.  
  6198.  Return:
  6199.  
  6200.  Carry set:
  6201.  AX
  6202.     2 = File not found
  6203.     3 = Path not found
  6204.     5 = Access denied
  6205.    16 = Current directory
  6206.  Carry not set:
  6207.     No error
  6208.  
  6209.  
  6210.  Comments:
  6211.  
  6212.  Function 3AH deletes a subdirectory. DX must contain the offset (from the
  6213.  segment address in DS) of an ASCIZ string that specifies the pathname of
  6214.  the subdirectory you want to delete.
  6215.  
  6216.  The subdirectory must not contain any files. You cannot erase the current
  6217.  directory. If there is an error, the carry flag (CF) is set and the error
  6218.  code returns in AX:
  6219.  
  6220.  Code  Meaning
  6221.  ───────────────────────────────────────────────────────────────────────────
  6222.  2     File not found
  6223.  
  6224.  3     Path not found
  6225.  
  6226.  5     Directory not empty, or path doesn't specify a directory,
  6227.        or it specifies the root directory, or it is invalid
  6228.  
  6229.  16    Path specifies current directory
  6230.  
  6231.  
  6232.  Macro Definition:
  6233.  
  6234.  rem_dir  macro  path
  6235.           mov    dx,offset path
  6236.           mov    ah,3AH
  6237.           int    21H
  6238.           endm
  6239.  
  6240.  
  6241.  Example:
  6242.  
  6243.  The following program adds a subdirectory named new_dir to the root
  6244.  directory on the disk in drive B and changes the current directory to
  6245.  new_dir. The program then changes the current directory back to the
  6246.  original directory and deletes new_dir. It displays the current directory
  6247.  after each step to confirm the changes.
  6248.  
  6249.  old_path  db        "b:
  6250.  new_path  db        "b:\new_dir",0
  6251.  buffer    db        "b:
  6252.  ;
  6253.  begin:    get_dir    2,old_path[03H]  ;See Function 47H
  6254.            jc         error_get        ;Routine not shown
  6255.            display_asciz  old_path     ;See end of chapter
  6256.            make_dir   new_path         ;See Function 39H
  6257.            jc         error_make       ;Routine not shown
  6258.            change_dir new_path         ;See Function 3BH
  6259.            jc         error_change     ;Routine not shown
  6260.            get_dir    2,buffer[03H]    ;See Function 47H
  6261.            jc         error_get        ;Routine not shown
  6262.            display_asciz  buffer       ;See end of chapter
  6263.            change_dir old_path         ;See Function 3BH
  6264.            jc         error_change     ;Routine not shown
  6265.            rem_dir    new_path         ;THIS FUNCTION
  6266.            jc         error_rem        ;Routine not shown
  6267.            get_dir    2,buffer[03H]    ;See Function 47H
  6268.            jc         error_get        ;Routine not shown
  6269.            display_asciz  buffer       ;See end of chapter
  6270.  
  6271.  
  6272.  Change Current Directory (Function 3BH)
  6273.  
  6274.  
  6275.  Call:
  6276.  
  6277.  AH = 3BH
  6278.  DS:DX
  6279.     Pointer to pathname
  6280.  
  6281.  
  6282.  Return:
  6283.  
  6284.  Carry set:
  6285.  AX
  6286.     2 = File not found
  6287.     3 = Path not found
  6288.  Carry not set:
  6289.     No error
  6290.  
  6291.  
  6292.  Comments:
  6293.  
  6294.  Function 3BH changes the current directory. DX must contain the offset
  6295.  (from the segment address in DS) of an ASCIZ string that specifies the
  6296.  pathname of the new current directory.
  6297.  
  6298.  The directory string is limited to 64 characters.
  6299.  
  6300.  If any member of the path doesn't exist, the path is unchanged.
  6301.  If there is an error, the carry flag (CF) is set and the error code returns
  6302.  in AX:
  6303.  
  6304.  Code  Meaning
  6305.  ───────────────────────────────────────────────────────────────────────────
  6306.  2     File not found
  6307.  
  6308.  3     Path either doesn't exist or it specifies a file instead of a
  6309.        directory
  6310.  
  6311.  
  6312.  Macro Definition:
  6313.  
  6314.  change_dir  macro  path
  6315.              mov    dx,offset path
  6316.              mov    ah,3BH
  6317.              int    21H
  6318.              endm
  6319.  
  6320.  
  6321.  Example:
  6322.  
  6323.  The following program adds a subdirectory named new_dir to the root
  6324.  directory that is on the disk in drive B and changes the current directory
  6325.  to new_dir. The program then changes the current directory back to the
  6326.  original directory and deletes new_dir. It displays the current directory
  6327.  after each step to confirm the changes.
  6328.  
  6329.  old_path  db        "b:
  6330.  new_path  db        "b:\new_dir",0
  6331.  buffer    db        "b:
  6332.  ;
  6333.  begin:    get_dir    2,old_path[03H]  ;See Function 47H
  6334.            jc         error_get        ;Routine not shown
  6335.            display_asciz  old_path     ;See end of chapter
  6336.            make_dir   new_path         ;See Function 39H
  6337.            jc         error_make       ;Routine not shown
  6338.            change_dir new_path         ;THIS FUNCTION
  6339.            jc         error_change     ;Routine not shown
  6340.            get_dir    2,buffer[03H]    ;See Function 47H
  6341.            jc         error_get        ;Routine not shown
  6342.            display_asciz  buffer       ;See end of chapter
  6343.            change_dir old_path         ;See Function 3BH
  6344.            jc         error_change     ;Routine not shown
  6345.            rem_dir    new_path         ;See Function 3AH
  6346.            jc         error_rem        ;Routine not shown
  6347.            get_dir    2,buffer[03H]    ;See Function 47H
  6348.            jc         error_get        ;Routine not shown
  6349.            display_asciz  buffer       ;See end of chapter
  6350.  
  6351.  
  6352.  Create Handle (Function 3CH)
  6353.  
  6354.  
  6355.  Call:
  6356.  
  6357.  AH = 3CH
  6358.  DS:DX
  6359.     Pointer to pathname
  6360.  CX
  6361.     File attribute
  6362.  
  6363.  
  6364.  Return:
  6365.  
  6366.  Carry set:
  6367.  AX
  6368.     2 = File not found
  6369.     3 = Path not found
  6370.     4 = Too many open files
  6371.     5 = Access denied
  6372.  Carry not set:
  6373.  AX
  6374.     Handle
  6375.  
  6376.  
  6377.  Comments:
  6378.  
  6379.  Function 3CH creates a file and assigns it the first available handle. DX
  6380.  must contain the offset (from the segment address in DS) of an ASCIZ string
  6381.  that specifies the pathname of the file to be created. CX must contain the
  6382.  attribute to be assigned to the file, as described under "File Attributes"
  6383.  earlier in this chapter.
  6384.  
  6385.  If the specified file does not exist, this function creates it. But
  6386.  if the file already exists, it is truncated to a length of 0. Function 3CH
  6387.  then assigns the attribute in CX to the file and opens it for read/write.
  6388.  AX returns the file handle.
  6389.  
  6390.  If there is an error, the carry flag (CF) is set and the error code
  6391.  returns in AX:
  6392.  
  6393.  Code  Meaning
  6394.  ───────────────────────────────────────────────────────────────────────────
  6395.  2     File not found
  6396.  
  6397.  3     Path is invalid
  6398.  
  6399.  4     Too many open files (no handle available)
  6400.  
  6401.  5     Directory is full, a directory with the same name exists, or a file
  6402.        with the same name exists with more restrictive attributes
  6403.  
  6404.  
  6405.  Macro Definition:
  6406.  
  6407.  create_handle  macro  path,attrib
  6408.                 mov    dx,offset path
  6409.                 mov    cx,attrib
  6410.                 mov    ah,3CH
  6411.                 int    21H
  6412.                 endm
  6413.  
  6414.  
  6415.  Example:
  6416.  
  6417.  The following program creates a file named dir.tmp, containing the name and
  6418.  extension of each file in the current directory, on the disk in drive B.
  6419.  
  6420.  srch_file db      "b:*.*",0
  6421.  tmp_file  db      "b:dir.tmp",0
  6422.  buffer    db       43 dup (?)
  6423.  handle    dw       ?
  6424.  ;
  6425.  begin:    set_dta buffer                ;See Function 1AH
  6426.            find_first_file  srch_file,16H  ;See Function 4EH
  6427.            cmp     ax,12H                ;Directory empty?
  6428.            je      all_done              ;Yes, go home
  6429.            create_handle  tmp_file,0     ;THIS FUNCTION
  6430.            jc      error                 ;Routine not shown
  6431.            mov     handle,ax             ;Save handle
  6432.  write_it: write_handle handle,buffer[1EH],12 ;Function 40H
  6433.            find_next_file                ;See Function 4FH
  6434.            cmp     ax,12H                ;Another entry?
  6435.            je      all_done              ;No, go home
  6436.            jmp     write_it              ;Yes, write record
  6437.  all_done: close_handle  handle          ;See Function 3EH
  6438.  
  6439.  
  6440.  Open Handle (Function 3DH)
  6441.  
  6442.  
  6443.  Call:
  6444.  
  6445.  AH = 3DH
  6446.  AL
  6447.     Access code (see text)
  6448.  DS:DX
  6449.     Pointer to pathname
  6450.  
  6451.  
  6452.  Return:
  6453.  
  6454.  Carry set:
  6455.  AX
  6456.     2      = File not found
  6457.     3      = Path not found
  6458.     4      = Too many open files
  6459.     5      = Access denied
  6460.    12      = Invalid access
  6461.  Carry not set:
  6462.     No error
  6463.  
  6464.  
  6465.  Comments:
  6466.  
  6467.  Function 3DH opens any file, including hidden and system files, for input
  6468.  or output. DX contains the offset (from the segment address in DS) of an
  6469.  ASCIZ string that specifies the pathname of the file to be opened. AL
  6470.  contains a code that specifies how the file is to be opened. This code
  6471.  is described later under "Controlling Access to the File."
  6472.  
  6473.  If there is no error, AX returns the file handle. MS-DOS sets the
  6474.  read/write pointer to the first byte of the file.
  6475.  
  6476.  
  6477.  Controlling Access to the File
  6478.  
  6479.  The value in AL is made up of three parts that specify whether the file
  6480.  is to be opened for read, write, or both (access code); what access other
  6481.  processes have to the file (sharing mode); and whether a child process
  6482.  inherits the file (inherit bit).
  6483.  
  6484.  
  6485.       |---|-----------|---------------|
  6486.  Bit  | 7 | 6   5   4 | 3   2   1   0 |
  6487.       |---|---|---|---|---|---|---|---|
  6488.        \/  \________/   \____________/
  6489.         |       |             |
  6490.         |       |             |-------->  Access code
  6491.         |       |
  6492.         |       |-----------------------> Sharing mode
  6493.         |
  6494.         |-------------------------------> Inherit bit
  6495.  
  6496.  
  6497.  Inherit Bit
  6498.  
  6499.  The high-order bit (bit 7) specifies whether the file is inherited by a
  6500.  child process created with Function 4BH (Load and Execute Program). If the
  6501.  bit is 0, the child process inherits the file; if the bit is 1, it doesn't.
  6502.  
  6503.  
  6504.  Sharing Mode
  6505.  
  6506.  The sharing mode bits (bits 4-6) specify what access, if any, other
  6507.  processes have to the open file. It can have the following values:
  6508.  
  6509.  
  6510.       Table 1.21
  6511.       Sharing Mode Bit Values
  6512. ╓┌───────────────┌───────────────┌───────────────────────────────────────────╖
  6513.       Bits 4-6   Sharing Mode    Description
  6514.       ────────────────────────────────────────────────────────────────────
  6515.       000        Compatibility   On a given machine, any process
  6516.                                  can open the file any number of
  6517.                                  times with this mode. Fails if
  6518.                                  the file has been opened with
  6519.                                  any of the other sharing modes.
  6520.  
  6521.       001        Deny both       Fails if the file has been
  6522.                                  opened in compatibility mode or
  6523.                                  for read or write access, even
  6524.                                  if by the current process.
  6525.  
  6526.       010        Deny write      Fails if the file has been
  6527.                                  opened in compatibility mode or
  6528.                                  for write access by any other
  6529.                                  process.
  6530.  
  6531.       011        Deny read       Fails if the file has been
  6532.                                  opened in compatibility mode or
  6533.       Bits 4-6   Sharing Mode    Description
  6534.                                 opened in compatibility mode or
  6535.                                  for read access by any other
  6536.                                  process.
  6537.  
  6538.       100        Deny none       Fails if the file has been
  6539.                                  opened in compatibility mode by
  6540.                                  any other process.
  6541.  
  6542.  
  6543.  Access Code
  6544.  
  6545.  The access code (bits 0-3) specifies how the file is to be used. It can
  6546.  have the following values:
  6547.  
  6548.  
  6549.       Table 1.22
  6550.       Access Code Bit Values
  6551. ╓┌───────────────┌─────────┌─────────────────────────────────────────────────╖
  6552.                  Access
  6553.       Bit 0-3    Allowed   Description
  6554.                  Access
  6555.       Bit 0-3    Allowed   Description
  6556.       ────────────────────────────────────────────────────────────────────
  6557.       0000       Read      Fails if the file has been opened in
  6558.                            deny read or deny both sharing mode.
  6559.  
  6560.       0001       Write     Fails if the file has been opened in
  6561.                            deny write or deny both sharing
  6562.                            mode.
  6563.  
  6564.       0010       Both      Fails if the file has been opened in
  6565.                            deny read, deny write, or deny both
  6566.                            sharing mode.
  6567.  
  6568.  
  6569.  If there is an error, the carry flag (CF) is set and the error code is
  6570.  returned in AX:
  6571.  
  6572.  Code  Meaning
  6573.  ───────────────────────────────────────────────────────────────────────────
  6574.  2     Specified file is invalid or doesn't exist
  6575.  
  6576.  3     Specified path is invalid or doesn't exist
  6577.  
  6578.  4     No handles are available in the current process or the internal
  6579.        system tables are full
  6580.  
  6581.  5     Program attempted to open a directory or VolumeID, or tried to open
  6582.        a read-only file for writing
  6583.  
  6584.  12    Access code (bits 0-3 of AL) not 0, 1, or 2
  6585.  
  6586.  If this system call fails because of a file-sharing error, MS-DOS
  6587.  issues Interrupt 24H with error code 2 (Drive Not Ready). A subsequent
  6588.  Function 59H (Get Extended Error) returns the extended error code that
  6589.  specifies a sharing violation.
  6590.  
  6591.  When opening a file, it is important to inform MS-DOS of any operations
  6592.  that other processes may perform on this file (sharing mode). The default
  6593.  (compatibility mode) denies all other processes access to the file, unless
  6594.  they also attempt to open the file in compatibility mode.
  6595.  
  6596.  The following table shows the effect of opening a file with compatibility
  6597.  mode set:
  6598.  
  6599.  Type of File Opening      Read-Only File    Not Read-Only
  6600.  ───────────────────────────────────────────────────────────────────────────
  6601.  First open for read,      Succeeds          Succeeds
  6602.  write, or both by
  6603.  machine/process "N"
  6604.  
  6605.  Subsequent opens by       Succeeds          Succeeds
  6606.  machine or process "N"
  6607.  
  6608.  An open by another        Succeeds          Fails
  6609.  machine or process
  6610.  
  6611.  Files may be read-only with the MS-DOS attrib command or by a read-only
  6612.  share over the network.
  6613.  
  6614.  It may be all right for other processes to continue to read the file
  6615.  while your process is operating on it. In this case, you should specify
  6616.  "Deny Write," which inhibits other processes from writing to your files
  6617.  but allows them to read from these files.
  6618.  
  6619.  Similarly, it is important for you to specify what operations your process
  6620.  will perform ("Access" mode). If another process has the file open with any
  6621.  sharing mode other than "Deny" mode, then the default mode ("Read/write")
  6622.  causes the open request to fail. If you only want to read the file, your
  6623.  open request succeeds unless all other processes have specified "Deny"
  6624.  mode or "Deny write."
  6625.  
  6626.  
  6627.  Macro Definition:
  6628.  
  6629.  open_handle  macro  path,access
  6630.               mov    dx, offset path
  6631.               mov    al, access
  6632.               mov    ah, 3DH
  6633.               int    21H
  6634.               endm
  6635.  
  6636.  
  6637.  Example:
  6638.  
  6639.  The following program prints a file named textfile.asc that is on the disk
  6640.  in drive B.
  6641.  
  6642.  file       db  "b:textfile.asc",0
  6643.  buffer     db   ?
  6644.  handle     dw   ?
  6645.  ;
  6646.  begin:     open_handle  file,0          ;THIS FUNCTION
  6647.             mov  handle,ax               ;Save handle
  6648.  read_char: read_handle handle,buffer,1  ;Read 1 character
  6649.             jc   error_read              ;Routine not shown
  6650.             cmp  ax,0                    ;End of file?
  6651.             je   return                  ;Yes, go home
  6652.             print_char  buffer           ;See Function 05H
  6653.             jmp  read_char               ;Read another
  6654.  
  6655.  
  6656.  Close Handle (Function 3EH)
  6657.  
  6658.  
  6659.  Call:
  6660.  
  6661.  AH = 3EH
  6662.  BX
  6663.     Handle
  6664.  
  6665.  
  6666.  Return:
  6667.  
  6668.  Carry set:
  6669.  AX
  6670.     6 = Invalid handle
  6671.  Carry not set:
  6672.     No error
  6673.  
  6674.  
  6675.  Comments:
  6676.  
  6677.  Function 3EH closes a file opened with Function 3DH (Open Handle) or 3CH
  6678.  (Create Handle). BX must contain the handle of the open file that you want
  6679.  to close.
  6680.  
  6681.  If there is no error, MS-DOS closes the file and flushes all internal
  6682.  buffers. If there is an error, the carry flag (CF) is set and the error
  6683.  code returns in AX:
  6684.  
  6685.  Code  Meaning
  6686.  ───────────────────────────────────────────────────────────────────────────
  6687.  6     Handle not open or invalid
  6688.  
  6689.  
  6690.  Macro Definition:
  6691.  
  6692.  close_handle  macro  handle
  6693.                mov    bx,handle
  6694.                mov    ah,3EH
  6695.                int    21H
  6696.                endm
  6697.  
  6698.  
  6699.  Example:
  6700.  
  6701.  The following program creates a file named dir.tmp, containing the filename
  6702.  and extension of each file in the current directory, in the current
  6703.  directory on the disk in drive B.
  6704.  
  6705.  srch_file  db  "b:*.*",0
  6706.  tmp_file   db  "b:dir.tmp",0
  6707.  buffer     db   43 dup (?)
  6708.  handle     dw   ?
  6709.  ;
  6710.  begin:     set_dta  buffer              ;See Function 1AH
  6711.             find_first_file  srch_file,16H  ;See Function 4EH
  6712.             cmp      ax,12H              ;Directory empty?
  6713.             je       all_done            ;Yes, go home
  6714.             create_handle  tmp_file,0    ;See Function 3CH
  6715.             jc       error_create        ;Routine not shown
  6716.             mov      handle,ax           ;Save handle
  6717.  write_it:  write_handle  handle,buffer[1EH],12 ;See Function 40H
  6718.             find_next_file               ;See Function 4FH
  6719.             cmp      ax,12H              ;Another entry?
  6720.             je       all_done            ;No, go home
  6721.             jmp      write_it            ;Yes, write record
  6722.  all_done:  close_handle  handle         ;See Function 3EH
  6723.             jc       error_close         ;Routine not shown
  6724.  
  6725.  
  6726.  Read Handle (Function 3FH)
  6727.  
  6728.  
  6729.  Call:
  6730.  
  6731.  AH = 3FH
  6732.  BX
  6733.     Handle
  6734.  CX
  6735.     Bytes to read
  6736.  DS:DX
  6737.     Pointer to buffer
  6738.  
  6739.  
  6740.  Return:
  6741.  
  6742.  Carry set:
  6743.  AX
  6744.     5 = Access denied
  6745.     6 = Invalid handle
  6746.  Carry not set:
  6747.  AX
  6748.     Bytes read
  6749.  
  6750.  
  6751.  Comments:
  6752.  
  6753.  Function 3FH reads from the file or device associated with the specified
  6754.  handle. BX must contain the handle. CX must contain the number of bytes
  6755.  to be read. DX must contain the offset (to the segment address in DS)
  6756.  of the buffer.
  6757.  
  6758.  If there is no error, AX returns the number of bytes read; if you
  6759.  attempt to read starting at end of file, AX returns 0. The number of bytes
  6760.  specified in CX is not necessarily transferred to the buffer; if you use
  6761.  this call to read from the keyboard, for example, it reads only up to the
  6762.  first carriage-return.
  6763.  
  6764.  If you use this function request to read from standard input, you can
  6765.  redirect the input.
  6766.  
  6767.  If there is an error, the carry flag (CF) is set and the error code
  6768.  returns in AX:
  6769.  
  6770.  Code  Meaning
  6771.  ───────────────────────────────────────────────────────────────────────────
  6772.  5     Handle not open for reading
  6773.  6     Handle not open or invalid
  6774.  
  6775.  
  6776.  Macro Definition:
  6777.  
  6778.  read_handle  macro  handle,buffer,bytes
  6779.               mov    bx,handle
  6780.               mov    dx,offset buffer
  6781.               mov    cx,bytes
  6782.               mov    ah,3FH
  6783.               int    21H
  6784.               endm
  6785.  
  6786.  
  6787.  Example:
  6788.  
  6789.  The following program displays a file named textfile.asc that is on the
  6790.  disk in drive B.
  6791.  
  6792.  filename   db     "b:\textfile.asc",0
  6793.  buffer     db      129 dup (?)
  6794.  handle     dw      ?
  6795.  ;
  6796.  begin:     open_handle  filename,0        ;See Function 3DH
  6797.             jc           error_open        ;Routine not shown
  6798.             mov          handle,ax         ;Save handle
  6799.  read_file: read_handle  buffer,file_handle,128
  6800.             jc           error_open        ;Routine not shown
  6801.             cmp          ax,0              ;End of file?
  6802.             je           return            ;Yes, go home
  6803.             mov          bx,ax             ;# of bytes read
  6804.             mov          buffer[bx],"$"    ;Make a string
  6805.             display      buffer            ;See Function 09H
  6806.             jmp          read_file         ;Read more
  6807.  
  6808.  
  6809.  Write Handle (Function 40H)
  6810.  
  6811.  
  6812.  Call:
  6813.  
  6814.  AH = 40H
  6815.  BX
  6816.     Handle
  6817.  CX
  6818.     Bytes to write
  6819.  DS:DX
  6820.     Pointer to buffer
  6821.  
  6822.  
  6823.  Return:
  6824.  
  6825.  Carry set:
  6826.  AX
  6827.     5 = Access denied
  6828.     6 = Invalid handle
  6829.  Carry not set:
  6830.  AX
  6831.     Bytes written
  6832.  
  6833.  
  6834.  Comments:
  6835.  
  6836.  Function 40H writes to the file or device associated with the specified
  6837.  handle. BX must contain the handle. CX must contain the number of bytes to
  6838.  be written. DX must contain the offset (to the segment address in DS) of
  6839.  the data to be written.
  6840.  
  6841.  If you set CX to zero, the file will be truncated at the current
  6842.  position of the file pointer. MS-DOS will not perform the write if the
  6843.  handle is read-only.
  6844.  
  6845.  If there is no error, AX returns the number of bytes written. Be sure
  6846.  to check AX after performing a write. If its value is less than the number
  6847.  in CX when the call was made, it indicates an error, even though the carry
  6848.  flag isn't set. If AX contains 0, and if the target is a disk file, the
  6849.  disk is full.
  6850.  
  6851.  If you use this function request to write to standard output, you can
  6852.  redirect the output. If you call this request with CX=0, the file size is
  6853.  set to the value of the read/write pointer. To satisfy the new file size,
  6854.  allocation units are allocated or released, as required.
  6855.  
  6856.  If there is an error, the carry flag (CF) is set and the error code
  6857.  returns in AX:
  6858.  
  6859.  Code     Meaning
  6860.  ───────────────────────────────────────────────────────────────────────────
  6861.  5        Handle not open for writing
  6862.  6        Handle not open or invalid
  6863.  
  6864.  
  6865.  Macro Definition:
  6866.  
  6867.  write_handle  macro  handle,buffer,bytes
  6868.                mov    bx,handle
  6869.                mov    dx,offset buffer
  6870.                mov    cx,bytes
  6871.                mov    ah,40H
  6872.                int    21H
  6873.                endm
  6874.  
  6875.  
  6876.  Example:
  6877.  
  6878.  The following program creates a file named dir.tmp, containing the filename
  6879.  and extension of each file in the current directory, in the current
  6880.  directory on the disk in drive B.
  6881.  
  6882.  srch_file db     "b:*.*",0
  6883.  tmp_file  db     "b:dir.tmp",0
  6884.  buffer    db      43 dup (?)
  6885.  handle    dw      ?
  6886.  ;
  6887.  begin:    set_dta buffer                ;See Function 1AH
  6888.            find_first_file  srch_file,16H ;Check directory
  6889.            cmp     ax,12H                ;Directory empty?
  6890.            je      return                ;Yes, go home
  6891.            create_handle  tmp_file,0     ;See Function 3CH
  6892.            jc      error_create          ;Routine not shown
  6893.            mov     handle,ax             ;Save handle
  6894.  write_it: write_handle handle,buffer[1EH],12 ;THIS FUNCTION
  6895.            jc      error_write           ;Routine not shown
  6896.            find_next_file                ;Check directory
  6897.            cmp     ax,12H                ;Another entry?
  6898.            je      all_done              ;No, go home
  6899.            jmp     write_it              ;Yes, write record
  6900.  all_done: close_handle  handle          ;See Function 3EH
  6901.            jc      error_close           ;Routine not shown
  6902.  
  6903.  
  6904.  Delete Directory Entry [Unlink] (Function 41H)
  6905.  
  6906.  
  6907.  Call:
  6908.  
  6909.  AH = 41H
  6910.  DS:DX
  6911.     Pointer to pathname
  6912.  
  6913.  
  6914.  Return:
  6915.  
  6916.  Carry set:
  6917.  AX
  6918.     2 = File not found
  6919.     3 = Path not found
  6920.     5 = Access denied
  6921.  Carry not set:
  6922.     No error
  6923.  
  6924.  
  6925.  Comments:
  6926.  
  6927.  Function 41H erases a file by deleting its directory entry. DX must
  6928.  contain the offset (from the segment address in DS) of an ASCIZ string that
  6929.  specifies the pathname of the file that you want to delete. You cannot use
  6930.  wildcard characters.
  6931.  
  6932.  If the file exists and is not read-only, the call deletes it. If there
  6933.  is an error, the call sets the carry flag (CF) and the error code returns
  6934.  in AX:
  6935.  
  6936.  Code     Meaning
  6937.  ───────────────────────────────────────────────────────────────────────────
  6938.  2        File doesn't exist, or specifies a directory
  6939.  3        Path is invalid
  6940.  5        File is read-only
  6941.  
  6942.  To delete a file with the read-only attribute, first change its
  6943.  attribute to 0 with Function 43H (Get/Set File Attribute).
  6944.  
  6945.  
  6946.  Macro Definition:
  6947.  
  6948.  delete_entry  macro  path
  6949.                mov    dx,offset path
  6950.                mov    ah,41H
  6951.                int    21H
  6952.                endm
  6953.  
  6954.  
  6955.  Example:
  6956.  
  6957.  The following program deletes all files, dated before December 31, 1986,
  6958.  from the disk in drive B.
  6959.  
  6960.  year      db       1986
  6961.  month     db       12
  6962.  day       db       31
  6963.  files     db       ?
  6964.  message   db      "NO FILES DELETED.",0DH,0AH,"$"
  6965.  path      db      "b:*.*", 0
  6966.  buffer    db       43 dup (?)
  6967.  ;
  6968.  begin:    set_dta  buffer           ;See Function 1AH
  6969.            select_disk "B"           ;See Function 0EH
  6970.            find_first_file  path,0   ;See Function 4EH
  6971.            jnc      compare          ;got one
  6972.            jmp      all_done         ;no match, go home
  6973.  compare:  convert_date  buffer[-1]  ;See end of chapter
  6974.            cmp      cx,year          ;After 1986?
  6975.            jg       next             ;Yes, don't delete
  6976.            cmp      dl,month         ;After December?
  6977.            jg       next             ;Yes, don't delete
  6978.            cmp      dh,day           ;31st or after?
  6979.            jge      next             ;Yes, don't delete
  6980.            delete_entry  buffer[1EH] ;THIS FUNCTION
  6981.            jc       error_delete     ;Routine not shown
  6982.            inc      files            ;Bump file counter
  6983.  next:     find_next_file            ;Check directory
  6984.            jnc      compare          ;Go home if done
  6985.  how_many: cmp      files,0          ;Was directory empty?
  6986.            je       all_done         ;Yes, go home
  6987.            convert  files,10,message ;See end of chapter
  6988.  all_done: display  message          ;See Function 09H
  6989.            select_disk "A"           ;See Function 0EH
  6990.  
  6991.  
  6992.  Move File Pointer (Function 42H)
  6993.  
  6994.  
  6995.  Call:
  6996.  
  6997.  AH = 42H
  6998.  AL
  6999.     Method of moving
  7000.  BX
  7001.     Handle
  7002.  CX:DX
  7003.     Distance in bytes (offset)
  7004.  
  7005.  
  7006.  Return:
  7007.  
  7008.  Carry set:
  7009.  AX
  7010.     1 = Invalid function
  7011.     6 = Invalid handle
  7012.  Carry not set:
  7013.  DX:AX
  7014.     New read/write pointer location
  7015.  
  7016.  
  7017.  Comments:
  7018.  
  7019.  Function 42H moves the read/write pointer of the file associated with the
  7020.  specified handle. BX must contain the handle. CX and DX must contain a 32-
  7021.  bit offset (CX contains the most significant byte). AL must contain a code
  7022.  that specifies how to move the pointer:
  7023.  
  7024.  Code     Cursor Moved to
  7025.  ───────────────────────────────────────────────────────────────────────────
  7026.  0        Beginning of file plus the offset
  7027.  1        Current pointer location plus the offset
  7028.  2        End of file plus the offset
  7029.  
  7030.  DX and AX return the new location of the read/write pointer (a 32-bit
  7031.  integer; DX contains the most significant byte). You can determine the
  7032.  length of a file by setting CX:DX to 0, AL to 2, and calling this function.
  7033.  DX:AX returns the offset of the byte following the last byte in the file
  7034.  (size of the file in bytes).
  7035.  
  7036.  If there is an error, the carry flag (CF) is set and the error code
  7037.  returns in AX:
  7038.  
  7039.  Code     Meaning
  7040.  ───────────────────────────────────────────────────────────────────────────
  7041.  1        AL not 0, 1, or 2
  7042.  6        Handle not open
  7043.  
  7044.  
  7045.  Macro Definition:
  7046.  
  7047.  move_ptr  macro  handle,high,low,method
  7048.            mov    bx,handle
  7049.            mov    cx,high
  7050.            mov    dx,low
  7051.            mov    al,method
  7052.            mov    ah,42H
  7053.            int    21H
  7054.            endm
  7055.  
  7056.  
  7057.  Example:
  7058.  
  7059.  The following program prompts for a letter, converts it to its alphabetic
  7060.  sequence (A=1, B=2, etc.), then reads and displays the corresponding record
  7061.  from the file named alphabet.dat that is in the current directory on the
  7062.  disk in drive B. The file contains 26 records, each 28 bytes long.
  7063.  
  7064.  file      db      "b:alphabet.dat",0
  7065.  buffer    db       28 dup (?),"$"
  7066.  prompt    db      "Enter letter: $"
  7067.  crlf      db       0DH,0AH,"$"
  7068.  handle    db       ?
  7069.  record_length  dw  28
  7070.  ;
  7071.  begin:    open_handle  file,0      ;See Function 3DH
  7072.            jc       error_open      ;Routine not shown
  7073.            mov      handle,ax       ;Save handle
  7074.  get_char: display  prompt          ;See Function 09H
  7075.            read_kbd_and_echo        ;See Function 01H
  7076.            sub      al,41h          ;Convert to sequence
  7077.            mul      byte ptr record_length  ;Calculate offset
  7078.            move_ptr handle,0,ax,0   ;THIS FUNCTION
  7079.            jc       error_move      ;Routine not shown
  7080.            read_handle handle,buffer,record_length
  7081.            jc       error_read      ;Routine not shown
  7082.            cmp      ax,0            ;End of file?
  7083.            je       return          ;Yes, go home
  7084.            display  crlf            ;See Function 09H
  7085.            display  buffer          ;See Function 09H
  7086.            display  crlf            ;See Function 09H
  7087.            jmp      get_char        ;Get another character
  7088.  
  7089.  
  7090.  Get/Set File Attributes (Function 43H)
  7091.  
  7092.  
  7093.  Call:
  7094.  
  7095.  AH = 43H
  7096.  AL
  7097.     0 = Get attributes
  7098.     1 = Set attributes
  7099.  CX (if AL=1)
  7100.     Attributes to be set
  7101.  DS:DX
  7102.     Pointer to pathname
  7103.  
  7104.  
  7105.  Return:
  7106.  
  7107.  Carry set:
  7108.  AX
  7109.     1 = Invalid function
  7110.     2 = File not found
  7111.     3 = Path not found
  7112.     5 = Access denied
  7113.  Carry not set:
  7114.  CX
  7115.     Attribute byte (if AL=0)
  7116.  
  7117.  
  7118.  Comments:
  7119.  
  7120.  Function 43H gets or sets the attributes of a file. DX must contain the
  7121.  offset (from the segment address in DS) of an ASCIZ string that specifies
  7122.  the pathname of a file. AL must specify whether to get or set the attribute
  7123.  (0=get, 1=set).
  7124.  
  7125.  If AL is 0 (get the attribute), the attribute byte returns in CX. If AL
  7126.  is 1 (set the attribute), CX must contain the attributes to be set. The
  7127.  attributes are described under "File Attributes" earlier in this chapter.
  7128.  
  7129.  You cannot change the VolumeID bit (08H) or the Subdirectory bit (10H)
  7130.  of the attribute byte with this function.
  7131.  
  7132.  If there is an error, the carry flag (CF) is set and the error code
  7133.  returns in AX:
  7134.  
  7135.  Code     Meaning
  7136.  ───────────────────────────────────────────────────────────────────────────
  7137.  1        AL not 0 or 1
  7138.  2        File doesn't exist
  7139.  3        Path invalid
  7140.  5        Attribute in CX cannot be changed (Subdirectory or VolumeID).
  7141.  
  7142.  
  7143.  Macro Definition:
  7144.  
  7145.  change_attr  macro  path,action,attrib
  7146.               mov    dx,offset path
  7147.               mov    al,action
  7148.               mov    cx,attrib
  7149.               mov    ah,43H
  7150.               int    21H
  7151.               endm
  7152.  
  7153.  
  7154.  Example:
  7155.  
  7156.  The following program displays the attributes assigned to the file named
  7157.  report.asm that is in the current directory on the disk in drive B.
  7158.  
  7159.  header    db      15 dup (20h),"Read-",0DH,0AH
  7160.            db     "Filename       Only      Hidden    "
  7161.            db     "System    Volume    Sub-Dir   Archive"
  7162.            db      0DH,0AH,0DH,0AH,"$"
  7163.  path      db     "b:report.asm",3 dup (0),"$"
  7164.  attribute dw      ?
  7165.  blanks    db      9 dup (20h),"$"
  7166.  ;
  7167.  begin:    change_attr  path,0,0  ;THIS FUNCTION
  7168.            jc      error_mode     ;Routine not shown
  7169.            mov     attribute,cx   ;Save attribute byte
  7170.            display header         ;See Function 09H
  7171.            display path           ;See Function 09H
  7172.            mov     cx,6           ;Check 6 bits (0-5)
  7173.            mov     bx,1           ;Start with bit 0
  7174.  chk_bit:  test    attribute,bx   ;Is the bit set?
  7175.            jz      no_attr        ;No
  7176.            display_char "X"       ;See Function 02H
  7177.            jmp short  next_bit    ;Done with this bit
  7178.  no_attr:  display_char  20h      ;See Function 02H
  7179.  next_bit: display blanks         ;See Function 09H
  7180.            shl     bx,1           ;Move to next bit
  7181.            loop    chk_bit        ;Check it
  7182.  
  7183.  
  7184.  IOCtl Data (Function 44H, Codes 0 and 1)
  7185.  
  7186.  
  7187.  Call:
  7188.  
  7189.  AH = 44H
  7190.  AL
  7191.     0 = Get device data
  7192.     1 = Set device data
  7193.  BX
  7194.     Handle
  7195.  DX
  7196.     Device data (see text)
  7197.  
  7198.  
  7199.  Return:
  7200.  
  7201.  Carry set:
  7202.  AX
  7203.     1 = Invalid function
  7204.     6 = Invalid handle
  7205.  Carry not set:
  7206.  DX
  7207.    Device data
  7208.  
  7209.  
  7210.  Comments:
  7211.  
  7212.  Function 44H, Codes 0 and 1, either gets or sets the data MS-DOS uses to
  7213.  control the device. AL must contain 0 to get the data or 1 to set it. BX
  7214.  must contain the handle. If AL is 1, DH must contain 0.
  7215.  
  7216.  The device-data word is specified or returned in DX. If bit 7 of the
  7217.  data is 1, the handle refers to a device and the other bits have the
  7218.  following meanings:
  7219.  
  7220.  
  7221.       Table 1.23
  7222.       MS-DOS Data Bit Values
  7223. ╓┌───────────┌───────┌───────────────────────────────────────────────────────╖
  7224.       Bit    Value   Meaning
  7225.       ────────────────────────────────────────────────────────────────────
  7226.       Bit    Value   Meaning
  7227.       ────────────────────────────────────────────────────────────────────
  7228.       0      1       Console input device
  7229.  
  7230.       1      1       Console output device
  7231.  
  7232.       2      1       Null device
  7233.  
  7234.       3      1       Clock device
  7235.  
  7236.       4      1       Reserved
  7237.  
  7238.       5      1       Don't check for control characters
  7239.              0       Check for control characters
  7240.  
  7241.       6      0       End of file on input
  7242.  
  7243.       8-10           Reserved
  7244.  
  7245.       11     1       Device understands open/close
  7246.  
  7247.       Bit    Value   Meaning
  7248. 
  7249.       12             Reserved
  7250.  
  7251.       13     1       Device supports output until busy
  7252.  
  7253.       14     1       Device can process control strings sent
  7254.                      with Function 44H, Codes 2 and 3 (IOCtl
  7255.                      character); bit can be read only, but
  7256.                      not set
  7257.  
  7258.       15             Reserved
  7259.  
  7260.  
  7261.  You must set the reserved bits to zero.
  7262.  
  7263.  The control characters referred to in the description of bit 5 are
  7264.  CONTROL-C, CONTROL-P, CONTROL-S, and CONTROL-Z. To read these characters as
  7265.  data, instead of as control characters, you must set bit 5 and use either
  7266.  Function 33H, CONTROL-C Check, or the MS-DOS break command to turn off
  7267.  CONTROL-C checking.
  7268.  
  7269.  If bit 7 of DX is 0, the handle refers to a file and the other bits
  7270.  have the following meanings:
  7271.  
  7272.  Bit    Value   Meaning
  7273.  ───────────────────────────────────────────────────────────────────────────
  7274.  0-5            Drive number (0=A, 1=B, etc.)
  7275.  6      0       The file has been written
  7276.  8-15           Reserved
  7277.  
  7278.  If there is an error, the carry flag (CF) is set and the error code returns
  7279.  in AX:
  7280.  
  7281.  Code     Meaning
  7282.  ───────────────────────────────────────────────────────────────────────────
  7283.  1        AL not 0 or 1, or AL is 1 but DH is not 0
  7284.  6        Handle in BX not open or is invalid
  7285.  
  7286.  
  7287.  Macro Definition:
  7288.  
  7289.  ioctl_data macro  code,handle
  7290.             mov    bx,handle
  7291.             mov    al,code
  7292.             mov    ah,44H
  7293.             int    21H
  7294.             endm
  7295.  
  7296.  
  7297.  Example:
  7298.  
  7299.  The following program gets the device data for standard output, sets the
  7300.  bit that specifies not to check for control characters (bit 5), and then
  7301.  clears the bit.
  7302.  
  7303.  get     equ         0
  7304.  set     equ         1
  7305.  stdout  equ         1
  7306.  ;
  7307.  begin:  ioctl_data  get,stdout          ;THIS FUNCTION
  7308.          jc          error               ;routine not shown
  7309.          mov         dh,0                ;clear DH
  7310.          or          dl,20H              ;set bit 5
  7311.          ioctl_data  set,stdout          ;THIS FUNCTION
  7312.          jc          error               ;routine not shown
  7313.  ;
  7314.  ;  <control characters now treated as data, or "raw mode">
  7315.  ;
  7316.          ioctl_data  get,stdout          ;THIS FUNCTION
  7317.          jc          error               ;routine not shown
  7318.          mov         dh,0                ;clear DH
  7319.          and         dl,0DFH             ;clear bit 5
  7320.          ioctl_data  set,stdout          ;THIS FUNCTION
  7321.  ;
  7322.  ; <control characters now interpreted, or "cooked mode">
  7323.  ;
  7324.  
  7325.  
  7326.  IOCtl Character (Function 44H, Codes 2 and 3)
  7327.  
  7328.  
  7329.  Call:
  7330.  
  7331.  AH = 44H
  7332.  AL
  7333.     2 = Send control data
  7334.     3 = Receive control data
  7335.  BX
  7336.     Handle
  7337.  CX
  7338.     Bytes to read or write
  7339.  DS:DX
  7340.     Pointer to buffer
  7341.  
  7342.  
  7343.  Return:
  7344.  
  7345.  Carry set:
  7346.  AX
  7347.     1 = Invalid function
  7348.     6 = Invalid handle
  7349.  Carry not set:
  7350.  AX
  7351.     Bytes transferred
  7352.  
  7353.  
  7354.  Comments:
  7355.  
  7356.  Function 44H, Codes 2 and 3, sends or receives control data to or from a
  7357.  character device. AL must contain 2 to send data or 3 to receive. BX must
  7358.  contain the handle of a character device, such as a printer or serial port.
  7359.  CX must contain the number of bytes to be read or written. DX must contain
  7360.  the offset (to the segment address in DS) of the data buffer.
  7361.  
  7362.  AX returns the number of bytes transferred. The device driver must
  7363.  support the IOCtl interface.
  7364.  
  7365.  If there is an error, the carry flag (CF) is set and the error code
  7366.  returns in AX:
  7367.  
  7368.  Code     Meaning
  7369.  ───────────────────────────────────────────────────────────────────────────
  7370.  1        AL not 2 or 3, or device cannot perform the specified function
  7371.  6        Handle in BX not open or doesn't exist
  7372.  
  7373.  
  7374.  Macro Definition:
  7375.  
  7376.  ioctl_char  macro  code,handle,buffer
  7377.              mov    bx,handle
  7378.              mov    dx,offset buffer
  7379.              mov    al,code
  7380.              mov    ah,44H
  7381.              int    21H
  7382.              endm
  7383.  
  7384.  
  7385.  Example:
  7386.  
  7387.  No general example is applicable, since processing of IOCtl control data
  7388.  depends on the device being used, as well as the device driver.
  7389.  
  7390.  
  7391.  IOCtl Block (Function 44H, Codes 4 and 5)
  7392.  
  7393.  
  7394.  Call:
  7395.  
  7396.  AH = 44H
  7397.  AL
  7398.     4 = Send control data
  7399.     5 = Receive control data
  7400.  BL
  7401.     Drive number (0=default, 1=A, etc.)
  7402.  CX
  7403.     Bytes to read or write
  7404.  DS:DX
  7405.     Pointer to buffer
  7406.  
  7407.  
  7408.  Return:
  7409.  
  7410.  Carry set:
  7411.  AX
  7412.     1 = Invalid function
  7413.     5 = Invalid drive
  7414.  Carry not set:
  7415.  AX
  7416.     Bytes transferred
  7417.  
  7418.  
  7419.  Comments:
  7420.  
  7421.  Function 44H, Codes 4 and 5, sends or receives control data to or from
  7422.  a block device. AL must contain 4 to send data or 5 to receive. BL must
  7423.  contain the drive number (0=default, 1=A, etc.). CX must contain the number
  7424.  of bytes to be read or written. DX must contain the offset (to the segment
  7425.  address in DS) of the data buffer.
  7426.  
  7427.  AX returns the number of bytes transferred. The device driver must
  7428.  support the IOCtl interface. To determine whether it does, use Function
  7429.  44H, Code 0, to get the device data, and test bit 14; if the bit is set,
  7430.  the driver supports IOCtl.
  7431.  
  7432.  If there is an error, the carry flag (CF) is set and the error code
  7433.  returns in AX:
  7434.  
  7435.  Code     Meaning
  7436.  ───────────────────────────────────────────────────────────────────────────
  7437.  1        AL not 4 or 5, or device cannot perform the specified function
  7438.  5        Number in BL not a valid drive number
  7439.  
  7440.  
  7441.  Macro Definition:
  7442.  
  7443.  ioctl_status macro  code,drive,buffer
  7444.               mov    bl,drive
  7445.               mov    dx,offset buffer
  7446.               mov    al,code
  7447.               mov    ah,44H
  7448.               int    21H
  7449.               endm
  7450.  
  7451.  
  7452.  Example:
  7453.  
  7454.  No general example is applicable, since processing of IOCtl control data
  7455.  depends on the device being used, as well as the device driver.
  7456.  
  7457.  
  7458.  IOCtl Status (Function 44H, Codes 6 and 7)
  7459.  
  7460.  
  7461.  Call:
  7462.  
  7463.  AH = 44H
  7464.  AL
  7465.     6 = Check input status
  7466.     7 = Check output status
  7467.  BX
  7468.     Handle
  7469.  
  7470.  
  7471.  Return:
  7472.  
  7473.  Carry set:
  7474.  AX
  7475.     1      = Invalid function
  7476.     5      = Access denied
  7477.     6      = Invalid handle
  7478.    13      = Invalid data
  7479.  Carry not set:
  7480.  AL
  7481.     00H    = Not ready
  7482.     0FFH   = Ready
  7483.  
  7484.  
  7485.  Comments:
  7486.  
  7487.  Function 44H, Codes 6 and 7, checks whether the file or device associated
  7488.  with a handle is ready. AL must contain 6 to check whether the handle
  7489.  is ready for input or 7 to check whether the handle is ready for output.
  7490.  BX must contain the handle.
  7491.  
  7492.  AL returns the status:
  7493.  
  7494.          Meaning for   Meaning for         Meaning for
  7495.  Value   Device        Input File          Output File
  7496.  ───────────────────────────────────────────────────────────────────────────
  7497.  00H     Not ready     Pointer is at EOF   Ready
  7498.  0FFH    Ready         Ready               Ready
  7499.  
  7500.  An output file always returns ready, even if the disk is full.
  7501.  
  7502.  If there is an error, the carry flag (CF) is set and the error code
  7503.  returns in AX:
  7504.  
  7505.  Code     Meaning
  7506.  ───────────────────────────────────────────────────────────────────────────
  7507.  1        AL not 6 or 7
  7508.  5        Access denied
  7509.  6        Number in BX not a valid, open handle
  7510.  13       Invalid data
  7511.  
  7512.  
  7513.  Macro Definition:
  7514.  
  7515.  ioctl_status  macro  code,handle
  7516.                mov    bx,handle
  7517.                mov    al,code
  7518.                mov    ah,44H
  7519.                int    21H
  7520.                endm
  7521.  
  7522.  
  7523.  Example:
  7524.  
  7525.  The following program displays a message that tells whether the file
  7526.  associated with handle 6 is ready for input or whether it is at
  7527.  end-of-file.
  7528.  
  7529.  stdout      equ          1
  7530.  ;
  7531.  message     db           "File is "
  7532.  ready       db           "ready."
  7533.  at_eof      db           "at EOF."
  7534.  crlf        db           ODH,OAH
  7535.  ;
  7536.  begin:      write_handle stdout,message,8   ;display message
  7537.              jc           write_error        ;routine not shown
  7538.              ioctl_status 6                  ;THIS FUNCTION
  7539.              jc           ioctl_error        ;routine not shown
  7540.              cmp          al,0               ;check status code
  7541.              jne          not_eof            ;file is ready
  7542.              write_handle stdout,at_eof,7    ;see Function 40H
  7543.              jc           write_error        ;routine not shown
  7544.              jmp          all_done           ;clean up & go home
  7545.  not_eof:    write_handle stdout,ready,6     ;see Function 40H
  7546.  all_done:   write_handle stdout,crlf,2      ;see Function 40H
  7547.              jc           write_error        ;routine not shown
  7548.  
  7549.  
  7550.  IOCtl Is Changeable (Function 44H, Code 08H)
  7551.  
  7552.  
  7553.  Call:
  7554.  
  7555.  AH = 44H
  7556.  AL = 08H
  7557.  BL
  7558.     Drive number (0=default, 1=A, etc.)
  7559.  
  7560.  
  7561.  Return:
  7562.  
  7563.  Carry set:
  7564.  AX
  7565.      1     = Invalid function
  7566.     15     = Invalid drive
  7567.  Carry not set:
  7568.  AX
  7569.     0 = Changeable
  7570.     1 = Not changeable
  7571.  
  7572.  
  7573.  Comments:
  7574.  
  7575.  Function 44H, Code 08H, checks whether a drive contains a removable or
  7576.  nonremovable disk. BL must contain the drive number (0=default, 1=A, etc.).
  7577.  AX returns 0 if the disk can be changed, 1 if it cannot.
  7578.  
  7579.  This call lets a program determine whether to issue a message to
  7580.  change disks.
  7581.  
  7582.  If there is an error, the carry flag (CF) is set and the error code
  7583.  returns in AX.
  7584.  
  7585.  Code     Meaning
  7586.  ───────────────────────────────────────────────────────────────────────────
  7587.  1        Device does not support this call
  7588.  15       Number in BL not a valid drive number
  7589.  
  7590.  When the call returns error 1 (because the driver doesn't support it),
  7591.  the caller asssumes that the driver cannot be changed.
  7592.  
  7593.  
  7594.  Macro Definition:
  7595.  
  7596.  ioctl_change  macro  drive
  7597.                mov    bl, drive
  7598.                mov    al, 08H
  7599.                mov    ah, 44H
  7600.                int    21H
  7601.                endm
  7602.  
  7603.  
  7604.  Example:
  7605.  
  7606.  The following program checks whether the current drive contains a removable
  7607.  disk. If not, processing continues; if so, the program prompts the user
  7608.  to replace the disk in the current drive.
  7609.  
  7610.  stdout    equ        1
  7611.  ;
  7612.  message   db        "Please replace disk in drive "
  7613.  drives    db        "ABCD"
  7614.  crlf      db         0DH,0AH
  7615.  ;
  7616.  begin:    ioctl_change 0                  ;THIS FUNCTION
  7617.            jc           ioctl_error        ;routine not shown
  7618.            cmp          ax,0               ;current drive changeable?
  7619.            jne          continue           ;no, continue processing
  7620.            write_handle stdout,message,29  ;see Function 40H
  7621.            jc           write_error        ;routine not shown
  7622.            current_disk                    ;see Function 19H
  7623.            xor          bx,bx              ;clear index
  7624.            mov          bl,al              ;get current drive
  7625.            display_char drives[bx]         ;see Function 02H
  7626.            write_handle stdout,crlf,2      ;see Function 40H
  7627.            jc           write_error        ;routine not shown
  7628.  continue:
  7629.  ;         (Further processing here)
  7630.  
  7631.  
  7632.  IOCtl Is Redirected Block (Function 44H, Code 09H)
  7633.  
  7634.  
  7635.  Call:
  7636.  
  7637.  AH = 44H
  7638.  AL = 09H
  7639.  BL
  7640.     Drive number (0=default, 1=A, etc.)
  7641.  
  7642.  
  7643.  Return:
  7644.  
  7645.  Carry set:
  7646.  AX
  7647.     1      = Invalid function code
  7648.    15      = Invalid drive number
  7649.  Carry not set:
  7650.  DX
  7651.     Device-attribute bits
  7652.  
  7653.  
  7654.  Comments:
  7655.  
  7656.  Function 44H, Code 09H, checks whether a drive letter refers to a drive
  7657.  on a Microsoft Networks workstation (local) or is redirected to a server
  7658.  (remote). BL must contain the drive number (0=default, 1=A, etc.).
  7659.  
  7660.  If the block device is local, DX returns the attribute word from the
  7661.  device header. If the block device is remote, only bit 12 (1000H) is set;
  7662.  the other bits are 0 (reserved).
  7663.  
  7664.  An application program should not test bit 12, because applications
  7665.  should not make distinctions between local and remote files (or devices).
  7666.  Programs should be written so that they will be independent of the location
  7667.  of a device that has been removed.
  7668.  
  7669.  If there is an error, the carry flag (CF) is set and the error code
  7670.  returns in AX:
  7671.  
  7672.  Code     Meaning
  7673.  ───────────────────────────────────────────────────────────────────────────
  7674.  1        File sharing must be loaded to use this system call
  7675.  15       Number in BL not a valid drive number
  7676.  
  7677.  
  7678.  Macro Definition:
  7679.  
  7680.  ioctl_rblock  macro  drive
  7681.                mov    bl, drive
  7682.                mov    al, 09H
  7683.                mov    ah, 44H
  7684.                int    21H
  7685.                endm
  7686.  
  7687.  
  7688.  Example:
  7689.  
  7690.  The following program checks whether drive B is local or remote and
  7691.  displays the appropriate message.
  7692.  
  7693.  stdout    equ        1
  7694.  ;
  7695.  message   db        "Drive B: is "
  7696.  loc       db        "local."
  7697.  rem       db        "remote."
  7698.  crlf      db         0DH,0AH
  7699.  ;
  7700.  begin:    write_handle stdout,message,12  ;display message
  7701.            jc           write_error        ;routine not shown
  7702.            ioctl_rblock 2                  ;THIS FUNCTION
  7703.            jc           ioctl_error        ;routine not shown
  7704.            test         dx,1000h           ;bit 12 set?
  7705.            jnz          not_loc            ;yes, it's remote
  7706.            write_handle stdout,loc,6       ;see Function 40H
  7707.            jc           write_error        ;routine not shown
  7708.            jmp          done
  7709.  not_loc:  write_handle stdout,rem,7       ;see Function 40H
  7710.            jc           write_error        ;routine not shown
  7711.  done:     write_handle stdout,crlf,2      ;see Function 40H
  7712.            jc           write_error        ;routine not shown
  7713.  
  7714.  
  7715.  IOCtl Is Redirected Handle (Function 44H, Code 0AH)
  7716.  
  7717.  
  7718.  Call:
  7719.  
  7720.  AH = 44H
  7721.  AL = 0AH
  7722.  BX
  7723.     Handle
  7724.  
  7725.  
  7726.  Return:
  7727.  
  7728.  Carry set:
  7729.  AX
  7730.     1 = Invalid function code
  7731.     6 = Invalid handle
  7732.  Carry not set:
  7733.  DX
  7734.     IOCtl bit field
  7735.  
  7736.  
  7737.  Comments:
  7738.  
  7739.  Function 44H, Code 0AH, checks whether a handle refers to a file or a
  7740.  device on a Microsoft Networks workstation (local) or is redirected to a
  7741.  server (remote). BX must contain the file handle. DX returns the IOCtl bit
  7742.  field; bit 15 is set if the handle refers to a remote file or device.
  7743.  
  7744.  An application program should not test bit 15, because applications
  7745.  should not make distinctions between local and remote files (or devices).
  7746.  Programs should be written so that they will be independent of the location
  7747.  of a device that has been removed.
  7748.  
  7749.  If there is an error, the carry flag (CF) is set and the error code
  7750.  returns in AX:
  7751.  
  7752.  Code     Meaning
  7753.  ───────────────────────────────────────────────────────────────────────────
  7754.  1        Network must be loaded to use this system call
  7755.  6        Handle in BX not a valid, open handle
  7756.  
  7757.  
  7758.  Macro Definition:
  7759.  
  7760.  ioctl_rhandle macro  handle
  7761.                mov    bx, handle
  7762.                mov    al, 0AH
  7763.                mov    ah, 44H
  7764.                int    21H
  7765.                endm
  7766.  
  7767.  
  7768.  Example:
  7769.  
  7770.  The following program checks whether handle 5 refers to a local or remote
  7771.  file or a device and displays the appropriate message.
  7772.  
  7773.  stdout    equ        1
  7774.  ;
  7775.  message   db        "Handle 5 is "
  7776.  loc       db        "local."
  7777.  rem       db        "remote."
  7778.  crlf      db         0DH,0AH
  7779.  ;
  7780.  begin:    write_handle stdout,message,12   ;display message
  7781.            jc           write_error         ;routine not shown
  7782.            ioctl_rhandle 5                  ;THIS FUNCTION
  7783.            jc           ioctl_error         ;routine not shown
  7784.            test         dx,8000h            ;bit 15 set?
  7785.            jnz          not_loc             ;yes, it's remote
  7786.            write_handle stdout,loc,6        ;see Function 40H
  7787.            jc           write_error         ;routine not shown
  7788.            jmp          done
  7789.  not_loc:  write_handle stdout,rem,7        ;see Function 40H
  7790.            jc           write_error         ;routine not shown
  7791.  done:     write_handle stdout,crlf,2       ;see Function 40H
  7792.            jc           write_error         ;routine not shown
  7793.  
  7794.  
  7795.  IOCtl Retry (Function 44H, Code 0BH)
  7796.  
  7797.  
  7798.  Call:
  7799.  
  7800.  AH = 44H
  7801.  AL = 0BH
  7802.  DX
  7803.     Number of retries
  7804.  CX
  7805.     Wait time
  7806.  
  7807.  
  7808.  Return:
  7809.  
  7810.  Carry set:
  7811.  AX
  7812.     1 = Invalid function code
  7813.  Carry not set:
  7814.     No error
  7815.  
  7816.  
  7817.  Comments:
  7818.  
  7819.  Function 44H, Code 0BH, specifies how many times MS-DOS should retry a disk
  7820.  operation that fails because of a file-sharing violation. DX must contain
  7821.  the number of retries. CX controls the pause between retries.
  7822.  
  7823.  MS-DOS retries this type of disk operation three times, unless you use
  7824.  this system call to specify a different number. After the specified number
  7825.  of retries, MS-DOS issues Interrupt 24H (Critical-Error-Handler Address)
  7826.  for the requesting process.
  7827.  
  7828.  The effect of the delay parameter in CX is machine-dependent because
  7829.  it specifies how many times MS-DOS should execute an empty loop. The actual
  7830.  time varies, depending on the processor and clock speed. You can determine
  7831.  the effect on your machine by using debug. Set the number of retries to 1
  7832.  and then time several values of CX.
  7833.  
  7834.  If there is an error, the carry flag (CF) is set and the error code
  7835.  returns in AX:
  7836.  
  7837.  Code     Meaning
  7838.  ───────────────────────────────────────────────────────────────────────────
  7839.  1        File sharing must be loaded to use this system call
  7840.  
  7841.  
  7842.  Macro Definition:
  7843.  
  7844.  ioctl_retry  macro  retries, wait
  7845.               mov    dx, retries
  7846.               mov    cx, wait
  7847.               mov    al, 0BH
  7848.               mov    ah, 44H
  7849.               int    21H
  7850.               endm
  7851.  
  7852.  
  7853.  Example:
  7854.  
  7855.  The following program sets the number of sharing retries to 10 and
  7856.  specifies a delay of 1000 between retries.
  7857.  
  7858.  begin:    ioctl_retry  10,1000          ;THIS FUNCTION
  7859.            jc           error            ;routine not shown
  7860.  
  7861.  
  7862.  Generic IOCtl (for Handles) (Function 44H, Code 0CH)
  7863.  
  7864.  
  7865.  Call:
  7866.  
  7867.  AH = 44H
  7868.  AL = 0CH
  7869.  BX
  7870.      Handle
  7871.  CH = 05H
  7872.      Category code (printer device)
  7873.  CL
  7874.      Function (minor) code
  7875.  DS:DX
  7876.      Pointer to data buffer
  7877.  
  7878.  
  7879.  Return:
  7880.  
  7881.  Carry set:
  7882.  AX
  7883.      1 = Invalid function code
  7884.  Carry not set:
  7885.      No error
  7886.  
  7887.  
  7888.  Comments:
  7889.  
  7890.  This call loads and selects code pages for devices on a per-device basis.
  7891.  It also sets or gets the output iteration count for a printer that supports
  7892.  "PRINT 'TIL BUSY."
  7893.  
  7894.  The category code may be one of the following:
  7895.  
  7896.  Code     Meaning
  7897.  ───────────────────────────────────────────────────────────────────────────
  7898.  00       Unknown device
  7899.  01       Serial printer
  7900.  03       Console device
  7901.  05       Parallel printer
  7902.  
  7903.  The function code may be one of the following:
  7904.  
  7905.  Code      Meaning
  7906.  ───────────────────────────────────────────────────────────────────────────
  7907.  45H       Sets iteration count for printer
  7908.  4AH       Select code page
  7909.  4CH       Start prepare list
  7910.  4DH       End prepare list
  7911.  65H       Gets iteration count for printer
  7912.  6AH       Query code page selected
  7913.  6BH       Query code page prepare list
  7914.  
  7915.  ───────────────────────────────────────────────────────────────────────────
  7916.  Note
  7917.    DS:DX points to a word that contains the new value for the total number
  7918.    of output iterations performed before proceeding. Thus, DS:DX points to
  7919.    a word that contains the character iteration count for the "PRINT 'TIL
  7920.    BUSY" loop. This is the number of times the device driver will wait for
  7921.    the device to signal "ready" before acknowledging "Device busy."
  7922.  ───────────────────────────────────────────────────────────────────────────
  7923.  
  7924.  
  7925.  Macro Definition:
  7926.  
  7927.  ioctl_handles       macro handle,function,category,buffer
  7928.                      mov ch,05H
  7929.                      mov cl,function
  7930.                      mov dx,offset buffer
  7931.                      mov bx,handle
  7932.                      mov ah,44H
  7933.                      mov al,0CH
  7934.                      int 21H
  7935.                      endm
  7936.  
  7937.  
  7938.  Generic IOCtl (for Devices) (Function 44H, Code 0DH)
  7939.  
  7940.  
  7941.  Call:
  7942.  
  7943.  AH = 44H
  7944.  AL = 0DH
  7945.  BL
  7946.      Drive number
  7947.          (0 = default, 1 = A, etc.)
  7948.  CH = 08H
  7949.      Category (major) code
  7950.  CL
  7951.      Function (minor) code
  7952.  DS:DX
  7953.      Pointer to parameter block -1
  7954.  
  7955.  
  7956.  Return:
  7957.  
  7958.  Carry set:
  7959.  AX
  7960.      1 = Invalid function code
  7961.      2 = Invalid drive
  7962.  Carry not set:
  7963.      No error
  7964.  
  7965.  
  7966.  Comments:
  7967.  
  7968.  The function code may be one of the following:
  7969.  
  7970.  Code      Meaning
  7971.  ───────────────────────────────────────────────────────────────────────────
  7972.  40        Set device parameters
  7973.  41        Write track on logical device
  7974.  42        Format track on logical device
  7975.  60        Get device parameters
  7976.  61        Read track on logical device
  7977.  62        Verify track on logical device
  7978.  
  7979.  ───────────────────────────────────────────────────────────────────────────
  7980.  Note
  7981.    You must issue "Set Device Parameters" before you can read, write,
  7982.    format, or verify a logical drive.
  7983.  ───────────────────────────────────────────────────────────────────────────
  7984.  
  7985.  You should use the following procedure when you want to read, write,
  7986.  format, or verify a logical drive:
  7987.  
  7988.    1.  Save drive parameters using "Get Device Parameters."
  7989.  
  7990.    2.  Set desired drive parameters using "Set Device Parameters."
  7991.  
  7992.    3.  Perform the I/O operation.
  7993.  
  7994.    4.  Restore the original drive parameters using "Set Device Parameters."
  7995.  
  7996.  
  7997.  Set Device Parameters (Function 44 0DH, CL=40H)
  7998.  
  7999.  When CL=40H, the parameter block has the following field format:
  8000.  
  8001.               --------------------------------------
  8002.               | BYTE      Special Functions        |
  8003.               |------------------------------------|
  8004.               | BYTE      Device Type              |
  8005.               |------------------------------------|
  8006.               | WORD      Device Attributes        |
  8007.               |------------------------------------|
  8008.               | WORD      Number of Cylinders      |
  8009.               |------------------------------------|
  8010.               | BYTE      Media Type               |
  8011.               |------------------------------------|
  8012.               |           Device BPB               |
  8013.               |------------------------------------|
  8014.               |           Track Layout             |
  8015.               --------------------------------------
  8016.  
  8017.  These fields have the following meanings:
  8018.  
  8019.  
  8020.  Special Functions
  8021.  
  8022. ╓┌───────┌────────┌──────────────────────────────────────────────────────────╖
  8023.  Bit     Value    Meaning
  8024.  Bit     Value    Meaning
  8025.  ───────────────────────────────────────────────────────────────────────────
  8026.   0      0        The Device BPB (BIOS Parameter Block)
  8027.                   field contains the new default BPB for
  8028.                   this device. If a previous "Set
  8029.                   Parameter Device" call set this bit,
  8030.                   Build BPB returns the actual media BPB;
  8031.                   otherwise, it returns the default BPB
  8032.                   for the device.
  8033.  
  8034.          1        All subsequent Build BPB requests
  8035.                   return the device BPB.
  8036.  
  8037.   1      0        Read all fields of the parameter block.
  8038.  
  8039.          1        Ignore all fields of the parameter
  8040.                   block except for the Track Layout
  8041.                   field.
  8042.  
  8043.   2      0        The sectors in the track may not all
  8044.                   be the same size. (You should not use
  8045.  Bit     Value    Meaning
  8046.                  be the same size. (You should not use
  8047.                   this setting.)
  8048.  
  8049.          1        The sectors in the track are all the
  8050.                   same size and the sector numbers range
  8051.                   between 1 and the total number of
  8052.                   sectors actually in the track. You
  8053.                   should always set this bit.
  8054.  
  8055.  3-7     0        These bits must be zero.
  8056.  
  8057.  
  8058.  Device Type
  8059.  
  8060.  This byte describes the physical device and is set by the device.
  8061.  When set, it has the following meanings:
  8062.  
  8063.  Value  Meaning
  8064.  ───────────────────────────────────────────────────────────────────────────
  8065.  0      320/360 KB
  8066.  1      1.2 MB
  8067.  2      720 KB
  8068.  3      8-inch, single-density
  8069.  4      8-inch, double-density
  8070.  5      Hard disk
  8071.  6      Tape drive
  8072.  7      Other
  8073.  
  8074.  
  8075.  Device Attributes
  8076.  
  8077.  Bit   Value   Meaning
  8078.  ───────────────────────────────────────────────────────────────────────────
  8079.          0     The media is removable.
  8080.  
  8081.   0      1     The media is not removable.
  8082.  
  8083.   1      0     Disk change-line is not
  8084.                supported; (no door lock
  8085.                support).
  8086.  
  8087.          1     Disk change-line is
  8088.                supported; (door lock
  8089.                support).
  8090.  
  8091.  2-7     0     These bits must be zero.
  8092.  
  8093.  
  8094.  Number of Cylinders
  8095.  
  8096.  This field indicates the maximum number of cylinders that the physical
  8097.  device can support. This information is set by the device.
  8098.  
  8099.  
  8100.  Media Type
  8101.  
  8102.  For drives that may contain different media, this field (which is
  8103.  device-dependent) indicates which media the drive expects.
  8104.  
  8105.  For a 1.2 MB disk, bit zero has the following meaning:
  8106.  
  8107.  Bit   Value   Meaning
  8108.  ───────────────────────────────────────────────────────────────────────────
  8109.   0      0     Quad-density, 1.2 MB disk
  8110.          1     Double-density, 320/360 KB disk
  8111.  
  8112.  The default media type is a quad-density 1.2 MB disk.
  8113.  
  8114.  
  8115.  Device BPB
  8116.  
  8117.  If bit 0 of the Special Functions field is clear, the BPB in this
  8118.  field is the new default BPB for the device.
  8119.  
  8120.  If bit 0 of the Special Functions field is set, the device driver
  8121.  returns the BPB from this field for subsequent Build BPB requests.
  8122.  
  8123.  
  8124.  Track Layout
  8125.  
  8126.  This field contains a table of variable length for each logical device
  8127.  and indicates the expected layout of the sectors on the media track.
  8128.  The field has the following format:
  8129.  
  8130.          ------------------------------------------------
  8131.          | WORD      Sector Count -- total # of sectors |
  8132.          |----------------------------------------------|
  8133.          | WORD      Sector Number -- sector #1         |
  8134.          |----------------------------------------------|
  8135.          | WORD      Sector Size -- sector #1           |
  8136.          |----------------------------------------------|
  8137.          | WORD      Sector Number -- sector #2         |
  8138.          |----------------------------------------------|
  8139.          | WORD      Sector Size -- sector #2           |
  8140.          ------------------------------------------------
  8141.                                |
  8142.                                |
  8143.                                |
  8144.          ------------------------------------------------
  8145.          | WORD      Sector Number -- sector #n         |
  8146.          |----------------------------------------------|
  8147.          | WORD      Sector Size -- sector #n           |
  8148.          ------------------------------------------------
  8149.  
  8150.  The Sector Count field indicates the total number of sectors. Each sector
  8151.  number must be unique and in the range of 1 to sector count (n).
  8152.  
  8153.  If bit 2 of the Special Functions field is set, all sector sizes must
  8154.  be the same.
  8155.  
  8156.  
  8157.  Get Device Parameters (Function 440DH, CL=60H)
  8158.  
  8159.  When CL=60H, the parameter block has the same field layout as for CL=40H.
  8160.  However, some of the fields have different meanings. These are described
  8161.  as follows:
  8162.  
  8163.  
  8164.  Special Functions
  8165.  
  8166.  Bit   Value   Meaning
  8167.  ───────────────────────────────────────────────────────────────────────────
  8168.   0      0     Returns the default BPB for the device.
  8169.          1     Returns the BPB that Build BPB would return.
  8170.  
  8171.  1-7     0     These bits must be zero.
  8172.  
  8173.  
  8174.  Track Layout
  8175.  
  8176.  The "Get Device Parameters" call does not use this field.
  8177.  
  8178.  
  8179.  Read/Write Track on Logical Drive (Function 440D, CL=61H/CL=41H)
  8180.  
  8181.  To write to a track on a logical drive, set CL=41H. To read a track on a
  8182.  logical drive, set CL=61H.
  8183.  
  8184.  When CL=41H or 61H, the parameter block has the following format:
  8185.  
  8186.              --------------------------------
  8187.              | BYTE      Special Functions  |
  8188.              |------------------------------|
  8189.              | WORD      Head               |
  8190.              |------------------------------|
  8191.              | WORD      Cylinder           |
  8192.              |------------------------------|
  8193.              | WORD      First Sector       |
  8194.              |------------------------------|
  8195.              | WORD      Number of Sectors  |
  8196.              |------------------------------|
  8197.              | DWORD     Transfer Address   |
  8198.              --------------------------------
  8199.  
  8200.  These fields are described as follows:
  8201.  
  8202.  
  8203.  Special Functions
  8204.  
  8205.  This byte must be zero.
  8206.  
  8207.  
  8208.  Head
  8209.  
  8210.  This field contains the number of the head on which you perform the
  8211.  write or read.
  8212.  
  8213.  
  8214.  Cylinder
  8215.  
  8216.  This field contains the number of the cylinder on which you perform
  8217.  the write or read.
  8218.  
  8219.  
  8220.  First Sector
  8221.  
  8222.  This field contains the number of the first sector on which you perform
  8223.  the write or read. Sectors are numbered starting with zero, so the fourth
  8224.  sector is numbered 3.
  8225.  
  8226.  
  8227.  Number of Sectors
  8228.  
  8229.  This field contains the total number of sectors.
  8230.  
  8231.  
  8232.  Transfer Address
  8233.  
  8234.  This field contains the address for storing the data to be written or
  8235.  the data just read.
  8236.  
  8237.  
  8238.  Format/Verify Track on Logical Drive (Function 440DH, CL=42/CL=62)
  8239.  
  8240.  To format and verify a track on a logical drive, set CL=42H. To verify a
  8241.  track on a logical drive, set CL=62H.
  8242.  
  8243.  When CL=42H or 62H, the parameter block has the following format:
  8244.  
  8245.              --------------------------------
  8246.              | BYTE      Special Functions  |
  8247.              |------------------------------|
  8248.              | WORD      Head               |
  8249.              |------------------------------|
  8250.              | WORD      Cylinder           |
  8251.              --------------------------------
  8252.  
  8253.  These fields are described as follows:
  8254.  
  8255.  
  8256.  Special Functions
  8257.  
  8258.  This byte must be zero.
  8259.  
  8260.  
  8261.  Head
  8262.  
  8263.  This field contains the number of the head on which you perform the
  8264.  format or verify.
  8265.  
  8266.  
  8267.  Cylinder
  8268.  
  8269.  This field contains the number of the cylinder on which you perform
  8270.  the format or verify.
  8271.  
  8272.  Get/Set IOCtl Drive Map (Function 44H, Codes 0EH and 0FH)
  8273.  
  8274.  
  8275.  Call:
  8276.  
  8277.  AH = 44H
  8278.  AL
  8279.      OEH = Get logical drive map
  8280.      OFH = Set logical drive map
  8281.  BX
  8282.      Drive number
  8283.          (0 = default, 1 = A, etc.)
  8284.  
  8285.  
  8286.  Return:
  8287.  
  8288.  Carry set:
  8289.  AX
  8290.      1 = Invalid function code
  8291.      5 = Invalid drive
  8292.  Carry not set:
  8293.  AL = Logical drive mapped onto physical drive
  8294.       (= 0 if only one drive is
  8295.       assigned to this physical drive)
  8296.  
  8297.  
  8298.  Comments:
  8299.  
  8300.  MS-DOS 3.3 supports the mapping of multiple logical drives onto a single
  8301.  physical block device. Get IOCtl Drive Map lets you query the DOS about
  8302.  which logical drive is currently mapped onto the corresponding physical
  8303.  device. Set IOCtl Drive Map alters the device that is currently mapped
  8304.  onto the physical device. These functions are only useful if there is
  8305.  more than one logical block device mapped onto a single physical device.
  8306.  
  8307.  A possible use for these functions is with applications that want to
  8308.  disable the DOS prompt in order to place the correct floppy disk in the
  8309.  drive when accessing the other logical drive.
  8310.  
  8311.  To detect whether a logical device currently owns the physical device
  8312.  it is mapped to, a program needs to check the value in AL after calling
  8313.  Function 440EH or 440FH (Get/Set IOCtl Drive Map).
  8314.  
  8315.  
  8316.  Duplicate File Handle (Function 45H)
  8317.  
  8318.  
  8319.  Call:
  8320.  
  8321.  AH = 45H
  8322.  BX
  8323.     Handle
  8324.  
  8325.  
  8326.  Return:
  8327.  
  8328.  Carry set:
  8329.  AX
  8330.     4 = Too many open files
  8331.     6 = Invalid handle
  8332.  Carry not set:
  8333.  AX
  8334.     New handle
  8335.  
  8336.  
  8337.  Comments:
  8338.  
  8339.  Function 45H creates an additional handle for a file. BX must contain the
  8340.  handle of an open file.
  8341.  
  8342.  MS-DOS returns the new handle in AX. The new handle refers to the same
  8343.  file as the handle in BX, with the file pointer at the same position.
  8344.  
  8345.  After you use this function request, moving the read/write pointer of
  8346.  either handle also moves the pointer for the other handle. You usually use
  8347.  this function request to redirect standard input (handle 0) and standard
  8348.  output (handle 1). For a description of standard input, standard output,
  8349.  and the advantages and techniques of manipulating them, see Software Tools
  8350.  by Brian W. Kernighan and P.J. Plauger (Addison-Wesley Publishing Co.,
  8351.  1976).
  8352.  
  8353.  If there is an error, the carry flag (CF) is set and the error code
  8354.  returns in AX:
  8355.  
  8356.  Code     Meaning
  8357.  ───────────────────────────────────────────────────────────────────────────
  8358.  4        Too many open files (no handle available)
  8359.  6        Handle not open or is invalid
  8360.  
  8361.  
  8362.  Macro Definition:
  8363.  
  8364.  xdup  macro  handle
  8365.        mov    bx,handle
  8366.        mov    ah,45H
  8367.        int    21H
  8368.        endm
  8369.  
  8370.  
  8371.  Example:
  8372.  
  8373.  The following program redirects standard output (handle 1) to a file named
  8374.  dirfile, invokes a second copy of command.com to list the directory (which
  8375.  writes the directory to dirfile), and then restores standard input to
  8376.  handle 1.
  8377.  
  8378.  pgm_file  db    "command.com",0
  8379.  cmd_line  db    9,"/c dir /w",0dH
  8380.  parm_blk  db    14 dup (0)
  8381.  path            db  "dirfile",0
  8382.  dir_file        dw      ?         ; For handle
  8383.  sav_stdout dw   ?                 ; For handle
  8384.  ;
  8385.  begin:    set_block  last_inst    ; See Function 4AH
  8386.            jc      error_setblk    ; Routine not shown
  8387.            create_handle  path,0   ; See Function 3CH
  8388.            jc      error_create    ; Routine not shown
  8389.            mov     dir_file,ax     ; Save handle
  8390.            xdup    1               ; THIS FUNCTION
  8391.            jc      error_xdup      ; Routine not shown
  8392.            mov     sav_stdout,ax   ; Save handle
  8393.            xdup2   dir_file,1      ; See Function 46H
  8394.            jc      error_xdup2     ; Routine not shown
  8395.            exec    pgm_file,cmd_line,parm_blk ; See Function 4BH
  8396.            jc      error_exec      ; Routine not shown
  8397.            xdup2   sav_stdout,1    ; See Function 46H
  8398.            jc      error_xdup2     ; Routine not shown
  8399.            close_handle sav_stdout ; See Function 3EH
  8400.            jc      error_close     ; Routine not shown
  8401.            close_handle dir_file   ; See Function 3EH
  8402.            jc      error_close     ; Routine not shown
  8403.  
  8404.  
  8405.  Force Duplicate File Handle (Function 46H)
  8406.  
  8407.  
  8408.  Call:
  8409.  
  8410.  AH = 46H
  8411.  BX
  8412.     Handle
  8413.  CX
  8414.     Second handle
  8415.  
  8416.  
  8417.  Return:
  8418.  
  8419.  Carry set:
  8420.  AX
  8421.     4 = Too many open files
  8422.     6 = Invalid handle
  8423.  Carry not set:
  8424.     No error
  8425.  
  8426.  
  8427.  Comments:
  8428.  
  8429.  Function 46H forces a specified handle to refer to the same file as
  8430.  a second handle already associated with an open file. BX must contain
  8431.  the handle of the open file; CX must contain the second handle.
  8432.  
  8433.  On return, the handle in CX now refers to the same file at the same
  8434.  position as the handle in BX. If the file referred to by the handle in
  8435.  CX was open at the time of the call, this function closes it.
  8436.  
  8437.  After you use this call, moving the read/write pointer of either handle
  8438.  also moves the pointer for the other handle. Normally, you would use this
  8439.  function request to redirect standard input (handle 0) and standard output
  8440.  (handle 1). For a description of standard input, standard output, and the
  8441.  advantages and techniques of manipulating them, see Software Tools by
  8442.  Brian W. Kernighan and P.J. Plauger (Addison-Wesley Publishing Co., 1976).
  8443.  
  8444.  If there is an error, the carry flag (CF) is set and the error code
  8445.  returns in AX:
  8446.  
  8447.  Code     Meaning
  8448.  ───────────────────────────────────────────────────────────────────────────
  8449.  4        Too many open files (no handle available)
  8450.  6        Handle not open or is invalid
  8451.  
  8452.  
  8453.  Macro Definition:
  8454.  
  8455.  xdup2  macro  handle1,handle2
  8456.         mov    bx,handle1
  8457.         mov    cx,handle2
  8458.         mov    ah,46H
  8459.         int    21H
  8460.         endm
  8461.  
  8462.  
  8463.  Example:
  8464.  
  8465.  The following program redirects standard output (handle 1) to a file named
  8466.  dirfile, invokes a second copy of command.com to list the directory (which
  8467.  writes the directory to dirfile), and then restores standard input to
  8468.  handle 1.
  8469.  
  8470.  pgm_file  db    "command.com",0
  8471.  cmd_line  db    9,"/c dir /w",0dH
  8472.  parm_blk  db    14 dup (0)
  8473.  path            db  "dirfile",0
  8474.  dir_file        dw      ?         ; For handle
  8475.  sav_stdout dw   ?                 ; For handle
  8476.  ;
  8477.  begin:    set_block  last_inst    ; See Function 4AH
  8478.            jc      error_setblk    ; Routine not shown
  8479.            create_handle  path,0   ; See Function 3CH
  8480.            jc      error_create    ; Routine not shown
  8481.            mov     dir_file,ax     ; Save handle
  8482.            xdup    1               ; See Function 45H
  8483.            jc      error_xdup      ; Routine not shown
  8484.            mov     sav_stdout,ax   ; Save handle
  8485.            xdup2   dir_file,1      ;
  8486.            jc      error_xdup2     ; Routine not shown
  8487.            exec    pgm_file,cmd_line,parm_blk ; See Function 4BH
  8488.            jc      error_exec      ; Routine not shown
  8489.            xdup2   sav_stdout,1    ; THIS FUNCTION
  8490.            jc      error_xdup2     ; Routine not shown
  8491.            close_handle sav_stdout ; See Function 3EH
  8492.            jc      error_close     ; Routine not shown
  8493.            close_handle dir_file   ; See Function 3EH
  8494.            jc      error_close     ; Routine not shown
  8495.  
  8496.  
  8497.  Get Current Directory (Function 47H)
  8498.  
  8499.  
  8500.  Call:
  8501.  
  8502.  AH = 47H
  8503.  DS:SI
  8504.     Pointer to 64-byte memory area
  8505.  DL
  8506.     Drive number
  8507.        (0 = default, 1 = A)
  8508.  
  8509.  
  8510.  Return:
  8511.  
  8512.  Carry set:
  8513.  AX
  8514.     15 = Invalid drive number
  8515.  Carry not set:
  8516.     No error
  8517.  
  8518.  
  8519.  Comments:
  8520.  
  8521.  Function 47H returns the pathname of the current directory on a specified
  8522.  drive. DL must contain a drive number (0=default, 1=A, etc.). SI must
  8523.  contain the offset (from the segment address in DS) of a 64-byte memory
  8524.  area.
  8525.  
  8526.  MS-DOS places an ASCIZ string in the memory area, consisting of the path
  8527.  (starting from the root directory) of the current directory for the drive
  8528.  specified in DL. The string does not begin with a backslash and does not
  8529.  include the drive letter.
  8530.  
  8531.  If there is an error, the carry flag (CF) is set and the error code
  8532.  returns in AX:
  8533.  
  8534.  Code     Meaning
  8535.  ───────────────────────────────────────────────────────────────────────────
  8536.  15       Number in DL not a valid drive number
  8537.  
  8538.  
  8539.  Macro Definition:
  8540.  
  8541.  get_dir  macro   drive,buffer
  8542.           mov     dl,drive
  8543.           mov     si,offset buffer
  8544.           mov     ah,47H
  8545.           int     21H
  8546.           endm
  8547.  
  8548.  
  8549.  Example:
  8550.  
  8551.  The following program displays the current directory that is on the disk in
  8552.  drive B.
  8553.  
  8554.  disk        db      "b:
  8555.  buffer      db       64 dup (?)
  8556.  ;
  8557.  begin:      get_dir  2,buffer       ;THIS FUNCTION
  8558.              jc       error_dir      ;Routine not shown
  8559.              display  disk           ;See Function 09H
  8560.              display_asciz  buffer   ;See end of chapter
  8561.  
  8562.  
  8563.  Allocate Memory (Function 48H)
  8564.  
  8565.  
  8566.  Call:
  8567.  
  8568.  AH = 48H
  8569.  BX
  8570.    Paragraphs of memory requested
  8571.  
  8572.  
  8573.  Return:
  8574.  
  8575.  Carry set:
  8576.  AX
  8577.    7 = Memory-control blocks damaged
  8578.    8 = Insufficient memory
  8579.  BX
  8580.    Paragraphs of memory available
  8581.  Carry not set:
  8582.  AX
  8583.    Segment address of allocated memory
  8584.  
  8585.  
  8586.  Comments:
  8587.  
  8588.  Function 48H tries to allocate the specified amount of memory to the
  8589.  current process. BX must contain the number of paragraphs of memory
  8590.  (one paragraph is 16 bytes).
  8591.  
  8592.  If sufficient memory is available to satisfy the request, AX returns
  8593.  the segment address of the allocated memory (the offset is 0). If
  8594.  sufficient memory is not available, BX returns the number of paragraphs
  8595.  of memory in the largest available block.
  8596.  
  8597.  If there is an error, the carry flag (CF) is set and the error code
  8598.  returns in AX:
  8599.  
  8600.  Code     Meaning
  8601.  ───────────────────────────────────────────────────────────────────────────
  8602.  7        Memory-control blocks damaged (a user program changed memory
  8603.           that doesn't belong to it)
  8604.  
  8605.  8        Not enough free memory to satisfy the request
  8606.  
  8607.  
  8608.  Macro Definition:
  8609.  
  8610.  allocate_memory  macro   bytes
  8611.                   mov     bx,bytes
  8612.                   mov     cl,4
  8613.                   shr     bx,cl
  8614.                   inc     bx
  8615.                   mov     ah,48H
  8616.                   int     21H
  8617.                   endm
  8618.  
  8619.  
  8620.  Example:
  8621.  
  8622.  The following program opens the file named textfile.asc, calculates its
  8623.  size with Function 42H (Move File Pointer), allocates a block of memory the
  8624.  size of the file, reads the file into the allocated memory block, and then
  8625.  frees the allocated memory.
  8626.  
  8627.  path      db      "textfile.asc",0
  8628.  msg1      db      "File loaded into allocated memory block.",
  8629.                     0DH,0AH
  8630.  msg2      db      "Allocated memory now being freed
  8631.                     (deallocated).",0DH,0AH
  8632.  handle    dw       ?
  8633.  mem_seg   dw       ?
  8634.  file_len  dw       ?
  8635.  ;
  8636.  begin:    open_handle  path,0
  8637.            jc       error_open         ;Routine not shown
  8638.            mov      handle,ax          ;Save handle
  8639.            move_ptr handle,0,0,2       ;See Function 42H
  8640.            jc       error_move         ;Routine not shown
  8641.            mov      file_len,ax        ;Save file length
  8642.            set_block  last_inst        ;See Function 4AH
  8643.            jc       error_setblk       ;Routine not shown
  8644.            allocate_memory  file_len   ;THIS FUNCTION
  8645.            jc       error_alloc        ;Routine not shown
  8646.            mov      mem_seg,ax         ;Save address of new memory
  8647.            move_ptr handle,0,0,0       ;See Function 42H
  8648.            jc       error_move         ;Routine not shown
  8649.            push     ds                 ;Save DS
  8650.            mov      ax,mem_seg         ;Get segment of new memory
  8651.            mov      ds,ax              ;Point DS at new memory
  8652.            read_handle  cs:handle,0,cs:file_len ;Read file into new memory
  8653.            pop      ds                 ;Restore DS
  8654.            jc       error_read         ;Routine not shown
  8655.  ;         (CODE TO PROCESS FILE GOES HERE)
  8656.            write_handle stdout,msg1,42 ;See Function 40H
  8657.            jc       write_error        ;Routine not shown
  8658.            free_memory  mem_seg        ;See Function 49H
  8659.            jc       error_freemem      ;Routine not shown
  8660.            write_handle stdout,msg2,49 ;See Function 40H
  8661.            jc       write_error        ;Routine not shown
  8662.  
  8663.  
  8664.  Free Allocated Memory (Function 49H)
  8665.  
  8666.  
  8667.  Call:
  8668.  
  8669.  AH = 49H
  8670.  ES
  8671.     Segment address of memory to be
  8672.     freed
  8673.  
  8674.  
  8675.  Return:
  8676.  
  8677.  Carry set:
  8678.  AX
  8679.     7 = Memory-control blocks damaged
  8680.     9 = Incorrect segment
  8681.  Carry not set:
  8682.     No error
  8683.  
  8684.  
  8685.  Comments:
  8686.  
  8687.  Function 49H frees (makes available) a block of memory previously allocated
  8688.  with Function 48H (Allocate Memory). ES must contain the segment address of
  8689.  the memory block to be freed.
  8690.  
  8691.  If there is an error, the carry flag (CF) is set and the error code
  8692.  returns in AX:
  8693.  
  8694.  Code     Meaning
  8695.  ───────────────────────────────────────────────────────────────────────────
  8696.  7        Memory-control blocks damaged (a user program changed memory
  8697.           that didn't belong to it)
  8698.  
  8699.  9        Memory pointed to by ES was not allocated with Function 48H
  8700.  
  8701.  
  8702.  Macro Definition:
  8703.  
  8704.  free_memory  macro     seg_addr
  8705.               mov       ax,seg_addr
  8706.               mov       es,ax
  8707.               mov       ah,49H
  8708.               int       21H
  8709.               endm
  8710.  
  8711.  
  8712.  Example:
  8713.  
  8714.  The following program opens a file named textfile.asc, calculates its size
  8715.  with Function 42H (Move File Pointer), allocates a block of memory the size
  8716.  of the file, reads the file into the allocated memory block, and then frees
  8717.  the allocated memory.
  8718.  
  8719.  path      db      "textfile.asc",0
  8720.  msg1      db      "File loaded into allocated memory block.",
  8721.                     0DH,0AH
  8722.  msg2      db      "Allocated memory now being freed
  8723.                     (deallocated).",0DH,0AH
  8724.  handle    dw       ?
  8725.  mem_seg   dw       ?
  8726.  file_len  dw       ?
  8727.  ;
  8728.  begin:    open_handle  path,0
  8729.            jc       error_open         ;Routine not shown
  8730.            mov      handle,ax          ;Save handle
  8731.            move_ptr handle,0,0,2       ;See Function 42H
  8732.            jc       error_move         ;Routine not shown
  8733.            mov      file_len,ax        ;Save file length
  8734.            set_block  last_inst        ;See Function 4AH
  8735.            jc       error_setblk       ;Routine not shown
  8736.            allocate_memory  file_len   ;See Function 48H
  8737.            jc       error_alloc        ;Routine not shown
  8738.            mov      mem_seg,ax         ;Save address of new memory
  8739.            mov_ptr  handle,0,0,0       ;See Function 42H
  8740.            jc       error_move         ;Routine not shown
  8741.            push     ds                 ;Save DS
  8742.            mov      ax,mem_seg         ;Get segment of new memory
  8743.            mov      ds,ax              ;Point DS at new memory
  8744.            read_handle  handle,code,file_len ;Read file into new memory
  8745.  ;
  8746.            pop      ds                 ;Restore DS
  8747.            jc       error_read         ;Routine not shown
  8748.  ;         (CODE TO PROCESS FILE GOES HERE)
  8749.            write_handle stdout,msg1,42 ;See Function 40H
  8750.            jc       write_error        ;Routine not shown
  8751.            free_memory  mem_seg        ;THIS FUNCTION
  8752.            jc       error_freemem      ;Routine not shown
  8753.            write_handle stdout,msg2,49 ;See Function 40H
  8754.            jc       write_error        ;Routine not shown
  8755.  
  8756.  
  8757.  Set Block (Function 4AH)
  8758.  
  8759.  
  8760.  Call:
  8761.  
  8762.  AH = 4AH
  8763.  BX
  8764.     Paragraphs of memory
  8765.  ES
  8766.     Segment address of memory area
  8767.  
  8768.  
  8769.  Return:
  8770.  
  8771.  Carry set:
  8772.  AX
  8773.     7 = Memory-control blocks damaged
  8774.     8 = Insufficient memory
  8775.     9 = Incorrect segment
  8776.  BX
  8777.     Paragraphs of memory available
  8778.  Carry not set:
  8779.     No error
  8780.  
  8781.  
  8782.  Comments:
  8783.  
  8784.  Function 4AH changes the size of a memory-allocation block. ES must
  8785.  contain the segment address of the memory block. BX must contain the
  8786.  new size of the memory block, in paragraphs (one paragraph is 16 bytes).
  8787.  
  8788.  MS-DOS attempts to change the size of the memory block. If the call
  8789.  fails on a request to increase memory, BX returns the maximum size
  8790.  (in paragraphs) to which the block can be increased.
  8791.  
  8792.  Since MS-DOS allocates all available memory to a .com program, you would
  8793.  use this call most often to reduce the size of a program's initial memory-
  8794.  allocation block.
  8795.  
  8796.  If there is an error, the carry flag (CF) is set and the error code
  8797.  returns in AX:
  8798.  
  8799.  Code     Meaning
  8800.  ───────────────────────────────────────────────────────────────────────────
  8801.  7        Memory-control blocks destroyed (a user program changed memory
  8802.           that didn't belong to it)
  8803.  
  8804.  8        Not enough free memory to satisfy the request
  8805.  
  8806.  9        Wrong address in ES (the memory block it points to cannot
  8807.           be modified with Set Block)
  8808.  
  8809.  The following macro shrinks the initial memory-allocation block of a
  8810.  .com program. It takes as a parameter the offset of the first byte
  8811.  following the last instruction of a program (LAST_INST in the sample
  8812.  programs), uses it to calculate the number of paragraphs in the program,
  8813.  and then adds 17 to the result: one to round up and 16 to set aside 256
  8814.  bytes for a stack. It then sets up SP and BP to point to this stack.
  8815.  
  8816.  
  8817.  Macro Definition:
  8818.  
  8819.  set_block  macro   last_byte
  8820.             mov     bx,offset last_byte
  8821.             mov     cl,4
  8822.             shr     bx,cl
  8823.             add     bx,17
  8824.             mov     ah,4AH
  8825.             int     21H
  8826.             mov     ax,bx
  8827.             shl     ax,cl
  8828.             dec     ax
  8829.             mov     sp,ax
  8830.             mov     bp,sp
  8831.             endm
  8832.  
  8833.  
  8834.  Example:
  8835.  
  8836.  The following program invokes a second copy of command.com and executes a
  8837.  dir (directory) command.
  8838.  
  8839.  pgm_file  db      "command.com",0
  8840.  cmd_line  db       9,"/c dir /w",0DH
  8841.  parm_blk  db       14 dup (?)
  8842.  reg_save  db       10 dup (?)
  8843.  ;
  8844.  begin: set_block  last_inst                     ;THIS FUNCTION
  8845.         exec       pgm_file,cmd_line,parm_blk,0  ;See Function 4BH
  8846.  
  8847.  
  8848.  Load and Execute Program (Function 4BH, Code 00H)
  8849.  
  8850.  
  8851.  Call:
  8852.  
  8853.  AH = 4BH
  8854.  AL = 00H
  8855.  DS:DX
  8856.     Pointer to pathname
  8857.  ES:BX
  8858.     Pointer to parameter block
  8859.  
  8860.  
  8861.  Return:
  8862.  
  8863.  Carry set:
  8864.  AX
  8865.     1      = Invalid function
  8866.     2      = File not found
  8867.     3      = Path not found
  8868.     4      = Too many open files
  8869.     5      = Access denied
  8870.     8      = Insufficient memory
  8871.    10      = Bad environment
  8872.    11      = Bad format
  8873.  Carry not set:
  8874.    No error
  8875.  
  8876.  
  8877.  Comments:
  8878.  
  8879.  Function 4BH, Code 00H, loads and executes a program. DX must contain the
  8880.  offset (from the segment address in DS) of an ASCIZ string that specifies
  8881.  the drive and pathname of an executable program file. BX must contain the
  8882.  offset (from the segment address in ES) of a parameter block. AL must
  8883.  contain 0.
  8884.  
  8885.  There must be enough free memory for MS-DOS to load the program file.
  8886.  MS-DOS allocates all available memory to a program when it loads it, so
  8887.  you must free some memory with Function 4AH (Set Block) before using this
  8888.  function request to load and execute another program. Unless you or MS-DOS
  8889.  needs the memory for some other purpose, you should shrink the memory to
  8890.  the minimum amount required by the current process before issuing
  8891.  this request.
  8892.  
  8893.  MS-DOS creates a Program Segment Prefix for the program being loaded
  8894.  and sets the terminate and CONTROL-C addresses to the instruction that
  8895.  immediately follows the call to Function 4BH in the invoking program.
  8896.  
  8897.  The parameter block consists of four addresses:
  8898.  
  8899.  
  8900.       Table 1.24
  8901.       Contents of the Parameter Block
  8902. ╓┌─────────────┌───────────┌─────────────────────────────────────────────────╖
  8903.       Offset   Length
  8904.       (Hex)    (Bytes)     Description
  8905.       ──────────────────────────────────────────────────────────────────────
  8906.       Offset   Length
  8907.       (Hex)    (Bytes)     Description
  8908.       ──────────────────────────────────────────────────────────────────────
  8909.       00       2 (word)    Segment address of the environment
  8910.                            to be passed; 00H means copy the
  8911.                            parent program's environment.
  8912.  
  8913.       02       4 (dword)   Segment: Offset of command line to
  8914.                            be placed at offset 80H of the new
  8915.                            Program Segment Prefix. Must be a
  8916.                            correctly-formed command line no
  8917.                            longer than 128 bytes.
  8918.  
  8919.       06       4 (dword)   Segment: Offset of FCB to be placed
  8920.                            at offset 5CH of the new Program
  8921.                            Segment Prefix (the Program Segment
  8922.                            Prefix is described in Chapter 4
  8923.                            "MS-DOS Control Blocks and Work Areas")
  8924.  
  8925.       0A       4 (dword)   Segment: Offset of FCB to be placed
  8926.                            at offset 6CH of the new Program
  8927.       Offset   Length
  8928.       (Hex)    (Bytes)     Description
  8929.                           at offset 6CH of the new Program
  8930.                            Segment Prefix
  8931.  
  8932.  
  8933.  All open files of a program are available to the newly loaded program,
  8934.  giving the parent program control over the definition of standard input,
  8935.  output, auxiliary, and printer devices. For example, a program could write
  8936.  a series of records to a file, open the file as standard input, open a
  8937.  second file as standard output, and then use Function 4BH, Code 00H (Load
  8938.  and Execute Program) to load and execute a program that takes its input
  8939.  from standard input, sorts records, and writes to standard output.
  8940.  
  8941.  The loaded program also receives an environment, a series of ASCIZ
  8942.  strings of the form parameter=value (for example, verify = on). The
  8943.  environment must begin on a paragraph boundary, be less than 32K bytes
  8944.  long, and end with a byte of 00H (that is, the final entry consists of an
  8945.  ASCIZ string followed by two bytes of 00H). Following the last byte of
  8946.  zeros is a set of initial arguments passed to a program containing a word
  8947.  count followed by an ASCIZ string. If the call finds the file in the
  8948.  current directory, the ASCIZ string contains the drive and pathname of the
  8949.  executable program as passed to Function 4BH. If the call finds the file
  8950.  in the path, it concatenates the filename with the path information. (A
  8951.  program may use this area to determine whence it was loaded.) If the word-
  8952.  environment address is 0, the loaded program either inherits a copy of the
  8953.  parent program's environment or receives a new environment built for it
  8954.  by the parent.
  8955.  
  8956.  Place the segment address of the environment at offset 2CH of the new
  8957.  Program Segment Prefix. To build an environment for the loaded program, put
  8958.  it on a paragraph boundary and place the segment address of the environment
  8959.  in the first word of the parameter block. To pass a copy of the parent's
  8960.  environment to the loaded program, put 00H in the first word of the
  8961.  parameter block.
  8962.  
  8963.  If there is an error, the carry flag (CF) is set and the error code
  8964.  returns in AX:
  8965.  
  8966.  Code   Meaning
  8967.  ───────────────────────────────────────────────────────────────────────────
  8968.  1      AL not 0 or 3
  8969.  
  8970.  2      Program file not found
  8971.  
  8972.  3      Path invalid or not found
  8973.  
  8974.  4      Too many open files (no handle available)
  8975.  
  8976.  5      Directory full, a directory with the same name exists,
  8977.         or a file with the same name exists
  8978.  
  8979.  8      Not enough memory to load the program
  8980.  
  8981.  10     Environment appears longer than 32K
  8982.  
  8983.  11     Program file is an .exe file that contains internally
  8984.         inconsistent information
  8985.  
  8986.  
  8987.  Executing Another Copy of Command.com
  8988.  
  8989.  Since command.com builds pathnames, searches command paths for program
  8990.  files, and relocates .exe files, the simplest way to load and execute
  8991.  another program is to load and execute an additional copy of command.com,
  8992.  passing it a command line that includes the /c switch, which invokes the
  8993.  .com or .exe file.
  8994.  
  8995.  This action requires 17K bytes of available memory, so a program that
  8996.  does it should be sure to shrink its initial memory-allocation block with
  8997.  Function 4AH (Set Block). The format of a command line that contains the
  8998.  /c switch:
  8999.  
  9000.  length,/c command,0DH
  9001.  
  9002.  Length is the length of the command line, counting the length byte but
  9003.  not the ending carriage-return (0DH).
  9004.  
  9005.  Command is any valid MS-DOS command.
  9006.  
  9007.  0DH is a carriage-return character.
  9008.  
  9009.  If a program executes another program directly--naming it as the program
  9010.  file to Function 4BH instead of command.com--it must perform all the
  9011.  processing normally done by command.com.
  9012.  
  9013.  
  9014.  Macro Definition:
  9015.  
  9016.  exec  macro  path,command,parms
  9017.        mov    dx,offset path
  9018.        mov    bx,offset parms
  9019.        mov    word ptr parms[02H],offset command
  9020.        mov    word ptr parms[04H],cs
  9021.        mov    word ptr parms[06H],5CH
  9022.        mov    word ptr parms[08H],es
  9023.        mov    word ptr parms[0AH],6CH
  9024.        mov    word ptr parms[0CH],es
  9025.        mov    al,0
  9026.        mov    ah,4BH
  9027.        int    21H
  9028.        endm
  9029.  
  9030.  
  9031.  Example:
  9032.  
  9033.  The following program invokes a second copy of command.com and executes a
  9034.  dir (directory) command by using the /w (wide) switch:
  9035.  
  9036.  pgm_file  db      "command.com",0
  9037.  cmd_line  db       9,"/c dir /w",0DH
  9038.  parm_blk  db       14 dup (?)
  9039.  reg_save  db       10 dup (?)
  9040.  ;
  9041.  begin:
  9042.     set_block  last_inst                    ;See Function 4AH
  9043.     exec       pgm_file,cmd_line,parm_blk,0 ;THIS FUNCTION
  9044.  
  9045.  
  9046.  Load Overlay (Function 4BH, Code 03H)
  9047.  
  9048.  
  9049.  Call:
  9050.  
  9051.  AH = 4BH
  9052.  AL = 03H
  9053.  DS:DX
  9054.     Pointer to pathname
  9055.  ES:BX
  9056.     Pointer to parameter block
  9057.  
  9058.  
  9059.  Return:
  9060.  
  9061.  Carry set:
  9062.  AX
  9063.     1      = Invalid function
  9064.     2      = File not found
  9065.     3      = Path not found
  9066.     4      = Too many open files
  9067.     5      = Access denied
  9068.     8      = Insufficient memory
  9069.    10      = Bad environment
  9070.  Carry not set:
  9071.    No error
  9072.  
  9073.  
  9074.  Comments:
  9075.  
  9076.  Function 4BH, Code 03H, loads a program segment (overlay). DX must contain
  9077.  the offset (from the segment address in DS) of an ASCIZ string that
  9078.  specifies the drive and pathname of the program file. BX must contain the
  9079.  offset (from the segment address in ES) of a parameter block. AL must
  9080.  contain 3.
  9081.  
  9082.  MS-DOS assumes that since the invoking program is loading into its own
  9083.  address space, it requires no free memory. This call does not create a
  9084.  Program Segment Prefix.
  9085.  
  9086.  The parameter block is four bytes long:
  9087.  
  9088.  
  9089.       Table 1.25
  9090.       Contents of the Parameter Block
  9091. ╓┌─────────────┌──────────┌──────────────────────────────────────────────────╖
  9092.       Offset   Length
  9093.       (Hex)    (Bytes)    Description
  9094.  ───────────────────────────────────────────────────────────────────────────
  9095.       Offset   Length
  9096.       (Hex)    (Bytes)    Description
  9097.  ───────────────────────────────────────────────────────────────────────────
  9098.       00       2 (word)   Segment address where program is to be loaded
  9099.  
  9100.       02       2 (word)   Relocation factor; usually the same as the
  9101.                           first word of the parameter block (for a
  9102.                           description of an .exe file and of
  9103.                           relocation, see Chapter 6, ".Exe File
  9104.                           Structure and Loading.")
  9105.  
  9106.  
  9107.  If there is an error, the carry flag (CF) is set and the error code returns
  9108.  in AX:
  9109.  
  9110.  Code     Meaning
  9111.  ───────────────────────────────────────────────────────────────────────────
  9112.  1        AL not 00H or 03H
  9113.  
  9114.  2        Program file not found
  9115.  
  9116.  3        Path invalid or not found
  9117.  
  9118.  4        Too many open files (no handle available)
  9119.  
  9120.  5        Directory is full, a directory with the same name exists,
  9121.           or a file with the same name exists
  9122.  
  9123.  8        Not enough memory to load the program
  9124.  
  9125.  10       Environment appears longer than 32K
  9126.  
  9127.  
  9128.  Macro Definition:
  9129.  
  9130.  exec_ovl  macro  path,parms,seg_addr
  9131.            mov    dx,offset path
  9132.            mov    bx,offset parms
  9133.            mov    parms,seg_addr
  9134.            mov    parms[02H],seg_addr
  9135.            mov    al,3
  9136.            mov    ah,4BH
  9137.            int    21H
  9138.            endm
  9139.  
  9140.  
  9141.  Example:
  9142.  
  9143.  The following program opens a file named textfile.asc, redirects standard
  9144.  input to that file, loads more.com as an overlay, and calls an overlay
  9145.  named bit.com, which reads textfile.asc as standard input. The overlay
  9146.  must establish its own addressability and end with a FAR return.
  9147.  
  9148.  stdin     equ       0
  9149.  ;
  9150.  file      db    "TEXTFILE.ASC",0
  9151.  cmd_file  db    "\bit.com",0
  9152.  parm_blk  dw     4 dup (?)
  9153.  overlay   label  dword
  9154.            dw     0
  9155.  handle    dw     ?
  9156.  new_mem   dw     ?
  9157.  ;
  9158.  begin:    set_block   last_inst            ;see Function 4AH
  9159.            jc          setblock_error       ;routine not shown
  9160.            allocate_memory  2000            ;see Function 48H
  9161.            jc          allocate_error       ;routine not shown
  9162.            mov         new_mem,ax           ;save seg of memory
  9163.            open_handle file,0               ;see Function 3DH
  9164.            jc          open_error           ;routine not shown
  9165.            mov         handle,ax            ;save handle
  9166.            xdup2       handle,stdin         ;see Function 45H
  9167.            jc          dup2_error           ;routine not shown
  9168.            close_handle handle              ;see Function 3EH
  9169.            jc          close_error          ;routine not shown
  9170.            mov         ax,new_mem           ;addr of new memory
  9171.            exec_ovl cmd_file,parm_blk,ax    ;THIS FUNCTION
  9172.            jc          exec_error           ;routine not shown
  9173.            call        overlay              ;call the overlay
  9174.            free_memory new_mem              ;see Function 49H
  9175.            jc          free_error           ;routine not shown
  9176.  ;
  9177.  
  9178.  
  9179.  End Process (Function 4CH)
  9180.  
  9181.  
  9182.  Call:
  9183.  
  9184.  AH = 4CH
  9185.  AL
  9186.     Return code
  9187.  
  9188.  
  9189.  Return:
  9190.  
  9191.  None
  9192.  
  9193.  
  9194.  Comments:
  9195.  
  9196.  Function 4CH terminates a process and returns to MS-DOS. AL contains a
  9197.  return code that can be retrieved by the parent process with Function 4DH
  9198.  (Get Return Code of Child Process) or the if command, using errorlevel.
  9199.  
  9200.  MS-DOS closes all open handles, ends the current process, and returns
  9201.  control to the invoking process.
  9202.  
  9203.  This function request doesn't require CS to contain the segment address
  9204.  of the Program Segment Prefix. You should use it to end a program (rather
  9205.  than Interrupt 20H or a jump to location 0) unless your program must be
  9206.  compatible with MS-DOS versions before 2.0.
  9207.  
  9208.  ───────────────────────────────────────────────────────────────────────────
  9209.  Note
  9210.    If you use file sharing, you must remove all locks issued by this
  9211.    process or the DOS will be in an uncertain state.
  9212.  ───────────────────────────────────────────────────────────────────────────
  9213.  
  9214.  
  9215.  Macro Definition:
  9216.  
  9217.  end_process  macro  return_code
  9218.               mov    al,return_code
  9219.               mov    ah,4CH
  9220.               int    21H
  9221.               endm
  9222.  
  9223.  
  9224.  Example:
  9225.  
  9226.  The following program displays a message and returns to MS-DOS with a
  9227.  return code of 8. It uses only the opening portion of the sample program
  9228.  skeleton shown at the beginning of this chapter.
  9229.  
  9230.  message   db     "Displayed by FUNC_4CH example",0DH,0AH,"$"
  9231.  ;
  9232.  begin:    display      message   ;See Function 09H
  9233.            end_process  8         ;THIS FUNCTION
  9234.  code      ends
  9235.            end          code
  9236.  
  9237.  
  9238.  Get Return Code of Child Process (Function 4DH)
  9239.  
  9240.  
  9241.  Call:
  9242.  
  9243.  AH = 4DH
  9244.  
  9245.  
  9246.  Return:
  9247.  
  9248.  AX
  9249.     Return code
  9250.  
  9251.  
  9252.  Comments:
  9253.  
  9254.  Function 4DH retrieves the return code specified when a child process
  9255.  terminates via either Function 31H (Keep Process) or Function 4CH (End
  9256.  Process). The code returns in AL. AH returns a code that specifies why
  9257.  the program ended:
  9258.  
  9259.  Code     Meaning
  9260.  ───────────────────────────────────────────────────────────────────────────
  9261.  0        Normal termination
  9262.  1        Terminated by CONTROL-C
  9263.  2        Critical device error
  9264.  3        Function 31H (Keep Process)
  9265.  
  9266.  This call can retrieve the exit code only once.
  9267.  
  9268.  
  9269.  Macro Definition:
  9270.  
  9271.  ret_code  macro
  9272.            mov    ah,4DH
  9273.            int    21H
  9274.            endm
  9275.  
  9276.  
  9277.  Example:
  9278.  
  9279.  No example is included for this function request, because the meaning of
  9280.  a return code varies.
  9281.  
  9282.  
  9283.  Find First File (Function 4EH)
  9284.  
  9285.  
  9286.  Call:
  9287.  
  9288.  AH = 4EH
  9289.  DS:DX
  9290.     Pointer to pathname
  9291.  CX
  9292.     Attributes to match
  9293.  
  9294.  
  9295.  Return:
  9296.  
  9297.  Carry set:
  9298.  AX
  9299.     2      = File not found
  9300.     3      = Path not found
  9301.    18      = No more files
  9302.  Carry not set:
  9303.     No error
  9304.  
  9305.  
  9306.  Comments:
  9307.  
  9308.  Function 4EH searches the current or specified directory for the first
  9309.  entry that matches the specified pathname. DX must contain the offset (from
  9310.  the segment address in DS) of an ASCIZ string that specifies the pathname,
  9311.  which can contain wildcard characters. CX must contain the attribute to
  9312.  be used in searching for the file, as described in Section 1.5.5, "File
  9313.  Attributes."
  9314.  
  9315.  If the attribute field is hidden file, system file, or subdirectory
  9316.  entry (02H, 04H, or 10H), or any combination of these values, all normal
  9317.  file entries are also searched. To search all directory entries except
  9318.  the volume label, set the attribute byte to 16H (hidden file, system file,
  9319.  and directory entry).
  9320.  
  9321.  If this function finds a directory entry that matches the name and
  9322.  attribute, it fills the current DTA as follows:
  9323.  
  9324.  
  9325.       Table 1.26
  9326. ╓┌─────────────┌────────┌────────────────────────────────────────────────────╖
  9327.       Offset   Length   Description
  9328.       ──────────────────────────────────────────────────────────────────────
  9329.       00H      21       Reserved for subsequent Function 4FH (Find
  9330.                         Next File)
  9331.  
  9332.       15H      1        Attribute found
  9333.  
  9334.       16H      2        Time file was last written
  9335.  
  9336.       18H      2        Date file was last written
  9337.  
  9338.       1AH      2        Low word of file size
  9339.  
  9340.       1CH      2        High word of file size
  9341.  
  9342.       1EH      13       Name and extension of the file, followed by 00H.
  9343.                         All blanks are removed; if there is an extension,
  9344.                         it is preceded by a period. (Volume labels include
  9345.                         a period after the eighth character.)
  9346.  
  9347.  
  9348.  If there is an error, the carry flag (CF) is set and the error code returns
  9349.  in AX:
  9350.  
  9351.  Code     Meaning
  9352.  ───────────────────────────────────────────────────────────────────────────
  9353.  2        Specified file invalid or doesn't exist
  9354.  3        Specified path invalid or doesn't exist
  9355.  18       No matching directory entry found
  9356.  
  9357.  
  9358.  Macro Definition:
  9359.  
  9360.  find_first_file  macro  path,attrib
  9361.                   mov    dx,offset path
  9362.                   mov    cx,attrib
  9363.                   mov    ah,4EH
  9364.                   int    21H
  9365.                   endm
  9366.  
  9367.  
  9368.  Example:
  9369.  
  9370.  The following program displays a message that specifies whether a file
  9371.  named report.asm exists in the current directory on the disk in drive B.
  9372.  
  9373.  yes        db      "File exists.",0DH,0AH,"$"
  9374.  no         db      "File does not exist.",0DH,0AH,"$"
  9375.  path       db      "b:report.asm",0
  9376.  buffer     db       43 dup (?)
  9377.  ;
  9378.  begin:     set_dta  buffer           ;See Function 1AH
  9379.             find_first_file  path,0   ;THIS FUNCTION
  9380.             jc       error_findfirst  ;Routine not shown
  9381.             cmp      al,12H           ;File found?
  9382.             je       not_there        ;No
  9383.             display  yes              ;See Function 09H
  9384.             jmp      return           ;All done
  9385.  not_there: display  no               ;See Function 09H
  9386.  
  9387.  
  9388.  Find Next File (Function 4FH)
  9389.  
  9390.  
  9391.  Call:
  9392.  
  9393.  AH = 4FH
  9394.  
  9395.  
  9396.  Return:
  9397.  
  9398.  Carry set:
  9399.  AX
  9400.    18 = No more files
  9401.  Carry not set:
  9402.     No error
  9403.  
  9404.  
  9405.  Comments:
  9406.  
  9407.  Function 4FH searches for the next directory entry that matches the name
  9408.  and attributes specified in a previous Function 4EH (Find First File).
  9409.  The current DTA must contain the information filled in by Function 4EH
  9410.  (Find First File).
  9411.  
  9412.  If the function finds a matching entry, it fills the current DTA just
  9413.  as it did for Find First File (see Function 4EH (Find First File)).
  9414.  
  9415.  If there is an error, the carry flag (CF) is set and the error code
  9416.  returns in AX:
  9417.  
  9418.  Code     Meaning
  9419.  ───────────────────────────────────────────────────────────────────────────
  9420.  2        Specified path invalid or doesn't exist
  9421.  18       No matching directory entry found
  9422.  
  9423.  
  9424.  Macro Definition:
  9425.  
  9426.  find_next_file  macro
  9427.                  mov    ah,4FH
  9428.                  int    21H
  9429.                  endm
  9430.  
  9431.  
  9432.  Example:
  9433.  
  9434.  The following program displays the number of files contained in the current
  9435.  directory on the disk in drive B.
  9436.  
  9437.  message     db      "No files",0DH,0AH,"$"
  9438.  files       dw       ?
  9439.  path        db      "b:*.*",0
  9440.  buffer      db       43 dup (?)
  9441.  ;
  9442.  begin:      set_dta  buffer            ;See Function 1AH
  9443.              find_first_file  path,0    ;See Function 4EH
  9444.              jc       error_findfirst   ;Routine not shown
  9445.              cmp      al,12H            ;Directory empty?
  9446.              je       all_done          ;Yes, go home
  9447.              inc      files             ;No, bump file counter
  9448.  search_dir: find_next_file             ;THIS FUNCTION
  9449.              jc       error_findnext    ;Routine not shown
  9450.              cmp      al,12H            ;Any more entries?
  9451.              je       done              ;No, go home
  9452.              inc      files             ;Yes, bump file counter
  9453.              jmp      search_dir        ;And check again
  9454.  done:       convert  files,10,message  ;See end of chapter
  9455.  all_done:   display  message           ;See Function 09H
  9456.  
  9457.  
  9458.  Get Verify State (Function 54H)
  9459.  
  9460.  
  9461.  Call:
  9462.  
  9463.  AH = 54H
  9464.  
  9465.  
  9466.  Return:
  9467.  
  9468.  AL
  9469.     0 = No verify after write
  9470.     1 = Verify after write
  9471.  
  9472.  
  9473.  Comments:
  9474.  
  9475.  Function 54H checks whether MS-DOS verifies write operations to disk files.
  9476.  The status returns in AL: 0 if verify is off, 1 if verify is on.
  9477.  
  9478.  You can set the verify status with Function 2EH (Set/Reset Verify Flag).
  9479.  
  9480.  
  9481.  Macro Definition:
  9482.  
  9483.  get_verify  macro
  9484.              mov    ah,54H
  9485.              int    21H
  9486.              endm
  9487.  
  9488.  
  9489.  Example:
  9490.  
  9491.  The following program displays the verify status:
  9492.  
  9493.  message   db     "Verify ","$"
  9494.  on        db     "on.",0DH,0AH,"$"
  9495.  off       db     "off.",0DH,0AH,"$"
  9496.  ;
  9497.  begin:    display message      ;See Function 09H
  9498.            get_verify           ;THIS FUNCTION
  9499.            cmp     al,0         ;Is flag off?
  9500.            jg      ver_on       ;No, it's on
  9501.            display off          ;See Function 09H
  9502.            jmp     return       ;Go home
  9503.  ver_on:   display on           ;See Function 09H
  9504.  
  9505.  
  9506.  Change Directory Entry (Function 56H)
  9507.  
  9508.  
  9509.  Call:
  9510.  
  9511.  AH = 56H
  9512.  DS:DX
  9513.     Pointer to pathname
  9514.  ES:DI
  9515.     Pointer to second pathname
  9516.  
  9517.  
  9518.  Return:
  9519.  
  9520.  Carry set:
  9521.  AX
  9522.     2      = File not found
  9523.     3      = Path not found
  9524.     5      = Access denied
  9525.    17      = Not same device
  9526.  Carry not set:
  9527.     No error
  9528.  
  9529.  
  9530.  Comments:
  9531.  
  9532.  Function 56H renames a file by changing its directory entry. DX must
  9533.  contain the offset (from the segment address in DS) of an ASCIZ string
  9534.  that contains the pathname of the entry to be changed. DI must contain
  9535.  the offset (from the segment address in ES) of an ASCIZ string that
  9536.  contains a second pathname to which the first is to be changed.
  9537.  
  9538.  If a directory entry for the first pathname exists, it is changed to
  9539.  the second pathname.
  9540.  
  9541.  The directory paths need not be the same; in effect, you can move the
  9542.  file to another directory by renaming it. You cannot use this function
  9543.  request to copy a file to another drive, however; if the second pathname
  9544.  specifies a drive, the first pathname must specify or default to the
  9545.  same drive.
  9546.  
  9547.  You cannot use this function request to rename an open file, a hidden
  9548.  file, a system file, or a subdirectory, because it may corrupt your disk.
  9549.  
  9550.  If there is an error, the carry flag (CF) is set and the error code
  9551.  returns in AX.
  9552.  
  9553.  Code     Meaning
  9554.  ───────────────────────────────────────────────────────────────────────────
  9555.  2        One of files is invalid or not open
  9556.  
  9557.  3        One of paths is invalid or not open
  9558.  
  9559.  5        First pathname specifies a directory, second pathname specifies
  9560.           an existing file; or second directory entry could not be opened
  9561.  
  9562.  17       Both files not on the same drive
  9563.  
  9564.  
  9565.  Macro Definition:
  9566.  
  9567.  rename_file  macro  old_path,new_path
  9568.               mov    dx,offset old_path
  9569.               push   ds
  9570.               pop    es
  9571.               mov    di,offset new_path
  9572.               mov    ah,56H
  9573.               int    21H
  9574.               endm
  9575.  
  9576.  
  9577.  Example:
  9578.  
  9579.  The following program prompts for the name of a file and a new name,
  9580.  then renames the file.
  9581.  
  9582.  prompt1   db     "Filename: $"
  9583.  prompt2   db     "New name: $"
  9584.  old_path  db      15,?,15 dup (?)
  9585.  new_path  db      15,?,15 dup (?)
  9586.  crlf      db      0DH,0AH,"$"
  9587.  ;
  9588.  begin:    display prompt1                      ;See Function 09H
  9589.            get_string  15,old_path              ;See Function 0AH
  9590.            xor     bx,bx                        ;To use BL as index
  9591.            mov     bl,old_path[1]               ;Get string length
  9592.            mov     old_path[bx+2],0             ;Make an ASCIZ string
  9593.            display crlf                         ;See Function 09H
  9594.            display prompt2                      ;See Function 09H
  9595.            get_string  15,new_path              ;See Function 0AH
  9596.            xor     bx,bx                        ;To use BL as index
  9597.            mov     bl,new_path[1]               ;Get string length
  9598.            mov     new_path[bx+2],0             ;Make an ASCIZ string
  9599.            display crlf                         ;See Function 09H
  9600.            rename_file old_path[2],new_path[2]  ;THIS FUNCTION
  9601.            jc      error_rename                 ;Routine not shown
  9602.  
  9603.  
  9604.  Get/Set Date/Time of File(Function 57H)
  9605.  
  9606.  
  9607.  Call:
  9608.  
  9609.  AH = 57H
  9610.  AL = Function code
  9611.     0 = Get date and time
  9612.     1 = Set date and time
  9613.  BX
  9614.     Handle
  9615.  CX (if AL = 1)
  9616.     Time to be set
  9617.  DX (if AL = 1)
  9618.     Date to be set
  9619.  
  9620.  
  9621.  Return:
  9622.  
  9623.  Carry set:
  9624.  AX
  9625.     1 = Invalid function
  9626.     6 = Invalid handle
  9627.  Carry not set:
  9628.  CX (if AL = 0)
  9629.     Time file last written
  9630.  DX (if AL = 0)
  9631.     Date file last written
  9632.  
  9633.  
  9634.  Comments:
  9635.  
  9636.  Function 57H gets or sets the time and date when a file was last written.
  9637.  To get the time and date, AL must contain 0; the time and date return in CX
  9638.  and DX. To set the time and date, AL must contain 1; CX and DX must contain
  9639.  the time and date. BX must contain the file handle. The time and date are
  9640.  in the form described in "Fields of the FCB" in Section 1.9.1.
  9641.  
  9642.  If there is an error, the carry flag (CF) is set and the error code
  9643.  returns in AX:
  9644.  
  9645.  Code     Meaning
  9646.  ───────────────────────────────────────────────────────────────────────────
  9647.  1        AL not 0 or 1
  9648.  6        Handle in BX invalid or not open
  9649.  
  9650.  
  9651.  Macro Definition:
  9652.  
  9653.  get_set_date_time macro  handle,action,time,date
  9654.                    mov    bx,handle
  9655.                    mov    al,action
  9656.                    mov    cx,word ptr time
  9657.                    mov    dx,word ptr date
  9658.                    mov    ah,57H
  9659.                    int    21H
  9660.                    endm
  9661.  
  9662.  
  9663.  Example:
  9664.  
  9665.  The following program gets the date of a file named report.asm in the
  9666.  current directory on the disk in drive B, increments the day, increments
  9667.  the month and/or year, if necessary, and sets the new date of the file.
  9668.  
  9669.  month     db      31,28,31,30,31,30,31,31,30,31,30,31
  9670.  path      db     "b:report.asm",0
  9671.  handle    dw      ?
  9672.  time      db      2 dup (?)
  9673.  date      db      2 dup (?)
  9674.  ;
  9675.  begin:    open_handle  path,0                  ;See Function 3DH
  9676.            mov     handle,ax                    ;Save handle
  9677.            get_set_date_time handle,0,time,date ;THIS FUNCTION
  9678.            jc      error_time                   ;Routine not shown
  9679.            mov     word ptr time,cx             ;Save time
  9680.            mov     word ptr date,dx             ;Save date
  9681.            convert_date  date[-24]              ;See end of chapter
  9682.            inc     dh                           ;Increment day
  9683.            xor     bx,bx                        ;To use BL as index
  9684.            mov     bl,dl                        ;Get month
  9685.            cmp     dh,month[bx-1]               ;Past last day?
  9686.            jle     month_ok                     ;No, go home
  9687.            mov     dh,1                         ;Yes, set day to 1
  9688.            inc     dl                           ;Increment month
  9689.            cmp     dl,12                        ;Is it past December?
  9690.            jle     month_ok                     ;No, go home
  9691.            mov     dl,1                         ;Yes, set month to 1
  9692.            inc     cx                           ;Increment year
  9693.  month_ok: pack_date  date                      ;See end of chapter
  9694.            get_set_date_time handle,1,time,date ;THIS FUNCTION
  9695.            jc      error_time                   ;Routine not shown
  9696.            close_handle  handle                 ;See Function 3EH
  9697.            jc      error_close                  ;Routine not shown
  9698.  
  9699.  
  9700.  Get/Set Allocation Strategy (Function 58H)
  9701.  
  9702.  
  9703.  Call:
  9704.  
  9705.  AH = 58H
  9706.  AL
  9707.     0 = Get strategy
  9708.     1 = Set strategy
  9709.  BX (AL = 1)
  9710.     0 = First fit
  9711.     1 = Best fit
  9712.     2 = Last fit
  9713.  
  9714.  
  9715.  Return:
  9716.  
  9717.  Carry set:
  9718.  AX
  9719.     1 = Invalid function code
  9720.  Carry not set:
  9721.  AX (AL = 0)
  9722.     0 = First fit
  9723.     1 = Best fit
  9724.     2 = Last fit
  9725.  
  9726.  
  9727.  Comments:
  9728.  
  9729.  Function 58H gets or sets the strategy that MS-DOS uses to allocate memory
  9730.  when a process requests it. If AL contains 0, the strategy is returned in
  9731.  AX. If AL contains 1, BX must contain the strategy. The three possible
  9732.  strategies are:
  9733.  
  9734.  
  9735.       Table 1.27
  9736.       Allocation Strategy
  9737. ╓┌────────────┌───────────┌──────────────────────────────────────────────────╖
  9738.       Value   Name        Description
  9739.       ──────────────────────────────────────────────────────────────────────
  9740.       0       First fit   MS-DOS starts searching at the lowest
  9741.                           available block and allocates the
  9742.                           first block it finds (the allocated
  9743.                           memory is the lowest available block).
  9744.                           This is the default strategy.
  9745.  
  9746.       Value   Name        Description
  9747. 
  9748.       1       Best fit    MS-DOS searches each available block
  9749.                           and allocates the smallest available
  9750.                           block that satisfies the request.
  9751.  
  9752.       2       Last fit    MS-DOS starts searching at the
  9753.                           highest available block and allocates
  9754.                           the first block it finds (the
  9755.                           allocated memory is the highest
  9756.                           available block).
  9757.  
  9758.  
  9759.  You can use this function request to control how MS-DOS uses its memory
  9760.  resources.
  9761.  
  9762.  If there is an error, the carry flag (CF) is set and the error code
  9763.  returns in AX:
  9764.  
  9765.  Code     Meaning
  9766.  ───────────────────────────────────────────────────────────────────────────
  9767.  1        AL doesn't contain 0 or 1, or BX doesn't contain 0, 1, or 2.
  9768.  
  9769.  
  9770.  Macro Definition:
  9771.  
  9772.  alloc_strat macro  code,strategy
  9773.              mov    bx,strategy
  9774.              mov    al,code
  9775.              mov    ah,58H
  9776.              int    21H
  9777.              endm
  9778.  
  9779.  
  9780.  Example:
  9781.  
  9782.  The following program displays the memory-allocation strategy in effect,
  9783.  then forces subsequent memory allocations to the top of memory by setting
  9784.  the strategy to last fit (code 2).
  9785.  
  9786.  get       equ       0
  9787.  set       equ       1
  9788.  stdout    equ       1
  9789.  last_fit  equ       2
  9790.  ;
  9791.  first     db       "First fit     ",0DH,0AH
  9792.  best      db       "Best fit      ",0DH,0AH
  9793.  last      db       "Last fit      ",0DH,0AH
  9794.  ;
  9795.  begin:    alloc_strat get               ;THIS FUNCTION
  9796.            jc         alloc_error        ;routine not shown
  9797.            mov        cl,4               ;multiply code by 16
  9798.            shl        ax,cl              ;to calculate offset
  9799.            mov        dx,offset first    ;point to first msg
  9800.            add        dx,ax              ;add to base address
  9801.            mov        bx,stdout          ;handle for write
  9802.            mov        cs,16              ;write 16 bytes
  9803.            mov        ah,40h             ;write handle
  9804.            int        21H                ;system call
  9805.  ;         jc         write_error        ;routine not shown
  9806.            alloc_strat set,last_fit      ;THIS FUNCTION
  9807.  ;         jc         alloc_error        ;routine not shown
  9808.  
  9809.  
  9810.  Get Extended Error (Function 59H)
  9811.  
  9812.  
  9813.  Call:
  9814.  
  9815.  AH = 59H
  9816.  BX = 0
  9817.  
  9818.  
  9819.  Return:
  9820.  
  9821.  AX
  9822.     Extended-error code
  9823.  BH
  9824.     Error class (see text)
  9825.  BL
  9826.     Suggested action (see text)
  9827.  CH
  9828.     Locus (see text)
  9829.  
  9830.  CL, DX, SI, DI, DS, ES destroyed
  9831.  
  9832.  
  9833.  Comments:
  9834.  
  9835.  Function 59H retrieves an extended-error code for the preceding system
  9836.  call. Each release of MS-DOS extends the error codes to cover new
  9837.  capabilities. These new codes are mapped to a simpler set of error codes
  9838.  based on MS-DOS Version 2.0, so that existing programs can continue to
  9839.  operate correctly. Note that this call destroys all registers except CS:IP
  9840.  and SS:SP.
  9841.  
  9842.  A user-written Interrupt 24H (Critical-Error Handler Address) can use
  9843.  Function 59H to get detailed information about the error that caused the
  9844.  interrupt to be issued.
  9845.  
  9846.  The input BX is a version indicator that specifies for what level of
  9847.  error handling the application was written. The current level is 0.
  9848.  
  9849.  The extended-error code consists of four separate codes in AX, BH, BL,
  9850.  and CH that give as much detail as possible about the error and suggest
  9851.  how the issuing program should respond.
  9852.  
  9853.  
  9854.  BH--Error Class
  9855.  
  9856.  BH returns a code that describes the class of error that occurred:
  9857.  
  9858. ╓┌──────┌────────────────────────────────────────────────────────────────────╖
  9859.  Class  Description
  9860.  ───────────────────────────────────────────────────────────────────────────
  9861.  1      Out of a resource, such as storage or channels
  9862.  
  9863.  2      Not an error, but a temporary situation (such as a locked region
  9864.         in a file) that is expected to end
  9865.  
  9866.  3      Authorization problem
  9867.  
  9868.  4      Internal error in system software
  9869.  
  9870.  5      Hardware failure
  9871.  
  9872.  Class  Description
  9873. 
  9874.  6      System software failure not the fault of the active process (could
  9875.         be caused by missing or incorrect configuration files, for example)
  9876.  
  9877.  7      Application program error
  9878.  
  9879.  8      File or item not found
  9880.  
  9881.  9      File or item of invalid format or type, or that is otherwise
  9882.         invalid or unsuitable
  9883.  
  9884.  10     Interlocked file or item
  9885.  
  9886.  11     Wrong disk in drive, bad spot on disk, or other problem
  9887.         with storage medium
  9888.  
  9889.  12     Other error
  9890.  
  9891.  
  9892.  BL--Suggested Action
  9893.  
  9894.  BL returns a code that suggests how the issuing program can respond to
  9895.  the error:
  9896.  
  9897.  Action     Description
  9898.  ───────────────────────────────────────────────────────────────────────────
  9899.  1          Retry, then prompt user
  9900.  
  9901.  2          Retry after a Pause
  9902.  
  9903.  3          If user entered data such as drive letter or filename,
  9904.             prompt for it again
  9905.  
  9906.  4          Terminate with cleanup
  9907.  
  9908.  5          Terminate immediately; system so unhealthy that program should
  9909.             exit as soon as possible without taking time to close files
  9910.             and update indexes
  9911.  
  9912.  6          Error is informational
  9913.  
  9914.  7          Prompt user to perform some action, such as changing disks,
  9915.             then retry operation
  9916.  
  9917.  
  9918.  CH--Locus
  9919.  
  9920.  CH returns a code that provides additional information to help locate the
  9921.  area involved in the failure. This code is particularly useful for hardware
  9922.  failures (BH=5).
  9923.  
  9924.  Locus  Description
  9925.  ───────────────────────────────────────────────────────────────────────────
  9926.  1      Unknown
  9927.  2      Related to random-access block devices, such as a disk drive
  9928.  3      Related to Network
  9929.  4      Related to serial-access character devices, such as a printer
  9930.  5      Related to random-access memory
  9931.  
  9932.  Your programs should handle errors by noting the error return from the
  9933.  original system call and then issuing this system call to get the extended-
  9934.  error code. If the program does not recognize the extended-error code, it
  9935.  should respond to the original error code.
  9936.  
  9937.  This system call is available during Interrupt 24H and may be used to
  9938.  return network-related errors.
  9939.  
  9940.  
  9941.  Macro Definition:
  9942.  
  9943.  get_error  macro
  9944.             mov    ah, 59H
  9945.             int    21H
  9946.             endm
  9947.  
  9948.  
  9949.  Example:
  9950.  
  9951.  Since this function request provides such detailed information, a general
  9952.  example is not practical. User programs can interpret the various codes to
  9953.  determine what sort of messages or prompts should be displayed, what action
  9954.  to take, and whether to terminate the program if recovery from the errors
  9955.  isn't possible.
  9956.  
  9957.  
  9958.  Create Temporary File (Function 5AH)
  9959.  
  9960.  
  9961.  Call:
  9962.  
  9963.  AH = 5AH
  9964.  CX
  9965.     Attribute
  9966.  DS:DX
  9967.     Pointer to pathname, followed by a
  9968.     byte of 0, and then by 13 bytes of memory
  9969.  
  9970.  
  9971.  Return:
  9972.  
  9973.  Carry set:
  9974.  AX
  9975.     2 = File not found
  9976.     3 = Path not found
  9977.     4 = Too many open files
  9978.     5 = Access denied
  9979.  Carry not set:
  9980.  AX
  9981.     Handle
  9982.  
  9983.  
  9984.  Comments:
  9985.  
  9986.  Function 5AH creates a file with a unique name. DX must contain the offset
  9987.  (from the segment address in DS) of an ASCIZ string that specifies a
  9988.  pathname and 13 bytes of memory (to hold the filename). CX must contain
  9989.  the attribute to be assigned to the file, as described in Section 1.5.5,
  9990.  "File Attributes," earlier in this chapter.
  9991.  
  9992.  MS-DOS creates a unique filename and appends it to the pathname pointed
  9993.  to by DS:DX, creates the file and opens it in compatibility mode, then
  9994.  returns the file handle in AX. A program that needs a temporary file should
  9995.  use this function request to avoid name conflicts.
  9996.  
  9997.  When the creating process exits, MS-DOS does not automatically delete
  9998.  a file created with Function 5AH. When you no longer need the file you
  9999.  should delete it.
  10000.  
  10001.  If there is an error, the carry flag (CF) is set and the error code
  10002.  returns in AX:
  10003.  
  10004.  Code     Meaning
  10005.  ───────────────────────────────────────────────────────────────────────────
  10006.  2        File is invalid or doesn't exist
  10007.  3        Directory pointed to by DS:DX is invalid or doesn't exist
  10008.  4        Too many open files (no handle available)
  10009.  5        Access denied
  10010.  
  10011.  
  10012.  Macro Definition:
  10013.  
  10014.  create_temp macro  pathname,attrib
  10015.              mov    cx,attrib
  10016.              mov    dx,offset pathname
  10017.              mov    ah,5AH
  10018.              int    21H
  10019.              endm
  10020.  
  10021.  
  10022.  Example:
  10023.  
  10024.  The following program creates a temporary file in the directory named
  10025.  \wp\docs, copies a file named textfile.asc that is in the current directory
  10026.  into the temporary file, and then closes both files.
  10027.  
  10028.  stdout   equ       1
  10029.  ;
  10030.  file     db       "TEXTFILE.ASC",0
  10031.  path     db       "\WP\DOCS",0
  10032.  temp     db        13 dup (0)
  10033.  open_msg db       " opened.",0DH,0AH
  10034.  crl_msg  db       " created.",0DH,0AH
  10035.  rd_msg   db       " read into buffer.",0DH,0AH
  10036.  wr_msg   db       "Buffer written to "
  10037.  cl_msg   db       "Files closed.",0DH,0AH
  10038.  crlf     db       0DH,0AH
  10039.  handle1  dw        ?
  10040.  handle2  dw        ?
  10041.  buffer   db        512 dup (?)
  10042.  ;
  10043.  begin:   open_handle file,0               ;see Function 3DH
  10044.           jc         open_error            ;routine not shown
  10045.           mov        handle1,ax            ;save handle
  10046.           write_handle stdout,file,12      ;see Function 40H
  10047.           jc         write_error           ;routine not shown
  10048.           write_handle stdout,open_msg,10  ;see Function 40H
  10049.           jc         write_error           ;routine not shown
  10050.           create_temp path,0               ;THIS FUNCTION
  10051.           jc         create_error          ;routine not shown
  10052.           mov        handle2,ax            ;save handle
  10053.           write_handle stdout,path,8       ;see Function 40H
  10054.           jc         write_error           ;routine not shown
  10055.           display_char "
  10056.           write_handle stdout,temp,12      ;see Function 40H
  10057.           jc         write_error           ;routine not shown
  10058.           write_handle stdout,crl_msg,11   ;See Function 40H
  10059.           jc         write_error           ;routine not shown
  10060.           read_handle handle1,buffer,512   ;see Function 3FH
  10061.           jc        read_error             ;routine not shown
  10062.           write_handle stdout,file,12      ;see Function 40H
  10063.           jc        write_error            ;routine not shown
  10064.           write_handle stdout,rd_msg,20    ;see Function 40H
  10065.           jc        write_error            ;routine not shown
  10066.           write_handle handle2,buffer,512  ;see Function 40H
  10067.           jc        write_error            ;routine not shown
  10068.           write_handle stdout,wr_msg,18    ;see Function 40H
  10069.           jc         write_error           ;routine not shown
  10070.           write_handle stdout,temp,12      ;see Function 40H
  10071.           jc         write_error           ;routine not shown
  10072.           write_handle stdout,crlf,2       ;see Function 40H
  10073.           jc        write_error            ;routine not shown
  10074.           close_handle handle1             ;see Function 3EH
  10075.           jc        close_error            ;routine not shown
  10076.           close_handle handle2             ;see Function 3EH
  10077.           jc        close_error            ;routine not shown
  10078.           write_handle stdout,cl_msg,15    ;see Function 40H
  10079.           jc        write_error            ;routine not shown
  10080.  
  10081.  
  10082.  Create New File (Function 5BH)
  10083.  
  10084.  
  10085.  Call:
  10086.  
  10087.  AH = 5BH
  10088.  CX
  10089.     Attribute
  10090.  DS:DX
  10091.     Pointer to pathname
  10092.  
  10093.  
  10094.  Return:
  10095.  
  10096.  Carry set:
  10097.  AX
  10098.      2     = File not found
  10099.      3     = Path not found
  10100.      4     = Too many open files
  10101.      5     = Access denied
  10102.     80     = File already exists
  10103.  Carry not set:
  10104.  AX
  10105.     Handle
  10106.  
  10107.  
  10108.  Comments:
  10109.  
  10110.  Function 5BH creates a new file. DX must contain the offset (from the
  10111.  segment address in DS) of an ASCIZ string that specifies a pathname.
  10112.  CX contains the attribute to be assigned to the file, as described in
  10113.  Section 1.5.5, "File Attributes."
  10114.  
  10115.  If there is no existing file with the same filename, MS-DOS creates
  10116.  the file, opens it in compatibility mode, and returns the file handle
  10117.  in AX.
  10118.  
  10119.  This function request fails if the specified file exists, unlike
  10120.  Function 3CH (Create Handle), which, under the same circumstances,
  10121.  truncates the file to a length of 0. In a multitasking system, the
  10122.  existence of a file is used as a semaphore; you can use this system
  10123.  call as a test-and-set semaphore.
  10124.  
  10125.  If there is an error, the carry flag (CF) is set and the error code
  10126.  returns in AX:
  10127.  
  10128.  Code     Meaning
  10129.  ───────────────────────────────────────────────────────────────────────────
  10130.  2        File is invalid or doesn't exist
  10131.  
  10132.  3        Directory pointed to by DS:DX is invalid or doesn't exist
  10133.  
  10134.  4        No free handles are available in the current process,
  10135.           or internal system tables are full
  10136.  
  10137.  5        Access denied
  10138.  
  10139.  80       File with the same specification pointed to by DS:DX
  10140.           already exists
  10141.  
  10142.  
  10143.  Macro Definition:
  10144.  
  10145.  create_new macro  pathname,attrib
  10146.             mov    cx, attrib
  10147.             mov    dx, offset pathname
  10148.             mov    ah, 5BH
  10149.             int    21H
  10150.             endm
  10151.  
  10152.  
  10153.  Example:
  10154.  
  10155.  The following program attempts to create a new file named report.asm in
  10156.  the current directory. If the file already exists, the program displays an
  10157.  error message and returns to MS-DOS. If the file doesn't exist and there
  10158.  are no other errors, the program saves the handle and continues processing.
  10159.  
  10160.  err_msg  db       "FILE ALREADY EXISTS",0DH,0AH,"$"
  10161.  path     db       "report.asm",0
  10162.  handle   dw        ?
  10163.  ;
  10164.  begin:    create_new path,0             ;THIS FUNCTION
  10165.            jnc        continue           ;further processing
  10166.            cmp        ax,80              ;file already exist?
  10167.            jne        error              ;routine not shown
  10168.            display    err_msg            ;see Function 09H
  10169.            jmp        return             ;return to MS-DOS
  10170.  continue: mov        handle,ax          ;save handle
  10171.  ;
  10172.  ;         (further processing here)
  10173.  
  10174.  
  10175.  Lock (Function 5CH, Code 00H)
  10176.  
  10177.  
  10178.  Call:
  10179.  
  10180.  AH = 5CH
  10181.  AL = 00H
  10182.  BX
  10183.     Handle
  10184.  CX:DX
  10185.     Offset of region to be locked
  10186.  SI:DI
  10187.     Length of region to be locked
  10188.  
  10189.  
  10190.  Return:
  10191.  
  10192.  Carry set:
  10193.  AX
  10194.     1      = Invalid function code
  10195.     6      = Invalid handle
  10196.    33      = Lock violation
  10197.    36      = Sharing buffer exceeded
  10198.  Carry not set:
  10199.     No error
  10200.  
  10201.  
  10202.  Comments:
  10203.  
  10204.  Function 5CH, Code 00H, denies all access (read or write) by any other
  10205.  process to the specified region of the file. BX must contain the handle of
  10206.  the file that contains the region to be locked. CX:DX (a four-byte integer)
  10207.  must contain the offset in the file of the beginning of the region. SI:DI
  10208.  (a four-byte integer) must contain the length of the region.
  10209.  
  10210.  If another process attempts to use (read or write) a locked region,
  10211.  MS-DOS retries three times; if the retries fail, MS-DOS issues Interrupt
  10212.  24H for the requesting process. You can change the number of retries with
  10213.  Function 44H, Code 0BH (IOCtl Retry).
  10214.  
  10215.  The locked region can be anywhere in the file. For instance, locking
  10216.  beyond the end of the file is not an error. A region should be locked for
  10217.  only a brief period, so if it is locked for more than ten seconds you
  10218.  should consider it to be an error.
  10219.  
  10220.  Function 45H (Duplicate File Handle) and Function 46H (Force Duplicate
  10221.  File Handle) duplicate access to any locked region. Passing an open file to
  10222.  a child process with Function 4BH, Code 00H (Load and Execute Program) does
  10223.  not duplicate access to locked regions.
  10224.  
  10225.  ───────────────────────────────────────────────────────────────────────────
  10226.  Warning
  10227.    If a program closes a file that contains a locked region or terminates
  10228.    with an open file that contains a locked region, the result is undefined.
  10229.  ───────────────────────────────────────────────────────────────────────────
  10230.  
  10231.  Programs that might be terminated by Interrupt 23H (CONTROL-C Handler
  10232.  Address) or Interrupt 24H (Critical-Error-Handler Address) should trap
  10233.  these interrupts and unlock any locked regions before exiting.
  10234.  
  10235.  Programs should not rely on being denied access to a locked region.
  10236.  A program can determine the status of a region (locked or unlocked)
  10237.  by attempting to lock the region and examining the error code.
  10238.  
  10239.  If there is an error, the carry flag (CF) is set and the error code is
  10240.  returned in AX:
  10241.  
  10242.  Code     Meaning
  10243.  ───────────────────────────────────────────────────────────────────────────
  10244.  1        File sharing must be loaded to use this function request.
  10245.  
  10246.  6        The handle in BX is not a valid, open handle.
  10247.  
  10248.  33       All or part of the specified region is already locked.
  10249.  
  10250.  36       There is no more room for lock entries in the buffer. Refer to
  10251.           the share command in the MS-DOS User's Reference for information
  10252.           on allocating more lock entries.
  10253.  
  10254.  
  10255.  Macro Definition:
  10256.  
  10257.  lock  macro  handle,start,bytes
  10258.        mov    bx, handle
  10259.        mov    cx, word ptr start
  10260.        mov    dx, word ptr start+2
  10261.        mov    si, word ptr bytes
  10262.        mov    di, word ptr bytes+2
  10263.        mov    al, 0
  10264.        mov    ah, 5CH
  10265.        int    21H
  10266.        endm
  10267.  
  10268.  
  10269.  Example:
  10270.  
  10271.  The following program opens a file named finalrpt in "Deny None" mode and
  10272.  locks two portions of it: the first 128 bytes and bytes 1024 through 5119.
  10273.  After some (unspecified) processing, it unlocks the same portions and
  10274.  closes the file.
  10275.  
  10276.  stdout    equ        1
  10277.  ;
  10278.  start1    dd         0
  10279.  lgth1     dd         128
  10280.  start2    dd         1023
  10281.  lgth2     dd         4096
  10282.  file      db        "FINALRPT",0
  10283.  op_msg    db        " opened.",0DH,0AH
  10284.  11_msg    db        "First 128 bytes locked.",0DH,0AH
  10285.  12_msg    db        "Bytes 1024-5119 locked.",0DH,0AH
  10286.  u1_msg    db        "First 128 bytes unlocked.",0DH,0AH
  10287.  u2_msg    db        "Bytes 1024-5119 unlocked.",0DH,0AH
  10288.  cl_msg    db        " closed.:,0DH,0AH
  10289.  handle    dw         ?
  10290.  ;
  10291.  begin:    open_handle file,01000010b     ;see Function 3DH
  10292.            jc         open_error          ;routine not shown
  10293.            write_handle stdout,file,8     ;see Function 40H
  10294.            jc         write_error         ;routine not shown
  10295.            write_handle stdout,op_msg,10  ;see Function 40H
  10296.            jc         write_error         ;routine not shown
  10297.            mov        handle,ax           ;save handle
  10298.            lock       handle,start1,lgth1 ;THIS FUNCTION
  10299.            jc         lock_error          ;routine not shown
  10300.            write_handle stdout,11_msg,25  ;see Function 40H
  10301.            jc         write_error         ;routine not shown
  10302.            lock       handle,start2,lgth2 ;THIS FUNCTION
  10303.            jc         lock_error          ;routine not shown
  10304.            write_handle stdout,12_msg,25  ;see Function 40H
  10305.            jc         write_error         ;routine not shown
  10306.  ;
  10307.  ; ( Further processing here )
  10308.  ;
  10309.            unlock     handle,start1,lgth1 ;See Function 5C01H
  10310.            jc         unlock_error        ;routine not shown
  10311.            write_handle stdout,ul_msg,27  ;see Function 40H
  10312.            jc         write_error         ;routine not shown
  10313.            unlock     handle,start2,lgth2 ;See Function 5C01H
  10314.            jc         unlock_error        ;routine not shown
  10315.            write_handle stdout,u2_msg,27  ;See Function 40H
  10316.            jc         write_error         ;routine not shown
  10317.            close_handle handle            ;See Function 3EH
  10318.            jc         close_error         ;routine not shown
  10319.            write_handle stdout,file,8     ;see Function 40H
  10320.            jc         write_error         ;routine not shown
  10321.            write_handle stdout,cl_msg,10  ;see Function 40H
  10322.            jc         write_error         ;routine not shown
  10323.  
  10324.  
  10325.  Unlock (Function 5CH, Code 01H)
  10326.  
  10327.  
  10328.  Call:
  10329.  
  10330.  AH = 5CH
  10331.  AL = 01H
  10332.  BX
  10333.     Handle
  10334.  CX:DX
  10335.     Offset of area to be unlocked
  10336.  SI:DI
  10337.     Length of area to be unlocked
  10338.  
  10339.  
  10340.  Return:
  10341.  
  10342.  Carry set:
  10343.  AX
  10344.     1      = Invalid function code
  10345.     6      = Invalid handle
  10346.    33      = Lock violation
  10347.    36      = Sharing buffer exceeded
  10348.  Carry not set:
  10349.     No error
  10350.  
  10351.  
  10352.  Comments:
  10353.  
  10354.  Function 5CH, Code 01H, unlocks a region previously locked by the same
  10355.  process. BX must contain the handle of the file that contains the region
  10356.  to be unlocked. CX:DX (a four-byte integer) must contain the offset in
  10357.  the file of the beginning of the region. SI:DI (a four-byte integer) must
  10358.  contain the length of the region. The offset and length must be exactly
  10359.  the same as the offset and length specified in the previous Function 5CH,
  10360.  Code 00H (Lock).
  10361.  
  10362.  The description of Function 5CH, Code 00H (Lock) describes how to use
  10363.  locked regions.
  10364.  
  10365.  If there is an error, the carry flag (CF) is set and the error code
  10366.  returns in AX:
  10367.  
  10368.  Code     Meaning
  10369.  ───────────────────────────────────────────────────────────────────────────
  10370.  1        File sharing must be loaded to use this function request.
  10371.  
  10372.  6        The handle in BX is not a valid, open handle.
  10373.  
  10374.  33       The region specified is not identical to one that was
  10375.           previously locked by the same process.
  10376.  
  10377.  36       There is no more room for lock entries in the buffer. Refer
  10378.           to the share command in the MS-DOS User's Reference for
  10379.           information on allocating more lock entries.
  10380.  
  10381.  You should issue Function 59H (Get Extended Error) to list the possible
  10382.  errors returned by this function.
  10383.  
  10384.  
  10385.  Macro Definition:
  10386.  
  10387.  unlock  macro  handle,start,bytes
  10388.          mov    bx, handle
  10389.          mov    cx, word ptr start
  10390.          mov    dx, word ptr start+2
  10391.          mov    si, word ptr bytes
  10392.          mov    di, word ptr bytes+2
  10393.          mov    al, 1
  10394.          mov    ah, 5CH
  10395.          int    21H
  10396.          endm
  10397.  
  10398.  
  10399.  Example:
  10400.  
  10401.  The following program opens a file named finalrpt in "Deny None" mode and
  10402.  locks two portions of it: the first 128 bytes and bytes 1024 through 5119.
  10403.  After some (unspecified) processing, it unlocks the same portions and
  10404.  closes the file.
  10405.  
  10406.  stdout    equ        1
  10407.  ;
  10408.  start1    dd         0
  10409.  lgth1     dd         128
  10410.  start2    dd         1023
  10411.  lgth2     dd         4096
  10412.  file      db        "FINALRPT",0
  10413.  op_msg    db        " opened.",0DH,0AH
  10414.  11_msg    db        "First 128 bytes locked.",0DH,0AH
  10415.  12_msg    db        "Bytes 1024-5119 locked.",0DH,0AH
  10416.  u1_msg    db        "First 128 bytes unlocked.",0DH,0AH
  10417.  u2_msg    db        "Bytes 1024-5119 unlocked.",0DH,0AH
  10418.  cl_msg    db        " closed.",0DH,0AH
  10419.  handle    dw         ?
  10420.  ;
  10421.  begin:    open_handle file,01000010b     ;see Function 3DH
  10422.            jc         open_error          ;routine not shown
  10423.            write_handle stdout,file,8     ;see Function 40H
  10424.            jc         write_error         ;routine not shown
  10425.            write_handle stdout,op_msg,10  ;see Function 40H
  10426.            jc         write_error         ;routine not shown
  10427.            mov        handle,ax           ;save handle
  10428.            lock       handle,start1,lgth1 ;See Function 5C00H
  10429.            jc         lock_error          ;routine not shown
  10430.            write_handle stdout,11_msg,25  ;see Function 40H
  10431.            jc         write_error         ;routine not shown
  10432.            lock       handle,start2,lgth2 ;See Function 5C00H
  10433.            jc         lock_error          ;routine not shown
  10434.            write_handle stdout,12_msg,25  ;see Function 40H
  10435.            jc         write_error         ;routine not shown
  10436.  ;
  10437.  ; ( Further processing here )
  10438.  ;
  10439.            unlock     handle,start1,lgth1 ;THIS FUNCTION
  10440.            jc         unlock_error        ;routine not shown
  10441.            write_handle stdout,u1_msg,27  ;see Function 40H
  10442.            jc         write_error         ;routine not shown
  10443.            unlock     handle,start2,lgth2 ;THIS FUNCTION
  10444.            jc         unlock_error        ;routine not shown
  10445.            write_handle stdout,u2_msg,27  ;see Function 40H
  10446.            jc         write_error         ;routine not shown
  10447.            close_handle handle            ;See Function 3EH
  10448.            jc         close_error         ;routine not shown
  10449.            write_handle stdout,file,8     ;see Function 40H
  10450.            jc         write_error         ;routine not shown
  10451.            write_handle stdout,cl_msg,10  ;see Function 40H
  10452.            jc         write_error         ;routine not shown
  10453.  
  10454.  
  10455.  Get Machine Name (Function 5EH, Code 00H)
  10456.  
  10457.  
  10458.  Call:
  10459.  
  10460.  AH = 5EH
  10461.  AL = 0
  10462.  DS:DX
  10463.     Pointer to 16-byte buffer
  10464.  
  10465.  
  10466.  Return:
  10467.  
  10468.  Carry set:
  10469.  AX
  10470.     1 = Invalid function code
  10471.  Carry not set:
  10472.  CX
  10473.     Identification number of local
  10474.     computer
  10475.  
  10476.  
  10477.  Comments:
  10478.  
  10479.  Function 5EH, Code 0, retrieves the net name of the local computer. DX
  10480.  must contain the offset (to the segment address in DS) of a 16-byte buffer.
  10481.  Microsoft Networks must be running.
  10482.  
  10483.  MS-DOS returns the local computer name (a 16-byte ASCIZ string,
  10484.  padded with blanks) in the buffer pointed to by DS:DX. CX returns the
  10485.  identification number of the local computer. If the network was never
  10486.  installed, the CH register returns with zero and the value in the CL
  10487.  register is invalid.
  10488.  
  10489.  If there is an error, the carry flag (CF) is set and the error code
  10490.  returns in AX:
  10491.  
  10492.  Code     Meaning
  10493.  ───────────────────────────────────────────────────────────────────────────
  10494.  1        Microsoft Networks must be running to use this function request.
  10495.  
  10496.  
  10497.  Macro Definition:
  10498.  
  10499.  get_machine_name  macro  buffer
  10500.                    mov    dx,offset buffer
  10501.                    mov    al,0
  10502.                    mov    ah,5EH
  10503.                    int    21H
  10504.                    endm
  10505.  
  10506.  
  10507.  Example:
  10508.  
  10509.  The following program displays the name of a Microsoft Networks work-
  10510.  station.
  10511.  
  10512.  stdout equ 1
  10513.  ;
  10514.  msg        db   "Netname: "
  10515.  mac_name   db   16 dup (?),0DH,0AH
  10516.  ;
  10517.  begin:    get_machine_name  mac_name        ;THIS FUNCTION
  10518.            jc                name_error      ;routine not shown
  10519.            write_handle      stdout,msg,27   ;see Function 40H
  10520.            jc                write_error     ;routine not shown
  10521.  
  10522.  
  10523.  Printer Setup (Function 5EH, Code 02H)
  10524.  
  10525.  
  10526.  Call:
  10527.  
  10528.  AH = 5EH
  10529.  AL = 02H
  10530.  BX
  10531.     Assign-list index
  10532.  CX
  10533.     Length of setup string
  10534.  DS:SI
  10535.     Pointer to setup string
  10536.  
  10537.  
  10538.  Return:
  10539.  
  10540.  Carry set:
  10541.  AX
  10542.     1 = Invalid function code
  10543.  Carry not set:
  10544.     No error
  10545.  
  10546.  
  10547.  Comments:
  10548.  
  10549.  Function 5EH, Code 02H, defines a string of control characters that MS-DOS
  10550.  adds to the beginning of each file sent to the network printer. BX must
  10551.  contain the index into the assign list that identifies the printer (entry 0
  10552.  is the first entry). CX must contain the length of the string. SI must
  10553.  contain the offset (to the segment address in DS) of the string itself.
  10554.  Microsoft Networks must be running.
  10555.  
  10556.  MS-DOS adds the setup string to the beginning of each file sent to the
  10557.  printer, which is specified by the assign-list index in BX. This function
  10558.  request lets each program that shares a printer have its own printer
  10559.  configuration. You can use Function 5F02H (Get Assign-List Entry) to
  10560.  determine which entry in the assign list refers to the printer.
  10561.  
  10562.  If there is an error, the carry flag (CF) is set and the error code
  10563.  returns in AX:
  10564.  
  10565.  Code     Meaning
  10566.  ───────────────────────────────────────────────────────────────────────────
  10567.  1        Microsoft Networks must be running to use this function request.
  10568.  
  10569.  
  10570.  Macro Definition:
  10571.  
  10572.  printer_setup  macro  index,lgth,string
  10573.                 mov    bx, index
  10574.                 mov    cx, lgth
  10575.                 mov    dx, offset string
  10576.                 mov    al, 2
  10577.                 mov    ah, 5EH
  10578.                 int    21H
  10579.                 endm
  10580.  
  10581.  
  10582.  Example:
  10583.  
  10584.  The following program defines a printer-setup string that consists of
  10585.  the control character to print expanded type on Epson-compatible printers.
  10586.  The printer cancels this mode at the first carriage return, so the effect
  10587.  is to print the first line of each file sent to the network printer as a
  10588.  title in expanded characters. The setup string is one character. This
  10589.  example assumes that the printer is the entry number 3 (the fourth entry)
  10590.  in the assign list. Use Function 5F02H (Get Assign-List Entry) to determine
  10591.  this value.
  10592.  
  10593.  setup     db   0EH
  10594.  ;
  10595.  begin:    printer_setup 3,1,setup       ;THIS FUNCTION
  10596.            jc            error           ;routine not shown
  10597.  
  10598.  
  10599.  Get Assign-List Entry (Function 5FH, Code 02H)
  10600.  
  10601.  
  10602.  Call:
  10603.  
  10604.  AH = 5FH
  10605.  AL = 02H
  10606.  BX
  10607.     Assign-list index
  10608.  DS:SI
  10609.     Pointer to buffer for local name
  10610.  ES:DI
  10611.     Pointer to buffer for remote name
  10612.  
  10613.  
  10614.  Return:
  10615.  
  10616.  Carry set:
  10617.  AX
  10618.     1 = Invalid function code
  10619.    18 = No more files
  10620.  Carry not set:
  10621.  BL
  10622.     3 = Printer
  10623.     4 = Drive
  10624.  CX
  10625.     Stored user value
  10626.  
  10627.  
  10628.  Comments:
  10629.  
  10630.  Function 5FH, Code 02H, retrieves the specified entry from the network list
  10631.  of assignments. BX must contain the assign-list index (entry 0 is the first
  10632.  entry). SI must contain the offset (to the segment address in DS) of a 16-
  10633.  byte buffer for the local name. DI must contain the offset (to the segment
  10634.  address in ES) of a 128-byte buffer for the remote name. Microsoft Networks
  10635.  must be running.
  10636.  
  10637.  MS-DOS puts the local name in the buffer pointed to by DS:SI and the
  10638.  remote name in the buffer pointed to by ES:DI. The local name can be a null
  10639.  ASCIZ string. BL returns 3 if the local device is a printer or 4 if the
  10640.  local device is a drive. CX returns the stored user value set with
  10641.  Function 5F03H (Make Assign-List Entry). The contents of the assign list
  10642.  can change between calls.
  10643.  
  10644.  You can use this function request to retrieve any entry, or to make a
  10645.  copy of the complete list by stepping through the table. To detect the end
  10646.  of the assign list, check for error code 18 (no more files), as you would
  10647.  when stepping through a directory by using Functions 4EH (Find First File)
  10648.  and 4FH (Find Next File).
  10649.  
  10650.  If there is an error, the carry flag (CF) is set and the error code
  10651.  returns in AX:
  10652.  
  10653.  Code     Meaning
  10654.  ───────────────────────────────────────────────────────────────────────────
  10655.  1        Microsoft Networks must be running to use this function request.
  10656.  
  10657.  18       The index passed in BX is greater than the number of entries
  10658.           in the assign list.
  10659.  
  10660.  
  10661.  Macro Definition:
  10662.  
  10663.  get_list  macro  index,local,remote
  10664.            mov    bx, index
  10665.            mov    si, offset local
  10666.            mov    di, offset remote
  10667.            mov    al,2
  10668.            mov    ah, 5FH
  10669.            int    21H
  10670.            endm
  10671.  
  10672.  
  10673.  Example:
  10674.  
  10675.  The following program displays the assign list on a Microsoft Networks
  10676.  workstation, showing the local name, remote name, and device type (drive
  10677.  or printer) for each entry.
  10678.  
  10679.  stdout    equ        1
  10680.  printer   equ        3
  10681.  ;
  10682.  local_nm  db         16 dup (?),2 dup (20h)
  10683.  remote_nm db         128 dup (?),2 dup (20h)
  10684.  header    db        "Local name",8 dup (20h)
  10685.            db        "Remote name",7 dup (20h)
  10686.            db        "Device Type"
  10687.  crlf      db         0dh,0ah,0dh,0ah
  10688.  drive_msg db        "drive"
  10689.  print_msg db        "printer"
  10690.  index     dw         ?
  10691.  ;
  10692.  begin:    write_handle stdout,header,51       ;see Function 40H
  10693.            jc         write_error              ;routine not shown
  10694.            mov        index,0                  ;assign list index
  10695.  ck_list:  get_list   index,local_nm,remote_nm ;THIS FUNCTION
  10696.            jnc        got_one                  ;got an entry
  10697.  error:    cmp        ax,18
  10698.            je         last_one                 ;yes
  10699.            jmp        error                    ;routine not shown
  10700.  got_one:  push       bx                       ;save device type
  10701.            write_handle  stdout,local_nm,148   ;see Function 40H
  10702.            jc         write_error              ;routine not shown
  10703.            pop        bx                       ;get device type
  10704.            cmp        bl,printer               ;is it a printer?
  10705.            je         prntr                    ;yes
  10706.            write_handle stdout,drive_msg,5     ;see Function 40H
  10707.            jc         write_error              ;routine not shown
  10708.            jmp        get_next                 ;finish message
  10709.  prntr:    write_handle stdout,print_msg,7     ;see Function 40H
  10710.            jc         write_error              ;routine not shown
  10711.  get_next: write_handle stdout,crlf,2          ;see Function 40H
  10712.            jc         write_error              ;routine not shown
  10713.            inc        index                    ;bump index
  10714.            jmp        ck_list                  ;get next entry
  10715.  last_one: write_handle stdout,crlf,4          ;see Function 40H
  10716.            jc         write_error              ;routine not shown
  10717.  ;
  10718.  
  10719.  
  10720.  Make Assign-List Entry (Function 5FH, Code 03H)
  10721.  
  10722.  
  10723.  Call:
  10724.  
  10725.  AH = 5FH
  10726.  AL = 03H
  10727.  BL
  10728.     3 = Printer
  10729.     4 = Drive
  10730.  CX
  10731.     User value
  10732.  DS:SI
  10733.     Pointer to name of source device
  10734.  ES:DI
  10735.     Pointer to name of destination
  10736.     device
  10737.  
  10738.  
  10739.  Return:
  10740.  
  10741.  Carry set:
  10742.  AX
  10743.     1 = Invalid function code
  10744.     5 = Access denied
  10745.     3 = Path not found
  10746.     8 = Insufficient memory
  10747.     (Other errors particular to the
  10748.     network may occur.)
  10749.  Carry not set:
  10750.     No error
  10751.  
  10752.  
  10753.  Comments:
  10754.  
  10755.  Function 5FH, Code 03H, redirects a printer or disk drive (source device)
  10756.  to a network directory (destination device). BL must contain 3 if the
  10757.  source device is a printer or 4 if it is a disk drive. SI must contain
  10758.  the offset (to the segment address in DS) of an ASCIZ string that specifies
  10759.  the name of the printer, or a drive letter followed by a colon, or a null
  10760.  string (one byte of 00H). DI must contain the offset (to the segment
  10761.  address in ES) of an ASCIZ string that specifies the name of a network
  10762.  directory. CX contains a user-specified 16-bit value that MS-DOS maintains.
  10763.  Microsoft Networks must be running.
  10764.  
  10765.  The destination string must be an ASCIZ string of the following form:
  10766.  
  10767.  machine-name pathname 00H password 00H
  10768.  
  10769.  where:
  10770.  
  10771.  Machine-name is the net name of the server that contains the network
  10772.  directory;
  10773.  
  10774.  Pathname is the alias of the network directory (not the directory
  10775.  path) to which the source device is to be redirected;
  10776.  
  10777.  00H is a null byte; and
  10778.  
  10779.  Password is the password for access to the network directory. If no
  10780.  password is specified, both null bytes must immediately follow the
  10781.  pathname.
  10782.  
  10783.  If BL=3, the source string must be PRN, LPT1, LPT2, or LPT3. This
  10784.  function buffers and sends all output for the named printer to the remote-
  10785.  printer spooler named in the destination string.
  10786.  
  10787.  If BL=4, the source string can be either a drive letter followed by a
  10788.  colon, or a null string. If the source string contains a valid drive letter
  10789.  and colon, this call redirects all subsequent drive-letter references to
  10790.  the network directory named in the destination string. If the source string
  10791.  is a null string, MS-DOS attempts to grant access to the network directory
  10792.  with the specified password.
  10793.  
  10794.  The maximum length of the destination string is 128 bytes. You can
  10795.  retrieve the value in CX by using Function 5FH, Code 02H (Get Assign-List
  10796.  Entry).
  10797.  
  10798.  If there is an error, the carry flag (CF) is set and the error code
  10799.  returns in AX:
  10800.  
  10801.  Code     Meaning
  10802.  ───────────────────────────────────────────────────────────────────────────
  10803.  1        Microsoft Networks must be running to use this function request;
  10804.           the value in BX is not 1 to 4, the source string is in the wrong
  10805.           format; the destination string is in the wrong format; or the
  10806.           source device is already redirected.
  10807.  
  10808.  3        The network directory path is invalid or doesn't exist.
  10809.  
  10810.  5        The network directory/password combination is not valid. This
  10811.           does not mean that the password itself was invalid; the directory
  10812.           might not exist on the server.
  10813.  
  10814.  8        There is not enough memory for string substitutions.
  10815.  
  10816.  
  10817.  Macro Definition:
  10818.  
  10819.  redir macro  device,value,source,destination
  10820.        mov    bl, device
  10821.        mov    cx, value
  10822.        mov    si, offset source
  10823.        mov    es, seg destination
  10824.        mov    di, offset destination
  10825.        mov    al, 03H
  10826.        mov    ah, 5FH
  10827.        int    21H
  10828.        endm
  10829.  
  10830.  
  10831.  Example:
  10832.  
  10833.  The following program redirects two drives and a printer from a workstation
  10834.  to a server named harold. It assumes the machine name, directory names,
  10835.  and driver letters shown:
  10836.  
  10837.  Local drive     Netname
  10838.  or printer      on server    Password
  10839.  E:              WORD         none
  10840.  F:              COMM         fred
  10841.  PRN:            PRINTER      quick
  10842.  
  10843.  printer   equ  3
  10844.  drive     equ  4
  10845.  ;
  10846.  local_1   db  "e:",0
  10847.  local_2   db  "f:",0
  10848.  local_3   db  "prn",0
  10849.  remote_1  db  "\harold\word",0,0
  10850.  remote_2  db  "\harold\comm",0,"fred",0
  10851.  remote_3  db  "\harold\printer",0,"quick",0
  10852.  ;
  10853.  begin:    redir  local_1,remote_1,drive,0     ;THIS FUNCTION
  10854.            jc     error                        ;routine not shown
  10855.            redir  local_2,remote_2,drive,0     ;THIS FUNCTION
  10856.            jc     error                        ;routine not shown
  10857.            redir  local_3,remote_3,printer,0   ;THIS FUNCTION
  10858.            jc     error                        ;routine not shown
  10859.  
  10860.  
  10861.  Cancel Assign-List Entry (Function 5FH, Code 04H)
  10862.  
  10863.  
  10864.  Call:
  10865.  
  10866.  AH = 5FH
  10867.  AL = 04H
  10868.  DS:SI
  10869.     Pointer to name of source device
  10870.  
  10871.  
  10872.  Return:
  10873.  
  10874.  Carry set:
  10875.  AX
  10876.     1      = Invalid function code
  10877.    15      = Redirection paused on server
  10878.    (Other errors particular to the network
  10879.    may occur.)
  10880.  Carry not set:
  10881.     No error
  10882.  
  10883.  
  10884.  Comments:
  10885.  
  10886.  Function 5FH, Code 04H, cancels the redirection of a printer or disk drive
  10887.  (source device) to a network directory (destination device) made with
  10888.  Function 5FH, Code 03H (Make Assign-List Entry). SI must contain the offset
  10889.  (to the segment address in DS) of an ASCIZ string that specifies the name
  10890.  of the printer or drive whose redirection is to be canceled. Microsoft
  10891.  Networks must be running.
  10892.  
  10893.  The ASCIZ string pointed to by DS:SI can contain one of three values:
  10894.  
  10895.      ■ The letter of a redirected drive, followed by a colon. Cancels the
  10896.        redirection and restores the drive to its physical meaning.
  10897.  
  10898.      ■ The name of a redirected printer (PRN, LPT1, LPT2, LPT3, or their
  10899.        machine-specific equivalents). Cancels the redirection and restores
  10900.        the printer name to its physical meaning.
  10901.  
  10902.      ■ A string starting with \\ (2 backslashes). Terminates the connection
  10903.        between the local machine and the network directory.
  10904.  
  10905.  If there is an error, the carry flag (CF) is set and the error code
  10906.  returns in AX:
  10907.  
  10908.  Code     Meaning
  10909.  ───────────────────────────────────────────────────────────────────────────
  10910.  1        Microsoft Networks must be running to use this function request;
  10911.           or the ASCIZ string names a nonexistent source device.
  10912.  
  10913.  15       Disk or printer redirection on the network server is paused.
  10914.  
  10915.  
  10916.  Macro Definition:
  10917.  
  10918.  cancel_redir  macro  local
  10919.                mov    si, offset local
  10920.                mov    al, 4
  10921.                mov    ah, 5FH
  10922.                int    21H
  10923.                endm
  10924.  
  10925.  
  10926.  Example:
  10927.  
  10928.  The following program cancels the redirection of drives E and F and the
  10929.  printer (PRN) of a Microsoft Networks workstation. It assumes that these
  10930.  local devices were redirected previously.
  10931.  
  10932.  local_1   db        "e:",0
  10933.  local_2   db        "f:",0
  10934.  local_3   db        "prn",0
  10935.  ;
  10936.  begin:    cancel_redir  local_1    ;THIS FUNCTION
  10937.            jc            error      ;routine not shown
  10938.            cancel_redir  local_2    ;THIS FUNCTION
  10939.            jc            error      ;routine not shown
  10940.            cancel_redir  local_3    ;THIS FUNCTION
  10941.            jc            error      ;routine not shown
  10942.  
  10943.  
  10944.  Get PSP (Function 62H)
  10945.  
  10946.  
  10947.  Call:
  10948.  
  10949.  AH = 62H
  10950.  
  10951.  
  10952.  Return:
  10953.  
  10954.  BX
  10955.     Segment address of the Program
  10956.     Segment Prefix of the current process
  10957.  
  10958.  
  10959.  Comments:
  10960.  
  10961.  Function 62H retrieves the segment address of the currently active process
  10962.  (the start of the Program Segment Prefix). The address returns in BX.
  10963.  
  10964.  
  10965.  Macro Definition:
  10966.  
  10967.  get_psp macro
  10968.          mov    ah, 62H
  10969.          int    21H
  10970.          endm
  10971.  
  10972.  
  10973.  Example:
  10974.  
  10975.  The following program displays the segment address of its Program Segment
  10976.  Prefix (PSP) in hexadecimal.
  10977.  
  10978.  msg       db       "PSP segment address:  H",0DH,0AH,"$"
  10979.  ;
  10980.  begin:    get_psp                       ;THIS FUNCTION
  10981.            convert   bx,16,msg[21]       ;see end of chapter
  10982.            display   msg                 ;see Function 09H
  10983.  
  10984.  
  10985.  Get Extended Country Information (Function 65H)
  10986.  
  10987.  
  10988.  Call:
  10989.  
  10990.  AH = 65H
  10991.  AL
  10992.    Function (minor) code
  10993.  BX
  10994.    Code page (-1 = active CON device)
  10995.  CX
  10996.    Amount of data to return
  10997.  DX
  10998.    Country ID for which information is to be returned
  10999.    (-1=default country)
  11000.  ES:DI
  11001.    Address of country information buffer
  11002.  
  11003.  
  11004.  Return:
  11005.  
  11006.  1 = Buffer has been filled
  11007.  2 = File not found
  11008.  
  11009.  
  11010.  Comments:
  11011.  
  11012.  Function 65H retrieves standard country information. This information
  11013.  includes country ID, code page, date and time format, currency symbol,
  11014.  separators (for thousands, decimals, data list, date and time) currency
  11015.  format flags, digits in currency, and case-mapping information.
  11016.  
  11017.  The function code passed in AL may be one of the following:
  11018.  
  11019.  Code   Description
  11020.  ───────────────────────────────────────────────────────────────────────────
  11021.  1      Return standard information
  11022.  2      Return pointer to uppercase table
  11023.  3      Return pointer to filename uppercase table
  11024.  4      Return pointer to collating table
  11025.  5      Reserved (no entry)
  11026.  6      Return pointer to collating sequence
  11027.  
  11028.  MS-DOS 3.3 provides more country-dependent information than previous
  11029.  versions of MS-DOS.  Only the information for the default country is kept
  11030.  in the kernel.  Country-dependent information for all other countries is
  11031.  contained in the country.sys file.  The MS-DOS nlsfunc command is used to
  11032.  access the country-dependent information in country.sys using this call.
  11033.  If the country code and code page number do not match, or if either is
  11034.  invalid, error code 2 is returned to AX.  If CX is less than 5, error code
  11035.  1 is returned.  If the amount of information requested is greater than the
  11036.  value of CX, only CX bytes are returned and no error is reported.
  11037.  
  11038.  If AL = 1, the buffer is filled with the following information:
  11039.  
  11040.  db    1    ;  Information ID
  11041.  dw    ?    ;  Size (<=38)
  11042.  dw    ?    ;  Country ID
  11043.  dw    ?    ;  Code page
  11044.  
  11045.  If AL = 2, the buffer is filled with the following information:
  11046.  db    2    ;  Information ID
  11047.  dd    ?    ;  Double-word pointer to uppercase table
  11048.  
  11049.  If AL = 4, the buffer is filled with the following information:
  11050.  
  11051.  db    4    ;  Information ID
  11052.  dd    ?    ;  Double-word pointer to filename uppercase table
  11053.  
  11054.  Both of these tables consist of a length field (two bytes) followed by 128
  11055.  uppercase values for the upper 128 ASCII characters. The following formula
  11056.  is used to compute the address of an uppercase equivalent in the table:
  11057.  
  11058.  Address of outchar = inchar - (256-table_len) = table_start
  11059.  
  11060.  where:
  11061.  
  11062.  Parameter     Meaning
  11063.  ───────────────────────────────────────────────────────────────────────────
  11064.  inchar        Character to be generated
  11065.  table_len     Length of list of uppercase values (two bytes)
  11066.  table_start   Starting address of uppercase table
  11067.  outchar       Uppercase value for inchar
  11068.  
  11069.  If inchar is greater than or equal to (256 - table_len), there is an
  11070.  uppercase equivalent in the table; otherwise, there is not.
  11071.  
  11072.  If AL = 6, the buffer is filled with the following information:
  11073.  
  11074.  db    6    ;  Information ID
  11075.  dd    ?    ;  Double-word pointer to collating sequence
  11076.  
  11077.  The table is 258 bytes long. The first word is the length of the table.
  11078.  The rest of the table is 256 ASCII values in the appropriate order.
  11079.  
  11080.  
  11081.  Get/Set Global Code Page (Function 66H)
  11082.  
  11083.  
  11084.  Call:
  11085.  
  11086.  AH = 66H
  11087.  AL
  11088.    Function (minor) code
  11089.  BX
  11090.    Code page to set (AL = 2)
  11091.  
  11092.  
  11093.  Return:
  11094.  
  11095.  Carry set:
  11096.  AX
  11097.   02 = File not found
  11098.   65 = Device not selected
  11099.  Carry not set:
  11100.    No error
  11101.  
  11102.  
  11103.  Comments:
  11104.  
  11105.  Function 66H gets or sets the code page used by the kernel and all devices.
  11106.  If no other code page has been set, this function gets the default code
  11107.  page from DX.  If another code page is set, this function retrieves the
  11108.  active code page from BX.
  11109.  
  11110.  The MS-DOS nlsfunc command and country.sys must be on the system if
  11111.  this function is to be used to change the global code page.
  11112.  
  11113.  The function code may be one of the following:
  11114.  
  11115.  Code   Description
  11116.  ───────────────────────────────────────────────────────────────────────────
  11117.  1      Get code page
  11118.  2      Set code page
  11119.  
  11120.  MS-DOS gets the new code page from the country.sys file. Devices must
  11121.  be prepared for code page switching before a code page can be selected.
  11122.  To prepare a device, a device driver that supports code page switching
  11123.  must be installed by using the device command in the config.sys file.
  11124.  The user must also use the prepare keyword with the MS-DOS mode command
  11125.  to prepare the device for code page switching.
  11126.  
  11127.  The code page selected must be compatible with the country code specified
  11128.  in the config.sys file. If MS-DOS cannot read country.sys or other
  11129.  specified country information file, error code 02 is returned to AX.
  11130.  
  11131.  
  11132.  Set Handle Count (Function 67H)
  11133.  
  11134.  
  11135.  Call:
  11136.  
  11137.  AH = 67H
  11138.  BX
  11139.    Number of allowed handles
  11140.  
  11141.  
  11142.  Return:
  11143.  
  11144.  Carry set:
  11145.  AX
  11146.  Carry not set:
  11147.    No error
  11148.  
  11149.  
  11150.  Comments:
  11151.  
  11152.  Function 67H increases or decreases the number of files a program can
  11153.  have open at one time. The maximum number of files handles is 64K. If less
  11154.  than 20 are specified, the minimum handle number, 20, is assumed. If this
  11155.  call is used to reduce the number of allowed handles, the new limit does
  11156.  not take affect until any handles above the new limit are closed.
  11157.  
  11158.  The user should use Call 4AH (Set Block) to allocate memory for the
  11159.  extended handle list if BX is greater than 255. The maximum number for
  11160.  the value of the config.sys command files is 255.
  11161.  
  11162.  
  11163.  Commit File (Function 68H)
  11164.  
  11165.  
  11166.  Call:
  11167.  
  11168.  AH = 68H
  11169.  BX
  11170.    File handle
  11171.  
  11172.  
  11173.  Return:
  11174.  
  11175.  Carry set:
  11176.  AX = error
  11177.  Carry not set
  11178.    No error
  11179.  
  11180.  
  11181.  Comments:
  11182.  
  11183.  Function 68H flushes all buffered data for a file without closing it.
  11184.  Using this call is more efficient than using the traditional close-open
  11185.  sequence, and is more effective for network environments. This call makes
  11186.  sure that the disk image of a file is current.
  11187.  
  11188.  ; Macro Definitions for MS-DOS System Call Examples
  11189.  ;
  11190.  ;*******************
  11191.  ; Interrupts
  11192.  ;*******************
  11193.  ;                                Interrupt 25H
  11194.  ABS_DISK_READ  macro  disk,buffer,num_sectors,first_sector
  11195.       mov    al,disk
  11196.       mov    bx,offset buffer
  11197.       mov    cx,num_sectors
  11198.       mov    dx,first_sector
  11199.       int    25H
  11200.       popf
  11201.       endm
  11202.  
  11203.  ;                                Interrupt 26H
  11204.  ABS_DISK_WRITE  macro  disk,buffer,num_sectors,first_sector
  11205.       mov    al,disk
  11206.       mov    bx,offset buffer
  11207.       mov    cx,num_sectors
  11208.       mov    dx,first_sector
  11209.       int    26H
  11210.       popf
  11211.       endm
  11212.  
  11213.  ;                                Interrupt 27H
  11214.  STAY_RESIDENT  macro  last_instruc
  11215.       mov    dx,offset last_instruc
  11216.       inc    dx
  11217.       int    27H
  11218.       endm
  11219.  ;
  11220.  ;
  11221.  ;*******************
  11222.  ; Function Requests
  11223.  ;*******************
  11224.  ;                                Function Request 00H
  11225.  TERMINATE_PROGRAM  macro
  11226.       xor    ah,ah
  11227.       int    21H
  11228.       endm
  11229.  
  11230.  ;                                Function Request 01H
  11231.  READ_KBD_AND_ECHO  macro
  11232.       mov    ah,01H
  11233.       int    21H
  11234.       endm
  11235.  ;                                Function Request 02H
  11236.  DISPLAY_CHAR  macro  character
  11237.       mov    dl,character
  11238.       mov    ah,02H
  11239.       int    21H
  11240.       endm
  11241.  
  11242.  ;                                Function Request 03H
  11243.  AUX_INPUT    macro
  11244.       mov     ah,03H
  11245.       int     21H
  11246.       endm
  11247.  
  11248.  ;                                Function Request 04H
  11249.  AUX_OUTPUT  macro
  11250.       mov    ah,04H
  11251.       int    21H
  11252.       endm
  11253.  ;                                Function Request 05H
  11254.  PRINT_CHAR  macro  character
  11255.       mov    dl,character
  11256.       mov    ah,05H
  11257.       int    21H
  11258.       endm
  11259.  
  11260.  ;                                Function Request 06H
  11261.  DIR_CONSOLE_IO  macro  switch
  11262.       mov    dl,switch
  11263.       mov    ah,06H
  11264.       int    21H
  11265.       endm
  11266.  ;                                Function Request 07H
  11267.  DIR_CONSOLE_INPUT  macro
  11268.       mov    ah,07H
  11269.       int    21H
  11270.       endm
  11271.  
  11272.  ;                                Function Request 08H
  11273.  READ_KBD  macro
  11274.       mov    ah,08H
  11275.       int    21H
  11276.       endm
  11277.  ;                                Function Request 09H
  11278.  DISPLAY  macro  string
  11279.       mov    dx,offset string
  11280.       mov    ah,09H
  11281.       int    21H
  11282.       endm
  11283.  
  11284.  ;                                Function Request 0AH
  11285.  GET_STRING  macro  limit,string
  11286.       mov    dx,offset string
  11287.       mov    string,limit
  11288.       mov    ah,0AH
  11289.       int    21H
  11290.       endm
  11291.  ;                                Function Request 0BH
  11292.  CHECK_KBD_STATUS  macro
  11293.       mov    ah,0BH
  11294.       int    21H
  11295.       endm
  11296.  
  11297.  ;                                Function Request 0CH
  11298.  FLUSH_AND_READ_KBD  macro  switch
  11299.       mov    al,switch
  11300.       mov    ah,0CH
  11301.       int    21H
  11302.       endm
  11303.  
  11304.  ;                                Function Request 0DH
  11305.  RESET_DISK  macro
  11306.       mov    ah,0DH
  11307.       int    21H
  11308.       endm
  11309.  ;                                Function Request 0EH
  11310.  SELECT_DISK  macro  disk
  11311.       mov    dl,disk[-65]
  11312.       mov    ah,0EH
  11313.       int    21H
  11314.       endm
  11315.  
  11316.  ;                                Function Request 0FH
  11317.  OPEN  macro  fcb
  11318.       mov    dx,offset fcb
  11319.       mov    ah,0FH
  11320.       int    21H
  11321.       endm
  11322.  ;                                Function Request 10H
  11323.  CLOSE  macro  fcb
  11324.       mov    dx,offset fcb
  11325.       mov    ah,10H
  11326.       int    21H
  11327.       endm
  11328.  
  11329.  ;                                Function Request 11H
  11330.  SEARCH_FIRST  macro  fcb
  11331.       mov    dx,offset fcb
  11332.       mov    ah,11H
  11333.       int    21H
  11334.       endm
  11335.  ;                                Function Request 12H
  11336.  SEARCH_NEXT  macro  fcb
  11337.       mov    dx,offset fcb
  11338.       mov    ah,12H
  11339.       int    21H
  11340.       endm
  11341.  
  11342.  ;                                Function Request 13H
  11343.  DELETE  macro  fcb
  11344.       mov    dx,offset fcb
  11345.       mov    ah,13H
  11346.       int    21H
  11347.       endm
  11348.  
  11349.  ;                                Function Request 14H
  11350.  READ_SEQ  macro  fcb
  11351.       mov    dx,offset fcb
  11352.       mov    ah,14H
  11353.       int    21H
  11354.       endm
  11355.  ;                                Function Request 15H
  11356.  WRITE_SEQ  macro  fcb
  11357.       mov    dx,offset fcb
  11358.       mov    ah,15H
  11359.       int    21H
  11360.       endm
  11361.  
  11362.  ;                                Function Request 16H
  11363.  CREATE  macro  fcb
  11364.       mov    dx,offset fcb
  11365.       mov    ah,16H
  11366.       int    21H
  11367.       endm
  11368.  ;                                Function Request 17H
  11369.  RENAME  macro  fcb,newname
  11370.       mov    dx,offset fcb
  11371.       mov    ah,17H
  11372.       int    21H
  11373.       endm
  11374.  
  11375.  ;                                Function Request 19H
  11376.  CURRENT_DISK  macro
  11377.       mov    ah,19H
  11378.       int    21H
  11379.       endm
  11380.  ;                                Function Request 1AH
  11381.  SET_DTA  macro  buffer
  11382.       mov    dx,offset buffer
  11383.       mov    ah,1AH
  11384.       endm
  11385.  
  11386.  ;                                Function Request 1BH
  11387.  DEF_DRIVE_DATA  macro
  11388.       mov    ah,1BH
  11389.       int    21H
  11390.       endm
  11391.  ;                                Function Request 1CH
  11392.  DRIVE_DATA  macro  drive
  11393.       mov    dl,drive
  11394.       mov    ah,1CH
  11395.       int    21H
  11396.       endm
  11397.  
  11398.  ;                                Function Request 21H
  11399.  READ_RAN  macro  fcb
  11400.       mov    dx,offset fcb
  11401.       mov    ah,21H
  11402.       int    21H
  11403.       endm
  11404.  
  11405.  ;                                Function Request 22H
  11406.  WRITE_RAN  macro  fcb
  11407.       mov    dx,offset fcb
  11408.       mov    ah,22H
  11409.       int    21H
  11410.       endm
  11411.  ;                                Function Request 23H
  11412.  FILE_SIZE  macro  fcb
  11413.       mov    dx,offset fcb
  11414.       mov    ah,23H
  11415.       int    21H
  11416.       endm
  11417.  
  11418.  ;                                Function Request 24H
  11419.  SET_RELATIVE_RECORD  macro  fcb
  11420.       mov    dx,offset fcb
  11421.       mov    ah,24H
  11422.       int    21H
  11423.       endm
  11424.  ;                                Function Request 25H
  11425.  SET_VECTOR  macro  interrupt,handler_start
  11426.       mov    al,interrupt
  11427.       mov    dx,offset handler_start
  11428.       mov    ah,25H
  11429.       int    21H
  11430.       endm
  11431.  
  11432.  ;                                Function Request 26H
  11433.  CREATE_PSP  macro  seg_addr
  11434.       mov    dx,offset seg_addr
  11435.       mov    ah,26H
  11436.       int    21H
  11437.       endm
  11438.  ;                                 Function Request 27H
  11439.  RAN_BLOCK_READ  macro  fcb,count,rec_size
  11440.       mov    dx,offset fcb
  11441.       mov    cx,count
  11442.       mov    word ptr fcb[14],rec_size
  11443.       mov    ah,27H
  11444.       int    21H
  11445.       endm
  11446.  
  11447.  ;                                 Function Request 28H
  11448.  RAN_BLOCK_WRITE  macro  fcb,count,rec_size
  11449.       mov    dx,offset fcb
  11450.       mov    cx,count
  11451.       mov    word ptr fcb[14],rec_size
  11452.       mov    ah,28H
  11453.       int    21H
  11454.       endm
  11455.  
  11456.  ;                                Function Request 29H
  11457.  PARSE  macro  string,fcb
  11458.       mov    si,offset string
  11459.       mov    di,offset fcb
  11460.       push   es
  11461.       push   ds
  11462.       pop    es
  11463.       mov    al,0FH
  11464.       mov    ah,29H
  11465.       int    21H
  11466.       pop    es
  11467.       endm
  11468.  
  11469.  ;                                 Function Request 2AH
  11470.  GET_DATE  macro
  11471.       mov    ah,2AH
  11472.       int    21H
  11473.       endm
  11474.  
  11475.  ;                                 Function Request 2BH
  11476.  SET_DATE  macro  year,month,day
  11477.       mov    cx,year
  11478.       mov    dh,month
  11479.       mov    dl,day
  11480.       mov    ah,2BH
  11481.       int    21H
  11482.       endm
  11483.  
  11484.  ;                                 Function Request 2CH
  11485.  GET_TIME  macro
  11486.       mov    ah,2CH
  11487.       int    21H
  11488.       endm
  11489.  
  11490.  ;                                 Function Request 2DH
  11491.  SET_TIME  macro  hour,minutes,seconds,hundredths
  11492.       mov    ch,hour
  11493.       mov    cl,minutes
  11494.       mov    dh,seconds
  11495.       mov    dl,hundredths
  11496.       mov    ah,2DH
  11497.       int    21H
  11498.       endm
  11499.  
  11500.  ;                                 Function Request 2EH
  11501.  VERIFY  macro  switch
  11502.       mov    al,switch
  11503.       mov    ah,2EH
  11504.       int    21H
  11505.       endm
  11506.  
  11507.  ;                                 Function Request 2FH
  11508.  GET_DTA  macro
  11509.       mov    ah,2FH
  11510.       int    21H
  11511.       endm
  11512.  
  11513.  ;                                 Function Request 30H
  11514.  GET_VERSION  macro
  11515.       mov    ah,30H
  11516.       int    21H
  11517.       endm
  11518.  
  11519.  ;                                 Function Request 31H
  11520.  KEEP_PROCESS  macro  return_code,last_byte
  11521.       mov    al,return_code
  11522.       mov    dx,offset last_byte
  11523.       mov    cl,4
  11524.       shr    dx,cl
  11525.       inc    dx
  11526.       mov    ah,31H
  11527.       int    21H
  11528.       endm
  11529.  
  11530.  ;                                 Function Request 33H
  11531.  CTRL_C_CK  macro  action,state
  11532.       mov    al,action
  11533.       mov    dl,state
  11534.       mov    ah,33H
  11535.       int    21H
  11536.       endm
  11537.  
  11538.  ;                                 Function Request 35H
  11539.  GET_VECTOR  macro  interrupt
  11540.       mov    al,interrupt
  11541.       mov    ah,35H
  11542.       int    21H
  11543.       endm
  11544.  
  11545.  ;                                 Function Request 36H
  11546.  GET_DISK_SPACE  macro  drive
  11547.       mov    dl,drive
  11548.       mov    ah,36H
  11549.       int    21H
  11550.       endm
  11551.  
  11552.  ;                                 Function Request 38H
  11553.  GET_COUNTRY  macro  country,buffer
  11554.               local  gc_01
  11555.               mov    dx,offset buffer
  11556.               mov    ax,country
  11557.               cmp    ax,0FFH
  11558.               jl     gc_01
  11559.               mov    al,0ffh
  11560.               mov    bx,country
  11561.  gc_01:       mov    ah,38H
  11562.               int    21H
  11563.               endm
  11564.  
  11565.  ;                                 Function Request 38H
  11566.  SET_COUNTRY  macro  country
  11567.               local  sc_01
  11568.               mov    dx,0FFFFH
  11569.               mov    ax,country
  11570.               cmp    ax,0FFH
  11571.               jl     sc_01
  11572.               mov    al,0ffh
  11573.               mov    bx,country
  11574.  sc_01:       mov    ah,38H
  11575.               int    21H
  11576.               endm
  11577.  
  11578.  ;                                 Function Request 39H
  11579.  MAKE_DIR  macro  path
  11580.       mov    dx,offset path
  11581.       mov    ah,39H
  11582.       int    21H
  11583.       endm
  11584.  
  11585.  ;                                 Function Request 3AH
  11586.  REM_DIR  macro  path
  11587.       mov    dx,offset path
  11588.       mov    ah,3AH
  11589.       int    21H
  11590.       endm
  11591.  
  11592.  ;                                 Function Request 3BH
  11593.  CHANGE_DIR  macro  path
  11594.       mov    dx,offset path
  11595.       mov    ah,3BH
  11596.       int    21H
  11597.       endm
  11598.  
  11599.  ;                                 Function Request 3CH
  11600.  CREATE_HANDLE  macro  path,attrib
  11601.       mov    dx,offset path
  11602.       mov    cx,attrib
  11603.       mov    ah,3CH
  11604.       int    21H
  11605.       endm
  11606.  
  11607.  ;                                 Function Request 3DH
  11608.  OPEN_HANDLE  macro  path,access
  11609.       mov    dx,offset path
  11610.       mov    al,access
  11611.       mov    ah,3DH
  11612.       int    21H
  11613.       endm
  11614.  
  11615.  ;                                 Function Request 3EH
  11616.  CLOSE_HANDLE  macro  handle
  11617.       mov    bx,handle
  11618.       mov    ah,3EH
  11619.       int    21H
  11620.       endm
  11621.  
  11622.  ;                                 Function Request 3FH
  11623.  READ_HANDLE  macro  handle,buffer,bytes
  11624.       mov    bx,handle
  11625.       mov    dx,offset buffer
  11626.       mov    cx,bytes
  11627.       mov    ah,3FH
  11628.       int    21H
  11629.       endm
  11630.  
  11631.  ;                                 Function Request 40H
  11632.  WRITE_HANDLE  macro  handle,buffer,bytes
  11633.       mov    bx,handle
  11634.       mov    dx,offset buffer
  11635.       mov    cx,bytes
  11636.       mov    ah,40H
  11637.       int    21H
  11638.       endm
  11639.  
  11640.  ;                                 Function Request 41H
  11641.  DELETE_ENTRY  macro  path
  11642.       mov    dx,offset path
  11643.       mov    ah,41H
  11644.       int    21H
  11645.       endm
  11646.  
  11647.  ;                                 Function Request 42H
  11648.  MOVE_PTR  macro  handle,high,low,method
  11649.       mov    bx,handle
  11650.       mov    cx,high
  11651.       mov    dx,low
  11652.       mov    al,method
  11653.       mov    ah,42H
  11654.       int    21H
  11655.       endm
  11656.  
  11657.  ;                                 Function Request 43H
  11658.  CHANGE_MODE  macro  path,action,attrib
  11659.       mov    dx,offset path
  11660.       mov    al,action
  11661.       mov    cx,attrib
  11662.       mov    ah,43H
  11663.       int    21H
  11664.       endm
  11665.  
  11666.  ;                                 Function Request 4400H,01H
  11667.  IOCTL_DATA  macro  code,handle
  11668.       mov    bx,handle
  11669.       mov    al,code
  11670.       mov    ah,44H
  11671.       int    21H
  11672.       endm
  11673.  
  11674.  ;                                 Function Request 4402H,03H
  11675.  IOCTL_CHAR  macro  code,handle,buffer
  11676.       mov    bx,handle
  11677.       mov    dx,offset buffer
  11678.       mov    al,code
  11679.       mov    ah,44H
  11680.       int    21H
  11681.       endm
  11682.  
  11683.  ;                                 Function Request 4404H,05H
  11684.  IOCTL_STATUS  macro  code,drive,buffer
  11685.       mov    bl,drive
  11686.       mov    dx,offset buffer
  11687.       mov    al,code
  11688.       mov    ah,44H
  11689.       int    21H
  11690.       endm
  11691.  
  11692.  ;                                 Function Request 4406H,07H
  11693.  IOCTL_STATUS macro  code,handle
  11694.       mov    bx,handle
  11695.       mov    al,code
  11696.       mov    ah,44H
  11697.       int    21H
  11698.       endm
  11699.  
  11700.  ;                                 Function Request 4408H
  11701.  IOCTL_CHANGE  macro  drive
  11702.       mov    bl,drive
  11703.       mov    al,08H
  11704.       mov    ah,44H
  11705.       int    21H
  11706.       endm
  11707.  
  11708.  ;                                 Function Request 4409H
  11709.  IOCTL_RBLOCK  macro  drive
  11710.       mov    bl,drive
  11711.       mov    al,09H
  11712.       mov    ah,44H
  11713.       int    21H
  11714.       endm
  11715.  
  11716.  ;                                 Function Request 440AH
  11717.  IOCTL_RHANDLE  macro  handle
  11718.       mov    bx,handle
  11719.       mov    al,0AH
  11720.       mov    ah,44H
  11721.       int    21H
  11722.       endm
  11723.  
  11724.  ;                                 Function Request 440BH
  11725.  IOCTL_RETRY  macro  retries,wait
  11726.       mov    dx,retries
  11727.       mov    cx,wait
  11728.       mov    al,0BH
  11729.       mov    ah,44H
  11730.       int    21H
  11731.       endm
  11732.  
  11733.  ;                                 Function Request 440CH
  11734.  GENERIC_IOCTL_HANDLES macro handle,function,category,buffer
  11735.       mov    ch,05H
  11736.       mov    cl,function
  11737.       mov    dx,offset buffer
  11738.       mov    bx,handle
  11739.       mov    ah,44H
  11740.       mov    al,0CH
  11741.       int    21H
  11742.       endm
  11743.  
  11744.  ;                                 Function Request 440DH
  11745.  GENERIC_IOCTL_BLOCK macro drive_num,function,category,parm_blk
  11746.       mov    ch,08H
  11747.       mov    cl,function
  11748.       mov    dx,offset parm_blk - 1
  11749.       mov    bx,drive_num
  11750.       mov    ah,44H
  11751.       mov    al,0DH
  11752.       int    21H
  11753.       endm
  11754.  
  11755.  ;                                 Function Request 440EH
  11756.  IOCTL_GET_DRIVE_MAP macro   logical_drv
  11757.       mov    bx,logical_drv
  11758.       mov    ah,44H
  11759.       mov    al,0EH
  11760.       int    21H
  11761.       endm
  11762.  
  11763.  ;                                 Function Request 440FH
  11764.  IOCTL_SET_DRIVE_MAP macro   logical_drv
  11765.       mov    bx,logical_drv
  11766.       mov    ah,44H
  11767.       mov    al,0FH
  11768.       int    21H
  11769.       endm
  11770.  
  11771.  ;                                 Function Request 45H
  11772.  XDUP  macro  handle
  11773.       mov    bx,handle
  11774.       mov    ah,45H
  11775.       int    21H
  11776.       endm
  11777.  
  11778.  ;                                 Function Request 46H
  11779.  XDUP2  macro  handle1,handle2
  11780.       mov    bx,handle1
  11781.       mov    cx,handle2
  11782.       mov    ah,46H
  11783.       int    21H
  11784.       endm
  11785.  
  11786.  ;                                 Function Request 47H
  11787.  GET_DIR  macro  drive,buffer
  11788.       mov    dl,drive
  11789.       mov    si,offset buffer
  11790.       mov    ah,47H
  11791.       int    21H
  11792.       endm
  11793.  
  11794.  ;                                 Function Request 48H
  11795.  ALLOCATE_MEMORY  macro  bytes
  11796.       mov    bx,bytes
  11797.       mov    cl,4
  11798.       shr    bx,cl
  11799.       inc    bx
  11800.       mov    ah,48H
  11801.       int    21H
  11802.       endm
  11803.  
  11804.  ;                                 Function Request 49H
  11805.  FREE_MEMORY  macro  seg_addr
  11806.       mov    ax,seg_addr
  11807.       mov    es,ax
  11808.       mov    ah,49H
  11809.       int    21H
  11810.       endm
  11811.  
  11812.  ;                                 Function Request 4AH
  11813.  SET_BLOCK  macro  last_byte
  11814.       mov    bx,offset last_byte
  11815.       mov    cl,4
  11816.       shr    bx,cl
  11817.       add    bx,17
  11818.       mov    ah,4AH
  11819.       int    21H
  11820.       mov     ax,bx
  11821.       shl     ax,cl
  11822.       dec     ax
  11823.       mov     sp,ax
  11824.       mov     bp,sp
  11825.       endm
  11826.  
  11827.  ;                                 Function Request 4B00H
  11828.  EXEC macro  path,command,parms
  11829.       mov    dx,offset path
  11830.       mov    bx,offset parms
  11831.       mov    word ptr parms[02h],offset command
  11832.       mov    word ptr parms[04h],cs
  11833.       mov    word ptr parms[06h],5ch
  11834.       mov    word ptr parms[08h],es
  11835.       mov    word ptr parms[0ah],6ch
  11836.       mov    word ptr parms[0ch],es
  11837.       mov    al,0
  11838.       mov    ah,4BH
  11839.       int    21H
  11840.       endm
  11841.  
  11842.  ;                                 Function Request 4B03H
  11843.  EXEC_OVL  macro  path,parms,seg_addr
  11844.        mov    dx,offset path
  11845.        mov    bx,offset parms
  11846.        mov    parms,seg_addr
  11847.        mov    parms[02H],seg_addr
  11848.        mov    al,3
  11849.        mov    ah,4BH
  11850.        int    21H
  11851.        endm
  11852.  
  11853.  ;                                 Function Request 4CH
  11854.  END_PROCESS   macro  return_code
  11855.               mov    al,return_code
  11856.               mov    ah,4CH
  11857.               int    21H
  11858.               endm
  11859.  
  11860.  ;                                 Function Request 4DH
  11861.  RET_CODE macro
  11862.        mov    ah,4DH
  11863.        int    21H
  11864.        endm
  11865.  
  11866.  ;                                 Function Request 4EH
  11867.  FIND_FIRST_FILE  macro  path,attrib
  11868.       mov    dx,offset path
  11869.       mov    cx,attrib
  11870.       mov    ah,4EH
  11871.       int    21H
  11872.       endm
  11873.  
  11874.  ;                                 Function Request 4FH
  11875.  FIND_NEXT_FILE  macro
  11876.       mov    ah,4FH
  11877.       int    21H
  11878.       endm
  11879.  
  11880.  ;                                 Function Request 54H
  11881.  GET_VERIFY  macro
  11882.       mov    ah,54H
  11883.       int    21H
  11884.       endm
  11885.  
  11886.  ;                                 Function Request 56H
  11887.  RENAME_FILE  macro  old_path,new_path
  11888.       mov    dx,offset old_path
  11889.       push   ds
  11890.       pop    es
  11891.       mov    di,offset new_path
  11892.       mov    ah,56H
  11893.       int    21H
  11894.       endm
  11895.  
  11896.  ;                                 Function Request 57H
  11897.  GET_SET_DATE_TIME  macro  handle,action,time,date
  11898.       mov    bx,handle
  11899.       mov    al,action
  11900.       mov    cx,word ptr time
  11901.       mov    dx,word ptr date
  11902.       mov    ah,57H
  11903.       int    21H
  11904.       endm
  11905.  
  11906.  ;                                 Function Request 58H
  11907.  ALLOC_STRAT  macro  code,strategy
  11908.       mov    bx,strategy
  11909.       mov    al,code
  11910.       mov    ah,58H
  11911.       int    21H
  11912.       endm
  11913.  
  11914.  ;                                 Function Request 59H
  11915.  GET_ERROR  macro
  11916.       mov    ah,59
  11917.       int    21H
  11918.       endm
  11919.  
  11920.  ;                                 Function Request 5AH
  11921.  CREATE_TEMP  macro  pathname,attrib
  11922.       mov    cx,attrib
  11923.       mov    dx,offset pathname
  11924.       mov    ah,5AH
  11925.       int    21H
  11926.       endm
  11927.  
  11928.  ;                                 Function Request 5BH
  11929.  CREATE_NEW  macro  pathname,attrib
  11930.       mov    cx,attrib
  11931.       mov    dx,offset pathname
  11932.       mov    ah,5BH
  11933.       int    21H
  11934.       endm
  11935.  
  11936.  ;                                 Function Request 5C00H
  11937.  LOCK        macro  handle,start,bytes
  11938.       mov    bx,handle
  11939.       mov    cx,word ptr start
  11940.       mov    dx,word ptr start+2
  11941.       mov    si,word ptr bytes
  11942.       mov    di,word ptr bytes+2
  11943.       mov    al,0
  11944.       mov    ah,5CH
  11945.       int    21H
  11946.       endm
  11947.  
  11948.  ;                                 Function Request 5C01H
  11949.  UNLOCK      macro  handle,start,bytes
  11950.       mov    bx,handle
  11951.       mov    cx,word ptr start
  11952.       mov    dx,word ptr start+2
  11953.       mov    si,word ptr bytes
  11954.       mov    di,word ptr bytes+2
  11955.       mov    al,1
  11956.       mov    ah,5CH
  11957.       int    21H
  11958.       endm
  11959.  
  11960.  ;                                 Function Request 5E00H
  11961.  GET_MACHINE_NAME  macro  buffer
  11962.       mov    dx,offset buffer
  11963.       mov    al,0
  11964.       mov    ah,5EH
  11965.       int    21H
  11966.       endm
  11967.  
  11968.  ;                                 Function Request 5E02H
  11969.  PRINTER_SETUP  macro  index,lgth,string
  11970.       mov    bx,index
  11971.       mov    cx,lgth
  11972.       mov    dx,offset string
  11973.       mov    al,2
  11974.       mov    ah,5EH
  11975.       int    21H
  11976.       endm
  11977.  
  11978.  ;                                 Function Request 5F02H
  11979.  GET_LIST    macro  index,local,remote
  11980.       mov    bx,index
  11981.       mov    si,offset local
  11982.       mov    di,offset remote
  11983.       mov    al,2
  11984.       mov    ah,5FH
  11985.       int    21H
  11986.       endm
  11987.  
  11988.  ;                                 Function Request 5F03H
  11989.  REDIR       macro  device,value,source,destination
  11990.       mov    bl,device
  11991.       mov    cx,value
  11992.       mov    si,offset source
  11993.       mov    es,seg destination
  11994.       mov    di,offset destination
  11995.       mov    al,03H
  11996.       mov    ah,5FH
  11997.       int    21H
  11998.       endm
  11999.  
  12000.  ;                                 Function Request 5F04H
  12001.  CANCEL_REDIR  macro  local
  12002.       mov    si,offset local
  12003.       mov    al,4
  12004.       mov    ah,5FH
  12005.       int    21H
  12006.       endm
  12007.  
  12008.  ;                                 Function Request 62H
  12009.  GET_PSP     macro
  12010.       mov    ah,62H
  12011.       int    21H
  12012.       endm
  12013.  ;
  12014.  ;
  12015.  ;*******************
  12016.  ; General
  12017.  ;*******************
  12018.  ;
  12019.  DISPLAY_ASCIIZ  macro  asciiz_string
  12020.       local  search,found_it
  12021.       mov    bx,offset asciiz_string
  12022.  
  12023.  search:
  12024.       cmp    byte ptr [bx],0
  12025.       je     found_it
  12026.       inc    bx
  12027.       jmp short search
  12028.  
  12029.  found_it:
  12030.       mov    byte ptr [bx],"$"
  12031.       display asciiz_string
  12032.       mov    byte ptr [bx],0
  12033.       display_char 0DH
  12034.       display_char 0AH
  12035.       endm
  12036.  
  12037.  ;
  12038.  MOVE_STRING  macro  source,destination,count
  12039.       push   es
  12040.       push   ds
  12041.       pop    es
  12042.       assume es:code
  12043.       mov    si,offset source
  12044.       mov    di,offset destination
  12045.       mov    cx,count
  12046.   rep movs   es:destination,source
  12047.       assume es:nothing
  12048.       pop    es
  12049.       endm
  12050.  
  12051.  ;
  12052.  CONVERT  macro  value,base,destination
  12053.       local  table,start
  12054.       jmp    start
  12055.  table  db   "0123456789ABCDEF"
  12056.  
  12057.  start:
  12058.       push   ax
  12059.       push   bx
  12060.       push   dx
  12061.       mov    al,value
  12062.       xor    ah,ah
  12063.       xor    bx,bx
  12064.       div    base
  12065.       mov    bl,al
  12066.       mov    al,cs:table[bx]
  12067.       mov    destination,al
  12068.       mov    bl,ah
  12069.       mov    al,cs:table[bx]
  12070.       mov    destination[1],al
  12071.       pop    dx
  12072.       pop    bx
  12073.       pop    ax
  12074.       endm
  12075.  
  12076.  ;
  12077.  CONVERT_TO_BINARY  macro  string,number,value
  12078.       local  ten,start,calc,mult,no_mult
  12079.       jmp    start
  12080.  ten  db     10
  12081.  
  12082.  start:
  12083.       mov    value,0
  12084.       xor    cx,cx
  12085.       mov    cl,number
  12086.       xor    si,si
  12087.  
  12088.  calc:
  12089.       xor    ax,ax
  12090.       mov    al,string[si]
  12091.       sub    al,48
  12092.       cmp    cx,2
  12093.       jl     no_mult
  12094.       push   cx
  12095.       dec    cx
  12096.  
  12097.  mult:
  12098.       mul    cs:ten
  12099.       loop   mult
  12100.       pop    cx
  12101.  
  12102.  no_mult:
  12103.       add    value,ax
  12104.       inc    si
  12105.       loop   calc
  12106.       endm
  12107.  
  12108.  ;
  12109.  CONVERT_DATE  macro  dir_entry
  12110.       mov    dx,word ptr dir_entry[24]
  12111.       mov    cl,5
  12112.       shr    dl,cl
  12113.       mov    dh,dir_entry[24]
  12114.       and    dh,1FH
  12115.       xor    cx,cx
  12116.       mov    cl,dir_entry[25]
  12117.       shr    cl,1
  12118.       add    cx,1980
  12119.       endm
  12120.  
  12121.  ;
  12122.  PACK_DATE  macro  date
  12123.       local set_bit
  12124.  ;
  12125.  ; On entry: DH=day, DL=month, CX=(year-1980)
  12126.  ;
  12127.       sub   cx,1980
  12128.       push  cx
  12129.       mov   date,dh
  12130.       mov   cl,5
  12131.       shl   dl,cl
  12132.       pop   cx
  12133.       jnc   set_bit
  12134.       or    cl,80h
  12135.  
  12136.  set_bit:
  12137.       or    date,dl
  12138.       rol   cl,1
  12139.       mov   date[1],cl
  12140.       endm
  12141.  ;
  12142.  
  12143.  
  12144.  
  12145.  Chapter 2  MS-DOS Device Drivers
  12146.  
  12147.  ───────────────────────────────────────────────────────────────────────────
  12148.  
  12149.  2.1  Introduction
  12150.  
  12151.  2.2  Format of a Device Driver
  12152.  
  12153.  2.3  How to Create a Device Driver
  12154.  
  12155.        2.3.1  Device Strategy Routine
  12156.  
  12157.        2.3.2  Device Interrupt Routine
  12158.  
  12159.  2.4  Installing Device Drivers
  12160.  
  12161.  2.5  Device Headers
  12162.  
  12163.        2.5.1  Pointer to Next Device Field
  12164.  
  12165.        2.5.2  Attribute Field
  12166.  
  12167.        2.5.3  Strategy and Interrupt Routines
  12168.  
  12169.        2.5.4  Name Field
  12170.  
  12171.  2.6  Request Header
  12172.  
  12173.        2.6.1  Length of Record
  12174.  
  12175.        2.6.2  Unit Code Field
  12176.  
  12177.        2.6.3  Command Code Field
  12178.  
  12179.        2.6.4  Status Field
  12180.  
  12181.  2.7  Device Driver Functions
  12182.  
  12183.        2.7.1  The Init Function
  12184.  
  12185.        2.7.2  The Media Check Function
  12186.  
  12187.        2.7.3  The Build BPB Function
  12188.  
  12189.        2.7.4  The Read or Write Function
  12190.  
  12191.        2.7.5  The Non-destructive Read, No Wait Function
  12192.  
  12193.        2.7.6  The Open or Close Function
  12194.  
  12195.        2.7.7  The Removable Media Function
  12196.  
  12197.        2.7.8  The Status Function
  12198.  
  12199.        2.7.9  The Flush Function
  12200.  
  12201.        2.7.10 The Generic IOCtl Function
  12202.  
  12203.        2.7.11 The Get/Set Logical Drive Map Function
  12204.  
  12205.  2.8  The Media Descriptor Byte
  12206.  
  12207.  2.9  Format of a Media Descriptor Table
  12208.  
  12209.  2.10 The CLOCK Device
  12210.  
  12211.  2.11 Anatomy of a Device Call
  12212.  
  12213.  2.12 Two Sample Device Drivers
  12214.  
  12215.  
  12216.  
  12217.  2.1  Introduction
  12218.  
  12219.  
  12220.  The io.sys file comprises the "resident" device drivers, which form the
  12221.  MS-DOS BIOS. These drivers are called upon by MS-DOS to handle input/output
  12222.  (I/O) requests initiated by application programs.
  12223.  
  12224.  One of the most powerful features of MS-DOS is the ability to add new
  12225.  devices such as printers, plotters, and mouse input devices without
  12226.  rewriting the BIOS. The MS-DOS BIOS is configurable; that is, new drivers
  12227.  can be added and existing drivers can be preempted. Nonresident, or
  12228.  installable, device drivers may be easily added at boot time by including
  12229.  a device command line in the config.sys file.
  12230.  
  12231.  At boot time, a minimum of five resident device drivers must be present.
  12232.  These drivers are in a linked list: the header of each one contains a DWORD
  12233.  pointer to the next. The last driver in the chain has an end-of-list marker
  12234.  of -1, -1 (all bits on).
  12235.  
  12236.  Each driver in the chain has two entry points: the strategy entry point
  12237.  and the interrupt entry point. MS-DOS does not take advantage of the two
  12238.  entry points: it calls the strategy routine, then immediately calls the
  12239.  interrupt routine.
  12240.  
  12241.  The dual entry points will accomodate future multitasking versions of
  12242.  MS-DOS and MS OS/2 operating systems. In multitasking environments,
  12243.  I/O must be asynchronous; to accomplish this, the strategy routine will be
  12244.  called to (internally) queue a request and return quickly. It is then the
  12245.  responsibility of the interrupt routine to perform the I/O at interrupt
  12246.  time by getting requests from the internal queue and processing them. When
  12247.  a request is completed, it is flagged as "done" by the interrupt routine.
  12248.  MS-DOS periodically scans the list of requests looking for those that are
  12249.  flagged as done, and "wakes up" the process waiting for the completion
  12250.  of the request.
  12251.  
  12252.  When requests are queued in this manner, it is no longer sufficient to
  12253.  pass I/O information in registers, since many requests may be pending at
  12254.  any time. Therefore, the MS-DOS device interface uses "packets" to pass
  12255.  request information. These request packets are of variable size and
  12256.  format, and are composed of two parts:
  12257.  
  12258.      1.  The static request header section, which has the same format for
  12259.          all requests
  12260.  
  12261.      2.  A section which has information specific to the type of request
  12262.  
  12263.  A driver is called with a pointer to a packet. In multitasking versions,
  12264.  this packet will be linked into a global chain of all pending I/O requests
  12265.  maintained by MS-DOS.
  12266.  
  12267.  MS-DOS does not implement a global or local queue. Only one request is
  12268.  pending at any one time. The strategy routine must store the address of
  12269.  the packet at a fixed location, and the interrupt routine, which is called
  12270.  immediately after the strategy routine, should process the packet by
  12271.  completing the request and returning. It is assumed that the request
  12272.  is completed when the interrupt routine returns.
  12273.  
  12274.  To make a device driver that sysinit can install, a .bin (core
  12275.  image) or .exe format file must be created with the device driver header
  12276.  at the beginning of the file. The link field should be initialized to -1
  12277.  (sysinit fills it in). Device drivers which are part of the BIOS should
  12278.  have their headers point to the next device in the list and the last header
  12279.  should be initialized to -1,-1. The BIOS must be a .bin (core image)
  12280.  format file.
  12281.  
  12282.  The .exe format installable device drivers may be used in non-IBM
  12283.  versions of MS-DOS. On the IBM Personal Computer, the .exe loader is
  12284.  located in command.com which is not present at the time that installable
  12285.  devices are being loaded.
  12286.  
  12287.  
  12288.  2.2  Format of a Device Driver
  12289.  
  12290.  
  12291.  A device driver is a program segment responsible for communication between
  12292.  DOS and the system hardware. It has a special header at the beginning
  12293.  identifying it as a device driver, defining entry points, and describing
  12294.  various attributes of the device.
  12295.  
  12296.  ───────────────────────────────────────────────────────────────────────────
  12297.  Note
  12298.    For device drivers, the file must not use the ORG 100H (like .com files).
  12299.    Because it does not use the Program Segment Prefix (PSP), the device
  12300.    driver is simply loaded; therefore, the file must have an origin of zero
  12301.    (ORG 0 or no ORG statement).
  12302.  ───────────────────────────────────────────────────────────────────────────
  12303.  
  12304.  There are two kinds of device drivers:
  12305.  
  12306.      ■ Character device drivers
  12307.  
  12308.      ■ Block device drivers
  12309.  
  12310.  Character devices perform serial character I/O. Examples are the console,
  12311.  communications port and printer. These devices are named (i.e., CON, AUX,
  12312.  CLOCK, etc.), and programs may open channels (handles or file control
  12313.  blocks) to do I/O to them.
  12314.  
  12315.  Block devices include all the disk drives on the system. They can perform
  12316.  random I/O in structured pieces called blocks (usually the physical sector
  12317.  size). These devices are not named as the character devices are, and
  12318.  therefore cannot be opened directly. Instead they have unit numbers and
  12319.  are identified by drive letters such as A, B, and C.
  12320.  
  12321.  A single block device driver may be responsible for one or more logically
  12322.  contiguous disk drives. For example, block device driver ALPHA may be
  12323.  responsible for drives A, B, C, and D. This means that it has four units
  12324.  defined (0-3), and therefore, takes up four drive letters. The position of
  12325.  the driver in the list of all drivers determines which units correspond to
  12326.  which driver letters. If driver ALPHA is the first block driver in the
  12327.  device list, and it defines four units (0-3), then they will be A, B, C,
  12328.  and D. If BETA is the second block driver and defines three units (0-2),
  12329.  then they will be E, F, and G, and so on. The theoretical limit is 63,
  12330.  but it should be noted that the device installation code will not allow
  12331.  the installation of a device if it would result in a drive letter greater
  12332.  than Z (5AH). All block device drivers present in the standard resident
  12333.  BIOS will be placed ahead of installable block device drivers in the list.
  12334.  
  12335.  ───────────────────────────────────────────────────────────────────────────
  12336.  Note
  12337.    Because they have only one name, character devices cannot define
  12338.    multiple units.
  12339.  ───────────────────────────────────────────────────────────────────────────
  12340.  
  12341.  
  12342.  2.3  How to Create a Device Driver
  12343.  
  12344.  
  12345.  To create a device driver that MS-DOS can install, you must create a
  12346.  binary file (.com or .exe format) with a device header at the beginning of
  12347.  the file. Note that for device drivers, the code should not be originated
  12348.  at 100H, but at 0. The device header contains a link field (a pointer to
  12349.  the next device header) which should be -1, unless there is more than one
  12350.  device driver in the file. The attribute field and entry points must be
  12351.  set correctly.
  12352.  
  12353.  If it is a character device, the name field should be filled in with
  12354.  the name of that character device. The name can be any legal eight-
  12355.  character filename. If the name is less than eight characters, it should
  12356.  be padded out to eight characters with spaces (20H). Note that device
  12357.  names do not include colons (:). The fact that CON is the same as CON: is a
  12358.  property of the default MS-DOS command interpreter (command.com) and not of
  12359.  the device driver or the MS-DOS interface. All character device names are
  12360.  handled in this way.
  12361.  
  12362.  MS-DOS always processes installable device drivers before handling the
  12363.  default devices, so to install a new CON device, simply name the device
  12364.  CON. Remember to set the standard input device and standard output device
  12365.  bits in the attribute word on a new CON device. The scan of the device
  12366.  list stops on the first match, so the installable device driver takes
  12367.  precedence.
  12368.  
  12369.  It is not possible to replace the resident disk block device driver
  12370.  with an installable device driver the same way you can replace the other
  12371.  device drivers in the BIOS. Block drivers can be used only for devices
  12372.  not directly supported by the default disk drivers in the io.sys file.
  12373.  
  12374.  ───────────────────────────────────────────────────────────────────────────
  12375.  Note
  12376.    Because MS-DOS can install the driver anywhere in memory, care must be
  12377.    taken when making far memory references. You should not expect that your
  12378.    driver will always be loaded in the same place every time.
  12379.  ───────────────────────────────────────────────────────────────────────────
  12380.  
  12381.  
  12382.  2.3.1  Device Strategy Routine
  12383.  
  12384.  The device strategy routine, which is called by MS-DOS for each device
  12385.  driver service request, is primarily responsible for queuing these requests
  12386.  in the order in which they are to be processed by the device interrupt
  12387.  routine. Such queuing can be a very important performance feature in a
  12388.  multitasking environment, or where asynchronous I/O is supported. As MS-DOS
  12389.  does not currently support these facilities, only one request can be
  12390.  serviced at a time, and this routine is usually very short. In the coding
  12391.  examples in Section 2.12, "Two Sample Device Drivers," each request is
  12392.  simply stored in a single pointer area.
  12393.  
  12394.  
  12395.  2.3.2  Device Interrupt Routine
  12396.  
  12397.  The device interrupt routine contains the code necessary to process
  12398.  the service request. It may interface to the hardware, or it may use
  12399.  ROM BIOS calls. It usually consists of a series of procedures that handle
  12400.  the specific command codes to be supported as well as some exit and error-
  12401.  handling routines. See the coding examples in Section 2.12, "Two Sample
  12402.  Device Drivers."
  12403.  
  12404.  
  12405.  2.4  Installing Device Drivers
  12406.  
  12407.  
  12408.  MS-DOS allows new device drivers to be installed dynamically at boot
  12409.  time. This is accomplished by initialization code in the io.sys file
  12410.  that reads and processes the config.sys file.
  12411.  
  12412.  MS-DOS calls upon the device drivers to perform their function in the
  12413.  following manner:
  12414.  
  12415.      1.  MS-DOS makes a FAR call to the strategy entry.
  12416.  
  12417.      2.  MS-DOS passes device driver information in a request header to the
  12418.          strategy routine.
  12419.  
  12420.      3.  MS-DOS makes a FAR call to the interrupt entry.
  12421.  
  12422.  This calling structure is designed to be easily upgraded to support
  12423.  any future multitasking environment.
  12424.  
  12425.  
  12426.  2.5  Device Headers
  12427.  
  12428.  
  12429.  A device header is required at the beginning of a device driver. A device
  12430.  header looks like this:
  12431.  
  12432.  
  12433.             +--------------------------------------+
  12434.             | DWORD Pointer to next device         |
  12435.             | (Usually set to -1 if this driver    |
  12436.             | is the last or only driver in the    |
  12437.             | file)                                |
  12438.             +--------------------------------------+
  12439.             | WORD Attributes                      |
  12440.             +--------------------------------------+
  12441.             | WORD Pointer to device strategy      |
  12442.             |      entry point                     |
  12443.             +--------------------------------------+
  12444.             | WORD Pointer to device interrupt     |
  12445.             |      entry point                     |
  12446.             +--------------------------------------+
  12447.             | 8-BYTE Character device name field   |
  12448.             | Character devices set a device name. |
  12449.             | For block devices the first byte is  |
  12450.             | the number of units.                 |
  12451.             +--------------------------------------+
  12452.  
  12453.                Figure 2.1  Sample Device Header
  12454.  
  12455.  
  12456.  Note that the device entry points are words. They must be offsets from the
  12457.  same segment number used to point to this table. For example, if xxx:yyy
  12458.  points to the start of this table, then xxx:strategy and xxx:interrupt are
  12459.  the entry points.
  12460.  
  12461.  The device header fields are described in the following section.
  12462.  
  12463.  
  12464.  2.5.1  Pointer to Next Device Field
  12465.  
  12466.  The pointer to the next device header field is a double-word field
  12467.  (offset followed by segment) that is set by MS-DOS to point at the next
  12468.  driver in the system list at the time the device driver is loaded. It is
  12469.  important that this field be set to -1 prior to load (when it is on the
  12470.  disk as a file) unless there is more than one device driver in the file.
  12471.  If there is more than one driver in the file, the first word of the
  12472.  double-word pointer should be the offset of the next driver's device
  12473.  header.
  12474.  
  12475.  ───────────────────────────────────────────────────────────────────────────
  12476.  Note
  12477.    If there is more than one device driver in the file, the last driver in
  12478.    the file must have the pointer to the next device header field set to -1.
  12479.  ───────────────────────────────────────────────────────────────────────────
  12480.  
  12481.  
  12482.  2.5.2  Attribute Field
  12483.  
  12484.  The attribute field is used to identify the type of device for which
  12485.  this driver is responsible. In addition to distinguishing between block
  12486.  and character devices, these bits are used to give selected character
  12487.  devices special treatment. (Note that if a bit in the attribute word is
  12488.  defined only for one type of device, a driver for the other type of device
  12489.  must set that bit to 0.)
  12490.  
  12491.  
  12492.       Table 2.1
  12493.       For Character Devices:
  12494. ╓┌───────────┌───────┌───────────────────────────────────────────────────────╖
  12495.       Bit    Value   Meaning
  12496.       ──────────────────────────────────────────────────────────────────────
  12497.       Bit    Value   Meaning
  12498.       ──────────────────────────────────────────────────────────────────────
  12499.       0      1       Device is console input (sti) device
  12500.       1      1       Device is console output (sto) device
  12501.       2      1       Device is nul device
  12502.       3      1       Device is clock device
  12503.       4-5            Reserved (must be 0)
  12504.       6      1       Device supports 3.2 functions
  12505.       7-10           Reserved (must be 0)
  12506.       11     1       Device understands Open/Close
  12507.       12             Reserved (must be 0)
  12508.       13     1       Device supports Output Until Busy (OUB)
  12509.       14     1       Device supports IOCtl control strings
  12510.       15     1       Character device
  12511.  
  12512.  
  12513.       Table 2.2
  12514.       For Block Devices:
  12515. ╓┌───────────┌───────┌───────────────────────────────────────────────────────╖
  12516.       Bit    Value   Meaning
  12517.       ──────────────────────────────────────────────────────────────────────
  12518.       Bit    Value   Meaning
  12519.       ──────────────────────────────────────────────────────────────────────
  12520.       0-5            Reserved (must be 0)
  12521.  
  12522.       6      1       Device supports 3.2 functions and Generic IOCtl
  12523.                      function calls
  12524.  
  12525.       7-10           Reserved (must be 0)
  12526.  
  12527.       11     1       Device understands Open/Close/Removable Media
  12528.  
  12529.       12             Reserved (must be 0)
  12530.  
  12531.       13     1       Device determines the media by examining the FATID byte
  12532.  
  12533.       14     1       Device supports IOCtl control strings
  12534.  
  12535.       15     0       Block device
  12536.  
  12537.  
  12538.  For example, assume that you have a new device driver that you want to use
  12539.  as the standard input and output. In addition to installing the driver,
  12540.  you must tell MS-DOS that you want the new driver to override the current
  12541.  standard input and standard output (the CON device). This is accomplished
  12542.  by setting the attributes to the desired characteristics, so you would set
  12543.  bits 0 and 1 to 1 (note that they are separate). Similarly, a new CLOCK
  12544.  device could be installed by setting that attribute. (Refer to Section
  12545.  2.10, "The Clock Device," in this chapter for more information.)
  12546.  Although there is a NUL device attribute, the NUL device cannot be
  12547.  reassigned. This attribute exists so that MS-DOS can determine if the
  12548.  NUL device is being used.
  12549.  
  12550.  Bit 13 for block devices affects the operation of the Build BPB (BIOS
  12551.  Parameter Block) device call. If set, it requires the first sector of the
  12552.  FAT always to reside in the same place. This bit has a different meaning
  12553.  on character devices. It indicates that the device implements the Output
  12554.  Until Busy device call.
  12555.  
  12556.  The IOCtl bit (bit 14) has meaning on character and block devices. The
  12557.  IOCtl functions allow data to be sent and received by the device for
  12558.  its own use (to set baud rate, stop bits, form length, etc.) instead of
  12559.  passing data over the device channel as a normal read or write does.
  12560.  The interpretation of the passed information is up to the device but
  12561.  it must not be treated as normal I/O. This bit tells MS-DOS whether
  12562.  the device can handle control strings by using the IOCtl system call,
  12563.  Function 44H.
  12564.  
  12565.  If a driver cannot process control strings, it should initially set
  12566.  this bit to 0. This tells MS-DOS to return an error if an attempt is made
  12567.  (via Function 44H) to send or receive control strings to this device. A
  12568.  device which can process control strings should initialize the IOCtl bit
  12569.  to 1. For drivers of this type, MS-DOS will make calls to the IOCtl input
  12570.  and output device functions to send and receive IOCtl strings.
  12571.  
  12572.  The IOCtl functions allow data to be sent and received by the device
  12573.  for its own use (for example, to set baud rate, stop bits, and form
  12574.  length), instead of passing data over the device channel as does a normal
  12575.  read or write. The interpretation of the passed information is up to the
  12576.  device, but it must not be treated as a normal I/O request.
  12577.  
  12578.  The Open/Close/Removable Media bit (bit 11) signals to MS-DOS 3.x
  12579.  and later versions whether this driver supports additional MS-DOS 3.x
  12580.  functionality. To support these old drivers, it is necessary to detect
  12581.  them. This bit was reserved in MS-DOS 2.x, and is 0. All new devices
  12582.  should support the Open, Close, and Removable Media calls and set this
  12583.  bit to 1. Since MS-DOS 2.x never makes these calls, the driver will
  12584.  be backward-compatible.
  12585.  
  12586.  The MS-DOS 3.2 bit (bit 6) signals whether the device supports logical
  12587.  drive mapping via Function 440EH (Get Logical Drive Map) and Function 440FH
  12588.  (Set Logical Drive Map). This bit also supports generic IOCtl functions via
  12589.  Function 440CH (Generic IOCtl for Handles) and Function 440DH (Generic
  12590.  IOCtl for Block Devices).
  12591.  
  12592.  
  12593.    15  14  13  12  11  10  9   8   7   6   5   4   3   2   1   0
  12594.  +---------------------------------------------------------------+
  12595.  | C | I |   |   | O |   |   |   |   | 3 |   |   | C | N | S | S |
  12596.  | H | O |   |   | P |   |   |   |   | . |   |   | L | U | T | T |
  12597.  | R | C |   |   | N |   |   |   |   | 2 |   |   | K | L | O | I |
  12598.  +---------------------------------------------------------------+
  12599.  
  12600.         Figure 2.2  Attribute Word for Character Devices
  12601.  
  12602.  
  12603.    15  14  13  12  11  10  9   8   7   6   5   4   3   2   1   0
  12604.  +---------------------------------------------------------------+
  12605.  |   | I | F |   | O |   |   |   |   | 3 |   |   |   |   |   |   |
  12606.  |   | O | A |   | P |   |   |   |   | . |   |   |   |   |   |   |
  12607.  |   | C | T |   | N |   |   |   |   | 2 |   |   |   |   |   |   |
  12608.  +---------------------------------------------------------------+
  12609.  
  12610.           Figure 2.3  Attribute Word for Block Devices
  12611.  
  12612.  
  12613.  2.5.3  Strategy and Interrupt Routines
  12614.  
  12615.  These two fields are the pointers to the entry points of the strategy
  12616.  and interrupt routines. They are word values, so they must be in the same
  12617.  segment as the device header.
  12618.  
  12619.  
  12620.  2.5.4  Name Field
  12621.  
  12622.  This is an eight-byte field that contains the name of a character
  12623.  device or the number of units of a block device. If the field refers
  12624.  to a block device, the number of units can be put in the first byte. This
  12625.  is optional, because MS-DOS will fill in this location with the value
  12626.  returned by the driver's Init code. For more information, see Section 2.4,
  12627.  "Installing Device Drivers."
  12628.  
  12629.  
  12630.  2.6  Request Header
  12631.  
  12632.  
  12633.  When MS-DOS calls a device driver to perform a function, it passes a
  12634.  request header in ES:BX to the strategy entry point. This is a fixed
  12635.  length header, followed by data pertinent to the operation being performed.
  12636.  Note that it is the device driver's responsibility to preserve the machine
  12637.  state (for example, save all registers, including flags, on entry, and
  12638.  restore them on exit). There is enough room on the stack when the strategy
  12639.  or interrupt routine is called to do about 20 pushes. If more room on the
  12640.  stack is needed, the driver should set up its own stack.
  12641.  
  12642.  The following figure illustrates a request header.
  12643.  
  12644.  
  12645.  REQUEST HEADER ->
  12646.                 +-----------------------------+
  12647.                 | BYTE Length of record       |
  12648.                 |  Length in bytes of this    |
  12649.                 |  request header             |
  12650.                 +-----------------------------+
  12651.                 | BYTE Unit code              |
  12652.                 |  The subunit the operation  |
  12653.                 |  is for (minor device)      |
  12654.                 |  (no meaning on character   |
  12655.                 |   devices)                  |
  12656.                 +-----------------------------+
  12657.                 | BYTE Command code           |
  12658.                 +-----------------------------+
  12659.                 | WORD Status                 |
  12660.                 +-----------------------------+
  12661.                 | 8 BYTES Reserved            |
  12662.                 |                             |
  12663.                 |-----------------------------|
  12664.  
  12665.                   Figure 2.4  Request Header
  12666.  
  12667.  
  12668.  The request header fields are described below.
  12669.  
  12670.  
  12671.  2.6.1  Length of Record
  12672.  
  12673.  This field contains the length (in bytes) of the request header.
  12674.  
  12675.  2.6.2  Unit Code Field
  12676.  
  12677.  The unit code field identifies which unit in your device driver the
  12678.  request is for. For example, if your device driver has three units defined,
  12679.  then the possible values of the unit code field would be 0, 1, and 2.
  12680.  
  12681.  
  12682.  2.6.3  Command Code Field
  12683.  
  12684.  The command code field in the request header can have the following
  12685.  values:
  12686.  
  12687. ╓┌───────┌───────────────────────────────────────────────────────────────────╖
  12688.  Code    Function
  12689.  ──────────────────────────────────────────────────────────────────────────
  12690.  0       Init
  12691.  
  12692.  1       Media Check (Block devices only)
  12693.  
  12694.  2       Build BPB (Block devices only)
  12695.  
  12696.  3       IOCtl Input (Only called if device has IOCtl)
  12697.  
  12698.  4       Input (Read)
  12699.  
  12700.  5       Non-destructive Read, No Wait (Character devices only)
  12701.  
  12702.  6       Input Status (Character devices only)
  12703.  
  12704.  7       Input Flush (Character devices only)
  12705.  
  12706.  8       Output (Write)
  12707.  Code    Function
  12708. 8       Output (Write)
  12709.  
  12710.  9       Output (Write) with Verify
  12711.  
  12712.  10      Output Status (Character devices only)
  12713.  
  12714.  11      Output Flush (Character devices only)
  12715.  
  12716.  12      IOCtl Output (Only called if device has IOCtl)
  12717.  
  12718.  13      Device Open (Only called if Open/Close/Removable Media bit set)
  12719.  
  12720.  14      Device Close (Only called if Open/Close/Removable Media bit set)
  12721.  
  12722.  15      Removable Media (Only called if Open/Close/Removable Media bit
  12723.          set and device is block)
  12724.  
  12725.  16      Output Until Busy (Only called if bit 13 is set on character
  12726.          devices)
  12727.  
  12728.  Code    Function
  12729. 
  12730.  19      Generic IOCtl Request
  12731.  
  12732.  23      Get Logical Device
  12733.  
  12734.  24      Set Logical Device
  12735.  
  12736.  
  12737.  2.6.4  Status Field
  12738.  
  12739.  The following figure illustrates the status field in the request header.
  12740.  
  12741.  
  12742.        15  14 13 12 11 10  9   8   7  6  5  4  3  2  1  0
  12743.      +---+---+--+--+--+--+---+---+--+--+--+--+--+--+--+--+
  12744.      | E |               | B | D |                       |
  12745.      | R |   Reserved    | U | O | Error code (bit 15 on)|
  12746.      | R |               | S | N |                       |
  12747.      |   |               | Y | E |                       |
  12748.      +---+---+--+--+--+--+---+---+--+--+--+--+--+--+--+--+
  12749.  
  12750.                    Figure 2.5  Status Field
  12751.  
  12752.  
  12753.  The status word is zero on entry and is set by the driver interrupt routine
  12754.  on return.
  12755.  
  12756.  Bit 8 is the done bit. When set, it means the operation has
  12757.  completed. The driver sets it to 1 when it exits.
  12758.  
  12759.  Bit 15 is the error bit. If it is set, then the low eight bits
  12760.  indicate the error. The errors are as follows:
  12761.  
  12762.  Error    Meaning
  12763.  ───────────────────────────────────────────────────────────────────────────
  12764.  0        Write protect violation
  12765.  1        Unknown unit
  12766.  2        Drive not ready
  12767.  3        Unknown command
  12768.  4        CRC error
  12769.  5        Bad drive request structure length
  12770.  6        Seek error
  12771.  7        Unknown media
  12772.  8        Sector not found
  12773.  9        Printer out of paper
  12774.  A        Write fault
  12775.  B        Read fault
  12776.  C        General failure
  12777.  D        Reserved
  12778.  E        Reserved
  12779.  F        Invalid disk change
  12780.  
  12781.  Bit 9 is the busy bit, which is set only by Status calls and the
  12782.  Removable Media call.
  12783.  
  12784.  
  12785.  2.7  Device Driver Functions
  12786.  
  12787.  
  12788.  Device drivers may perform all or some of these general functions. In some
  12789.  cases, these functions break down into several command codes, for specific
  12790.  cases. Each of the following general functions is described in this
  12791.  section.
  12792.  
  12793.      ■ Init
  12794.  
  12795.      ■ Media Check
  12796.  
  12797.      ■ Build BPB
  12798.  
  12799.      ■ Read, or Write, or Write Until Busy, or Write with Verify,
  12800.        or Read IOCtl, or Write IOCtl
  12801.  
  12802.      ■ Non-destructive Read, No Wait
  12803.  
  12804.      ■ Open or Close (3.x)
  12805.  
  12806.      ■ Removable Media (3.x)
  12807.  
  12808.      ■ Status
  12809.  
  12810.      ■ Flush
  12811.  
  12812.      ■ Generic IOCtl
  12813.  
  12814.      ■ Get or Set Logical Device
  12815.  
  12816.  All strategy routines are called with ES:BX pointing to the request header.
  12817.  The interrupt routines get the pointers to the request header from the
  12818.  queue that the strategy routines store them in. The command code in the
  12819.  request header tells the driver which function to perform and what data
  12820.  follows the request header.
  12821.  
  12822.  ───────────────────────────────────────────────────────────────────────────
  12823.  Note
  12824.    All DWORD pointers are stored offset first, then segment.
  12825.  ───────────────────────────────────────────────────────────────────────────
  12826.  
  12827.  
  12828.  2.7.1  The Init Function
  12829.  
  12830.  Command code = 0
  12831.  
  12832.  INIT - ES:BX ->
  12833.  +------------------------------------+
  12834.  | 13-BYTE Request header             |
  12835.  +------------------------------------+
  12836.  | BYTE Number of units               |
  12837.  +------------------------------------+
  12838.  | DWORD End Address                  |
  12839.  +------------------------------------+
  12840.  | DWORD Pointer to BPB array         |
  12841.  | (Not set by character devices)     |
  12842.  +------------------------------------+
  12843.  | BYTE Block device number           |
  12844.  +------------------------------------+
  12845.  
  12846.  One of the functions defined for each device driver is Init. This routine
  12847.  is called only once when the device is installed. The Init routine must
  12848.  return the end address, which is a DWORD pointer to the end of the portion
  12849.  of the device driver to remain resident. To save space, you can use this
  12850.  pointer method to delete initialization code that is needed only once.
  12851.  
  12852.  The number of units, end address, and BPB pointer are to be set by the
  12853.  driver. However, on entry for installable device drivers, the DWORD that
  12854.  is to be set by the driver to the BPB array (on block devices) points to
  12855.  the character after the "=" on the line in config.sys that caused this
  12856.  device driver to be loaded. This allows drivers to scan the config.sys
  12857.  invocation line for parameters that might be passed to the driver. This
  12858.  line is terminated by a RETURN or a linefeed character. This data is
  12859.  read-only and allows the device to scan the config.sys command line
  12860.  for arguments.
  12861.  
  12862.       device=\dev\vt52.sys /l
  12863.              |
  12864.              |_____BPB address points here
  12865.  
  12866.  Also, for block devices only, the drive number assigned to the first unit
  12867.  defined by this driver (A=0) as contained in the block device number field.
  12868.  This is also read-only.
  12869.  
  12870.  ───────────────────────────────────────────────────────────────────────────
  12871.  Note
  12872.    The Init routine can issue only Functions 01H-0CH, 25H, 30H, and 35H.
  12873.  ───────────────────────────────────────────────────────────────────────────
  12874.  
  12875.  For installable character devices, the end address parameter must be
  12876.  returned. This is a pointer to the first available byte of memory above
  12877.  the driver and may be used to throw away initialization code.
  12878.  
  12879.  Block devices must return the following information:
  12880.  
  12881.      1.  The number of units must be returned. MS-DOS uses this number
  12882.          to determine logical device names. If the current maximum logical
  12883.          device letter is F at the time of the install call, and the Init
  12884.          routine returns 4 as the number of units, then they will have
  12885.          logical names G, H, I, and J. This mapping is determined by the
  12886.          position of the driver in the device list, and by the number of
  12887.          units on the device (stored in the first byte of the device
  12888.          name field).
  12889.  
  12890.      2.  A DWORD pointer to an array of word offsets (pointers) to BPBs
  12891.          (BIOS Parameter Blocks) must be returned. The BPBs passed
  12892.          by the device driver are used by MS-DOS to create an internal
  12893.          structure. There must be one entry in this array for each unit
  12894.          defined by the device driver. In this way, if all units are the
  12895.          same, all the pointers can point to the same BPB, saving space. If
  12896.          the device driver defines two units, then the DWORD pointer points
  12897.          to the first of two one-word offsets which in turn point to BPBs.
  12898.          The format of the BPB is described later in this chapter in Section
  12899.          2.7.3, "The Build BPB Function."
  12900.  
  12901.          Note that this array of word offsets must be protected (below the
  12902.          free pointer set by the return), since an internal DOS structure
  12903.          will be built starting at the byte pointed to by the free pointer.
  12904.          The defined sector size must be less than or equal to the maximum
  12905.          sector size defined by the resident device drivers (BIOS) during
  12906.          initialization. If it isn't, the installation will fail.
  12907.  
  12908.      3.  The last thing that the Init function of a block device must pass
  12909.          back is the media descriptor byte. This byte means nothing to
  12910.          MS-DOS, but is passed to devices so that they know what parameters
  12911.          MS-DOS is currently using for a particular drive.
  12912.  
  12913.  ───────────────────────────────────────────────────────────────────────────
  12914.  Note
  12915.    If there are multiple device drivers in a single file, MS-DOS uses the
  12916.    ending address returned by the last Init function called. All device
  12917.    drivers in a single file should return the same ending address. All
  12918.    devices in a single file should be grouped together low in memory with
  12919.    the initialization code for all devices following it in memory.
  12920.  ───────────────────────────────────────────────────────────────────────────
  12921.  
  12922.  
  12923.  2.7.2  The Media Check Function
  12924.  
  12925.  Command Code = 1
  12926.  
  12927.  MEDIA CHECK - ES:BX ->
  12928.  +------------------------------------+
  12929.  | 13-BYTE Request header             |
  12930.  +------------------------------------+
  12931.  | BYTE Media descriptor from BPB     |
  12932.  +------------------------------------+
  12933.  | BYTE Returned                      |
  12934.  +------------------------------------+
  12935.  | Returned DWORD pointer to previous |
  12936.  | Volume ID if bit 11 set and        |
  12937.  | Disk Changed is returned           |
  12938.  +------------------------------------+
  12939.  
  12940.  The Media Check function is used only with block devices. It is called
  12941.  when there is a pending drive-access call other than a file read or write,
  12942.  such as Open, Close, delete, and rename. Its purpose is to determine
  12943.  whether the media in the drive has been changed. If the driver can assure
  12944.  that the media has not been changed (through a door-lock or other interlock
  12945.  mechanism), MS-DOS performance is enhanced, because MS-DOS does not need to
  12946.  reread the FAT and invalidate in-memory buffers for each directory access.
  12947.  
  12948.  When a disk-access call to the DOS occurs (other than a file read or
  12949.  write), the following sequence of events takes place:
  12950.  
  12951.      1.  The DOS converts the drive letter into a unit number
  12952.          of a particular block device.
  12953.  
  12954.      2.  The device driver is then called to request a media check on that
  12955.          subunit to see if the disk might have been changed. MS-DOS passes
  12956.          the old media descriptor byte. The driver returns one of the
  12957.          following:
  12958.  
  12959.          Return    Meaning
  12960.          ───────────────────────────────────────────────────────────────────
  12961.          (1)       Media not changed
  12962.          (0)       Don't know if changed
  12963.          (-1)      Media changed
  12964.          value     Error (value is a standard error code value)
  12965.  
  12966.          If the media has not been changed, MS-DOS proceeds with the
  12967.          disk access.
  12968.  
  12969.          If the value returned is -1, then if there are any disk sectors
  12970.          that have been modified and not written back out to the disk for
  12971.          this unit, MS-DOS assumes that the disk has not been changed and
  12972.          proceeds. MS-DOS invalidates any other buffers for the unit and
  12973.          does a Build BPB call (see Step 3, following).
  12974.  
  12975.          If the media has been changed, MS-DOS invalidates all buffers
  12976.          associated with this unit including buffers with modified data that
  12977.          are waiting to be written, and requests a new BIOS Parameter Block
  12978.          via the Build BPB call (see Step 3).
  12979.  
  12980.      3.  Once the BPB has been returned, MS-DOS corrects its internal
  12981.          structure for the drive from the new BPB and proceeds with the
  12982.          access after reading the directory and the FAT.
  12983.  
  12984.  Note that the previous media ID byte is passed to the device driver.
  12985.  If the old media ID byte is the same as the new one, the disk might have
  12986.  been changed and a new disk may be in the drive; therefore, all FAT,
  12987.  directory, and data sectors that are buffered in memory for the drive
  12988.  are considered invalid.
  12989.  
  12990.  If the driver has bit 11 of the device attribute word set to 1, and
  12991.  the driver returns -1 (Media Changed) the driver must set the DWORD pointer
  12992.  to the previous Volume ID field. If the DOS determines that "Media changed"
  12993.  is an error based on the state of the DOS buffer cache, the DOS will
  12994.  generate a 0FH error on behalf of the device. If the driver does not
  12995.  implement volume ID support, but has bit 11 set, (it should set a static
  12996.  pointer to the string "NO NAME" ,0.)
  12997.  
  12998.  It is not possible for a user to change a disk in less than two
  12999.  seconds. So when Media Check occurs within two seconds of a disk access,
  13000.  the driver reports "Media not changed (1)." This improves performance
  13001.  tremendously.
  13002.  
  13003.  ───────────────────────────────────────────────────────────────────────────
  13004.  Note
  13005.    If the media ID byte in the returned BPB is the same as the previous
  13006.    media ID byte, MS-DOS will assume that the format of the disk is the same
  13007.    (even though the disk may have been changed) and will skip the step of
  13008.    updating its internal structure. Therefore, all BPBs must have unique
  13009.    media bytes regardless of FAT ID bytes.
  13010.  ───────────────────────────────────────────────────────────────────────────
  13011.  
  13012.  
  13013.  2.7.3  The Build BPB Function
  13014.  
  13015.  Command code = 2
  13016.  
  13017.  BUILD BPB - ES:BX ->
  13018.  +------------------------------------+
  13019.  | 13-BYTE Request header             |
  13020.  +------------------------------------+
  13021.  | BYTE Media descriptor from BPB     |
  13022.  +------------------------------------+
  13023.  | DWORD Transfer address             |
  13024.  | (Points to one sector worth of     |
  13025.  |  scratch space or first sector     |
  13026.  |  of FAT depending on the value     |
  13027.  |  of Bit 13 in the device attribute |
  13028.  |  word.)                            |
  13029.  +------------------------------------+
  13030.  | DWORD Pointer to BPB               |
  13031.  +------------------------------------+
  13032.  
  13033.  The Build BPB function is used with block devices only. As described in
  13034.  the Media Check function, the Build BPB function will be called any time
  13035.  that a preceding Media Check call indicates that the disk has been or might
  13036.  have been changed. The device driver must return a pointer to a BPB. This
  13037.  is different from the Init call where the device driver returns a pointer
  13038.  to an array of word offsets to BPBs.
  13039.  
  13040.  The Build BPB call gets a DWORD pointer to a one-sector buffer. The
  13041.  contents of this buffer are determined by the non-FAT ID bit (bit 13)
  13042.  in the attribute field. If the bit is zero, then the buffer contains the
  13043.  first sector of the first FAT. The FAT ID byte is the first byte of this
  13044.  buffer. In this case, the driver must not alter this buffer. Note that
  13045.  the location of the FAT must be the same for all possible media because
  13046.  this first FAT sector must be read before the actualBPB is returned.
  13047.  If the non-FAT ID bit is set, the pointer points to one sector of scratch
  13048.  space (which may be used for anything). For information on how to construct
  13049.  the BPB, see Section 2.8, "The Media Descriptor Byte," and Section 2.9,
  13050.  "Format of a Media Descriptor Table."
  13051.  
  13052.  MS-DOS 3.x includes additional support for devices that have door-locks
  13053.  or some other means of telling when a disk has been changed. There is a new
  13054.  error that can be returned from the device driver (error 15). The error
  13055.  means "the disk has been changed when it shouldn't have been," and the user
  13056.  is prompted for the correct disk using a volume ID. The driver may generate
  13057.  this error on read or write. The DOS may generate the error on Media Check
  13058.  calls if the driver reports media changed, and there are buffers in the DOS
  13059.  buffer cache that need to be flushed to the previous disk.
  13060.  
  13061.  For drivers that support this error, the Build BPB function is a trigger
  13062.  that causes a new volume ID to be read off the disk. This action indicates
  13063.  that the disk has been legally changed. A volume ID is placed on a disk by
  13064.  the format command, and is simply an entry in the root directory of the
  13065.  disk that has the Volume ID attribute. It is stored by the driver as an
  13066.  ASCIZ string.
  13067.  
  13068.  The requirement that the driver return a volume ID does not exclude
  13069.  some other volume identifier scheme as long as the scheme uses ASCIZ
  13070.  strings. A NUL (nonexistent or unsupported) volume ID is by convention
  13071.  the following string:
  13072.  
  13073.  DB     "NO NAME     ",0
  13074.  
  13075.  
  13076.  2.7.4  The Read or Write Function
  13077.  
  13078.  Command codes = 3,4,8,9,12, and 16
  13079.  
  13080.  READ OR WRITE (Including IOCtl) or
  13081.     OUTPUT UNTIL BUSY - ES:BX ->
  13082.  +------------------------------------+
  13083.  | 13-BYTE Request header             |
  13084.  +------------------------------------+
  13085.  | BYTE Media descriptor from BPB     |
  13086.  +------------------------------------+
  13087.  | DWORD Transfer address             |
  13088.  +------------------------------------+
  13089.  | WORD Byte/sector count             |
  13090.  +------------------------------------+
  13091.  | WORD Starting sector number        |
  13092.  |  (Ignored on character devices)    |
  13093.  +------------------------------------+
  13094.  | Returned DWORD pointer to requested|
  13095.  | Volume ID if error 0FH             |
  13096.  +------------------------------------+
  13097.  
  13098.  Code      Request
  13099.  ───────────────────────────────────────────────────────────────────────────
  13100.  3         IOCtl read
  13101.  4         Read (block or character device)
  13102.  8         Write (block or character device)
  13103.  9         Write with Verify
  13104.  12        IOCtl Write
  13105.  16        Output Until Busy (character device only)
  13106.  
  13107.  The driver must perform the Read or Write call depending on which command
  13108.  code is set. Block devices read or write sectors; character devices read or
  13109.  write bytes.
  13110.  
  13111.  When I/O completes, the device driver must set the status word and report
  13112.  the number of sectors or bytes successfully transferred. This should be
  13113.  done even if an error prevented the transfer from being completed. Setting
  13114.  the error bit and error code alone is not sufficient.
  13115.  
  13116.  In addition to setting the status word, the driver must set the sector
  13117.  count to the actual number of sectors (or bytes) transferred. No error
  13118.  check is performed on an IOCtl I/O call. The device driver must always
  13119.  set the return byte/sector count to the actual number of bytes/sectors
  13120.  successfully transferred.
  13121.  
  13122.  If the verify switch is on, the device driver will be called with command
  13123.  code 9 (Write with Verify). Your device driver will be responsible for
  13124.  verifying the write.
  13125.  
  13126.  If the driver returns error code 0FH (Invalid disk change), it must
  13127.  return a DWORD pointer to an ASCIZ string (which is the correct volume ID).
  13128.  Returning this error code triggers the DOS to prompt the user to re-insert
  13129.  the disk. The device driver should have read the volume ID as a result of
  13130.  the Build BPB function.
  13131.  
  13132.  Drivers may maintain a reference count of open files on the disk
  13133.  by monitoring the Open and Close functions. This allows the driver to
  13134.  determine when to return error 0FH. If there are no open files (reference
  13135.  count = 0), and the disk has been changed, the I/O is okay. If there are
  13136.  open files, however, an 0FH error may exist.
  13137.  
  13138.  The Output Until Busy call is a speed optimization on character devices
  13139.  only for print spoolers. The device driver is expected to output all the
  13140.  characters possible until the device returns busy. Under no circumstances
  13141.  should the device driver block during this function. Note that it is not an
  13142.  error for the device driver to return the number of bytes output as being
  13143.  less than the number of bytes requested (or = 0).
  13144.  
  13145.  The Output Until Busy call allows spooler programs to take advantage
  13146.  of the "burst" behavior of most printers. Many printers have on-board
  13147.  RAM buffers that typically hold a line or a fixed amount of characters.
  13148.  These buffers fill up without the printer going busy, or going busy for
  13149.  a short period (less than ten instructions) between characters. A line of
  13150.  characters can be quickly output to the printer, after which the printer
  13151.  is busy for a long time while the characters are being printed. This new
  13152.  device call allows background spooling programs to use this burst behavior
  13153.  efficiently. Rather than take the overhead of a device driver call for
  13154.  each character, or risk getting stuck in the device driver outputting a
  13155.  block of characters, this call allows a burst of characters to be output
  13156.  without the device driver having to wait for the device to be ready.
  13157.  
  13158.  
  13159.  The Following Applies to Block Device Drivers:
  13160.  
  13161.  Under certain circumstances, the BIOS may be asked to perform a write
  13162.  operation of 64K bytes, which seems to be a "wrap-around" of the transfer
  13163.  address in the BIOS I/O packet. This request, which arises due to an
  13164.  optimization added to the write code in MS-DOS, will manifest itself only
  13165.  on user writes that are within a sector size of 64K bytes on files
  13166.  "growing" past the current end-of-file (EOF) mark. It is allowable for
  13167.  the BIOS to ignore the balance of the write that "wraps around" if it so
  13168.  chooses. For example, a write of 10000H bytes worth of sectors with a
  13169.  transfer address of xxx:1 could ignore the last two bytes. A user program
  13170.  can never request an I/O of more than FFFFH bytes and cannot wrap around
  13171.  (even to 0) in the transfer segment. Therefore, in this case, the last
  13172.  two bytes can be ignored.
  13173.  
  13174.  MS-DOS maintains two FATs. If the DOS has problems reading the first,
  13175.  it automatically tries the second before reporting the error. The BIOS is
  13176.  responsible for all retries.
  13177.  
  13178.  Although the command.com handler does no automatic retries, there are
  13179.  applications that have their own Interrupt 24H handlers that do automatic
  13180.  retries on certain types of Interrupt 24H errors before reporting them.
  13181.  
  13182.  
  13183.  2.7.5  The Non-destructive Read, No Wait Function
  13184.  
  13185.  Command code = 5
  13186.  
  13187.  NON-DESTRUCTIVE READ NO WAIT - ES:BX ->
  13188.  +------------------------------------+
  13189.  | 13-BYTE Request header             |
  13190.  +------------------------------------+
  13191.  | BYTE Read from device              |
  13192.  +------------------------------------+
  13193.  
  13194.  The Non-destructive Read, No Wait function allows MS-DOS to look ahead one
  13195.  input character. The device sets the done bit in the status word.
  13196.  
  13197.  If the character device returns busy bit = 0 (there are characters in
  13198.  the buffer), then the next character that would be read is returned.
  13199.  This character is not removed from the input buffer (hence the term
  13200.  "Non-destructive Read"). If the character device returns busy bit = 1,
  13201.  there are no characters in the buffer.
  13202.  
  13203.  
  13204.  2.7.6  The Open or Close Function
  13205.  
  13206.  Command codes = 13 and 14
  13207.  
  13208.  OPEN or CLOSE  - ES:BX ->
  13209.  +------------------------------------+
  13210.  | 13-BYTE Static request header      |
  13211.  +------------------------------------+
  13212.  
  13213.  The Open and Close functions are called by MS-DOS 3.x only if the device
  13214.  driver sets the Open/Close/Removable Media attribute bit in the device
  13215.  header. They are designed to inform the device about current file activity
  13216.  on the device. On block devices, they can be used to manage local
  13217.  buffering. The device can keep a reference count. Every Open causes the
  13218.  device to increment the count, every Close to decrement. When the count
  13219.  goes to zero, it means there are no open files on the device, and the
  13220.  device should flush any buffers that have been written to that may have
  13221.  been used inside the device, because it is now "legal" for the user to
  13222.  change the media on a removable media drive.
  13223.  
  13224.  There are problems with this mechanism on block devices because programs
  13225.  that use FCB calls can open files without closing them. It is therefore
  13226.  advisable to reset the count to zero without flushing the buffers when the
  13227.  answer to "Has the media been changed?" is yes, and the Build BPB call
  13228.  is made to the device.
  13229.  
  13230.  These calls are more useful on character devices. The Open call, for
  13231.  instance, can be used to send a device initialization string. On a printer,
  13232.  this could cause a string for setting font and page size characteristics to
  13233.  be sent to the printer so that it would always be in a known state at the
  13234.  start of an I/O stream. Using IOCtl to set these pre- and post- strings
  13235.  provides a flexible mechanism of serial I/O device stream control. The
  13236.  reference count mechanism can also be used to detect a simultaneous access
  13237.  error. It may be desirable to disallow more than one Open on a device at
  13238.  any given time. In this case, a second Open would result in an error.
  13239.  
  13240.  Note that since all processes have access to stdin, stdout, stderr,
  13241.  stdaux, and stdprn (handles 0,1,2,3,4), the CON, AUX, and PRN devices are
  13242.  always open.
  13243.  
  13244.  
  13245.  2.7.7  The Removable Media Function
  13246.  
  13247.  Command code = 15
  13248.  
  13249.  REMOVABLE MEDIA - ES:BX ->
  13250.  +------------------------------------+
  13251.  | 13-BYTE Static request header      |
  13252.  +------------------------------------+
  13253.  
  13254.  The Removable Media function is called by MS-DOS 3.x only if the device
  13255.  driver sets the Open/Close/Removable Media attribute bit in the device
  13256.  header. This call is given only to block devices by a subfunction of the
  13257.  IOCtl system call. It is sometimes desirable for a utility to know whether
  13258.  it is dealing with a nonremovable media drive (such as a hard disk), or a
  13259.  removable media drive (like a floppy). An example is the format command,
  13260.  which prints different versions of some of the prompts.
  13261.  
  13262.  The information is returned in the busy bit of the status word. If the
  13263.  busy bit is 1, then the media is nonremovable. If the busy bit is 0,
  13264.  then the media is removable. Note that the error bit is not checked.
  13265.  It is assumed that this call always succeeds.
  13266.  
  13267.  
  13268.  2.7.8  The Status Function
  13269.  
  13270.  Command codes = 6 and 10
  13271.  
  13272.  STATUS Calls ES:BX ->
  13273.  +------------------------------------+
  13274.  | 13-BYTE Request header             |
  13275.  +------------------------------------+
  13276.  
  13277.  The Status function returns information to the DOS as to whether data is
  13278.  waiting for input or output. All the driver must do is set the status word
  13279.  and the busy bit as follows:
  13280.  
  13281.      ■ For output on character devices--if the driver sets bit 9 to 1 on
  13282.        return, it informs the DOS that a write request (if made) would wait
  13283.        for completion of a current request. If it is 0, there is no current
  13284.        request, and a write request (if made) would start immediately.
  13285.  
  13286.      ■ For input on character devices with a buffer--A return of 1 implies
  13287.        that no characters are buffered and that a read request (if made)
  13288.        would go to the physical device. If it is 0 on return, then there are
  13289.        characters in the device buffer and a read would not be blocked. A
  13290.        return of 0 implies that the user has typed something. MS-DOS assumes
  13291.        that all character devices have an input type-ahead buffer.
  13292.  
  13293.  Devices that do not have a type-ahead buffer should always return
  13294.  busy = 0 so that the DOS will not "hang" waiting for something to get
  13295.  into a nonexistent buffer.
  13296.  
  13297.  
  13298.  2.7.9  The Flush Function
  13299.  
  13300.  Command codes = 7 and 11
  13301.  
  13302.  FLUSH Calls - ES:BX ->
  13303.  +------------------------------------+
  13304.  | 13-BYTE Request header             |
  13305.  +------------------------------------+
  13306.  
  13307.  The Flush function tells the driver to flush (terminate) all pending
  13308.  requests. This call is used to flush the input queue on character devices.
  13309.  
  13310.  The device driver performs the flush function, sets the status word,
  13311.  and returns.
  13312.  
  13313.  
  13314.  2.7.10  The Generic IOCtl Function
  13315.  
  13316.  Command code = 19
  13317.  
  13318.  ES:BX ->
  13319.  +------------------------------------+
  13320.  | 13-BYTE Static request header      |
  13321.  +------------------------------------+
  13322.  | BYTE Category (Major) code         |
  13323.  +------------------------------------+
  13324.  | BYTE Function (Minor) code         |
  13325.  +------------------------------------+
  13326.  | WORD (SI) Contents                 |
  13327.  +------------------------------------+
  13328.  | WORD (DI) Contents                 |
  13329.  +------------------------------------+
  13330.  | DWORD Pointer to data buffer       |
  13331.  +------------------------------------+
  13332.  
  13333.  The Generic IOCtl function provides a generic, expandable IOCtl facility
  13334.  that replaces and makes the Read IOCtl and Write IOCtl device driver
  13335.  functions obsolete. The MS-DOS 2.0 IOCtl functions remain to support
  13336.  existing uses of the IOCtl system call (Subfunctions 2, 3, 4, and 5),
  13337.  but new device drivers should use this generic MS-DOS IOCtl facility.
  13338.  
  13339.  The Generic IOCtl function contains both a category and function code.
  13340.  The DOS examines the category field in order to intercept and obey device
  13341.  commands that are actually serviced by the DOS code; all other command
  13342.  categories are forwarded to the device driver for servicing.
  13343.  
  13344.  For more information on these category and function codes, refer to
  13345.  Function 440CH (Generic IOCtl for Handles) and Function 440DH (Generic
  13346.  IOCtl for Block Devices) in Chapter 1, "System Calls."
  13347.  
  13348.  
  13349.  2.7.11  The Get/Set Logical Drive Map Function
  13350.  
  13351.  Command codes = 23 (Get) or 24 (Set)
  13352.  
  13353.   +----------------------------------------+
  13354.   | 13-BYTE Static request header          |
  13355.   +----------------------------------------+
  13356.   | BYTE    Input (unit code)              |
  13357.   +----------------------------------------+
  13358.   | BYTE    Output (last device referenced)|
  13359.   +----------------------------------------+
  13360.   | BYTE    Command code                   |
  13361.   +----------------------------------------+
  13362.   | WORD    Status                         |
  13363.   +----------------------------------------+
  13364.   | DWORD   Reserved                       |
  13365.   +----------------------------------------+
  13366.  
  13367.  The Get/Set Logical Drive Map function is called by MS-DOS only if the
  13368.  device driver sets the DOS 3.2 attribute bit in the device header. The
  13369.  call is issued only to block devices by the subfunction of the IOCtl system
  13370.  call. The logical drive to be mapped is passed in the Unit field of the
  13371.  header to the device driver. The device driver returns the current logical
  13372.  drive owner of the physical device that maps to the requested physical
  13373.  drive. To detect whether a logical device currently owns the physical
  13374.  device to which it is mapped, a program needs to verify that, after a call
  13375.  of Function 440EH or 440FH (Get/Set Logical Drive Map), the value of the
  13376.  Unit field is unchanged.
  13377.  
  13378.  
  13379.  2.8  The Media Descriptor Byte
  13380.  
  13381.  
  13382.  In MS-DOS, the media descriptor byte is used to inform the DOS that a
  13383.  different type of media is present. The media descriptor byte can be any
  13384.  value between 0 and FFH. It does not have to be the same as the FAT ID
  13385.  byte. The FAT ID byte, which is the first byte of the FAT, was used in
  13386.  MS-DOS 1.00 to distinguish between different types of disk media, and may
  13387.  be used as well under 2.x and 3.x disk device drivers. However, FAT ID
  13388.  bytes have significance only for block device drivers where the
  13389.  non-FAT ID bit is not set (0).
  13390.  
  13391.  Values of the media descriptor byte or the FAT ID byte have no
  13392.  significance to MS-DOS. They are passed to the device driver so that
  13393.  programs can determine the media type.
  13394.  
  13395.  
  13396.  2.9  Format of a Media Descriptor Table
  13397.  
  13398.  
  13399.  The MS-DOS file system uses a linked list of pointers (one for each cluster
  13400.  or allocation unit) called the File Allocation Table (FAT). Unused clusters
  13401.  are represented by zero and end-of-file by FFFH (or FFFFH on units with
  13402.  16-bit FAT entries). No valid entry should ever point to a zero entry, but
  13403.  if one does, the first FAT entry (which would be pointed to by a zero
  13404.  entry) was reserved and set to end of chain. Eventually, several end of
  13405.  chain values were defined ([F]FF8-[F]FFFH), and these were used to
  13406.  distinguish different types of media.
  13407.  
  13408.  A preferable technique is to write a complete media descriptor table
  13409.  in the boot sector and use it for media identification. To ensure backward
  13410.  compatibility for systems whose drivers do not set the non-FAT ID bit
  13411.  (including the IBM PC implementation), it is necessary also to write the
  13412.  FAT ID bytes during the format process.
  13413.  
  13414.  To allow more flexibility for supporting many different disk formats
  13415.  in the future, it is recommended that the information relating to the BPB
  13416.  for a particular piece of media be kept in the boot sector. Figure 2.6
  13417.  shows the format of such a boot sector.
  13418.  
  13419.  
  13420.              +------------------------------------+
  13421.              | 3 BYTE Near JUMP to boot code      |
  13422.              +------------------------------------+
  13423.              | 8 BYTES OEM name and version       |
  13424.           ---+------------------------------------+---
  13425.           B  | WORD Bytes per sector              |
  13426.              +------------------------------------+
  13427.           B  | BYTE Sectors per allocation unit   |
  13428.              +------------------------------------+
  13429.           |  | WORD Reserved sectors              |
  13430.           V  +------------------------------------+
  13431.              | BYTE Number of FATs                |
  13432.              +------------------------------------+
  13433.              | WORD Number of root dir entries    |
  13434.              +------------------------------------+
  13435.              | WORD Number of sectors in logical  |
  13436.           ^  | image                              |
  13437.           |  +------------------------------------+
  13438.           B  | BYTE Media descriptor              |
  13439.           P  +------------------------------------+
  13440.           B  | WORD Number of FAT sectors         |
  13441.           ---+------------------------------------+---
  13442.              | WORD Sectors per track             |
  13443.              +------------------------------------+
  13444.              | WORD Number of heads               |
  13445.              +------------------------------------+
  13446.              | WORD Number of hidden sectors      |
  13447.              +------------------------------------+
  13448.              | WORD High order number of hidden   |
  13449.              | sectors                            |
  13450.              +------------------------------------+
  13451.              | DWORD Number of logical sectors    |
  13452.              +------------------------------------+
  13453.  
  13454.               Figure 2.6  Format of a Boot Sector
  13455.  
  13456.  
  13457.  Although MS-DOS does not use the five fields that follow the BPB, these
  13458.  fields may be used by a device driver to help it understand the media.
  13459.  
  13460.  The "Sectors per track" and "Number of heads" fields are useful for
  13461.  supporting different media which may have the same logical layout, but a
  13462.  different physical layout (for example, 40-track, double-sided versus
  13463.  80-track, single-sided). "Sectors per track" tells the device driver how
  13464.  the logical disk format is laid out on the physical disk.
  13465.  
  13466.  The "Number of hidden sectors" and "High order number of hidden sectors"
  13467.  fields may be used to support drive-partitioning schemes.
  13468.  
  13469.  The "Number of logical sectors" field is not currently used, but will
  13470.  tell the device driver how many sectors to reserve if the "Number of
  13471.  sectors in logical image" field is zero. (Note that this is intended
  13472.  for supporting devices that access more than 32 megabytes.)
  13473.  
  13474.  The following procedure is recommended for media determination by
  13475.  NON FAT ID format drivers:
  13476.  
  13477.      1.  Read the boot sector of the drive into the one-sector scratch
  13478.          space pointed to by the DWORD transfer address.
  13479.  
  13480.      2.  Determine if the first byte of the boot sector is an E9H or EBIT
  13481.          (the first byte of a 3-byte NEAR or 2-byte SHORT jump) or an EBH
  13482.          (the first byte of a 2-byte jump followed by an NOP). If so, a BPB
  13483.          is located beginning at offset 3. Return a pointer to it.
  13484.  
  13485.      3.  If the boot sector does not have a BPB table, it is probably a disk
  13486.          formatted under a 1.x version of MS-DOS and probably uses a FAT ID
  13487.          byte for determining media.
  13488.  
  13489.          The driver may optionally attempt to read the first sector of the
  13490.          FAT into the one-sector scratch area and read the first byte to
  13491.          determine media type based upon whatever FAT ID bytes may have been
  13492.          used on disks that are expected to be read by this system. Return
  13493.          a pointer to a hard-coded BPB.
  13494.  
  13495.  
  13496.  2.10  The CLOCK Device
  13497.  
  13498.  
  13499.  MS-DOS assumes that some sort of clock is available in the system.
  13500.  This may either be a CMOS real-time clock or an interval timer that
  13501.  is initialized at boot time by the user. The CLOCK device defines and
  13502.  performs functions like any other character device, except that it is
  13503.  identified by a bit in the attribute word. The DOS uses this bit to
  13504.  identify it; consequently, the CLOCK device may take any name. The IBM
  13505.  implementation uses the name $CLOCK so as not to conflict with existing
  13506.  files named clock.
  13507.  
  13508.  The CLOCK device is unique in that MS-DOS will read or write a 6-byte
  13509.  sequence that encodes the date and time. A write to this device will set
  13510.  the date and time; a read will get the date and time.
  13511.  
  13512.  Figure 2.7 illustrates the binary time format used by the CLOCK device:
  13513.  
  13514.  
  13515.    byte 0   byte 1   byte 2    byte 3   byte 4   byte 5
  13516.  +--------+--------+---------+--------+--------+---------+
  13517.  |        |        |         |        |        |         |
  13518.  |days since 1-1-80| minutes |  hours | sec/100| seconds |
  13519.  |low byte|hi byte |         |        |        |         |
  13520.  +--------+--------+---------+--------+--------+---------+
  13521.  
  13522.            Figure 2.7  Format of a Clock Device
  13523.  
  13524.  
  13525.  2.11  Anatomy of a Device Call
  13526.  
  13527.  The following steps illustrate what happens when MS-DOS calls on a block
  13528.  device driver to perform a Write request:
  13529.  
  13530.      1.  MS-DOS writes a request packet in a reserved area of memory.
  13531.  
  13532.      2.  MS-DOS calls the strategy entry point of the block device driver.
  13533.  
  13534.      3.  The device driver saves the ES and BX registers (ES:BX points
  13535.          to the request packet) and does a FAR return.
  13536.  
  13537.      4.  MS-DOS calls the interrupt entry point.
  13538.  
  13539.      5.  The device driver retrieves the pointer to the request packet and
  13540.          reads the command code (offset 2) to determine that this is a Write
  13541.          request. The device driver converts the command code to an index
  13542.          into a dispatch table and control passes to the Write routine.
  13543.  
  13544.      6.  The device driver reads the unit code (offset 1) to determine which
  13545.          disk drive it is supposed to write to.
  13546.  
  13547.      7.  Since the command is a disk Write, the device driver must get the
  13548.          transfer address (offset 14), the sector count (offset 18), and
  13549.          the start sector (offset 20) in the request packet.
  13550.  
  13551.      8.  The device driver translates the first logical sector number into
  13552.          a track, head, and sector number.
  13553.  
  13554.      9.  The device driver writes the specified number of sectors, starting
  13555.          at the beginning sector on the drive defined by the unit code (the
  13556.          subunit defined  by this device driver), and transfers data from
  13557.          the transfer address indicated in the request packet. Note that
  13558.          this may involve multiple Write commands to the disk controller.
  13559.  
  13560.     10.  After the transfer is complete, the device driver must report
  13561.          the status of the request to MS-DOS by setting the done bit in the
  13562.          status word (offset 3 in the request packet). It reports the number
  13563.          of sectors actually transferred in the sector count area of the
  13564.          request packet.
  13565.  
  13566.     11.  If an error occurs, the driver sets the done bit and the error
  13567.          bit in the status word and fills in the error code in the lower
  13568.          half of the status word. The number of sectors actually
  13569.          transferred must be written in the request header. It is not
  13570.          sufficient just to set the error bit of the status word.
  13571.  
  13572.     12.  The device driver does a FAR return to MS-DOS.
  13573.  
  13574.  The device drivers should preserve the state of MS-DOS. This means
  13575.  that all registers (including flags) should be preserved. The direction
  13576.  flag and interrupt enable bits are critical. When the interrupt entry
  13577.  point in the device driver is called, MS-DOS has room for about 40 to 50
  13578.  bytes on its internal stack. Your device driver should switch to a local
  13579.  stack if it uses extensive stack operations.
  13580.  
  13581.  
  13582.  12.12  Two Sample Device Drivers
  13583.  
  13584.  The following two examples illustrate a block device driver and a
  13585.  character device driver program. These examples are provided as guides
  13586.  for writing your own device drivers. However, since device drivers are
  13587.  hardware-dependent, your device drivers will differ.
  13588.  
  13589.  
  13590.  Block Device Driver
  13591.  
  13592.  
  13593.  ;********************* A Block Device *******************
  13594.  
  13595.          Title   5.25-inch Disk Driver
  13596.  
  13597.  ;This driver is intended to drive up to four 5.25-inch
  13598.  ;drives hooked to a single disk controller. All standard
  13599.  ;IBM PC formats are supported.
  13600.  
  13601.  
  13602.  FALSE   EQU     0
  13603.  TRUE    EQU     NOT FALSE
  13604.  
  13605.  ;The I/O port address of the disk controller
  13606.  DISK    EQU     0E0H
  13607.  ;DISK+0
  13608.  ;       1793    Command/Status
  13609.  ;DISK+1
  13610.  ;       1793    Track
  13611.  ;DISK+2
  13612.  ;       1793    Sector
  13613.  ;DISK+3
  13614.  ;       1793    Data
  13615.  ;DISK+4
  13616.  ;       Aux Command/Status
  13617.  ;DISK+5
  13618.  ;       Wait Sync
  13619.  
  13620.  ;Back side select bit
  13621.  BACKBIT EQU     04H
  13622.  ;5 1/4" select bit
  13623.  SMALBIT EQU     10H
  13624.  ;Double Density bit
  13625.  DDBIT   EQU     08H
  13626.  
  13627.  ;Done bit in status register
  13628.  DONEBIT EQU     01H
  13629.  
  13630.  ;Use table below to select head step speed.
  13631.  ;Step times for 5" drives
  13632.  ;are double that shown in the table.
  13633.  ;
  13634.  ;Step value    1771    1793
  13635.  ;
  13636.  ;    0          6ms     3ms
  13637.  ;    1          6ms     6ms
  13638.  ;    2         10ms    10ms
  13639.  ;    3         20ms    15ms
  13640.  ;
  13641.  STPSPD  EQU     1
  13642.  
  13643.  NUMERR  EQU     ERROUT-ERRIN
  13644.  
  13645.  CR      EQU     0DH
  13646.  LF      EQU     0AH
  13647.  
  13648.  CODE    SEGMENT
  13649.  ASSUME  CS:CODE,DS:NOTHING,ES:NOTHING,SS:NOTHING
  13650.  ;-----------------------------------------------------
  13651.  ;
  13652.  ;       Device Header
  13653.  ;
  13654.  DRVDEV  LABEL   WORD
  13655.          DW      -1,-1
  13656.          DW      0000     ;IBM format-compatible, Block
  13657.          DW      STRATEGY
  13658.          DW      DRV$IN
  13659.  DRVMAX  DB      4
  13660.  
  13661.  DRVTBL  LABEL   WORD
  13662.          DW      DRV$INIT
  13663.          DW      MEDIA$CHK
  13664.          DW      GET$BPB
  13665.          DW      CMDERR
  13666.          DW      DRV$READ
  13667.          DW      EXIT
  13668.          DW      EXIT
  13669.          DW      EXIT
  13670.          DW      DRV$WRIT
  13671.          DW      DRV$WRIT
  13672.          DW      EXIT
  13673.          DW      EXIT
  13674.          DW      EXIT
  13675.  
  13676.  ;------------------------------------
  13677.  ;
  13678.  ;       Strategy
  13679.  
  13680.  PTRSAV  DD      0
  13681.  
  13682.  STRATP  PROC    FAR
  13683.  STRATEGY:
  13684.          MOV     WORD PTR [PTRSAV],BX
  13685.          MOV     WORD PTR [PTRSAV+2],ES
  13686.          RET
  13687.  STRATP  ENDP
  13688.  
  13689.  ;--------------------------------------
  13690.  ;
  13691.  ;       Main Entry
  13692.  
  13693.  
  13694.  CMDLEN  =       0       ;Length of this command
  13695.  UNIT    =       1       ;Subunit specified
  13696.  CMDC    =       2       ;Command Code
  13697.  STATUS  =       3       ;Status
  13698.  MEDIA   =       13      ;Media Descriptor
  13699.  TRANS   =       14      ;Transfer Address
  13700.  COUNT   =       18      ;Count of blocks or characters
  13701.  START   =       20      ;First block to transfer
  13702.  
  13703.  DRV$IN:
  13704.          PUSH    SI
  13705.          PUSH    AX
  13706.          PUSH    CX
  13707.          PUSH    DX
  13708.          PUSH    DI
  13709.          PUSH    BP
  13710.          PUSH    DS
  13711.          PUSH    ES
  13712.          PUSH    BX
  13713.  
  13714.          LDS     BX,[PTRSAV]     ;Get pointer to I/O packet
  13715.  
  13716.          MOV     AL,BYTE PTR [BX].UNIT   ;AL = Unit Code
  13717.          MOV     AH,BYTE PTR [BX].MEDIA  ;AH = Media Descrip
  13718.          MOV     CX,WORD PTR [BX].COUNT  ;CX = Count
  13719.          MOV     DX,WORD PTR [BX].START  ;DX = Start Sector
  13720.          PUSH    AX
  13721.          MOV     AL,BYTE PTR [BX].CMDC   ;Command code
  13722.          CMP     AL,15
  13723.          JA      CMDERRP                 ;Bad command
  13724.          CBW
  13725.          SHL     AX,1                    ;2 times command =
  13726.                                          ;word table index
  13727.          MOV     SI,OFFSET DRVTBL
  13728.          ADD     SI,AX                   ;Index into table
  13729.          POP     AX                      ;Get back media
  13730.                                          ;and unit
  13731.  
  13732.          LES     DI,DWORD PTR [BX].TRANS ;ES:DI = Transfer
  13733.                                          ;Address
  13734.  
  13735.          PUSH    CS
  13736.          POP     DS
  13737.  
  13738.  ASSUME  DS:CODE
  13739.  
  13740.          JMP     WORD PTR [SI]             ;GO DO COMMAND
  13741.  
  13742.  ;----------------------------------------------------------
  13743.  ;
  13744.  ;       EXIT - All Routines return through this path
  13745.  ;
  13746.  ASSUME  DS:NOTHING
  13747.  CMDERRP:
  13748.          POP     AX                    ;Clean stack
  13749.  CMDERR:
  13750.          MOV     AL,3                  ;Unknown command error
  13751.          JMP     SHORT ERR$EXIT
  13752.  
  13753.  ERR$CNT:LDS     BX,[PTRSAV]
  13754.          SUB     WORD PTR [BX].COUNT,CX ;# OF SUCCESS. I/Os
  13755.  
  13756.  ERR$EXIT:
  13757.  ;AL has error code
  13758.          MOV     AH,10000001B            ;Mark error return
  13759.          JMP     SHORT ERR1
  13760.  
  13761.  EXITP   PROC    FAR
  13762.  
  13763.  EXIT:   MOV     AH,00000001B
  13764.  ERR1:   LDS     BX,[PTRSAV]
  13765.          MOV     WORD PTR [BX].STATUS,AX
  13766.                                      ;Mark Operation
  13767.  CompleteE
  13768.  
  13769.          POP     BX
  13770.          POP     ES
  13771.          POP     DS
  13772.          POP     BP
  13773.          POP     DI
  13774.          POP     DX
  13775.          POP     CX
  13776.          POP     AX
  13777.          POP     SI
  13778.          RET                         ;Restore REGS and return
  13779.  EXITP   ENDP
  13780.  
  13781.  CURDRV  DB      -1
  13782.  
  13783.  TRKTAB  DB      -1,-1,-1,-1
  13784.  
  13785.  SECCNT  DW      0
  13786.  
  13787.  DRVLIM  =       8       ;Number of sectors on device
  13788.  SECLIM  =       13      ;Maximum Sector
  13789.  HDLIM   =       15      ;Maximum Head
  13790.  
  13791.  ;WARNING - preserve order of drive and curhd!
  13792.  
  13793.  DRIVE   DB      0       ;Physical Drive Code
  13794.  CURHD   DB      0       ;Current Head
  13795.  CURSEC  DB      0       ;Current Sector
  13796.  CURTRK  DW      0       ;Current Track
  13797.  
  13798.  ;
  13799.  MEDIA$CHK:              ;Always indicates Don't know
  13800.  ASSUME  DS:CODE
  13801.          TEST    AH,00000100B       ;Test if Media Removable
  13802.          JZ      MEDIA$EXT
  13803.          XOR     DI,DI              ;Say I Don't know
  13804.  MEDIA$EXT:
  13805.          LDS     BX,[PTRSAV]
  13806.          MOV     WORD PTR [BX].TRANS,DI
  13807.          JMP     EXIT
  13808.  
  13809.  BUILD$BPB:
  13810.  ASSUME  DS:CODE
  13811.          MOV     AH,BYTE PTR ES:[DI]       ;Get FAT ID Byte
  13812.          CALL    BUILDBP                   ;Translate
  13813.  SETBPB: LDS     BX,[PTRSAV]
  13814.          MOV     [BX].MEDIA,AH
  13815.          MOV     [BX].COUNT,DI
  13816.          MOV     [BX].COUNT+2,CS
  13817.          JMP     EXIT
  13818.  
  13819.  BUILDBP:
  13820.  ASSUME  DS:NOTHING
  13821.  ;AH is media byte on entry
  13822.  ;DI points to correct BPB on return
  13823.          PUSH    AX
  13824.          PUSH    CX
  13825.          PUSH    DX
  13826.          PUSH    BX
  13827.          MOV     CL,AH       ;Save Media
  13828.          AND     CL,0F8H     ;Normalize
  13829.          CMP     CL,0F8H     ;Compare with Good Media Byte
  13830.          JZ      GOODID
  13831.          MOV     AH,0FEH     ;Default to 8-sector,
  13832.                              ;Single-sided
  13833.  GOODID:
  13834.          MOV     AL,1        ;Set number of FAT sectors
  13835.          MOV     BX,64*256+8 ;Set Dir Entries and Sector Max
  13836.          MOV     CX,40*8     ;Set Size of Drive
  13837.          MOV     DX,01*256+1 ;Set Head Limit & Sec/All Unit
  13838.          MOV     DI,OFFSET DRVBPB
  13839.          TEST    AH,00000010B ;Test for 8 OR 9 Sectors
  13840.          JNZ     HAS8        ;NZ = has 8 sectors
  13841.          INC     AL          ;Inc Number of FAT sectors
  13842.          INC     BL          ;Inc Sector Max
  13843.          ADD     CX,40       ;Increase Size
  13844.  HAS8:   TEST    AH,00000001B    ;Test for 1 or 2 Heads
  13845.          JZ      HAS1        ;Z = 1 Head
  13846.          ADD     CX,CX       ;Double Size of Disk
  13847.          MOV     BH,112      ;Increase # of Dir Entries
  13848.          INC     DH          ;Inc Sec/All Unit
  13849.          INC     DL          ;Inc Head Limit
  13850.  HAS1:   MOV     BYTE PTR [DI].2,DH
  13851.          MOV     BYTE PTR [DI].6,BH
  13852.          MOV     WORD PTR [DI].8,CX
  13853.          MOV     BYTE PTR [DI].10,AH
  13854.          MOV     BYTE PTR [DI].11,AL
  13855.          MOV     BYTE PTR [DI].13,BL
  13856.          MOV     BYTE PTR [DI].15,DL
  13857.          POP     BX
  13858.          POP     DX
  13859.          POP     CX
  13860.          POP     AX
  13861.          RET
  13862.  
  13863.  ;----------------------------------------------------------
  13864.  ;
  13865.  ;       Disk I/O Handlers
  13866.  ;
  13867.  ;ENTRY:
  13868.  ;       AL = Drive Number (0-3)
  13869.  ;       AH = Media Descriptor
  13870.  ;       CX = Sector Count
  13871.  ;       DX = First Sector
  13872.  ;       DS = CS
  13873.  ;       ES:DI = Transfer Address
  13874.  ;EXIT:
  13875.  ;       IF Successful Carry Flag = 0
  13876.  ;         ELSE CF=1 AND AL contains (MS-DOS) Error Code,
  13877.            CX # sectors NOT transferred
  13878.  
  13879.  DRV$READ:
  13880.  ASSUME  DS:CODE
  13881.          JCXZ    DSKOK
  13882.          CALL    SETUP
  13883.          JC      DSK$IO
  13884.          CALL    DISKRD
  13885.          JMP     SHORT DSK$IO
  13886.  
  13887.  DRV$WRIT:
  13888.  ASSUME  DS:CODE
  13889.          JCXZ    DSKOK
  13890.          CALL    SETUP
  13891.          JC      DSK$IO
  13892.          CALL    DISKWRT
  13893.  ASSUME  DS:NOTHING
  13894.  DSK$IO: JNC     DSKOK
  13895.          JMP     ERR$CNT
  13896.  DSKOK:  JMP     EXIT
  13897.  
  13898.  SETUP:
  13899.  ASSUME  DS:CODE
  13900.  ;Input same as above
  13901.  ;On output
  13902.  ; ES:DI = Trans addr
  13903.  ; DS:BX Points to BPB
  13904.  ; Carry set if error (AL is error code (MS-DOS))
  13905.  ; else
  13906.  ;       [DRIVE] = Drive number (0-3)
  13907.  ;       [SECCNT] = Sectors to transfer
  13908.  ;       [CURSEC] = Sector number of start of I/O
  13909.  ;       [CURHD]  = Head number of start of I/O   ;Set
  13910.  ;       [CURTRK] = Track # of start of I/O ;Seek performed
  13911.  ; All other registers destroyed
  13912.  
  13913.          XCHG   BX,DI              ;ES:BX = Transfer Address
  13914.          CALL   BUILDBP            ;DS:DI = PTR to B.P.B
  13915.          MOV    SI,CX
  13916.          ADD    SI,DX
  13917.          CMP    SI,WORD PTR [DI].DRVLIM
  13918.                                   ;Compare Against Drive Max
  13919.          JBE    INRANGE
  13920.          MOV    AL,8
  13921.          STC
  13922.          RET
  13923.  
  13924.  INRANGE:
  13925.          MOV    [DRIVE],AL
  13926.          MOV    [SECCNT],CX     ;Save Sector Count
  13927.          XCHG   AX,DX           ;Set Up Logical Sector
  13928.                                 ;For Divide
  13929.          XOR    DX,DX
  13930.          DIV    WORD PTR [DI].SECLIM ;Divide by Sec per Track
  13931.          INC    DL
  13932.          MOV    [CURSEC],DL          ;Save Current Sector
  13933.          MOV    CX,WORD PTR [DI].HDLIM ;Get Number of Heads
  13934.          XOR    DX,DX   ;Divide Tracks by Heads per Cylinder
  13935.          DIV    CX
  13936.          MOV    [CURHD],DL      ;Save Current Head
  13937.          MOV    [CURTRK],AX     ;Save Current Track
  13938.  SEEK:
  13939.          PUSH   BX              ;Xaddr
  13940.          PUSH   DI              ;BPB pointer
  13941.          CALL   CHKNEW          ;Unload head if change drives
  13942.          CALL   DRIVESEL
  13943.          MOV    BL,[DRIVE]
  13944.          XOR    BH,BH           ;BX drive index
  13945.          ADD    BX,OFFSET TRKTAB        ;Get current track
  13946.          MOV    AX,[CURTRK]
  13947.          MOV    DL,AL         ;Save desired track
  13948.          XCHG   AL,DS:[BX]    ;Make desired track current
  13949.          OUT    DISK+1,AL     ;Tell Controller current track
  13950.          CMP    AL,DL         ;At correct track?
  13951.          JZ     SEEKRET       ;Done if yes
  13952.          MOV    BH,2          ;Seek retry count
  13953.          CMP    AL,-1         ;Position Known?
  13954.          JNZ    NOHOME        ;If not home head
  13955.  TRYSK:
  13956.          CALL   HOME
  13957.          JC     SEEKERR
  13958.  NOHOME:
  13959.          MOV    AL,DL
  13960.          OUT    DISK+3,AL       ;Desired track
  13961.          MOV    AL,1CH+STPSPD   ;Seek
  13962.          CALL   DCOM
  13963.          AND    AL,98H    ;Accept not rdy, seek, & CRC errors
  13964.          JZ     SEEKRET
  13965.          JS     SEEKERR         ;No retries if not ready
  13966.          DEC    BH
  13967.          JNZ    TRYSK
  13968.  SEEKERR:
  13969.          MOV    BL,[DRIVE]
  13970.          XOR    BH,BH           ;BX drive index
  13971.          ADD    BX,OFFSET TRKTAB        ;Get current track
  13972.          MOV    BYTE PTR DS:[BX],-1     ;Make current track
  13973.                                         ;unknown
  13974.          CALL   GETERRCD
  13975.          MOV    CX,[SECCNT]     ;Nothing transferred
  13976.          POP    BX              ;BPB pointer
  13977.          POP    DI              ;Xaddr
  13978.          RET
  13979.  
  13980.  SEEKRET:
  13981.          POP    BX              ;BPB pointer
  13982.          POP    DI              ;Xaddr
  13983.          CLC
  13984.          RET
  13985.  
  13986.  ;---------------------------------------------
  13987.  ;
  13988.  ;       Read
  13989.  ;
  13990.  
  13991.  DISKRD:
  13992.  ASSUME  DS:CODE
  13993.          MOV    CX,[SECCNT]
  13994.  RDLP:
  13995.          CALL   PRESET
  13996.          PUSH   BX
  13997.          MOV    BL,10              ;Retry count
  13998.          MOV    DX,DISK+3          ;Data port
  13999.  RDAGN:
  14000.          MOV    AL,80H             ;Read command
  14001.          CLI                       ;Disable for 1793
  14002.          OUT    DISK,AL            ;Output read command
  14003.          MOV    BP,DI              ;Save address for retry
  14004.          JMP    SHORT RLOOPENTRY
  14005.  RLOOP:
  14006.          STOSB
  14007.  RLOOPENTRY:
  14008.          IN     AL,DISK+5          ;Wait for DRQ or INTRQ
  14009.          SHR    AL,1
  14010.          IN     AL,DX              ;Read data
  14011.          JNC    RLOOP
  14012.          STI                       ;Ints OK now
  14013.          CALL   GETSTAT
  14014.          AND    AL,9CH
  14015.          JZ     RDPOP              ;Ok
  14016.          MOV    DI,BP              ;Get back transfer
  14017.          DEC    BL
  14018.          JNZ    RDAGN
  14019.          CMP    AL,10H             ;Record not found?
  14020.          JNZ    GOT_CODE           ;No
  14021.          MOV    AL,1               ;Map it
  14022.  GOT_CODE:
  14023.          CALL   GETERRCD
  14024.          POP    BX
  14025.          RET
  14026.  
  14027.  RDPOP:
  14028.          POP    BX
  14029.          LOOP   RDLP
  14030.          CLC
  14031.          RET
  14032.  
  14033.  ;---------------------------------------------
  14034.  ;
  14035.  ;       Write
  14036.  ;
  14037.  
  14038.  DISKWRT:
  14039.  ASSUME  DS:CODE
  14040.          MOV     CX,[SECCNT]
  14041.          MOV     SI,DI
  14042.          PUSH    ES
  14043.          POP     DS
  14044.  ASSUME  DS:NOTHING
  14045.  WRLP:
  14046.          CALL    PRESET
  14047.          PUSH    BX
  14048.          MOV     BL,10                   ;Retry count
  14049.          MOV     DX,DISK+3               ;Data port
  14050.  WRAGN:
  14051.          MOV     AL,0A0H            ;Write command
  14052.          CLI                        ;Disable for 1793
  14053.          OUT     DISK,AL            ;Output write command
  14054.          MOV     BP,SI              ;Save address for retry
  14055.  WRLOOP:
  14056.          IN      AL,DISK+5
  14057.          SHR     AL,1
  14058.          LODSB                      ;Get data
  14059.          OUT     DX,AL              ;Write data
  14060.          JNC     WRLOOP
  14061.          STI                        ;Ints OK now
  14062.          DEC     SI
  14063.          CALL    GETSTAT
  14064.          AND     AL,0FCH
  14065.          JZ      WRPOP              ;Ok
  14066.          MOV     SI,BP              ;Get back transfer
  14067.          DEC     BL
  14068.          JNZ     WRAGN
  14069.          CALL    GETERRCD
  14070.          POP     BX
  14071.          RET
  14072.  
  14073.  WRPOP:
  14074.          POP     BX
  14075.          LOOP    WRLP
  14076.          CLC
  14077.          RET
  14078.  
  14079.  PRESET:
  14080.  ASSUME  DS:NOTHING
  14081.          MOV     AL,[CURSEC]
  14082.          CMP     AL,CS:[BX].SECLIM
  14083.          JBE     GOTSEC
  14084.          MOV     DH,[CURHD]
  14085.          INC     DH
  14086.          CMP     DH,CS:[BX].HDLIM
  14087.          JB      SETHEAD            ;Select new head
  14088.          CALL    STEP               ;Go on to next track
  14089.          XOR     DH,DH              ;Select head zero
  14090.  SETHEAD:
  14091.          MOV     [CURHD],DH
  14092.          CALL    DRIVESEL
  14093.          MOV     AL,1               ;First sector
  14094.          MOV     [CURSEC],AL        ;Reset CURSEC
  14095.  GOTSEC:
  14096.          OUT     DISK+2,AL     ;Tell controller which sector
  14097.          INC     [CURSEC]      ;We go on to next sector
  14098.          RET
  14099.  
  14100.  STEP:
  14101.  ASSUME  DS:NOTHING
  14102.          MOV     AL,58H+STPSPD  ;Step in w/ update, no verify
  14103.          CALL    DCOM
  14104.          PUSH    BX
  14105.          MOV     BL,[DRIVE]
  14106.          XOR     BH,BH           ;BX drive index
  14107.          ADD     BX,OFFSET TRKTAB        ;Get current track
  14108.          INC     BYTE PTR CS:[BX]        ;Next track
  14109.          POP     BX
  14110.          RET
  14111.  
  14112.  HOME:
  14113.  ASSUME  DS:NOTHING
  14114.          MOV     BL,3
  14115.  TRYHOM:
  14116.          MOV     AL,0CH+STPSPD   ;Restore with verify
  14117.          CALL    DCOM
  14118.          AND     AL,98H
  14119.          JZ      RET3
  14120.          JS      HOMERR          ;No retries if not ready
  14121.          PUSH    AX              ;Save real error code
  14122.          MOV     AL,58H+STPSPD   ;Step in w/ update no verify
  14123.          CALL    DCOM
  14124.          DEC     BL
  14125.          POP     AX              ;Get back real error code
  14126.          JNZ     TRYHOM
  14127.  HOMERR:
  14128.          STC
  14129.  RET3:   RET
  14130.  
  14131.  CHKNEW:
  14132.  ASSUME  DS:NOTHING
  14133.          MOV     AL,[DRIVE]      ;Get disk drive number
  14134.          MOV     AH,AL
  14135.          XCHG    AL,[CURDRV]     ;Make new drive current.
  14136.          CMP     AL,AH           ;Changing drives?
  14137.          JZ      RET1            ;No
  14138.  ; If changing drives, unload head so the head load delay
  14139.  ;one-shot will fire again. Do it by seeking to the same
  14140.  ;track with the H bit reset.
  14141.  ;
  14142.          IN      AL,DISK+1       ;Get current track number
  14143.          OUT     DISK+3,AL       ;Make it the track to seek
  14144.          MOV     AL,10H          ;Seek and unload head
  14145.  
  14146.  DCOM:
  14147.  ASSUME  DS:NOTHING
  14148.          OUT     DISK,AL
  14149.          PUSH    AX
  14150.          AAM                     ;Delay 10 microseconds
  14151.          POP     AX
  14152.  GETSTAT:
  14153.          IN      AL,DISK+4
  14154.          TEST    AL,DONEBIT
  14155.          JZ      GETSTAT
  14156.          IN      AL,DISK
  14157.  RET1:   RET
  14158.  
  14159.  DRIVESEL:
  14160.  ASSUME  DS:NOTHING
  14161.  ;Select the drive based on current info
  14162.  ;Only AL altered
  14163.          MOV     AL,[DRIVE]
  14164.          OR      AL,SMALBIT + DDBIT      ;5 1/4" IBM PC disks
  14165.          CMP     [CURHD],0
  14166.          JZ      GOTHEAD
  14167.          OR      AL,BACKBIT      ;Select side 1
  14168.  GOTHEAD:
  14169.          OUT     DISK+4,AL       ;Select drive and side
  14170.          RET
  14171.  
  14172.  GETERRCD:
  14173.  ASSUME  DS:NOTHING
  14174.          PUSH    CX
  14175.          PUSH    ES
  14176.          PUSH    DI
  14177.          PUSH    CS
  14178.          POP     ES              ;Make ES the local segment
  14179.          MOV     CS:[LSTERR],AL  ;Terminate list w/ error code
  14180.          MOV     CX,NUMERR       ;Number of error conditions
  14181.          MOV     DI,OFFSET ERRIN ;Point to error conditions
  14182.          RECRE   SCASB
  14183.          MOV     AL,NUMERR-1[DI] ;Get translation
  14184.          STC                     ;Flag error condition
  14185.          POP     DI
  14186.          POP     ES
  14187.          POP     CX
  14188.          RET                     ;and return
  14189.  
  14190.  ;*********************************************************
  14191.  ;       BPB for an IBM floppy disk, Various parameters are
  14192.  ;       patched by BUILDBP to reflect the type of Media
  14193.  ;       inserted
  14194.  ;       This is a 9-sector, single-side BPB
  14195.  DRVBPB:
  14196.          DW      512          ;Physical sector size in bytes
  14197.          DB      1            ;Sectors/allocation unit
  14198.          DW      1            ;Reserved sectors for DOS
  14199.          DB      2            ;# of allocation tables
  14200.          DW      64           ;Number directory entries
  14201.          DW      9*40         ;Number 512-byte sectors
  14202.          DB      11111100B    ;Media descriptor
  14203.          DW      2            ;Number of FAT sectors
  14204.          DW      9            ;Sector limit
  14205.          DW      1            ;Head limit
  14206.  
  14207.  INITAB  DW      DRVBPB               ;Up to four units
  14208.          DW      DRVBPB
  14209.          DW      DRVBPB
  14210.          DW      DRVBPB
  14211.  
  14212.  ERRIN:  ;Disk errors returned from the controller
  14213.          DB      80H             ;No response
  14214.          DB      40H             ;Write protect
  14215.          DB      20H             ;Write Fault
  14216.          DB      10H             ;SEEK error
  14217.          DB      8               ;CRC error
  14218.          DB      1               ;Mapped from 10H
  14219.                                  ;(record not found) on Read
  14220.  LSTERR  DB      0               ;All other errors
  14221.  
  14222.  ERROUT: ;Returned error codes corresponding to above
  14223.          DB      2               ;No response
  14224.          DB      0               ;Write Attempt
  14225.                                  ;On Write-protected disk
  14226.          DB      0AH             ;Write fault
  14227.          DB      6               ;SEEK Failure
  14228.          DB      4               ;Bad CRC
  14229.          DB      8               ;Sector not found
  14230.          DB      12              ;General error
  14231.  
  14232.  DRV$INIT:
  14233.  ;
  14234.  ; Determine number of physical drives by reading config.sys
  14235.  ;
  14236.  ASSUME  DS:CODE
  14237.          PUSH    DS
  14238.          LDS     SI,[PTRSAV]
  14239.  ASSUME  DS:NOTHING
  14240.          LDS     SI,DWORD PTR [SI.COUNT] ;DS:SI points to
  14241.                                          ;config.sys
  14242.  SCAN_LOOP:
  14243.          CALL    SCAN_SWITCH
  14244.          MOV     AL,CL
  14245.          OR      AL,AL
  14246.          JZ      SCAN4
  14247.          CMP     AL,"s"
  14248.          JZ      SCAN4
  14249.  
  14250.  WERROR: POP     DS
  14251.  ASSUME  DS:CODE
  14252.          MOV     DX,OFFSET ERRMSG2
  14253.  WERROR2: MOV    AH,9
  14254.          INT     21H
  14255.          XOR     AX,AX
  14256.          PUSH    AX                      ;No units
  14257.          JMP     SHORT ABORT
  14258.  
  14259.  BADNDRV:
  14260.          POP     DS
  14261.          MOV     DX,OFFSET ERRMSG1
  14262.          JMP     WERROR2
  14263.  
  14264.  SCAN4:
  14265.  ASSUME  DS:NOTHING
  14266.  ;BX is number of floppies
  14267.          OR      BX,BX
  14268.          JZ      BADNDRV                 ;User error
  14269.          CMP     BX,4
  14270.          JA      BADNDRV                 ;User error
  14271.          POP     DS
  14272.  ASSUME  DS:CODE
  14273.          PUSH    BX                      ;Save unit count
  14274.  ABORT:  LDS     BX,[PTRSAV]
  14275.  ASSUME  DS:NOTHING
  14276.          POP     AX
  14277.          MOV     BYTE PTR [BX].MEDIA,AL           ;Unit count
  14278.          MOV     [DRVMAX],AL
  14279.          MOV     WORD PTR [BX].TRANS,OFFSET DRV$INIT ;SET
  14280.                                                ;BREAK ADDRESS
  14281.          MOV     [BX].TRANS+2,CS
  14282.          MOV     WORD PTR [BX].COUNT,OFFSET INITAB
  14283.                                   ;SET POINTER TO BPB ARRAY
  14284.          MOV     [BX].ceOUNT+2,CS
  14285.          JMP     EXIT
  14286.  ;
  14287.  ; Put switch in CL, value in BX
  14288.  ;
  14289.  SCAN_SWITCH:
  14290.          XOR     BX,BX
  14291.          MOV     CX,BX
  14292.          LODSB
  14293.          CMP     AL,10
  14294.          JZ      NUMRET
  14295.          CMP     AL,"-"
  14296.          JZ      GOT_SWITCH
  14297.          CMP     AL,"/"
  14298.          JNZ     SCAN_SWITCH
  14299.  GOT_SWITCH:
  14300.          CMP     BYTE PTR [SI+1],":"
  14301.          JNZ     TERROR
  14302.          LODSB
  14303.          OR      AL,20H          ; Convert to lowercase
  14304.          MOV     CL,AL           ; Get switch
  14305.          LODSB                   ; Skip ":"
  14306.  ;
  14307.  ;  Get number pointed to by [SI]
  14308.  ;
  14309.  ;  Wipes out AX,DX only     BX returns number
  14310.  ;
  14311.  GETNUM1:LODSB
  14312.          SUB     AL,"0"
  14313.          JB      CHKRET
  14314.          CMP     AL,9
  14315.          JA      CHKRET
  14316.          CBW
  14317.          XCHG    AX,BX
  14318.          MOV     DX,10
  14319.          MUL     DX
  14320.          ADD     BX,AX
  14321.          JMP     GETNUM1
  14322.  
  14323.  CHKRET: ADD     AL,"0"
  14324.          CMP     AL," "
  14325.          JBE     NUMRET
  14326.          CMP     AL,"-"
  14327.          JZ      NUMRET
  14328.          CMP     AL,"/"
  14329.          JZ      NUMRET
  14330.  TERROR:
  14331.          POP     DS              ; Get rid of return address
  14332.          JMP     WERROR
  14333.  NUMRET: DEC     SI
  14334.          RET
  14335.  
  14336.  ERRMSG1 DB      "SMLDRV: Bad number of drives",13,10,"$"
  14337.  ERRMSG2 DB      "SMLDRV: Invalid parameter",13,10,"$"
  14338.  CODE    ENDS
  14339.          END
  14340.  
  14341.  
  14342.  Character Device Driver
  14343.  
  14344.  The following program illustrates a character device driver program.
  14345.  
  14346.  
  14347.  ;******************** A Character Device *******************
  14348.  
  14349.  Title   VT52 Console for 2.0    (IBM)
  14350.  
  14351.  ;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  14352.  ;
  14353.  ;       IBM Addresses for I/O
  14354.  ;
  14355.  ;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  14356.  
  14357.          CR=13              ;Carriage-Return
  14358.          BACKSP=8           ;BACKSPACE
  14359.          ESC=1BH
  14360.          BRKADR=6CH         ;006C  Break vector address
  14361.          ASNMAX=200         ;Size of key assignment buffer
  14362.  
  14363.  CODE    SEGMENT BYTE
  14364.  
  14365.     ASSUME CS:CODE,DS:NOTHING,ES:NOTHING
  14366.  ;----------------------------------------------------------
  14367.  ;
  14368.  ;       C O N - Console Device Driver
  14369.  ;
  14370.  CONDEV:                            ;Header for device "CON"
  14371.          DW      -1,-1
  14372.          DW      1000000000010011B  ;CON IN AND CON OUT
  14373.          DW      STRATEGY
  14374.          DW      ENTRY
  14375.          DB      'CON     '
  14376.  
  14377.  ;-----------------------------------------------------------
  14378.  ;
  14379.  ;       Command JUMP Tables
  14380.  CONTBL:
  14381.          DW      CON$INIT
  14382.          DW      EXIT
  14383.          DW      EXIT
  14384.          DW      CMDERR
  14385.          DW      CON$READ
  14386.          DW      CON$RDND
  14387.          DW      EXIT
  14388.          DW      CON$FLSH
  14389.          DW      CON$WRIT
  14390.          DW      CON$WRIT
  14391.          DW      EXIT
  14392.          DW      EXIT
  14393.  
  14394.  CMDTABL DB      'A'
  14395.          DW      CUU             ;cursor up
  14396.          DB      'B'
  14397.          DW      CUD             ;cursor down
  14398.          DB      'C'
  14399.          DW      CUF             ;cursor forward
  14400.          DB      'D'
  14401.          DW      CUB             ;cursor back
  14402.          DB      'H'
  14403.          DW      CUH             ;cursor position
  14404.          DB      'J'
  14405.          DW      ED              ;erase display
  14406.          DB      'K'
  14407.          DW      EL              ;erase line
  14408.          DB      'Y'
  14409.          DW      CUP             ;cursor position
  14410.          DB      'j'
  14411.          DW      PSCP            ;save cursor position
  14412.          DB      'k'
  14413.          DW      PRCP            ;restore cursor position
  14414.          DB      'y'
  14415.          DW      RM              ;reset mode
  14416.          DB      'x'
  14417.          DW      SM              ;set mode
  14418.          DB      00
  14419.  
  14420.  PAGE
  14421.  ;---------------------------------------------------
  14422.  ;
  14423.  ;       Device entry point
  14424.  ;
  14425.  CMDLEN  =       0       ;Length of this command
  14426.  UNIT    =       1       ;Subunit Specified
  14427.  CMD     =       2       ;Command Code
  14428.  STATUS  =       3       ;Status
  14429.  MEDIA   =       13      ;Media Descriptor
  14430.  TRANS   =       14      ;Transfer Address
  14431.  COUNT   =       18      ;Count of blocks or characters
  14432.  START   =       20      ;First block to transfer
  14433.  
  14434.  PTRSAV  DD      0
  14435.  
  14436.  STRATP  PROC    FAR
  14437.  
  14438.  STRATEGY:
  14439.          MOV     WORD PTR CS:[PTRSAV],BX
  14440.          MOV     WORD PTR CS:[PTRSAV+2],ES
  14441.          RET
  14442.  
  14443.  STRATP  ENDP
  14444.  
  14445.  ENTRY:
  14446.          PUSH    SI
  14447.          PUSH    AX
  14448.          PUSH    CX
  14449.          PUSH    DX
  14450.          PUSH    DI
  14451.          PUSH    BP
  14452.          PUSH    DS
  14453.          PUSH    ES
  14454.          PUSH    BX
  14455.  
  14456.          LDS     BX,CS:[PTRSAV]  ;GET POINTER TO I/O PACKET
  14457.  
  14458.          MOV     CX,WORD PTR DS:[BX].COUNT    ;CX = COUNT
  14459.  
  14460.          MOV     AL,BYTE PTR DS:[BX].CMD
  14461.          CBW
  14462.          MOV     SI,OFFSET CONTBL
  14463.          ADD     SI,AX
  14464.          ADD     SI,AX
  14465.          CMP     AL,11
  14466.          JA      CMDERR
  14467.  
  14468.          LES     DI,DWORD PTR DS:[BX].TRANS
  14469.  
  14470.          PUSH    CS
  14471.          POP     DS
  14472.  
  14473.          ASSUME  DS:CODE
  14474.  
  14475.          JMP     WORD PTR [SI]              ;GO DO COMMAND
  14476.  
  14477.  PAGE
  14478.  ;=====================================================
  14479.  ;=
  14480.  ;=      Subroutines Shared by Multiple Devices
  14481.  ;=
  14482.  ;=====================================================
  14483.  ;-----------------------------------------------------
  14484.  ;
  14485.  ;       EXIT - All routines return through this path
  14486.  ;
  14487.  BUS$EXIT:                               ;Device Busy Exit
  14488.          MOV     AH,00000011B
  14489.          JMP     SHORT ERR1
  14490.  
  14491.  CMDERR:
  14492.          MOV     AL,3                ;Unknown command error
  14493.  
  14494.  ERR$EXIT:
  14495.          MOV     AH,10000001B            ;Mark error Return
  14496.          JMP     SHORT ERR1
  14497.  
  14498.  EXITP   PROC    FAR
  14499.  
  14500.  EXIT:   MOV     AH,00000001B
  14501.  ERR1:   LDS     BX,CS:[PTRSAV]
  14502.          MOV     WORD PTR [BX].STATUS,AX ;Mark
  14503.                                          ;Operation Complete
  14504.  
  14505.          POP     BX
  14506.          POP     ES
  14507.          POP     DS
  14508.          POP     BP
  14509.          POP     DI
  14510.          POP     DX
  14511.          POP     CX
  14512.          POP     AX
  14513.          POP     SI
  14514.          RET                        ;Restore REGS and Return
  14515.  EXITP   ENDP
  14516.  ;-----------------------------------------------
  14517.  ;
  14518.  ;       BREAK Key Handling
  14519.  ;
  14520.  BREAK:
  14521.          MOV     CS:ALTAH,3         ;Indicate BREAK key Set
  14522.  INTRET: IRET
  14523.  
  14524.  PAGE
  14525.  ;
  14526.  ;       WARNING - Variables are very order dependent,
  14527.                    so be careful when adding new ones!
  14528.  ;
  14529.  WRAP    DB      0               ; 0 = WRAP, 1 = NO WRAP
  14530.  STATE   DW      S1
  14531.  MODE    DB      3
  14532.  MAXCOL  DB      79
  14533.  COL     DB      0
  14534.  ROW     DB      0
  14535.  SAVCR   DW      0
  14536.  ALTAH   DB      0               ;Special key handling
  14537.  
  14538.  ;-------------------------------------------------------
  14539.  ;
  14540.  ;    CHROUT - Write out Char in AL using current attribute
  14541.  ;
  14542.  ATTRW   LABEL   WORD
  14543.  ATTR    DB      00000111B       ;Character Attribute
  14544.  BPAGE   DB      0               ;Base Page
  14545.  base    dw      0b800h
  14546.  
  14547.  chrout: cmp     al,13
  14548.          jnz     trylf
  14549.          mov     [col],0
  14550.          jmp     short setit
  14551.  
  14552.  trylf:  cmp     al,10
  14553.          jz      lf
  14554.          cmp     al,7
  14555.          jnz     tryback
  14556.  torom:
  14557.          mov     bx,[attrw]
  14558.          and     bl,7
  14559.          mov     ah,14
  14560.          int     10h
  14561.  ret5:   ret
  14562.  
  14563.  tryback:
  14564.          cmp     al,8
  14565.          jnz     outchr
  14566.          cmp     [col],0
  14567.          jz      ret5
  14568.          dec     [col]
  14569.          jmp     short setit
  14570.  
  14571.  outchr:
  14572.          mov     bx,[attrw]
  14573.          mov     cx,1
  14574.          mov     ah,9
  14575.          int     10h
  14576.          inc     [col]
  14577.          mov     al,[col]
  14578.          cmp     al,[maxcol]
  14579.          jbe     setit
  14580.          cmp     [wrap],0
  14581.          jz      outchr1
  14582.          dec     [col]
  14583.          ret
  14584.  outchr1:
  14585.          mov     [col],0
  14586.  lf:     inc     [row]
  14587.          cmp     [row],24
  14588.          jb      setit
  14589.          mov     [row],23
  14590.          call    scroll
  14591.  
  14592.  setit:  mov     dh,row
  14593.          mov     dl,col
  14594.          xor     bh,bh
  14595.          mov     ah,2
  14596.          int     10h
  14597.          ret
  14598.  
  14599.  scroll: call    getmod
  14600.          cmp     al,2
  14601.          jz      myscroll
  14602.          cmp     al,3
  14603.          jz      myscroll
  14604.          mov     al,10
  14605.          jmp     torom
  14606.  myscroll:
  14607.          mov     bh,[attr]
  14608.          mov     bl,' '
  14609.          mov     bp,80
  14610.          mov     ax,[base]
  14611.          mov     es,ax
  14612.          mov     ds,ax
  14613.          xor     di,di
  14614.          mov     si,160
  14615.          mov     cx,23*80
  14616.          cld
  14617.          cmp     ax,0b800h
  14618.          jz      colorcard
  14619.  
  14620.          rep     movsw
  14621.          mov     ax,bx
  14622.          mov     cx,bp
  14623.          rep     stosw
  14624.  sret:   push    cs
  14625.          pop     ds
  14626.          ret
  14627.  
  14628.  colorcard:
  14629.          mov     dx,3dah
  14630.  wait2:  in      al,dx
  14631.          test    al,8
  14632.          jz      wait2
  14633.          mov     al,25h
  14634.          mov     dx,3d8h
  14635.          out     dx,al           ;turn off video
  14636.          rep     movsw
  14637.          mov     ax,bx
  14638.          mov     cx,bp
  14639.          rep     stosw
  14640.          mov     al,29h
  14641.          mov     dx,3d8h
  14642.          out     dx,al           ;turn on video
  14643.          jmp     sret
  14644.  
  14645.  GETMOD: MOV     AH,15
  14646.          INT     16             ;get column information
  14647.          MOV     BPAGE,BH
  14648.          DEC     AH
  14649.          MOV     WORD PTR MODE,AX
  14650.          RET
  14651.  ;------------------------------------------------------
  14652.  ;
  14653.  ;       Console Read Routine
  14654.  ;
  14655.  CON$READ:
  14656.          JCXZ    CON$EXIT
  14657.  CON$LOOP:
  14658.          PUSH    CX              ;Save Count
  14659.          CALL    CHRIN           ;Get Char in AL
  14660.          POP     CX
  14661.          STOSB                   ;Store Char at ES:DI
  14662.          LOOP    CON$LOOP
  14663.  CON$EXIT:
  14664.          JMP     EXIT
  14665.  ;---------------------------------------------------------
  14666.  ;
  14667.  ;       Input Single Char into AL
  14668.  ;
  14669.  CHRIN:  XOR     AX,AX
  14670.          XCHG    AL,ALTAH     ;Get Character & Zero ALTAH
  14671.          OR      AL,AL
  14672.          JNZ     KEYRET
  14673.  
  14674.  INAGN:  XOR     AH,AH
  14675.          INT     22
  14676.  ALT10:
  14677.          OR      AX,AX       ;Check for non-key after BREAK
  14678.          JZ      INAGN
  14679.          OR      AL,AL       ;Special case?
  14680.          JNZ     KEYRET
  14681.          MOV     ALTAH,AH        ;Store special key
  14682.  KEYRET: RET
  14683.  ;----------------------------------------------------------
  14684.  ;
  14685.  ;       Keyboard Non-descructive Read, No Wait
  14686.  ;
  14687.  CON$RDND:
  14688.          MOV     AL,[ALTAH]
  14689.          OR      AL,AL
  14690.          JNZ     RDEXIT
  14691.  
  14692.  RD1:    MOV     AH,1
  14693.          INT     22
  14694.          JZ      CONBUS
  14695.          OR      AX,AX
  14696.          JNZ     RDEXIT
  14697.          MOV     AH,0
  14698.          INT     22
  14699.          JMP     CON$RDND
  14700.  
  14701.  RDEXIT: LDS     BX,[PTRSAV]
  14702.          MOV     [BX].MEDIA,AL
  14703.  EXVEC:  JMP     EXIT
  14704.  CONBUS: JMP     BUS$EXIT
  14705.  ;----------------------------------------------------------
  14706.  ;
  14707.  ;       Keyboard Flush Routine
  14708.  ;
  14709.  CON$FLSH:
  14710.          MOV     [ALTAH],0         ;Clear out holding buffer
  14711.  
  14712.          PUSH    DS
  14713.          XOR     BP,BP
  14714.          MOV     DS,BP                   ;Select segment 0
  14715.          MOV     DS:BYTE PTR 41AH,1EH    ;Reset KB queue head
  14716.                                          ;pointer
  14717.          MOV     DS:BYTE PTR 41CH,1EH    ;Reset tail pointer
  14718.          POP     DS
  14719.          JMP     EXVEC
  14720.  ;----------------------------------------------------------
  14721.  ;
  14722.  ;       Console Write Routine
  14723.  ;
  14724.  CON$WRIT:
  14725.          JCXZ    EXVEC
  14726.          PUSH    CX
  14727.          MOV     AH,3            ;Set current cursor position
  14728.          XOR     BX,BX
  14729.          INT     16
  14730.          MOV     WORD PTR [COL],DX
  14731.          POP     CX
  14732.  
  14733.  CON$LP: MOV     AL,ES:[DI]      ;Get Char
  14734.          INC     DI
  14735.          CALL    OUTC            ;Output Char
  14736.          LOOP    CON$LP          ;Repeat until all through
  14737.          JMP     EXVEC
  14738.  
  14739.  COUT:   STI
  14740.          PUSH    DS
  14741.          PUSH    CS
  14742.          POP     DS
  14743.          CALL    OUTC
  14744.          POP     DS
  14745.          IRET
  14746.  
  14747.  OUTC:   PUSH    AX
  14748.          PUSH    CX
  14749.          PUSH    DX
  14750.          PUSH    SI
  14751.          PUSH    DI
  14752.          PUSH    ES
  14753.          PUSH    BP
  14754.          CALL    VIDEO
  14755.          POP     BP
  14756.          POP     ES
  14757.          POP     DI
  14758.          POP     SI
  14759.          POP     DX
  14760.          POP     CX
  14761.          POP     AX
  14762.          RET
  14763.  
  14764.  ;----------------------------------------------------------
  14765.  ;
  14766.  ;       Output Single Char in AL to Video Device
  14767.  ;
  14768.  VIDEO:  MOV     SI,OFFSET STATE
  14769.          JMP     [SI]
  14770.  
  14771.  S1:     CMP     AL,ESC                 ;Escape sequence?
  14772.          JNZ     S1B
  14773.          MOV     WORD PTR [SI],OFFSET S2
  14774.          RET
  14775.  
  14776.  S1B:    CALL    CHROUT
  14777.  S1A:    MOV     WORD PTR [STATE],OFFSET S1
  14778.          RET
  14779.  
  14780.  S2:     PUSH    AX
  14781.          CALL    GETMOD
  14782.          POP     AX
  14783.          MOV     BX,OFFSET CMDTABL-3
  14784.  S7A:    ADD     BX,3
  14785.          CMP     BYTE PTR [BX],0
  14786.          JZ      S1A
  14787.          CMP     BYTE PTR [BX],AL
  14788.          JNZ     S7A
  14789.          JMP     WORD PTR [BX+1]
  14790.  
  14791.  MOVCUR: CMP     BYTE PTR [BX],AH
  14792.          JZ      SETCUR
  14793.          ADD     BYTE PTR [BX],AL
  14794.  SETCUR: MOV     DX,WORD PTR COL
  14795.          XOR     BX,BX
  14796.          MOV     AH,2
  14797.          INT     16
  14798.          JMP     S1A
  14799.  
  14800.  CUP:    MOV     WORD PTR [SI],OFFSET CUP1
  14801.          RET
  14802.  CUP1:   SUB     AL,32
  14803.          MOV     BYTE PTR [ROW],AL
  14804.          MOV     WORD PTR [SI],OFFSET CUP2
  14805.          RET
  14806.  CUP2:   SUB     AL,32
  14807.          MOV     BYTE PTR [COL],AL
  14808.          JMP     SETCUR
  14809.  
  14810.  SM:     MOV     WORD PTR [SI],OFFSET S1A
  14811.          RET
  14812.  
  14813.  CUH:    MOV     WORD PTR COL,0
  14814.          JMP     SETCUR
  14815.  
  14816.  CUF:    MOV     AH,MAXCOL
  14817.          MOV     AL,1
  14818.  CUF1:   MOV     BX,OFFSET COL
  14819.          JMP     MOVCUR
  14820.  
  14821.  CUB:    MOV     AX,00FFH
  14822.          JMP     CUF1
  14823.  
  14824.  CUU:    MOV     AX,00FFH
  14825.  CUU1:   MOV     BX,OFFSET ROW
  14826.          JMP     MOVCUR
  14827.  
  14828.  CUD:    MOV     AX,23*256+1
  14829.          JMP     CUU1
  14830.  
  14831.  PSCP:   MOV     AX,WORD PTR COL
  14832.          MOV     SAVCR,AX
  14833.          JMP     SETCUR
  14834.  
  14835.  PRCP:   MOV     AX,SAVCR
  14836.          MOV     WORD PTR COL,AX
  14837.          JMP     SETCUR
  14838.  
  14839.  ED:     CMP     BYTE PTR [ROW],24
  14840.          JAE     EL1
  14841.  
  14842.          MOV     CX,WORD PTR COL
  14843.          MOV     DH,24
  14844.          JMP     ERASE
  14845.  
  14846.  EL1:    MOV     BYTE PTR [COL],0
  14847.  EL:     MOV     CX,WORD PTR [COL]
  14848.  EL2:    MOV     DH,CH
  14849.  ERASE:  MOV     DL,MAXCOL
  14850.          MOV     BH,ATTR
  14851.          MOV     AX,0600H
  14852.          INT     16
  14853.  ED3:    JMP     SETCUR
  14854.  
  14855.  
  14856.  RM:     MOV     WORD PTR [SI],OFFSET RM1
  14857.          RET
  14858.  RM1:    XOR     CX,CX
  14859.          MOV     CH,24
  14860.          JMP     EL2
  14861.  
  14862.  CON$INIT:
  14863.          int     11h
  14864.          and     al,00110000b
  14865.          cmp     al,00110000b
  14866.          jnz     iscolor
  14867.          mov     [base],0b000h          ;look for bw card
  14868.  iscolor:
  14869.          cmp     al,00010000b           ;look for 40 col mode
  14870.          ja      setbrk
  14871.          mov     [mode],0
  14872.          mov     [maxcol],39
  14873.  
  14874.  setbrk:
  14875.          XOR     BX,BX
  14876.          MOV     DS,BX
  14877.          MOV     BX,BRKADR
  14878.          MOV     WORD PTR [BX],OFFSET BREAK
  14879.          MOV     WORD PTR [BX+2],CS
  14880.  
  14881.          MOV     BX,29H*4
  14882.          MOV     WORD PTR [BX],OFFSET COUT
  14883.          MOV     WORD PTR [BX+2],CS
  14884.  
  14885.          LDS     BX,CS:[PTRSAV]
  14886.          MOV     WORD PTR [BX].TRANS,OFFSET CON$INIT
  14887.                                ;SET BREAK ADDRESS
  14888.          MOV     [BX].TRANS+2,CS
  14889.          JMP     EXIT
  14890.  
  14891.  CODE    ENDS
  14892.          END
  14893.  
  14894.  
  14895.  
  14896.  Chapter 3  MS-DOS Technical Information
  14897.  
  14898.  ───────────────────────────────────────────────────────────────────────────
  14899.  
  14900.  3.1  Introduction
  14901.  
  14902.  3.2  MS-DOS Initialization
  14903.  
  14904.  3.3  The Command Processor
  14905.  
  14906.  3.4  MS-DOS Disk Allocation
  14907.  
  14908.  3.5  MS-DOS Disk Directory
  14909.  
  14910.  3.6  File Allocation Table (FAT)
  14911.  
  14912.        3.6.1  How to Use the FAT (12-Bit FAT Entries)
  14913.  
  14914.        3.6.2  How to Use the FAT (16-Bit FAT Entries)
  14915.  
  14916.  3.7  MS-DOS Standard Disk Formats
  14917.  
  14918.  
  14919.  
  14920.  3.1  Introduction
  14921.  
  14922.  
  14923.  This chapter describes how MS-DOS initializes and how it allocates disk
  14924.  space for the root directory, the File Allocation Tables (FAT), and the
  14925.  data area. For programmers writing installable device drivers, this chapter
  14926.  explains MS-DOS disk directory entries and File Allocation Tables. At the
  14927.  end of the chapter, Tables 3.1 and 3.2 describe MS-DOS standard formats
  14928.  for floppy disks.
  14929.  
  14930.  
  14931.  3.2  MS-DOS Initialization
  14932.  
  14933.  
  14934.  MS-DOS initialization consists of several steps. When you reset your
  14935.  computer or turn on its power, the ROM (Read Only Memory) BIOS is invoked
  14936.  and performs hardware checks and initialization. The ROM BIOS then examines
  14937.  drive A for the boot sector. If it locates a boot sector, the ROM BIOS
  14938.  reads it into low memory and gives it control. If it doesn't find the boot
  14939.  sector, the ROM BIOS then looks in the active partition of the hard disk.
  14940.  If it still doesn't find the boot sector, the ROM BIOS then invokes
  14941.  ROM BASIC.
  14942.  
  14943.  On a removable disk (3.5-inch, 5.25-inch, or 8-inch disk), the boot
  14944.  sector sector is always located on track 0, sector 1, side 0 of the disk.
  14945.  On a hard disk, the boot sector begins on the first sector of the MS-DOS
  14946.  partition. The hard disk boot sector also includes a partition table. This
  14947.  table identifies the active MS-DOS partition and any other partitions,
  14948.  such as an extended MS-DOS partition, on the hard disk. Note that extended
  14949.  MS-DOS partitions are not bootable.
  14950.  
  14951.  The boot sector then reads the following files, in the order listed:
  14952.  
  14953.  io.sys
  14954.  msdos.sys
  14955.  
  14956.  ───────────────────────────────────────────────────────────────────────────
  14957.  Note
  14958.    Versions of MS-DOS prior to 3.3 required the io.sys file to be
  14959.    contiguous. This is no longer a requirement.
  14960.  ───────────────────────────────────────────────────────────────────────────
  14961.  
  14962.  Next, the system initialization routine SYSINIT loads all of the resident
  14963.  device drivers. Then, it searches for a config.sys file on the boot disk.
  14964.  SYSINIT allocates memory for buffers and files, based on settings in the
  14965.  config.sys file, or system default settings. If the config.sys file
  14966.  specifies any installable device drivers, these are installed next.
  14967.  
  14968.  Finally, SYSINIT executes the MS-DOS command processor, command.com.
  14969.  
  14970.  
  14971.  3.3  The Command Processor
  14972.  
  14973.  
  14974.  The command processor command.com consists of three parts:
  14975.  
  14976.      ■  A resident part resides in memory immediately following msdos.sys
  14977.         and its data area. This part contains routines to process Interrupts
  14978.         22H (Terminate Process Exit Address), 23H (CONTROL-C Exit Address),
  14979.         and 24H (Critical-Error-Handler Address), as well as a routine to
  14980.         reload the transient part, if needed. All standard MS-DOS error
  14981.         handling is done within this part of command.com. This includes
  14982.         displaying error messages and processing the Abort, Retry, Fail,
  14983.         or Ignore messages.
  14984.  
  14985.      ■  An initialization part follows the resident part. During startup,
  14986.         the initialization part is given control; it contains the processor
  14987.         setup routine in the autoexec.bat file. The initialization part
  14988.         determines the segment address at which programs can be loaded, and
  14989.         because it is no longer needed, is overlaid by the first program
  14990.         that command.com loads.
  14991.  
  14992.      ■  A transient part is loaded at the high end of memory. This part
  14993.         contains all the internal command processors and the batch file
  14994.         processor.
  14995.  
  14996.         The transient part of the command processor produces the system
  14997.         prompt (A>, for example), reads commands from the keyboard (or from
  14998.         batch files), and causes them to be executed. For external commands,
  14999.         the transient part builds a command line and issues Function 4BH
  15000.         (Load and Execute Program) to load and transfer control to the
  15001.         program.
  15002.  
  15003.  
  15004.  3.4  MS-DOS Disk Allocation
  15005.  
  15006.  
  15007.  The area on a disk partitioned for use by MS-DOS is formatted as follows:
  15008.  
  15009.      1.  Reserved area--variable size
  15010.  
  15011.      2.  First copy of File Allocation Table--variable size
  15012.  
  15013.      3.  Additional copies of File Allocation Table--variable size
  15014.          (optional)
  15015.  
  15016.      4.  Root directory--variable size
  15017.  
  15018.      5.  File data area
  15019.  
  15020.  Space for a file in the data area is not preallocated. The space is
  15021.  allocated one cluster at a time. A cluster consists of one or more
  15022.  consecutive sectors (the number of sectors in a cluster must be a
  15023.  power of 2); the cluster size is determined at format time. All the
  15024.  clusters for a file are "chained" together in the File Allocation Table,
  15025.  discussed in greater detail in Section 3.5, "File Allocation Table (FAT)."
  15026.  MS-DOS normally keeps a second copy of the FAT for consistency, except in
  15027.  the case of reliable storage such as a virtual RAM disk. Should the disk
  15028.  develop a bad sector in the middle of the first FAT, MS-DOS can use the
  15029.  second. This avoids loss of data due to an unreadable FAT.
  15030.  
  15031.  
  15032.  3.5  MS-DOS Disk Directory
  15033.  
  15034.  The format utility builds the root directory for all disks. This
  15035.  directory's location on the disk and the maximum number of entries are
  15036.  dependent on the media. Specifications for standard removable-disk formats
  15037.  are outlined later in this chapter. Note, however, that MS-DOS regards
  15038.  directories, other than the root directory, as files, so there is no limit
  15039.  to the number of files that the subdirectories under the root directory
  15040.  may contain.
  15041.  
  15042.  All directory entries are 32 bytes in length and are in the following
  15043.  format (note that byte offsets are in hexadecimal):
  15044.  
  15045. ╓┌───────┌───────────────────────────────────────────────────────────────────╖
  15046.  Byte    Function
  15047.  ───────────────────────────────────────────────────────────────────────────
  15048.  0-7     Filename. Eight characters, left-aligned and padded, if necessary,
  15049.          with blanks. The first byte of this field indicates the file
  15050.          status as follows:
  15051.  
  15052.          Byte Status
  15053.          ───────────────────────────────────────────────────────────────────
  15054.          00H  The directory entry has never been used. This is used to
  15055.               limit the length of directory searches, for performance
  15056.               reasons.
  15057.  
  15058.          05H  The first character of the filename contains an E5H character.
  15059.  Byte    Function
  15060.         05H  The first character of the filename contains an E5H character.
  15061.  
  15062.          2EH  The entry is for a directory. If the second byte is also 2EH,
  15063.               the cluster field contains the cluster number of this
  15064.               directory's parent directory (0000H if the parent directory is
  15065.               the root directory). Otherwise, bytes 01H through 0AH are all
  15066.               spaces, and the cluster field contains the cluster number of
  15067.               this directory.
  15068.  
  15069.          E5H  The file was used, but it has since been erased.
  15070.  
  15071.          Any other character is the first character of a filename.
  15072.  
  15073.  8-0A    Filename extension.
  15074.  
  15075.  0B      File attribute. The attribute byte is mapped as follows (values
  15076.          are in hexadecimal):
  15077.  
  15078.          Byte Contents
  15079.          ───────────────────────────────────────────────────────────────────
  15080.  Byte    Function
  15081.         ───────────────────────────────────────────────────────────────────
  15082.          01H  File is marked read-only. An attempt to open the file for
  15083.               writing using Function 3DH (Open Handle) results in an error
  15084.               code being returned. This value can be used in programs along
  15085.               with the other attributes in this list. Attempts to delete
  15086.               the file with Function 13H (Delete File) or Function 41H
  15087.               (Delete Directory Entry) will also fail.
  15088.  
  15089.          02H  Hidden file. The file is excluded from normal directory
  15090.               searches.
  15091.  
  15092.          04H  System file. The file is excluded from normal directory
  15093.               searches.
  15094.  
  15095.          08H  The entry contains the volume label in the first 11 bytes.
  15096.               The entry contains no other usable information (except date
  15097.               and time of creation), and may exist only in the root
  15098.               directory.
  15099.  
  15100.          10H  The entry defines a subdirectory, and is excluded from
  15101.  Byte    Function
  15102.         10H  The entry defines a subdirectory, and is excluded from
  15103.               normal directory searches.
  15104.  
  15105.          20H  Archive bit. The bit is set to "on" whenever the file
  15106.               has been written to and closed.
  15107.  
  15108.               Note:  The system files (io.sys and msdos.sys) are marked
  15109.               as read-only, hidden, and system files. Files can be marked
  15110.               hidden when they are created. Also, you may change the read-
  15111.               only, hidden, system, and archive attributes through Function
  15112.               43H (Get/Set File Attributes).
  15113.  
  15114.  0C-15   Reserved.
  15115.  
  15116.  16-17   Time the file was created or last updated. The hour, minutes, and
  15117.          seconds are mapped into two bytes as follows (bit 7 on the left,
  15118.          0 on the right):
  15119.  
  15120.          Offset 17H
  15121.          | H | H | H | H | H | M | M | M |
  15122.  Byte    Function
  15123.         | H | H | H | H | H | M | M | M |
  15124.  
  15125.          Offset 16H
  15126.          | M | M | M | S | S | S | S | S |
  15127.  
  15128.          where:
  15129.  
  15130.          H is the binary number of hours (0-23).
  15131.          M is the binary number of minutes (0-59).
  15132.          S is the binary number of two-second increments.
  15133.  
  15134.  18-19   Date the file was created or last updated. The year, month,
  15135.          and day are mapped into two bytes as follows:
  15136.  
  15137.          Offset 19H
  15138.          | Y | Y | Y | Y | Y | Y | Y | M |
  15139.  
  15140.          Offset 18H
  15141.          | M | M | M | D | D | D | D | D |
  15142.  
  15143.  Byte    Function
  15144. 
  15145.          where:
  15146.  
  15147.          Y is the year, 0-119 (1980-2099).
  15148.          M is the month (1-12).
  15149.          D is the day of the month (1-31).
  15150.  
  15151.  1A-1B   Starting cluster; the number of the first cluster in the file.
  15152.  
  15153.          ■ Note that the first cluster for data space on all disks
  15154.            is cluster 002.
  15155.  
  15156.          ■ The cluster number is stored with the least significant
  15157.            byte first.
  15158.  
  15159.          ■ For details about converting cluster numbers to
  15160.            logical sector numbers, see Sections 3.6.1 and 3.6.2.
  15161.  
  15162.  1C-1F   File size in bytes. The first word of this four-byte field
  15163.          is the low-order part of the size.
  15164.  Byte    Function
  15165.         is the low-order part of the size.
  15166.  
  15167.  
  15168.  3.6  File Allocation Table (FAT)
  15169.  
  15170.  
  15171.  This section explains how MS-DOS allocates disk space in the data area
  15172.  for a file by using the File Allocation Table to convert the clusters of a
  15173.  file to logical sector numbers. The device driver is then responsible for
  15174.  locating the logical sector on the disk. Programs should use the MS-DOS
  15175.  file management function calls for accessing files. Programs that access
  15176.  the FAT are not guaranteed to be upwardly-compatible with future releases
  15177.  of MS-DOS. The following information is useful to system programmers who
  15178.  wish to write installable device drivers.
  15179.  
  15180.  The File Allocation Table is an array of 12-bit entries (1.5 bytes) for
  15181.  each cluster on the disk. For disks containing more than 4085 clusters,
  15182.  a 16-bit FAT entry is used.
  15183.  
  15184.  The first two FAT entries are reserved; however, the device driver may
  15185.  use the first byte as a FAT ID byte for determining media. For hard disks,
  15186.  the value of this byte is F8H. See Tables 3.1 and 3.2 for the media byte
  15187.  descriptors used for 8-inch, 5.25-inch, and 3.5-inch disks.
  15188.  
  15189.  The third FAT entry, which starts at byte offset 4, begins the mapping
  15190.  of the data area (cluster 002). The operating system does not always
  15191.  sequentially write (to the disk) files in the data area. Instead, the
  15192.  system allocates the data area one cluster at a time, skipping over
  15193.  clusters it has already allocated. The first free cluster following
  15194.  the last cluster allocated for that file is the next cluster allocated,
  15195.  regardless of its physical location on the disk. This permits the most
  15196.  efficient use of disk space, since if you erase old files, you can free
  15197.  clusters, which the operating system can then allocate for new files.
  15198.  
  15199.  Each FAT entry contains three or four hexadecimal characters,
  15200.  depending on whether it is a 12-bit or 16-bit entry:
  15201.  
  15202.  Entry       Contents
  15203.  ───────────────────────────────────────────────────────────────────────────
  15204.  (0)000      If the cluster is unused and available.
  15205.  
  15206.  (F)FF7      The cluster has a bad sector in it if it is not part of any
  15207.              cluster chain. MS-DOS will not allocate such a cluster. So for
  15208.              its report, the chkdsk command counts the number of bad
  15209.              clusters, which are not part of any allocation chain.
  15210.  
  15211.  (F)FF8-FFF  The last cluster of a file.
  15212.  
  15213.  (X)XXX      Any other characters that are the cluster number of the next
  15214.              cluster in the file. The number of the first cluster in the
  15215.              file is in the file's directory entry.
  15216.  
  15217.  The File Allocation Table always begins on the first sector after the
  15218.  reserved sectors. If the FAT is larger than one sector, the sectors are
  15219.  contiguous. The operating system usually writes two copies of the FAT to
  15220.  preserve data integrity. MS-DOS reads the FAT into one of its buffers,
  15221.  whenever needed (open, read, write, etc.). The operating system also gives
  15222.  this buffer a high priority to keep it in memory as long as possible.
  15223.  
  15224.  
  15225.  3.6.1  How to Use the FAT (12-Bit FAT Entries)
  15226.  
  15227.  To get the starting cluster of a file, examine its directory entry (in the
  15228.  FAT). Then, to locate each subsequent cluster of the file, follow these
  15229.  steps:
  15230.  
  15231.      1.  Multiply the cluster number just used by 1.5 (each FAT entry is
  15232.          1.5 bytes in length).
  15233.  
  15234.      2.  The whole part of the product is an offset into the FAT, pointing
  15235.          to the entry that maps the cluster just used. That entry contains
  15236.          the cluster number of the next cluster of the file.
  15237.  
  15238.      3.  Use a MOV instruction to move the word at the calculated FAT offset
  15239.          into a register.
  15240.  
  15241.      4.  If the last cluster used was an even number, keep the low-order
  15242.          12 bits of the register by using the AND operator with 0FFFH and
  15243.          the register. If the last cluster used was an odd number, keep
  15244.          the high-order 12 bits by using the SHR instruction to shift the
  15245.          register right four bits.
  15246.  
  15247.      5.  If the resultant 12 bits are 0FF8H-0FFFH, the file contains no more
  15248.          clusters. Otherwise, the 12 bits contain the number of the next
  15249.          cluster in the file.
  15250.  
  15251.  To convert the cluster to a logical sector number (relative sector,
  15252.  such as that used by Interrupts 25H and 26H (Absolute Disk Read/Write) and
  15253.  by debug), follow these steps:
  15254.  
  15255.      1.  Subtract two from the cluster number.
  15256.  
  15257.      2.  Multiply the result by the number of sectors per cluster.
  15258.  
  15259.      3.  To this result, add the logical sector number of the beginning
  15260.          of the data area.
  15261.  
  15262.  
  15263.  3.6.2  How to Use the FAT (16-Bit FAT Entries)
  15264.  
  15265.  To get the starting cluster of a file, examine its directory entry (in the
  15266.  FAT). Then, to find the next file cluster, follow these steps:
  15267.  
  15268.      1.  Multiply the cluster number last used by 2 (each FAT entry is
  15269.          2 bytes).
  15270.  
  15271.      2.  Use a MOV WORD instruction to move the word at the calculated FAT
  15272.          offset into a register.
  15273.  
  15274.      3.  If the resultant 16 bits are 0FFF8-0FFFH, no more clusters are in
  15275.          the file. Otherwise, the 16 bits contain the number of the next
  15276.          cluster in the file.
  15277.  
  15278.  
  15279.  3.7  MS-DOS Standard Disk Formats
  15280.  
  15281.  
  15282.  MS-DOS arranges data clusters on a disk to minimize head movement.
  15283.  MS-DOS then allocates all the space on one track (or cylinder) before
  15284.  moving to the next. It uses the sequential sectors on the lowest-numbered
  15285.  head, then all the sectors on the next head, and so on, until it has used
  15286.  all the sectors on all the heads of the track.
  15287.  
  15288.  The size of the MS-DOS partition on a hard disk determines the size
  15289.  of the FAT and root directory. Likewise, the type of floppy disk (tracks
  15290.  per side, sectors per track, etc.) determines how MS-DOS uses the disk.
  15291.  The removable disk formats listed in Tables 3.1 and 3.2 are standard and
  15292.  should be readable in the appropriate standard drive.
  15293.  
  15294.  
  15295.  Table 3.1
  15296.  MS-DOS Standard Removable-Disk Formats
  15297. ╓┌─────────────────────────────┌──────────────────────────┌──────────────────╖
  15298.  Disk Size in inches                     5.25                     8
  15299.  ───────────────────────────── ────────────────────────── ──────────────────
  15300.  WORD no. heads                  1     1     2     2         1     2     1
  15301.  Tracks/side                    40    40    40    40        77    77    77
  15302.  WORD sectors/track              8     9     8     9        26    26     8
  15303.  WORD bytes/sector             512   512   512   512       128   128   024
  15304.  BYTE sectors/cluster            1     1     2     2         4     4     1
  15305.  WORD reserved sectors           1     1     1     1         1     4     1
  15306.  Byte no. FATs                   2     2     2     2         2     2     2
  15307.  WORD root directory entries    64    64   112   112        68    68   192
  15308.  WORD no. sectors              320   360   640   720      2002  2002   616
  15309.  BYTE media descriptor          FE    FC    FF    FD       FE1   FD   FE1
  15310.  WORD sectors/FAT                1     2     1     2         6     6     2
  15311.  Disk Size in inches                     5.25                     8
  15312. WORD sectors/FAT                1     2     1     2         6     6     2
  15313.  WORD no. hidden sectors         0     0     0     0         0     0     0
  15314.  
  15315.  
  15316.  Table 3.2
  15317.  MS-DOS Standard Removable Disk Formats (High-Density)
  15318. ╓┌─────────────────────────┌────────────────────────────┌───────┌────────────╖
  15319.  Disk Size in inches              3.5 or 5.25             3.5      5.25
  15320.  ───────────────────────── ──────────────────────────── ─────── ────────────
  15321.  WORD no. heads              1     2      2      2         2         2
  15322.  Tracks/side                80    80     80     80        80        80
  15323.  WORD sectors/track          8     9      8      9        18        15
  15324.  WORD bytes/sector         512   512    512    512       512       512
  15325.  BYTE sectors/cluster        2     2      2      2         1         1
  15326.  WORD reserved sectors       1     1      1      1         1         1
  15327.  BYTE no. FATs               2     2      2      2         2         2
  15328.  WORD root dir entries     112   112    112    112       224       224
  15329.  WORD no. sectors          640   720   1280   1440      2880      2400
  15330.  BYTE media descriptor1    FA    FC     FB     F9        F0        F9
  15331.  WORD sectors/FAT            1     2      2      3         9         7
  15332.  Disk Size in inches              3.5 or 5.25             3.5      5.25
  15333. WORD sectors/FAT            1     2      2      3         9         7
  15334.  WORD no. hidden sectors     0     0      0      0         0         0
  15335.  
  15336.  
  15337.  
  15338.  
  15339.  Chapter 4  MS-DOS Control Blocks and Work Areas
  15340.  
  15341.  ───────────────────────────────────────────────────────────────────────────
  15342.  
  15343.  4.1  Introduction
  15344.  
  15345.  4.2  Typical Contents of an MS-DOS Memory Map
  15346.  
  15347.  4.3  MS-DOS Program Segment
  15348.  
  15349.  
  15350.  
  15351.  4.1  Introduction
  15352.  
  15353.  
  15354.  This chapter describes a typical MS-DOS memory map and explains how a
  15355.  program is loaded into memory. It also describes the structure of an
  15356.  MS-DOS program segment and the contents of register segments for .exe
  15357.  and .com program files.
  15358.  
  15359.  
  15360.  4.2  Typical Contents of an MS-DOS Memory Map
  15361.  
  15362.  
  15363.  A typical MS-DOS memory map contains the following information:
  15364.  
  15365.      +-----------------------------------------------------+
  15366.      |             ROM and Video Buffers                   |
  15367.      +-----------------------------------------------------+
  15368.      |          Transient Part of COMMAND.COM              |
  15369.      +-----------------------------------------------------+
  15370.      |                                                     |
  15371.      |                                                     |
  15372.      |                                                     |
  15373.      |                                                     |
  15374.      |              Transient Program Area                 |
  15375.      |- - - - - - - - - - - - - - - - - - - - - - - - - - -|
  15376.      |                                                     |
  15377.      |                                                     |
  15378.      |                                                     |
  15379.      |                                                     |
  15380.      |          External Commands and Utilities            |
  15381.      |                                                     |
  15382.      +-----------------------------------------------------+
  15383.      |           Resident Part of COMMAND.COM              |
  15384.      +-----------------------------------------------------+
  15385.      | MS-DOS buffers, control areas, & installed drivers  |
  15386.      +-----------------------------------------------------+
  15387.      |                                                     |
  15388.      |                MSDOS.SYS                            |
  15389.      +-----------------------------------------------------+
  15390.      |        IO.SYS and resident device drivers           |
  15391.      +-----------------------------------------------------+
  15392.      |                 Interrupt Vectors                   |
  15393.    0 +-----------------------------------------------------+
  15394.  
  15395.  During system initialization, MS-DOS loads the io.sys and msdos.sys files
  15396.  into low memory (Note that in MS-DOS 3.3, these files are not required to
  15397.  be written contiguously to the disk). The io.sys system file is the MS-DOS
  15398.  interface to hardware. The msdos.sys system file includes MS-DOS interrupt
  15399.  handlers, service routines (Interrupt 21H functions).
  15400.  
  15401.  Next, the system initialization routine loads the resident and installable
  15402.  device drivers. Above the installable device drivers, MS-DOS writes the
  15403.  resident part of command.com. This part includes interrupt handlers for
  15404.  Interrupts 22H (Terminate Process Exit Address), 23H (CONTROL-C Handler
  15405.  Address), 24H (Critical-Error-Handler Address) and code to reload the
  15406.  transient part. The transient part of command.com is reloaded into high
  15407.  memory. It includes the command interpreter, the internal MS-DOS commands,
  15408.  and the batch processor.
  15409.  
  15410.  External command and utility (.com and .exe) files are loaded into the
  15411.  transient program area. MS-DOS also allocates 256 bytes for user stack
  15412.  used with .com files. User memory is allocated from the lowest end of
  15413.  available memory that fulfills the allocation request.
  15414.  
  15415.  
  15416.  4.3  MS-DOS Program Segment
  15417.  
  15418.  
  15419.  When you type an external command or execute a program through Function 4BH
  15420.  (Load and Execute Program, also called EXEC), MS-DOS determines the lowest
  15421.  available free memory address to use as the start of the program. The
  15422.  memory starting at this address is called the Program Segment.
  15423.  
  15424.  The EXEC system call sets up the first 256 bytes of the Program Segment
  15425.  for the program being loaded into memory. The program is then loaded
  15426.  following this block. An .exe file with minalloc and maxalloc both set
  15427.  to zero is loaded as high as possible.
  15428.  
  15429.  At offset 0 within the Program Segment, MS-DOS builds the Program
  15430.  Segment Prefix control block. The program returns from EXEC by one of
  15431.  five methods:
  15432.  
  15433.      ■ By issuing an Interrupt 21H with AH=4CH
  15434.  
  15435.      ■ By issuing an Interrupt 21H with AH=31H (Keep Process)
  15436.  
  15437.      ■ By a long jump to offset 0 in the Program Segment Prefix
  15438.  
  15439.      ■ By issuing an Interrupt 20H with CS:0 pointing at the PSP
  15440.  
  15441.      ■ By issuing an Interrupt 21H with register AH=0 and with CS:0
  15442.        pointing at the PSP
  15443.  
  15444.  ───────────────────────────────────────────────────────────────────────────
  15445.  Note
  15446.    The first two methods are preferred for functionality, compatibility,
  15447.    and efficiency in future versions of MS-DOS.
  15448.  ───────────────────────────────────────────────────────────────────────────
  15449.  
  15450.  All five methods transfer control to the program that issued the EXEC call.
  15451.  The first two methods return a completion code. They also restore the
  15452.  addresses of Interrupts 22H, 23H, and 24H (Terminate Process Exit Address,
  15453.  CONTROL-C Handler Address, and Critical-Error-Handler Address) from the
  15454.  values saved in the Program Segment Prefix of the terminating program.
  15455.  Control then passes to the terminate address.
  15456.  
  15457.  If a program returns to command.com, control transfers to the resident
  15458.  portion. If the program is a batch file (in process), it continues.
  15459.  Otherwise, command.com performs a checksum on the transient part, reloads
  15460.  it if necessary, issues the system prompt, and waits for you to type
  15461.  another command.
  15462.  
  15463.  When a program receives control, the following conditions are in effect:
  15464.  
  15465.  
  15466.  For all programs:
  15467.  
  15468.      ■ The segment address of the passed environment is at offset 2CH
  15469.        in the Program Segment Prefix.
  15470.  
  15471.      ■ The environment is a series of ASCII strings (totaling less than
  15472.         32K) in the form:
  15473.  
  15474.         NAME=parameter
  15475.  
  15476.      ■ A byte of zeros terminates each string, and another byte of zeros
  15477.        terminates the set of strings.
  15478.  
  15479.        Following the last byte of zeros is a set of initial arguments
  15480.        that the operating system passes to a program. This set of
  15481.        arguments contains a word count followed by an ASCII string.
  15482.        If the file is in the current directory, the ASCII string
  15483.        contains the drive and pathname of the executable program as
  15484.        passed to the EXEC function call. If the file is not in the
  15485.        current directory, EXEC concatenates the name of the file with
  15486.        the name of the path. Programs may use this area to determine
  15487.        where the program was loaded.
  15488.  
  15489.      ■ The environment built by the command processor contains at least
  15490.        a comspec= string (the parameters on comspec define the path that
  15491.        MS-DOS uses to locate command.com on disk). The last path and
  15492.        prompt commands issued are also in the environment, along with any
  15493.        environment strings you have defined with the MS-DOS set command.
  15494.  
  15495.      ■ EXEC passes a copy of the invoking process environment. If your
  15496.        application uses a "keep process" concept, you should be aware
  15497.        that the copy of the environment passed to you is static. That
  15498.        is, it will not change even if you issue subsequent set, path,
  15499.        or prompt commands. Conversely, any modification of the passed
  15500.        environment by the application is not reflected in the parent
  15501.        process environment. For instance, a program cannot change the
  15502.        MS-DOS environment values as the set command does.
  15503.  
  15504.      ■ The Disk Transfer Address (DTA) is set to 80H (default DTA in the
  15505.        Program Segment Prefix). The Program Segment Prefix contains file
  15506.        control blocks at 5CH and 6CH. MS-DOS formats these blocks using
  15507.        the first two parameters that you typed when entering the command.
  15508.        If either parameter contained a pathname, then the corresponding
  15509.        FCB contains only the valid drive number. The filename field is
  15510.        not valid.
  15511.  
  15512.      ■ An unformatted parameter area at 81H contains all the characters
  15513.        typed after the command (including leading and embedded delimiters),
  15514.        with the byte at 80H set to the number of characters. If you type
  15515.        <, >, or parameters on the command line, they do not appear in this
  15516.        area (nor the filenames associated with them). Redirection of
  15517.        standard input and output is transparent to applications.
  15518.  
  15519.      ■ Offset 6 (one word) contains the number of bytes available in
  15520.        the segment.
  15521.  
  15522.      ■ Register AX indicates whether the drive specifiers (entered with
  15523.        the first two parameters) are valid, as follows:
  15524.  
  15525.        AL=FF if the first parameter contained an invalid drive specifier
  15526.        (otherwise AL=00)
  15527.  
  15528.        AH=FF if the second parameter contained an invalid drive specifier
  15529.        (otherwise AH=00)
  15530.  
  15531.      ■ Offset 2 (one word) contains the segment address of the first byte
  15532.        of unavailable memory. Programs must not modify addresses beyond
  15533.        this point unless these addresses were obtained by allocating
  15534.        memory via Function 48H (Allocate Memory).
  15535.  
  15536.  
  15537.  For Executable (.exe) Programs:
  15538.  
  15539.      ■ DS and ES registers point to the Program Segment Prefix.
  15540.  
  15541.      ■ CS,IP,SS, and SP registers contain the values that Microsoft link
  15542.        sets in the .exe image.
  15543.  
  15544.  
  15545.  For Executable (.com) Programs:
  15546.  
  15547.      ■ All four segment registers contain the segment address of the initial
  15548.        allocation block that starts with the Program Segment Prefix control
  15549.        block.
  15550.  
  15551.      ■ .com programs allocate all of user memory. If the program invokes
  15552.        another program through Function 4BH (EXEC), it must first free some
  15553.        memory through Function 4AH (Set Block) to provide space for the
  15554.        program being executed.
  15555.  
  15556.      ■ The Instruction Pointer (IP) is set to 100H.
  15557.  
  15558.      ■ The Stack Pointer register is set to the end of the program's
  15559.        segment. The segment size at offset 6 is reduced by 100H to allow
  15560.        for a stack of that size.
  15561.  
  15562.      ■ A .com program places a word of zeros on top of the stack. Then by
  15563.        doing a RET instruction last, your program can exit to command.com.
  15564.        This method assumes, however, that you have maintained your stack
  15565.        and code segments.
  15566.  
  15567.  Figure 4.1 illustrates the format of the Program Segment Prefix. All
  15568.  offsets are in hexadecimal.
  15569.  
  15570.  
  15571.                        (Offsets in Hex)
  15572.  0 -----------------------------------------------------------
  15573.    |             | End of      |                             |
  15574.    |   INT 20H   | alloc.      |        Reserved             |
  15575.    |             | block       |         04H                 |
  15576.  8 -----------------------------------------------------------
  15577.    |             |   Terminate address    |   CONTROL-C exit |
  15578.    |  Reserved   |       (IP, CS)         |   address (IP)   |
  15579.    |             |                        |                  |
  15580.  10-----------------------------------------------------------
  15581.    |CONTROL-C   | Hard error exit address |                  |
  15582.    |exit        |       (IP, CS)          |                  |
  15583.    |address (CS)|                         |                  |
  15584.    ----------------------------------------                  |
  15585.    |                                                         |
  15586.    |                   Used by MS-DOS                        |
  15587.    |                                                         |
  15588.    |                         5CH                             |
  15589.    |                                                         |
  15590.    -----------------------------------------------------------
  15591.    |                                                         |
  15592.    |    Formatted Parameter Area 1 formatted as standard     |
  15593.    |                    unopened FCB 6CH                     |
  15594.    -----------------------------------------------------------
  15595.    |                                                         |
  15596.    |    Formatted Parameter Area 2 formatted as standard     |
  15597.    |     unopened FCB (overlaid if FCB at 5CH is opened)     |
  15598.  80-----------------------------------------------------------
  15599.    |             Unformatted Parameter Area                  |
  15600.    |            (default Disk Transfer Area)                 |
  15601.    |       Initially contains command invocation line.       |
  15602.    -----------------------------------------------------------
  15603.  100
  15604.  
  15605.                 Figure 4.1  Program Segment Prefix
  15606.  
  15607.  
  15608.  ───────────────────────────────────────────────────────────────────────────
  15609.  Important
  15610.    Programs must not alter any part of the Program Segment Prefix below
  15611.    offset 5CH.
  15612.  ───────────────────────────────────────────────────────────────────────────
  15613.  
  15614.  
  15615.  
  15616.  Chapter 5  National Language Support
  15617.  
  15618.  ───────────────────────────────────────────────────────────────────────────
  15619.  
  15620.  5.1  Introduction
  15621.  
  15622.  5.2  National Language Support Calls
  15623.  
  15624.  5.3  Font Files
  15625.  
  15626.        5.3.1  Font File Structure
  15627.  
  15628.                5.3.1.1  File Header
  15629.  
  15630.                5.3.1.2  Information Header
  15631.  
  15632.                5.3.1.3  Code Page Entry Header
  15633.  
  15634.                5.3.1.4  Font Data Header
  15635.  
  15636.                5.3.1.5  Font Header
  15637.  
  15638.  
  15639.  
  15640.  5.1  Introduction
  15641.  
  15642.  
  15643.  National language support for this version of MS-DOS 3.3 includes these
  15644.  major features:
  15645.  
  15646.      ■ Country-dependent information
  15647.  
  15648.      ■ Support for national keyboard layouts
  15649.  
  15650.      ■ Programming interfaces for national language support
  15651.  
  15652.      ■ Utility commands
  15653.  
  15654.  Country-dependent information is available on a per-country basis and
  15655.  includes the following:
  15656.  
  15657.      ■ Time, date, and currency
  15658.  
  15659.      ■ Lowercase-to-uppercase character-conversion tables
  15660.  
  15661.      ■ Collating sequence for character sorting
  15662.  
  15663.      ■ Valid single-byte characters used in filenames
  15664.  
  15665.  Selectable keyboard support for different keyboard layouts is provided.
  15666.  
  15667.  The MS-DOS 3.3 programming interfaces for national language support allow
  15668.  applications to use the country-dependent information just described.
  15669.  To access this information, applications do not need to change the
  15670.  current country code of the system.
  15671.  
  15672.  Utility commands allow the user to select the keyboard layout and
  15673.  system country code.
  15674.  
  15675.  This version of MS-DOS does not support right-to-left national languages.
  15676.  
  15677.  
  15678.  5.2  National Language Support Calls
  15679.  
  15680.  
  15681.  The following function calls allow an application to tailor its operation
  15682.  to the current country code and to accept or change the current code page.
  15683.  A country code defines the country in which you live or work. MS-DOS
  15684.  uses this code to prepare and assign default code pages for your system.
  15685.  A code page is a table that defines the character set you are using.
  15686.  A character set is a country-specific or language-specific group of
  15687.  characters that are translated from the code page table and displayed
  15688.  on your screen or printer. Each code page character set contains
  15689.  256 characters.
  15690.  
  15691.  The following function calls are also used by MS-DOS 3.3 to support
  15692.  the National Language requirements:
  15693.  
  15694.      ■ Function 44H, Code 0CH (Generic IOCtl)--supports code page switching
  15695.        on a per-device basis.
  15696.  
  15697.      ■ Function 65H (Get Extended Country Information)--returns standard
  15698.        country information, and points to related case-map or collating
  15699.        tables.
  15700.  
  15701.      ■ Function 66H (Get/Set Global Code Page)--gets or sets the code page
  15702.        used by the kernel and by all devices.
  15703.  
  15704.  These functions support access to country-dependent information, all
  15705.  of which resides in one file named country.sys.
  15706.  
  15707.  
  15708.  5.3  Font Files
  15709.  
  15710.  
  15711.  Font files, also called code page information files, contain the images
  15712.  of code page character sets for use by console-screen or printer devices.
  15713.  These font files are identified by a filename extension of .cpi. Four
  15714.  font files are included with MS-DOS 3.3:
  15715.  
  15716.  Font file   Supported device
  15717.  ───────────────────────────────────────────────────────────────────────────
  15718.  ega.cpi     Color console used with an EGA card
  15719.  lcd.cpi     Liquid crystal display
  15720.  4201.cpi    IBM Proprinter
  15721.  5202.cpi    Quietwriter III printer
  15722.  
  15723.  
  15724.  5.3.1  Font File Structure
  15725.  
  15726.  The contents of printer or console-screen font files are structured as
  15727.  follows:
  15728.  
  15729.  
  15730.             +--------------------------------------+
  15731.             | 22-BYTE File Header                  |
  15732.             +--------------------------------------+
  15733.             | WORD Information Header              |
  15734.             +--------------------------------------+
  15735.             | 13-BYTE Code Page Entry Header       |
  15736.             +--------------------------------------+
  15737.             | 6-BYTE Font Data Header              |
  15738.             +--------------------------------------+
  15739.             | Variable size Font Header(s)         |
  15740.             +--------------------------------------+
  15741.  
  15742.                 Figure 5.1  Font File Structure
  15743.  
  15744.  
  15745.  The font file fields are described in the following sections.
  15746.  
  15747.  
  15748.  5.3.1.1  File Header
  15749.  
  15750.  Each file must begin with a file header that includes the following:
  15751.  
  15752.  Length     Parameter
  15753.  ───────────────────────────────────────────────────────────────────────────
  15754.  8 BYTES    File tag
  15755.  8 BYTES    Reserved
  15756.  WORD       Number of pointers
  15757.  2 WORDS    Offset
  15758.  
  15759.  where:
  15760.  
  15761.  File tag begins with the byte 0FFH and is followed by a string "font   "
  15762.  (seven characters).
  15763.  
  15764.  Reserved is eight bytes of zeros.
  15765.  
  15766.  Number of pointers is the number of pointers in the header. For
  15767.  MS-DOS 3.3, the value of this word should be 1.
  15768.  
  15769.  Offset is the two-word offset from the beginning of the file.
  15770.  
  15771.  
  15772.  5.3.1.2  Information Header
  15773.  
  15774.  Following the file header is a one-word information header:
  15775.  
  15776.  Length     Parameter
  15777.  ───────────────────────────────────────────────────────────────────────────
  15778.  WORD       Number of code pages
  15779.  
  15780.  where:
  15781.  
  15782.  Number of code pages is the number of code page entries in the file.
  15783.  
  15784.  
  15785.  5.3.1.3  Code Page Entry Header
  15786.  
  15787.  For each code page entry, a header in the following format is included in
  15788.  the font file:
  15789.  
  15790.  Length     Parameter
  15791.  ───────────────────────────────────────────────────────────────────────────
  15792.  WORD       Length
  15793.  WORD       Pointer
  15794.  WORD       Device type
  15795.  8 BYTES    Device subtype
  15796.  WORD       Code page ID
  15797.  WORD       Reserved
  15798.  2 WORDS    Offset
  15799.  
  15800.  where:
  15801.  
  15802.  Length is the size of the code page entry header.
  15803.  
  15804.  Pointer points to the next code page entry header (last header=0, 0).
  15805.  
  15806.  Device type is 1 if the device is a console screen, or 2 if the device
  15807.  is a printer.
  15808.  
  15809.  Device subtype names the type of console screen or printer. This
  15810.  field also determines the name of the font file. For example, if the
  15811.  subtype is "CGA," the font file name is cga.cpi
  15812.  
  15813.  Code page ID defines a valid three-digit code page identification
  15814.  number. Valid code page numbers are 437, 850, 860, 863, and 865.
  15815.  
  15816.  Reserved is eight bytes of zeros.
  15817.  
  15818.  Offset is a pointer to the Font Data Header.
  15819.  
  15820.  
  15821.  5.3.1.4  Font Data Header
  15822.  
  15823.  The Font Data Header includes the following fields:
  15824.  
  15825.  Length     Parameter
  15826.  ───────────────────────────────────────────────────────────────────────────
  15827.  WORD       Reserved
  15828.  WORD       Number of fonts
  15829.  WORD       Length of font data
  15830.  
  15831.  where:
  15832.  
  15833.  Reserved must be 1.
  15834.  
  15835.  Number of fonts is equal to the number of fonts defined in the font file.
  15836.  
  15837.  Length of font data is equal to the size of the font-data portion of the
  15838.  font file.
  15839.  
  15840.  
  15841.  5.3.1.5  Font Header
  15842.  
  15843.  The font-data portion of a font file will vary for each device. The
  15844.  structure of the font-data portion consists of a set of data for each font
  15845.  type. The following illustrates the data portion of a font file for a
  15846.  console-screen device:
  15847.  
  15848.  font_header:
  15849.     db   16, 8             ; character pixels
  15850.                            ; (rows, columns)
  15851.     db   0, 0              ; aspect ratio (unused)
  15852.     dw   256               ; number of characters in set
  15853.  
  15854.  
  15855.  len_data   equ ($ - font_header)
  15856.  
  15857.  
  15858.  
  15859.  Chapter 6  .EXE File Structure and Loading
  15860.  
  15861.  ───────────────────────────────────────────────────────────────────────────
  15862.  
  15863.  6.1  Format of a File Header
  15864.  
  15865.  6.2  The Relocation Table
  15866.  
  15867.  
  15868.  
  15869.  ───────────────────────────────────────────────────────────────────────────
  15870.  Note
  15871.    This chapter describes .exe file structure and loading procedures
  15872.    for systems that use a version of MS-DOS earlier than 2.0. For MS-DOS
  15873.    versions 2.0 and later, use Function 4B00H (Load and Execute a Program)
  15874.    to load (or load and execute) an .exe file.
  15875.  ───────────────────────────────────────────────────────────────────────────
  15876.  
  15877.  The .exe files produced by link consist of two parts:
  15878.  
  15879.      ■ Control and relocation information
  15880.  
  15881.      ■ The load module
  15882.  
  15883.  The control and relocation information is at the beginning of the file in
  15884.  an area called the header. Immediately following this header is the load
  15885.  module.
  15886.  
  15887.  
  15888.  6.1  Format of a File Header
  15889.  
  15890.  
  15891.  The header is formatted as follows (note that offsets are in hexadecimal):
  15892.  
  15893. ╓┌───────┌───────────────────────────────────────────────────────────────────╖
  15894.  Offset  Contents
  15895.  ───────────────────────────────────────────────────────────────────────────
  15896.  0-1     Must contain 4DH, 5AH.
  15897.  
  15898.  2-3     Number of bytes contained in last page; useful for reading
  15899.  Offset  Contents
  15900. 2-3     Number of bytes contained in last page; useful for reading
  15901.          overlays.
  15902.  
  15903.  4-5     Size of the file in 512-byte pages, including the header.
  15904.  
  15905.  6-7     Number of relocation entries in table.
  15906.  
  15907.  8-9     Size of the header in 16-byte paragraphs. Used to locate the
  15908.          beginning of the load module in the file.
  15909.  
  15910.  AH-BH   Minimum number of 16-byte paragraphs required above the end of
  15911.          the loaded program.
  15912.  
  15913.  CH-DH   Maximum number of 16-byte paragraphs required above the end of the
  15914.          loaded program. If both minalloc and maxalloc are 0, the program
  15915.          is loaded as high as possible.
  15916.  
  15917.  EH-FH   Initial value to be loaded into stack segment before starting
  15918.          program execution. Must be adjusted by relocation.
  15919.  
  15920.  Offset  Contents
  15921. 
  15922.  10-11   Value to be loaded into the SP register before starting
  15923.          program execution.
  15924.  
  15925.  12-13   Negative sum of all the words in the file.
  15926.  
  15927.  14-15   Initial value to be loaded into the IP register before starting
  15928.          program execution.
  15929.  
  15930.  16-17   Initial value to be loaded into the CS register before starting
  15931.          program execution. Must be adjusted by relocation.
  15932.  
  15933.  18-19   Relative byte offset from beginning of run file to
  15934.          relocation table.
  15935.  
  15936.  1AH-1BH The number of the overlay as generated by link.
  15937.  
  15938.  
  15939.  6.2  The Relocation Table
  15940.  
  15941.  
  15942.  The relocation table that follows the formatted area above, consists of
  15943.  a variable number of relocation items. Each relocation item contains two
  15944.  fields: a two-byte offset value, followed by a two-byte segment value.
  15945.  These two fields contain the offset into a word's load module. This item
  15946.  requires modification before the module is given control. The following
  15947.  steps describe this process:
  15948.  
  15949.      1. The formatted part of the header is read into memory. Its size
  15950.         is 1BH.
  15951.  
  15952.      2. MS-DOS allocates a portion of memory depending on the size of the
  15953.         load module and the allocation numbers (AH-BH and CH-DH). MS-DOS
  15954.         then attempts to allocate 0FFFH paragraphs. This attempt always
  15955.         fails, and returns the size of the largest free block. If this
  15956.         block is smaller than minalloc and loadsize, there is no
  15957.         memory error. But if this block is larger than maxalloc and
  15958.         loadsize, MS-DOS allocates (maxalloc + loadsize). Otherwise,
  15959.         it allocates the largest free block of memory.
  15960.  
  15961.      3. A Program Segment Prefix is built in the lowest part of the
  15962.         allocated memory.
  15963.  
  15964.      4. MS-DOS calculates the load module size (using offsets 4-5 and
  15965.         8-9) by subtracting the header size from the file size. The actual
  15966.         size is adjusted down based on the contents of offsets 2-3. The
  15967.         operating system determines (based on the setting of the high/low
  15968.         load switch) an appropriate segment, called the start segment,
  15969.         where it loads the load module.
  15970.  
  15971.      5. The load module is read into memory beginning with the start
  15972.         segment.
  15973.  
  15974.      6. The items in the relocation table are read into a work area.
  15975.  
  15976.      7. MS-DOS adds the segment value of each relocation table item to the
  15977.         start segment value. This calculated segment, plus value, points
  15978.         to the module to which the start segment value is added. The
  15979.         result is then placed back into the word in the load module.
  15980.  
  15981.      8. Once all relocation items have been processed, the operating system
  15982.         sets the SS and SP registers, using the values in the header.
  15983.         MS-DOS then adds the start segment value to SS and sets the ES and
  15984.         DS registers to the segment address of the Program Segment Prefix.
  15985.         The start segment value is then added to the header CS register
  15986.         value. The result, along with the header IP value, is the initial
  15987.         CS:IP to transfer to before starting execution of the program.
  15988.  
  15989.  
  15990.  
  15991.  Chapter 7  Microsoft Relocatable Object Module Formats
  15992.  
  15993.  ───────────────────────────────────────────────────────────────────────────
  15994.  
  15995.  7.1  Introduction
  15996.  
  15997.        7.1.1  Definition of Terms
  15998.  
  15999.  7.2  Module Identification and Attributes
  16000.  
  16001.        7.2.1  Segment Definition
  16002.  
  16003.        7.2.2  Addressing a Segment
  16004.  
  16005.        7.2.3  Symbol Definition
  16006.  
  16007.        7.2.4  Indices
  16008.  
  16009.  7.3  Conceptual Framework for Fixups
  16010.  
  16011.        7.3.1  Self-Relative Fixup
  16012.  
  16013.        7.3.2  Segment-Relative Fixup
  16014.  
  16015.  7.4  Record Sequence
  16016.  
  16017.  7.5  Introducing the Record Formats
  16018.  
  16019.        7.5.1  Sample Record Format (SAMREC)
  16020.  
  16021.        7.5.2  T-Module Header Record (THEADR)
  16022.  
  16023.        7.5.3  L-Module Header Record (LHEADR)
  16024.  
  16025.        7.5.4  List of Names Record (LNAMES)
  16026.  
  16027.        7.5.5  Segment Definition Record (SEGDEF)
  16028.  
  16029.        7.5.6  Group Definition Record (GRPDEF)
  16030.  
  16031.        7.5.7  Public Names Definition Record (PUBDEF)
  16032.  
  16033.        7.5.8  Communal Names Definition Record (COMDEF)
  16034.  
  16035.        7.5.9  Local Symbols Record (LOCSYM)
  16036.  
  16037.        7.5.10 External Names Definition Record (EXTDEF)
  16038.  
  16039.        7.5.11 Line Numbers Record (LINNUM)
  16040.  
  16041.        7.5.12 Logical Enumerated Data Record (LEDATA)
  16042.  
  16043.        7.5.13 Logical Iterated Data Record (LIDATA)
  16044.  
  16045.        7.5.14 Fixupp Record (FIXUPP)
  16046.  
  16047.        7.5.15 Module End Record (MODEND)
  16048.  
  16049.        7.5.16 Comment Record (COMENT)
  16050.  
  16051.  7.6  Microsoft Type Representations for Communal Variables
  16052.  
  16053.  
  16054.  
  16055.  7.1  Introduction
  16056.  
  16057.  
  16058.  This chapter presents the object record formats that define the relocatable
  16059.  object language for the 8086, 80186, and 80286 microprocessors. The 8086
  16060.  object language is the output of all language translators that have an
  16061.  8086 processor and that will be linked by the Microsoft linker. The
  16062.  8086 object language is used for input and output for object language
  16063.  processors such as linkers and librarians, and is used in the XENIX,
  16064.  PC-DOS, and MS-DOS operating systems.
  16065.  
  16066.  The 8086 object module formats let you specify relocatable memory images
  16067.  that may be linked together. These formats also allow efficient use of the
  16068.  memory mapping facilities of the 8086 family of microprocessors.
  16069.  
  16070.  The following table lists the record formats (each described in this
  16071.  chapter) that Microsoft supports (the abbreviations appear in parentheses):
  16072.  
  16073.  
  16074.       Table 7.1
  16075.       Object Module Record Formats
  16076.  ───────────────────────────────────────────────────────────────────────────
  16077.       Symbol Definition Records
  16078.  
  16079.       Public Names Definition Record     (PUBDEF)
  16080.       Communal Names Definition Record   (COMDEF)
  16081.       Local Symbols Record               (LOCSYM)
  16082.       External Names Definition Record   (EXTDEF)
  16083.       Line Numbers Record                (LINNUM)
  16084.  
  16085.       Data Records
  16086.  
  16087.       Logical Enumerated Data Record     (LEDATA)
  16088.       Logical Iterated Data Record       (LIDATA)
  16089.       T-Module Header Record             (THEADR)
  16090.       L-Module Header Record             (LHEADR)
  16091.       List of Names Record               (LNAMES)
  16092.       Segment Definition Record          (SEGDEF)
  16093.       Group Definition Record            (GRPDEF)
  16094.       Fixup Record                       (FIXUPP)
  16095.       Module End Record                  (MODEND)
  16096.       Comment Record                     (COMENT)
  16097.  
  16098.  
  16099.  ───────────────────────────────────────────────────────────────────────────
  16100.  Note
  16101.    If an object module contains any undefined values, the behavior of the
  16102.    Microsoft linker is undefined. All undefined values should be considered
  16103.    reserved by Microsoft for future use.
  16104.  ───────────────────────────────────────────────────────────────────────────
  16105.  
  16106.  
  16107.  7.1.1  Definition of Terms
  16108.  
  16109.  The following terms are fundamental to 8086 relocation and linkage:
  16110.  
  16111.  
  16112.  OMF--Object Module Formats
  16113.  
  16114.  
  16115.  MAS--Memory Address Space
  16116.  
  16117.  The 8086 MAS is one megabyte (1,048,576 bytes). Note that the MAS is
  16118.  distinguished from actual memory, which may occupy only a portion of
  16119.  the MAS.
  16120.  
  16121.  
  16122.  Module
  16123.  
  16124.  A module is an "inseparable" collection of object code and other
  16125.  information produced by a translator.
  16126.  
  16127.  
  16128.  T-Module
  16129.  
  16130.  A T-module is a module created by a translator, such as Pascal or FORTRAN.
  16131.  
  16132.  The following restrictions apply to object modules:
  16133.  
  16134.      ■ Every module should have a name. Translators provide default
  16135.        names (possibly filenames or null names) for T-modules if neither
  16136.        the source code nor the user specifies otherwise.
  16137.  
  16138.      ■ Every T-module in a collection of linked modules should have a
  16139.        different name so that symbolic debugging systems can distinguish
  16140.        the various line numbers and local symbols. The Microsoft linker
  16141.        does not require or enforce this restriction.
  16142.  
  16143.  
  16144.  Frame
  16145.  
  16146.  A frame is a contiguous region of 64K of memory address space (MAS),
  16147.  beginning on a paragraph boundary (i.e., on a multiple of 16 bytes)
  16148.  or on a selector on the 80286 processor. This concept is useful because
  16149.  the contents of the four 8086 segment registers define four (possibly
  16150.  overlapping) frames; no 16-bit address in the 8086 code can access a
  16151.  memory location outside the current four frames.
  16152.  
  16153.  
  16154.  LSEG (Logical Segment)
  16155.  
  16156.  A logical segment (LSEG) is a contiguous region of memory whose contents
  16157.  are determined at translation time (except for address-binding). Neither
  16158.  the size nor the location in MAS are necessarily determined during
  16159.  translation: the size, although partially fixed, may not be final because
  16160.  the linker may combine the LSEG when linking with other LSEGs, forming
  16161.  a single LSEG. So that it can fit in a frame, an LSEG must not be larger
  16162.  than 64K. Thus, a 16-bit offset, from the base of a frame that covers
  16163.  the LSEG, may address any byte in that LSEG.
  16164.  
  16165.  
  16166.  PSEG (Physical Segment)
  16167.  
  16168.  This term is equivalent to frame. Some prefer "PSEG" to "frame" because
  16169.  the terms PSEG and LSEG reflect the "physical" and "logical" nature of the
  16170.  underlying segments.
  16171.  
  16172.  
  16173.  Frame Number
  16174.  
  16175.  Every frame begins on a paragraph boundary. The "paragraphs" in MAS can
  16176.  be numbered from 0 through 65,535. These numbers, each of which defines
  16177.  a frame, are called frame numbers.
  16178.  
  16179.  
  16180.  Group
  16181.  
  16182.  A group is a collection of LSEGs defined at translation time, whose
  16183.  final locations in MAS have been constrained so that at least one frame
  16184.  exists that covers (contains) every LSEG in the collection.
  16185.  
  16186.  The notation "Gr A(X,Y,Z,)" means that LSEGs X, Y, and Z form a group
  16187.  named A. That X, Y, and Z are all LSEGs in the same group does not imply
  16188.  any ordering of X, Y, and Z in MAS, nor does it imply any contiguity
  16189.  between X, Y, and Z.
  16190.  
  16191.  The Microsoft linker does not currently allow an LSEG to be a member
  16192.  of more than one group.
  16193.  
  16194.  
  16195.  Canonic
  16196.  
  16197.  On the 8086 processor, any location in MAS is contained in exactly 4096
  16198.  distinct frames, but one of these frames can be distinguished because
  16199.  it has a higher frame number. This frame is called the canonic frame of
  16200.  the location. In other words, the canonic frame of a given byte is the
  16201.  frame chosen so that the byte's offset from that frame lies in the range
  16202.  0 to 15 (decimal).
  16203.  
  16204.  For example, suppose FOO is a symbol defining a memory location. You
  16205.  would then refer to this frame as the "canonic frame of FOO." Similarly,
  16206.  if S is any set of memory locations, then a unique frame exists that has
  16207.  the lowest frame number in the set of canonic frames of the locations in S.
  16208.  This unique frame is called the canonic frame of the set S. You might refer
  16209.  similarly to the canonic frame of an LSEG or of a group of LSEGs.
  16210.  
  16211.  
  16212.  Segment Name
  16213.  
  16214.  LSEGs are assigned Segment Names at translation time. These names serve
  16215.  two purposes:
  16216.  
  16217.      ■ During linking they play a role in determining which LSEGs
  16218.        are combined with other LSEGs.
  16219.  
  16220.      ■ They are used in assembly source code to specify membership
  16221.        in groups.
  16222.  
  16223.  
  16224.  Class Name
  16225.  
  16226.  The translator may optionally assign class names to LSEGs during
  16227.  translation. Classes define a partition on LSEGs: two LSEGs are in
  16228.  the same class if they have the same class name.
  16229.  
  16230.  The Microsoft linker applies the following semantics to class names:
  16231.  the class name "CODE", or any class name whose suffix is "CODE", implies
  16232.  that all segments of that class contain only code and may be considered
  16233.  read-only. Such segments may be overlaid if you specify the module
  16234.  containing the segment as part of an overlay.
  16235.  
  16236.  
  16237.  Overlay Name
  16238.  
  16239.  The linker may optionally assign an overlay name to LSEGs. The overlay
  16240.  name of an LSEG is ignored by Microsoft language linkers for version 3.00
  16241.  and later languages, but the standard MS-DOS linker supports it.
  16242.  
  16243.  
  16244.  Complete Name
  16245.  
  16246.  The complete name of an LSEG consists of the segment name, class name,
  16247.  and overlay name. The linker combines LSEGs from different modules if their
  16248.  complete names are identical.
  16249.  
  16250.  
  16251.  7.2  Module Identification and Attributes
  16252.  
  16253.  
  16254.  A module header record, which provides a module name, is always the first
  16255.  record in a module. In addition to having a name, a module may represent
  16256.  a main program and may have a specified starting address. When linking
  16257.  multiple modules together, you should give only one module with the
  16258.  main attribute. If more than one main module appears, the first takes
  16259.  precedence.
  16260.  
  16261.  In summary, modules may or may not be main and may or may not have a
  16262.  starting address.
  16263.  
  16264.  
  16265.  7.2.1  Segment Definition
  16266.  
  16267.  A module is a collection of object code defined by a sequence of
  16268.  records that a translator produces. The object code represents contiguous
  16269.  regions of memory whose contents the linker determines during translation.
  16270.  These regions are LSEGs. A module defines the attributes of each LSEG.
  16271.  The segment definition record (SEGDEF) is responsible for maintaining
  16272.  all LSEG information (name, length, memory alignment, etc.). The linker
  16273.  requires the LSEG information when you combine multiple LSEGs and when
  16274.  it establishes segment addressability. The SEGDEF records must follow the
  16275.  first header record.
  16276.  
  16277.  
  16278.  7.2.2  Addressing a Segment
  16279.  
  16280.  The 8086 addressing mechanism provides segment base registers from
  16281.  which you may address a 64K-byte region of memory (a Frame). There is
  16282.  one code segment base register (CS), two data segment base registers
  16283.  (DS, ES), and one stack segment base register (SS).
  16284.  
  16285.  The possible number of LSEGs that may make up a memory image far exceeds
  16286.  the number of available base registers. Thus, base registers may require
  16287.  frequent loading. This would be the case in a modular program with many
  16288.  small data and/or code LSEGs.
  16289.  
  16290.  Since such frequent loading of base registers is undesirable, it is a good
  16291.  strategy to collect many small LSEGs together into a single unit that will
  16292.  fit in one memory frame. Then all the LSEGs may be addressed using the same
  16293.  base register value. This addressable unit is a group and has been defined
  16294.  earlier in Section 7.1.1, "Definition of Terms."
  16295.  
  16296.  To establish addressability of objects within a group, you must explicitly
  16297.  define each group in the module. The group definition record (GRPDEF) lists
  16298.  constituent segments by their segment names.
  16299.  
  16300.  The GRPDEF records within a module must follow all SEGDEF records
  16301.  because GRPDEF records will reference SEGDEF records in defining a Group.
  16302.  The GRPDEF records must also precede all other records except header
  16303.  records, which the linker must process first.
  16304.  
  16305.  
  16306.  7.2.3  Symbol Definition
  16307.  
  16308.  The Microsoft linker supports three different types of records
  16309.  belonging to the class of symbol definition records. The types are public
  16310.  names definition records (PUBDEFs), communal names definition records
  16311.  (COMDEFs), and external names definition records (EXTDEFs). You use these
  16312.  record types to define globally visible procedures and data items and
  16313.  to resolve external references.
  16314.  
  16315.  
  16316.  7.2.4  Indices
  16317.  
  16318.  "Index" fields appear throughout this chapter. An index is an integer
  16319.  that selects a particular item from a collection of items; for example:
  16320.  name index, segment index, group index, external index, type index, etc.
  16321.  
  16322.  ───────────────────────────────────────────────────────────────────────────
  16323.  Note
  16324.    An index is normally a positive number. The index value zero is reserved,
  16325.    and may carry a special meaning depending on the type of index (for
  16326.    example, a segment index of zero specifies the "Unnamed" absolute pseudo-
  16327.    segment; a type index of zero specifies the "Untyped type.")
  16328.  ───────────────────────────────────────────────────────────────────────────
  16329.  
  16330.  In general, indices must assume values that are quite large (that is, much
  16331.  larger than 255). Nevertheless, a great number of object files contain no
  16332.  indices with values greater than 50 or 100. Therefore, indices are encoded
  16333.  in one or two bytes, as required.
  16334.  
  16335.  The high-order (left-most) bit of the first (and possibly the only) byte
  16336.  determines whether the index occupies one byte or two. If the bit is 0,
  16337.  the index is a number between 0 and 127, occupying one byte. If the bit
  16338.  is 1, the index is a number between 0 and 32K-1, occupying two bytes, and
  16339.  is determined as follows: the low-order eight bits are in the second byte,
  16340.  and the high-order seven bits are in the first byte.
  16341.  
  16342.  
  16343.  7.3  Conceptual Framework for Fixups
  16344.  
  16345.  
  16346.  A fixup is a modification to object code that achieves address binding
  16347.  that a translator requested and a linker performed.
  16348.  
  16349.  ───────────────────────────────────────────────────────────────────────────
  16350.  Note
  16351.    This is the linker's definition of fixup. Nevertheless, the linker
  16352.    can modify object code (make a "fixup") that does not conform to this
  16353.    definition. For example, binding code to either hardware or software
  16354.    floating-point subroutines is a modification to an operation code,
  16355.    which is treated as an address. The previous definition of fixup is not
  16356.    intended to disallow or discourage modifications to the object code.
  16357.  ───────────────────────────────────────────────────────────────────────────
  16358.  
  16359.  8086-family translators need four kinds of data to specify a fixup:
  16360.  
  16361.      ■ The place and type of a Location to be fixed up.
  16362.  
  16363.      ■ One of two possible fixup modes.
  16364.  
  16365.      ■ A target, which is the memory address that Location must refer to.
  16366.  
  16367.      ■ A frame that defines a context in which the reference
  16368.        takes place.
  16369.  
  16370.  Location--There are five types of Locations: a pointer, a base,
  16371.  an offset, a hibyte, and a lobyte.
  16372.  
  16373.  The vertical alignment of the following figure illustrates four points
  16374.  (remember that the high-order byte of a word in 8086 memory is the byte
  16375.  with the higher address):
  16376.  
  16377.      ■ A base is the high-order word of a pointer (the linker doesn't care
  16378.        whether the low-order word of the pointer is present).
  16379.  
  16380.      ■ An offset is the low-order word of a pointer (the linker doesn't care
  16381.        whether the high-order word follows).
  16382.  
  16383.      ■ A hibyte is the high-order half of an offset (the linker doesn't care
  16384.        whether the low-order half precedes).
  16385.  
  16386.      ■ A lobyte is the low-order half of an offset (the linker doesn't care
  16387.        whether the high-order half follows).
  16388.  
  16389.  
  16390.            +----+----+----+----+
  16391.  Pointer:  |                   |
  16392.            +----+----+----+----+
  16393.  
  16394.                      +----+----+
  16395.  Base:               |         |
  16396.                      +----+----+
  16397.  
  16398.            +----+----+
  16399.  Offset:   |         |
  16400.            +----+----+
  16401.  
  16402.                 +----+
  16403.  Hibyte:        |    |
  16404.                 +----+
  16405.  
  16406.            +----+
  16407.  Lobyte:   |    |
  16408.            +----+
  16409.  
  16410.          Figure 7.1  Location Types
  16411.  
  16412.  
  16413.  A Location is specified by two kinds of data: the Location type, and where
  16414.  the Location is.
  16415.  
  16416.  The Location type is specified by the LOC field in the FIXUPP record's
  16417.  LOCAT field; where the Location is is specified by the Data Record Offset
  16418.  field in the same LOCAT field.
  16419.  
  16420.  Mode--The Microsoft linker supports two kinds of fixups: self-relative
  16421.  and segment-relative.
  16422.  
  16423.  Self-relative fixups support the 8-bit and 16-bit offsets used in CALL,
  16424.  JUMP, and SHORT-JUMP instructions. Segment-relative fixups support all
  16425.  other addressing modes of the 8086.
  16426.  
  16427.  Target--The target is the location in MAS that the linker references.
  16428.  (More explicitly, the linker considers the target the lowest byte in the
  16429.  object that it is referencing.) The linker specifies a target by one of six
  16430.  methods. There are three "primary" methods and three "secondary" ones. Each
  16431.  primary method of specifying a target uses two kinds of data: an index
  16432.  number X, and a displacement D.
  16433.  
  16434.  Method      Explanation
  16435.  ───────────────────────────────────────────────────────────────────────────
  16436.  (T0)        X is a segment index. The target is the Dth byte in the
  16437.              LSEG that the segment index identifies.
  16438.  
  16439.  (T1)        X is a group index. The target is the Dth byte in the
  16440.              LSEG that the group index identifies.
  16441.  
  16442.  (T2)        X is an external index. The external index identifies the
  16443.              external name that (eventually) gives the address of a byte.
  16444.              The Dth byte following this byte is the target.
  16445.  
  16446.  Each secondary method of specifying a target uses only one item of data--
  16447.  the index number X; this assumes an implicit displacement equal to zero.
  16448.  
  16449.  Method      Explanation
  16450.  ───────────────────────────────────────────────────────────────────────────
  16451.  (T4)        X is a segment index. The target is the 0th (first) byte in
  16452.              the LSEG that the segment index identifies.
  16453.  
  16454.  (T5)        X is a group index. The target is the 0th (first) byte in the
  16455.              LSEG in the specified group located (eventually) lowest in MAS.
  16456.  
  16457.  (T6)        X is an external index. The target is the byte whose address
  16458.              is the external name that the external index identifies.
  16459.  
  16460.  The following nomenclature describes a target:
  16461.  
  16462.  Nomenclature                                      Method
  16463.  ───────────────────────────────────────────────────────────────────────────
  16464.  Target:  SI(segment name), displacement           [T0]
  16465.  Target:  GI(group name), displacement             [T1]
  16466.  Target:  EI(symbol name), displacement            [T2]
  16467.  Target:  SI (segment name)                        [T4]
  16468.  Target:  GI (group name)                          [T5]
  16469.  Target:  EI (symbol name)                         [T6]
  16470.  
  16471.  The following examples illustrate how this notation is used:
  16472.  
  16473.  Sample Nomenclature             Explanation
  16474.  ───────────────────────────────────────────────────────────────────────────
  16475.  Target:  SI(CODE), 1024         The 1025th byte in the segment CODE.
  16476.  
  16477.  Target:  GI(DATAAREA)           The location in MAS of a group called
  16478.                                  DATAAREA.
  16479.  
  16480.  Target:  EI(SIN)                The address of the external subroutine SIN.
  16481.  
  16482.  Target:  EI(PAYSCHEDULE), 24    The 24th byte following the location of an
  16483.                                  external data structure called PAYSCHEDULE.
  16484.  
  16485.  Frame--Every 8086 memory reference is to a location contained within
  16486.  a frame. This frame is designated by the content of a segment register.
  16487.  For the linker to form a correct, usable memory reference, it must know
  16488.  what the target is, and to which frame the reference is being made. Thus,
  16489.  every fixup specifies such a frame, in one of six methods. Some methods
  16490.  use data, X, which is in the index number. Other methods require no data.
  16491.  
  16492.  The five methods of specifying frames are as follows:
  16493.  
  16494. ╓┌───────────┌───────────────────────────────────────────────────────────────╖
  16495.  Method      Explanation
  16496.  ───────────────────────────────────────────────────────────────────────────
  16497.  (F0)        X is a segment index. The frame is the canonic frame of the
  16498.              LSEG that the segment index defines.
  16499.  
  16500.  (F1)        X is a group index. The frame is the canonic frame defined
  16501.              by the group (that is, the canonic frame defined by the LSEG
  16502.              in the group located (eventually) lowest in MAS).
  16503.  
  16504.  (F2)        X is an external index. The frame is determined when the
  16505.              linker finds the external name's public definition. There
  16506.              are two cases:
  16507.  
  16508.  Method      Explanation
  16509. 
  16510.              Case        Explanation
  16511.              ───────────────────────────────────────────────────────────────
  16512.              (F2a)       The linker defines the symbol relative to some
  16513.                          LSEG, and there is no associated group. The linker
  16514.                          also specifies the LSEG's canonic frame.
  16515.  
  16516.              (F2c)       Regardless of how the linker defines the symbol,
  16517.                          there is an associated group. And the linker
  16518.                          specifies the canonic frame of the group. (The
  16519.                          Group Index field of the PUBDEF record
  16520.                          specifies the group.)
  16521.  
  16522.  (F4)        No X. The frame is the canonic frame of the LSEG that contains
  16523.              Location.
  16524.  
  16525.  (F5)        No X. The target determines the frame. There are three cases:
  16526.  
  16527.              Case        Explanation
  16528.              ───────────────────────────────────────────────────────────────
  16529.  Method      Explanation
  16530.             ───────────────────────────────────────────────────────────────
  16531.              (F5a)       The target specifies a segment index: in this case,
  16532.                          the frame is determined as in (F0).
  16533.  
  16534.              (F5b)       The target specifies a group index: in this case,
  16535.                          the frame is determined as in (F1).
  16536.  
  16537.              (F5c)       The target specifies an external index: in this
  16538.                          case, the frame is determined as in (F2).
  16539.  
  16540.  The nomenclature that describes frames is similar to the above
  16541.  nomenclature for targets.
  16542.  
  16543.  Nomenclature                       Method
  16544.  ───────────────────────────────────────────────────────────────────────────
  16545.  Frame:  SI (segment name)          [F0]
  16546.  Frame:  GI (group name)            [F1]
  16547.  Frame:  EI (symbol name)           [F2]
  16548.  Frame:  Location                   [F4]
  16549.  Frame:  target                     [F5]
  16550.  Frame:  None                       [F6]
  16551.  
  16552.  For an 8086 memory reference, the frame specified by a self-relative
  16553.  reference is usually the canonic frame of the LSEG that contains Location.
  16554.  Also, the frame specified by a segment-relative reference is the canonic
  16555.  frame of the LSEG that contains the target.
  16556.  
  16557.  
  16558.  7.3.1  Self-Relative Fixup
  16559.  
  16560.  A self-relative fixup works as follows:  Location implicitly defines
  16561.  a memory address-namely, the address of the byte following Location
  16562.  (because at the time of a self-relative reference, the 8086 IP
  16563.  (Instruction Pointer) is pointing to the byte following the reference).
  16564.  
  16565.  For 8086 self-relative references, if either the Location or the target
  16566.  is outside the specified frame, the linker gives a warning. Otherwise,
  16567.  there is a unique l6-bit displacement that, when added to the address
  16568.  implicitly defined by Location, yields the relative position of the
  16569.  target in the frame.
  16570.  
  16571.      ■ If Location is an offset, the linker adds the displacement
  16572.        to Location (modulo 65,536) and reports no errors.
  16573.  
  16574.      ■ If Location is a lobyte, the displacement must be within the
  16575.        range {-128:127}; otherwise, the linker gives a warning. The
  16576.        linker adds the displacement to Location (modulo 256).
  16577.  
  16578.      ■ If Location is a base, pointer, or hibyte, it is unclear what
  16579.        the translator intended, so the linker's action is undefined.
  16580.  
  16581.  
  16582.  7.3.2  Segment-Relative Fixup
  16583.  
  16584.  A segment-relative fixup operates as follows: a nonnegative 16-bit
  16585.  number, FBVAL, is defined as the frame number of the frame or selector
  16586.  value that the fixup specifies. A signed 20-bit number, FOVAL, is defined
  16587.  as the distance from the base of the frame to the target. If this signed
  16588.  20-bit number is less than 0 or greater than 65,535, the linker reports
  16589.  an error. Otherwise, the linker uses FBVAL and FOVAL to fix up Location
  16590.  in the following fashion:
  16591.  
  16592.      ■ If Location is a pointer, the linker adds FBVAL (modulo 65,536) to
  16593.        the high-order word of pointer, and adds FOVAL (modulo 65,536) to
  16594.        the low-order word of pointer.
  16595.  
  16596.      ■ If Location is a base, the linker adds FBVAL (modulo 65,536) to
  16597.        the base and ignores FOVAL.
  16598.  
  16599.      ■ If Location is an offset, the linker adds FOVAL (modulo 65,536)
  16600.        to the offset and ignores FBVAL.
  16601.  
  16602.      ■ If Location is a hibyte, the linker adds (FOVAL/256) (modulo 256)
  16603.        to the hibyte and ignores FBVAL. (The division indicated is integer
  16604.        division; that is, the linker discards the remainder.)
  16605.  
  16606.      ■ If Location is a lobyte, the linker adds (FOVAL modulo 256)
  16607.        (modulo 256) to the lobyte and ignores FBVAL.
  16608.  
  16609.  
  16610.  7.4  Record Sequence
  16611.  
  16612.  
  16613.  A object code file must contain a sequence of (one or more) modules,
  16614.  or a library containing zero or more modules. The following syntax shows
  16615.  the valid record ordering necessary to form a module. In addition, the
  16616.  given semantic rules provide information about how to interpret the record
  16617.  sequence.
  16618.  
  16619.  ───────────────────────────────────────────────────────────────────────────
  16620.  Note
  16621.    The description language used in the following syntax is defined in
  16622.    WIRTH: CACM, November 1977, vol. 20, no. 11, pp. 822-823. The character
  16623.    strings represented by capital letters are not literals but identifiers,
  16624.    and are further defined in the record format section.
  16625.  ───────────────────────────────────────────────────────────────────────────
  16626.  
  16627.  object file  = tmodule
  16628.  
  16629.  tmodule      = {THEADR | LHEADR} seg-grp {component} modtail
  16630.  
  16631.  seg_grp      = {LNAMES} {SEGDEF} {EXTDEF | GRPDEF}
  16632.  
  16633.  component    = data | debug_record
  16634.  
  16635.  data         = content_def | thread_def |
  16636.                      PUBDEF | EXTDEF | COMDEF | LOCSYM
  16637.  
  16638.  debug_record = LINNUM
  16639.  
  16640.  content_def  = data_record {FIXUPP}
  16641.  
  16642.  thread_def   = FIXUPP (containing only Thread fields)
  16643.  
  16644.  data_record  = LIDATA | LEDATA
  16645.  
  16646.  modtail      = MODEND
  16647.  
  16648.  The following rules apply:
  16649.  
  16650.      ■ A FIXUPP record always refers to the previous data record.
  16651.  
  16652.      ■ All LNAMES, SEGDEF, GRPDEF, and EXTDEF records must precede all
  16653.        records that refer to them.
  16654.  
  16655.      ■ Comment records may appear anywhere in a file, except as the
  16656.        first or last record in a file or module, or within a content_def.
  16657.  
  16658.  
  16659.  7.5  Introducing the Record Formats
  16660.  
  16661.  
  16662.  The following pages present diagrams of record formats in schematic form.
  16663.  Here is a sample record format that illustrates the various conventions:
  16664.  
  16665.  
  16666.  7.5.1  Sample Record Format (SAMREC)
  16667.  
  16668.  -----------------------///---------||||-----------
  16669.  |     |          |            |            |     |
  16670.  | REC |  Record  |    Name    |   Number   | CHK |
  16671.  | TYP |  Length  |            |            | SUM |
  16672.  | xxH |          |            |            |     |
  16673.  |     |          |            |            |     |
  16674.  ----------------------///----------||||-----------
  16675.                   |            |
  16676.                   +----rpt-----+
  16677.  
  16678.  
  16679.  The Title and Official Abbreviation
  16680.  
  16681.  At the top of the figure is the name of the record format described, with
  16682.  its official abbreviation. To promote uniformity among various programs,
  16683.  including translators and debuggers, use the abbreviation in both code and
  16684.  documentation. The abbreviation of the record format is always six letters.
  16685.  
  16686.  
  16687.  The Boxes
  16688.  
  16689.  Each format is drawn with boxes of two sizes. The narrow boxes represent
  16690.  single bytes. The wide boxes each represent two bytes. The wide boxes
  16691.  with three slashes in the top and bottom represent a variable number of
  16692.  bytes, one or more, depending upon content. The wide boxes with four
  16693.  vertical bars in the top and bottom represent four-byte fields.
  16694.  
  16695.  
  16696.  RECTYP
  16697.  
  16698.  The first byte in each record contains a value between 0 and 255,
  16699.  indicating the record type.
  16700.  
  16701.  
  16702.  Record Length
  16703.  
  16704.  The second field in each record contains the number of bytes in the record,
  16705.  exclusive of the first two fields, where a field is a 16-bit number--
  16706.  a low byte followed by a high byte.
  16707.  
  16708.  
  16709.  Name
  16710.  
  16711.  Any field that indicates a name has the following internal structure:
  16712.  the first byte contains a number between 0 and 127, inclusive, indicating
  16713.  the number of remaining bytes in the field. The remaining bytes are
  16714.  interpreted as a byte string.
  16715.  
  16716.  Most translators constrain the character set to a subset of the ASCII
  16717.  character set.
  16718.  
  16719.  
  16720.  Number
  16721.  
  16722.  A four-byte number field represents a 32-bit unsigned integer, where
  16723.  the first eight bits (least-significant) are stored in the first byte
  16724.  (lowest address), the next eight bits are stored in the second byte,
  16725.  and so on.
  16726.  
  16727.  
  16728.  Repeated or Conditional Fields
  16729.  
  16730.  Some portions of a record format contain a field or series of fields that
  16731.  may be repeated one or more times. Such portions are indicated by the
  16732.  "repeated" or "rpt" brackets below the boxes.
  16733.  
  16734.  Similarly, some portions of a record format are present only if some given
  16735.  condition is true; these fields are indicated by similar "conditional"
  16736.  or "cond" brackets below the boxes.
  16737.  
  16738.  
  16739.  CHKSUM
  16740.  
  16741.  The last field in each record is a check sum, which contains the two's
  16742.  complement of the sum (modulo 256) of all other bytes in the record.
  16743.  Therefore, the sum (modulo 256) of all bytes in the record is zero.
  16744.  
  16745.  
  16746.  Bit Fields
  16747.  
  16748.  Sometimes descriptions of contents of fields are at the bit level.
  16749.  Boxes with vertical lines drawn through them represent bytes or words;
  16750.  the vertical lines indicate bit boundaries. Thus, the following byte
  16751.  representation has three bit fields of three, one, and four bits,
  16752.  respectively.
  16753.  
  16754.  ---------------------------------
  16755.  |   |   |   |   |   |   |   |   |
  16756.  |           |   |               |
  16757.  |   |   |   |   |   |   |   |   |
  16758.  ---------------------------------
  16759.        3       1         4
  16760.  
  16761.  
  16762.  7.5.2  T-Module Header Record (THEADR)
  16763.  
  16764.  
  16765.  -----------------------///-----------
  16766.  |     |          |            |     |
  16767.  | REC |  Record  |    T-      | CHK |
  16768.  | TYP |  Length  |    Module  | SUM |
  16769.  | 80H |          |    Name    |     |
  16770.  |     |          |            |     |
  16771.  ----------------------///------------
  16772.  
  16773.  
  16774.  T-Module Name
  16775.  
  16776.  The T-Module Name field contains the name for the T-module.
  16777.  
  16778.  
  16779.  7.5.3  L-Module Header Record (LHEADR)
  16780.  
  16781.  
  16782.  -----------------------///-----------
  16783.  |     |          |            |     |
  16784.  | REC |  Record  |    L-      | CHK |
  16785.  | TYP |  Length  |    Module  | SUM |
  16786.  | 82H |          |    Name    |     |
  16787.  |     |          |            |     |
  16788.  ----------------------///------------
  16789.  
  16790.  
  16791.  L-Module Name
  16792.  
  16793.  The L-Module Name field contains the name for the L-module.
  16794.  
  16795.  Every module output from a translator must have a T-module or L-module
  16796.  header record. The linker requires a THEADR or LHEADR record to come first
  16797.  in the module and ignores any others. The LHEADR record is identical to
  16798.  the THEADR record, except it has a record type of 82H.
  16799.  
  16800.  
  16801.  7.5.4  List of Names Record (LNAMES)
  16802.  
  16803.  
  16804.  -----------------------///-----------
  16805.  |     |          |            |     |
  16806.  | REC |  Record  |    Name    | CHK |
  16807.  | TYP |  Length  |            | SUM |
  16808.  | 96H |          |            |     |
  16809.  |     |          |            |     |
  16810.  ----------------------///------------
  16811.                   |            |
  16812.                   +----rpt-----+
  16813.  
  16814.  The LNAMES record contains a list of names that the following SEGDEF and
  16815.  GRPDEF records may use as the names of segments, classes, and/or groups.
  16816.  
  16817.  The order of LNAMES records in a module and the order of names within
  16818.  each LNAMES record imply a mapping of these names to numbers: 1, 2, 3, etc.
  16819.  These numbers are used as "Name Indices" in the Segment Name Index, Class
  16820.  Name Index, and Group Name Index fields of the SEGDEF and GRPDEF records.
  16821.  
  16822.  
  16823.  Name
  16824.  
  16825.  This repeatable field provides a name, which may have zero length.
  16826.  
  16827.  
  16828.  7.5.5  Segment Definition Record (SEGDEF)
  16829.  
  16830.  -----------------///-----------------///-----///---///------
  16831.  |   |        |         |         |         |     |     |   |
  16832.  |REC| Record | Segment | Segment | Segment |Class|Over |CHK|
  16833.  |TYP| Length |   ATTR  | Length  |   Name  |Name |Lay  |SUM|
  16834.  |98H|        |         |         |  Index  |Index|Name |   |
  16835.  |   |        |         |         |         |     |Index|   |
  16836.  -----------------///-----------------///-----///---///------
  16837.  
  16838.  Segment index values 1 through 32,767, which are used in other record
  16839.  types to refer to specific LSEGs, are defined implicitly by the sequence
  16840.  in which SEGDEF records appear in the object file.
  16841.  
  16842.  
  16843.  SEG ATTR
  16844.  
  16845.  The SEG ATTR field provides information on various attributes of a
  16846.  segment, and has the following format:
  16847.  
  16848.  ------------------------
  16849.  |     |        |       |
  16850.  | ACB | Frame  |  Off- |
  16851.  |  P  | Number |  Set  |
  16852.  |     |        |       |
  16853.  |     |        |       |
  16854.  -------------r----------
  16855.        |                |
  16856.        +---conditional--+
  16857.  
  16858.  The ACBP byte contains four numbers--the A, C, B, and P attribute
  16859.  specifications. This byte has the following format:
  16860.  
  16861.  ---------------------------------
  16862.  |   |   |   |   |   |   |   |   |
  16863.  |     A     |     C     | B | P |
  16864.  |   |   |   |   |   |   |   |   |
  16865.  ---------------------------------
  16866.  
  16867.  A (Alignment) is a 3-bit subfield that specifies the alignment attribute of
  16868.  the LSEG. The semantics are defined as follows:
  16869.  
  16870.  ───────────────────────────────────────────────────────────────────────────
  16871.  A=0      SEGDEF describes an absolute LSEG.
  16872.  A=1      SEGDEF describes a relocatable, byte-aligned LSEG.
  16873.  A=2      SEGDEF describes a relocatable, word-aligned LSEG.
  16874.  A=3      SEGDEF describes a relocatable, paragraph-aligned LSEG.
  16875.  A=4      SEGDEF describes a relocatable, page(256-byte)-aligned LSEG.
  16876.  
  16877.  If A=0, the Frame Number and Offset fields are present. With the Microsoft
  16878.  linker, you may use absolute segments for addressing only; for example,
  16879.  to define the starting address of a ROM and to define symbolic names for
  16880.  addresses within the ROM. The linker ignores any data that belongs to an
  16881.  absolute LSEG, and issues a warning if absolute segments are defined for
  16882.  a program that runs in protected mode.
  16883.  
  16884.  C (Combination) is a 3-bit subfield that specifies the Combination
  16885.  attribute of the LSEG. Absolute segments (A=0) must have combination
  16886.  zero (C=0). For relocatable segments, the C field encodes a number
  16887.  (0,1,2,3,4,5,6, or 7) that indicates how the segment can be combined.
  16888.  One way to interpret this attribute is to consider how two LSEGs
  16889.  are combined.
  16890.  
  16891.  For example, suppose that X and Y are LSEGs, and that Z is the LSEG
  16892.  resulting from the combination of X and Y. Let LX and LY be the lengths of
  16893.  X and Y, and let MXY denote the maximum of LX, LY. Now, to accommodate the
  16894.  alignment attribute of Y, let G be the length of any gap required between
  16895.  the X and Y components of Z. Then, let LZ denote the length of the
  16896.  (combined) LSEG, Z; let dx (0≤dx<LX) be the offset in X of a byte,
  16897.  and similarly, let dy be the offset (of a byte) in Y.
  16898.  
  16899.  The following table gives the length LZ of the combined LSEG, Z, and the
  16900.  offsets dx' and dy' in Z for the bytes corresponding to dx in X, and to
  16901.  dy in Y.
  16902.  
  16903.  
  16904.       Table 7.2
  16905.       Combination Attribute Example
  16906.  ───────────────────────────────────────────────────────────────────────────
  16907.       C   LZ        dx'   dy'
  16908.       2   LX+LY+G   dx    dy+LX+G   "Public"
  16909.       5   LX+LY+G   dx    dy+LX+G   "Stack"
  16910.       6   MXY       dx    dy        "Common"
  16911.  
  16912.  
  16913.  Table 7.2 has no lines for C=0, 1, 3, 4, or 7. C=0 indicates that the
  16914.  relocatable LSEG may not be combined; C=1 and C=3 are undefined. C=4 and
  16915.  C=7 are treated the same as C=2.
  16916.  
  16917.  B (Big) is a 1-bit subfield, which, if set to 1, indicates that the
  16918.  segment length is exactly 64K (65,536 bytes). In this case, the Segment
  16919.  Length field must contain zero.
  16920.  
  16921.  The P field must always be zero.
  16922.  
  16923.  The Frame Number and Offset fields (present only for absolute segments,
  16924.  A=0) specify the placement in MAS of the absolute segment. Offset is in
  16925.  the range between 0 and 15, inclusive. If you want an offset value larger
  16926.  than 15, you should adjust the frame number.
  16927.  
  16928.  
  16929.  Segment Length
  16930.  
  16931.  The Segment Length field gives a segment's length in bytes. This length
  16932.  may be zero. If it is, the linker does not delete the segment from the
  16933.  module. The Segment Length field is only large enough to hold numbers from
  16934.  0 to 64K-1, inclusive. To give the segment a length of 64K, you must use
  16935.  the B attribute bit in the ACBP field (see SEG ATTR in this section).
  16936.  
  16937.  
  16938.  Segment Name Index
  16939.  
  16940.  The segment name is a name that a programmer or translator assigns to
  16941.  the segment; for example, CODE, DATA, TAXDATA, MODULENAME_CODE, or STACK.
  16942.  The Segment Name Index field provides the segment name by indexing into
  16943.  the list of names provided by the LNAMES record.
  16944.  
  16945.  
  16946.  Class Name Index
  16947.  
  16948.  The class name is a name the programmer or translator assigns to a segment.
  16949.  If none is assigned, the name is null, and has a length of zero. The
  16950.  purpose of a class name is to let the programmer define a "handle" to
  16951.  order the LSEGs in MAS; for example,  RED, WHITE, BLUE; or ROM FASTRAM,
  16952.  DISPLAYRAM. The Class Name Index field provides the class name by indexing
  16953.  into the list of names provided by the LNAMES record.
  16954.  
  16955.  
  16956.  Overlay Name Index
  16957.  
  16958.  The overlay name is a name that the translator and/or the linker, at
  16959.  the programmer's request, applies to a segment. The overlay name, like the
  16960.  class name, may be null. The Overlay Name Index field provides the overlay
  16961.  name by indexing into the list of names provided by the LNAMES record.
  16962.  
  16963.  ───────────────────────────────────────────────────────────────────────────
  16964.  Note
  16965.    Microsoft language linkers (versions 3.00 and later) ignore the Overlay
  16966.    Name Index field, but the standard MS-DOS linker supports it.
  16967.  ───────────────────────────────────────────────────────────────────────────
  16968.  
  16969.  
  16970.  7.5.6  Group Definition Record (GRPDEF)
  16971.  
  16972.  -----------------------///---------///------------
  16973.  |     |          |            |            |     |
  16974.  | REC |  Record  |    Group   |   Group    | CHK |
  16975.  | TYP |  Length  |    Name    |  Component | SUM |
  16976.  | 9AH |          |    Index   | Descriptor |     |
  16977.  |     |          |            |            |     |
  16978.  --------------------///----------///--------------
  16979.                                |            |
  16980.                                +--repeated--+
  16981.  
  16982.  
  16983.  Group Name Index
  16984.  
  16985.  The linker may reference a collection of LSEGs with the group name. Most
  16986.  importantly, when the LSEGs are eventually fixed in MAS, a frame must
  16987.  exist that "covers" every LSEG of the group.
  16988.  
  16989.  The Group Name Index field provides the group name by indexing into the
  16990.  list of names provided by the LNAMES record.
  16991.  
  16992.  
  16993.  Group Component Descriptor
  16994.  
  16995.  This repeatable field has the following format:
  16996.  
  16997.  -----------///-----
  16998.  |     |           |
  16999.  | FFH |  Segment  |
  17000.  |     |   Index   |
  17001.  |     |           |
  17002.  |     |           |
  17003.  -------------------
  17004.  
  17005.  The first byte of the Group Component Descriptor field contains 0FFH; the
  17006.  descriptor contains one field, which is a segment index that selects the
  17007.  LSEG described by a preceding SEGDEF record.
  17008.  
  17009.  
  17010.  7.5.7  Public Names Definition Record (PUBDEF)
  17011.  
  17012.  ---------------------///------///--------------///---------
  17013.  |    |          |         |         |       |       |     |
  17014.  | REC|  Record  |  Public | Public  |Public | Type  | CHK |
  17015.  | TYP|  Length  |   Base  |  Name   |Offset | Index | SUM |
  17016.  | 90H|          |         |         |       |       |     |
  17017.  |    |          |         |         |       |       |     |
  17018.  ---------------------///-----///--------------///----------
  17019.                            |                         |
  17020.                            +---------repeated--------+
  17021.  
  17022.  The PUBDEF record provides a list of one or more public names. For each
  17023.  name, three kinds of data are provided: (1) a base value for the name,
  17024.  (2) the offset value of the name, and (3) the type of entity represented
  17025.  by the name.
  17026.  
  17027.  
  17028.  Public Base
  17029.  
  17030.  The Public Base field has the following format:
  17031.  
  17032.  -----///---------///-----------------
  17033.  |           |           |           |
  17034.  |   Group   |  Segment  |   Frame   |
  17035.  |   Index   |   Index   |   Number  |
  17036.  |           |           |           |
  17037.  -----///---------///-----------------
  17038.                          |           |
  17039.                          +conditional+
  17040.  
  17041.  The Group Index field has a format given earlier, and contains a number
  17042.  between 0 and 32,767, inclusive. A nonzero value in the Group Index
  17043.  field associates a group with the public symbol, and is used as described
  17044.  in case (F2c) of Section 7.3, "Conceptual Framework for Fixups." A zero
  17045.  value in the Group Index field indicates that there is no associated group.
  17046.  
  17047.  The Segment Index field has a format given earlier, and contains a number
  17048.  between 0 and 32,767, inclusive.
  17049.  
  17050.  A nonzero value in the Segment Index field selects an LSEG. In this case,
  17051.  the location of each public symbol defined in the record is taken as a
  17052.  nonnegative displacement (given by a Public Offset field) from the first
  17053.  byte of the selected LSEG. Also, the Frame Number field must be absent.
  17054.  
  17055.  A zero value in the Segment Index field means that the defined are
  17056.  absolute, and that the absolute addresses of the symbols are the values
  17057.  in the Public Offset field. The Group Index field is ignored.
  17058.  
  17059.  The Frame Number field contains a frame number only if the value of the
  17060.  Segment Index field is zero. The linker ignores this field.
  17061.  
  17062.  A nonzero value in the Group Index field selects some group. This group
  17063.  is taken as the "frame of reference" for references to all public symbols
  17064.  defined in this record. That is, the linker performs the following actions:
  17065.  
  17066.      ■ The linker converts any fixup of the form:
  17067.  
  17068.        Target: EI(P)
  17069.  
  17070.        Frame: Target
  17071.  
  17072.        (where P is a public symbol in this PUBDEF record) to a fixup of
  17073.        the form:
  17074.  
  17075.        Target: SI(L),d
  17076.  
  17077.        Frame:  GI(G)
  17078.  
  17079.        where SI(L) and d are provided by the Segment Index and Public Offset
  17080.        fields. (The "normal" action would have the frame specifier in the
  17081.        new fixup be the same as in the old fixup: Frame:Target.)
  17082.  
  17083.      ■ When the linker converts the value of a public symbol, as defined
  17084.        by the Segment Index, Public Offset, and (optionally) Frame Number
  17085.        fields, to a {base,offset} pair, the base part is the base of the
  17086.        indicated group.
  17087.  
  17088.  A zero value in the Group Index field selects no group. The linker
  17089.  does not alter the frame specification of fixups referencing the symbol,
  17090.  and takes, as the base part of the absolute value of the public symbol,
  17091.  the canonic frame of the segment (either LSEG or PSEG) determined by
  17092.  the Segment Index field.
  17093.  
  17094.  
  17095.  Public Name
  17096.  
  17097.  The Public Name field gives the name of the object whose location in MAS
  17098.  the linker makes available to other modules. The name must contain one
  17099.  or more characters.
  17100.  
  17101.  
  17102.  Public Offset
  17103.  
  17104.  The Public Offset field is a 16-bit value. It is either the offset of the
  17105.  public symbol with respect to an LSEG (if the segment index is greater than
  17106.  zero), or the offset of the public symbol with respect to the specified
  17107.  frame (if the segment index is equal to zero).
  17108.  
  17109.  
  17110.  Type Index
  17111.  
  17112.  The Type Index field identifies a single preceding TYPDEF (Type Definition
  17113.  Record), which contains a descriptor for the type of entity represented by
  17114.  the public symbol. The linker ignores this field.
  17115.  
  17116.  
  17117.  7.5.8  Communal Names Definition Record (COMDEF)
  17118.  
  17119.  -----------------///---------///-----------------------------
  17120.  |     |     |           |           |      |          |     |
  17121.  | REC | REC | Communal  |   Type    | Data | Communal | CHK |
  17122.  | TYP | LEN |   Name    |   Index   | Seg  | Length   | SUM |
  17123.  | B0H |     |           |           | Type |          |     |
  17124.  |     |     |           |           |      |          |     |
  17125.  ------------+----///---------///----------------------+------
  17126.              |                                         |
  17127.              +-------repeated--------------------------+
  17128.  
  17129.  The COMDEF record provides a list of one or more Communal Names, which
  17130.  define communal variables. A communal variable is an unitialized public
  17131.  variable whose final size and location are not fixed during compiling.
  17132.  
  17133.  Communal variables are similar to FORTRAN common blocks in that if you
  17134.  are linking object modules that each declare a communal variable, then
  17135.  the size of that variable is the largest of the declared variables. In the
  17136.  C language, all uninitialized public variables are communal. The following
  17137.  example shows three different declarations of the same C communal variable:
  17138.  
  17139.  char    foo[4];         /* In file a.c */
  17140.  char    foo[1];         /* In file b.c */
  17141.  char    foo[1024];      /* In file c.c */
  17142.  
  17143.  If the objects produced from a.c, b.c, and c.c are linked together, the
  17144.  linker allocates 1024 bytes for the character array "foo."
  17145.  
  17146.  ───────────────────────────────────────────────────────────────────────────
  17147.  Note
  17148.    This record requires that a COMENT record from the Microsoft
  17149.    Extension class appear before it in the object module.
  17150.  ───────────────────────────────────────────────────────────────────────────
  17151.  
  17152.  
  17153.  Communal Name
  17154.  
  17155.  The Communal Name field gives the communal variable name, and must contain
  17156.  one or more characters.
  17157.  
  17158.  Communal names are treated as external names when an external name is
  17159.  requested elsewhere in the module. Communal names are ordered together
  17160.  with external names for the purpose of referring to an external name by
  17161.  its index. (See the description of the EXTDEF record later in this section
  17162.  for more details on external names.)
  17163.  
  17164.  
  17165.  Type Index
  17166.  
  17167.  The Type Index field is ignored by the Microsoft linker.
  17168.  
  17169.  
  17170.  Data Segment Type
  17171.  
  17172.  The Data Segment Type field is a single byte that describes the data
  17173.  segment in which the communal variable resides. It can contain the
  17174.  following values:
  17175.  
  17176.      62H (NEAR) = the communal variable is in the default data segment.
  17177.      61H (FAR) = the communal variable is not in the default data segment.
  17178.  
  17179.  
  17180.  Communal Length
  17181.  
  17182.  The Communal Length field describes the length of the communal variable o
  17183.  according to its data segment type.
  17184.  
  17185.  If its value is NEAR (62H), the field represents the length in bytes.
  17186.  
  17187.  If its value is FAR (61H), the field represents:
  17188.  
  17189.  +----///----+-----///------+
  17190.  | Number of | Element size |
  17191.  | elements  | in bytes     |
  17192.  +----///----+-----///------+
  17193.  
  17194.  The format of all the length fields is as follows:
  17195.  
  17196.  -------
  17197.  |     |
  17198.  |  0  |
  17199.  | to  |
  17200.  | 128 |
  17201.  |     |
  17202.  -------
  17203.  
  17204.  -------------------
  17205.  |     |           |
  17206.  |     |     0     |
  17207.  | 129 |    to     |
  17208.  |(81H)|   64K-1   |
  17209.  |     |           |
  17210.  -------------------
  17211.  
  17212.  -------------------------
  17213.  |     |                 |
  17214.  |     |        0        |
  17215.  | 132 |       to        |
  17216.  |(84H)|      16M-1      |
  17217.  |     |                 |
  17218.  -------------------------
  17219.  
  17220.  -------------------------
  17221.  |     |                 |
  17222.  |     |     -2G-1       |
  17223.  | 136 |       to        |
  17224.  |(88H)|      2G-1       |
  17225.  |     |                 |
  17226.  -------------------------
  17227.  
  17228.  The first format (single byte), containing a value between 0 and 127,
  17229.  represents the number given.
  17230.  
  17231.  The second format, with a leading byte containing 129, represents the
  17232.  number contained in the following two bytes.
  17233.  
  17234.  The third format, with a leading byte containing 132, represents the
  17235.  number contained in the following three bytes.
  17236.  
  17237.  The fourth format, with a leading byte containing 136, represents the
  17238.  number contained in the following four bytes with its sign extended if
  17239.  necessary.
  17240.  
  17241.  
  17242.  Link-Time Semantics
  17243.  
  17244.  A PUBDEF matching a communal variable definition overrides the communal
  17245.  variable definition. Two communal variable definitions match if the names
  17246.  in their definitions match. If two matching definitions disagree whether a
  17247.  communal variable is NEAR or FAR, the linker assumes the variable is NEAR.
  17248.  
  17249.  If the variable is NEAR, then its size is the largest of the sizes
  17250.  specified for it. If the variable is FAR, the linker issues a warning
  17251.  if the array element sizes conflict. If these sizes don't conflict,
  17252.  the variable's size is the element size multiplied by the largest number
  17253.  of elements specified. In addition, the sum of the sizes of all NEAR
  17254.  variables must not exceed 64K bytes, and the sum of the sizes of all
  17255.  FAR variables must not exceed the size of the machine's addressable
  17256.  memory space.
  17257.  
  17258.  
  17259.  HUGE Communal Variables:
  17260.  
  17261.  A FAR communal variable that is larger than 64K bytes (a HUGE communal
  17262.  variable) resides in segments that are contiguous (on an 8086) or that
  17263.  have consecutive selectors (on an 80286). No other data items reside
  17264.  in the segments occupied by a HUGE communal variable.
  17265.  
  17266.  If the linker finds matching HUGE and NEAR communal variable definitions,
  17267.  it issues a warning message, since it is impossible for a NEAR variable
  17268.  to be larger than 64K bytes.
  17269.  
  17270.  
  17271.  7.5.9  Local Symbols Record (LOCSYM)
  17272.  
  17273.  ---------------------///------///--------------///---------
  17274.  |    |          |         |         |       |       |     |
  17275.  | REC|  Record  |  Local  | Local   | Local | Type  | CHK |
  17276.  | TYP|  Length  |   Base  |  Name   |Offset | Index | SUM |
  17277.  | 92H|          |         |         |       |       |     |
  17278.  |    |          |         |         |       |       |     |
  17279.  ---------------------///-----///--------------///----------
  17280.                            |                         |
  17281.                            +---------repeated--------+
  17282.  
  17283.  The LOCSYM record provides information for the definition of a local
  17284.  symbol, one that is visible only within the module in which it is
  17285.  defined.
  17286.  
  17287.  The form and meaning of each of the fields is identical to those in the
  17288.  PUBDEF record.
  17289.  
  17290.  ───────────────────────────────────────────────────────────────────────────
  17291.  Note
  17292.    The LOCSYM record requires that a COMENT record from the Microsoft
  17293.    Extensions class appear before it in the object module. Also, it is
  17294.    only recognized by Microsoft language linkers later than version 3.07.
  17295.  ───────────────────────────────────────────────────────────────────────────
  17296.  
  17297.  
  17298.  7.5.10  External Names Definition Record (EXTDEF)
  17299.  
  17300.  -----------------------///---------///-----------
  17301.  |     |           |           |           |     |
  17302.  | REC |  Record   | External  |   Type    | CHK |
  17303.  | TYP |  Length   |   Name    |   Index   | SUM |
  17304.  | 8CH |           |           |           |     |
  17305.  |     |           |           |           |     |
  17306.  -----------------------///---------///-----------
  17307.                    |                       |
  17308.                    +-------repeated--------+
  17309.  
  17310.  The EXTDEF record provides a list of external names, and for each name, the
  17311.  type of object it represents. The linker assigns to each external name the
  17312.  value provided by an identical public name or local name (if such a name
  17313.  is found).
  17314.  
  17315.  
  17316.  External Name
  17317.  
  17318.  The External Name field provides the external object name, which must have
  17319.  nonzero length.
  17320.  
  17321.  Including a name in an EXTDEF record is an implicit request to link the
  17322.  object file to a module containing the same name declared as a public
  17323.  symbol, unless the name is defined as a local symbol within the same
  17324.  module as the EXTDEF. This request determines whether the external name
  17325.  is referenced within some FIXUPP record in the module.
  17326.  
  17327.  The order of EXTDEF records in a module and the order of external names
  17328.  within each EXTDEF record, together with COMDEF records and communal
  17329.  names, implies a mapping on the set of all external names requested
  17330.  by the module; for example: 1, 2, 3, etc. So to refer to a particular
  17331.  external name, the linker uses these numbers as "external indices"
  17332.  in the Target Datum and/or Frame Datum fields of FIXUPP records.
  17333.  
  17334.  External indices may not reference forward. For example, an EXTDEF
  17335.  defining the kth object must precede any record referring to that
  17336.  object with index k.
  17337.  
  17338.  
  17339.  Type Index
  17340.  
  17341.  The Type Index field is ignored by the Microsoft linker, except for linker
  17342.  versions earlier than 3.05, and for object modules lacking the COMENT
  17343.  record from the Microsoft Extensions class, in which case, refer to
  17344.  Section 7.6, "Microsoft Type Representation for Communal Variables."
  17345.  
  17346.  
  17347.  7.5.11  Line Numbers Record (LINNUM)
  17348.  
  17349.  ----------------------///-----------------------------------
  17350.  |     |          |           |           |                 |
  17351.  | REC |  Record  |   Line    |   Line    |   Line    | CHK |
  17352.  | TYP |  Length  |  Number   |  Number   |  Number   | SUM |
  17353.  | 94H |          |   Base    |           |  Offset   |     |
  17354.  |     |          |           |           |           |     |
  17355.  ----------------------///-----------------------------------
  17356.                               |                       |
  17357.                               +--------repeated-------+
  17358.  
  17359.  The LINNUM record allows a translator to relate a line number in source
  17360.  code to the corresponding line in translated code.
  17361.  
  17362.  
  17363.  Line Number Base
  17364.  
  17365.  The Line Number Base field has the following format:
  17366.  
  17367.  -----///---------///-----
  17368.  |           |           |
  17369.  |   Group   |  Segment  |
  17370.  |   Index   |   Index   |
  17371.  |           |           |
  17372.  -----///---------///-----
  17373.  
  17374.  The Group Index field is ignored by the Microsoft linker.
  17375.  
  17376.  The Segment Index field determines the location of the first byte of code
  17377.  corresponding to some source line number.
  17378.  
  17379.  
  17380.  Line Number
  17381.  
  17382.  The Line Number field provides a binary line number between 0 and 32,767,
  17383.  inclusive. If the high-order bit is not zero, the number is considered
  17384.  undefined.
  17385.  
  17386.  
  17387.  Line Number Offset
  17388.  
  17389.  The Line Number Offset field is a 16-bit value, which is the offset of
  17390.  the line number with respect to an LSEG (if the segment index is greater
  17391.  than zero).
  17392.  
  17393.  
  17394.  7.5.12  Logical Enumerated Data Record (LEDATA)
  17395.  
  17396.  -----------------------///-----------------------------
  17397.  |     |           |           |           |     |     |
  17398.  | REC |  Record   |  Segment  | Enumerated|     | CHK |
  17399.  | TYP |  Length   |   Index   |   Data    | DAT | SUM |
  17400.  | A0H |           |           |  offset   |     |     |
  17401.  |     |           |           |           |     |     |
  17402.  -----------------------///-----------------------------
  17403.                                            |     |
  17404.                                            +-rpt-+
  17405.  
  17406.  The LEDATA record provides contiguous data from which the linker may
  17407.  construct a portion of an 8086 memory image.
  17408.  
  17409.  
  17410.  Segment Index
  17411.  
  17412.  The Segment Index field, which must be nonzero, specifies an index relative
  17413.  to the SEGDEF records that precede the LEDATA record.
  17414.  
  17415.  
  17416.  Enumerated Data Offset
  17417.  
  17418.  The Enumerated Data Offset field specifies an offset that is relative to
  17419.  the base of the LSEG specified by the segment index. The field also defines
  17420.  the relative location of the first byte of the DAT field. Successive data
  17421.  bytes in the DAT field occupy successively higher locations of memory.
  17422.  
  17423.  
  17424.  DAT
  17425.  
  17426.  The DAT field provides up to 1024 consecutive bytes of relocatable or
  17427.  absolute data.
  17428.  
  17429.  
  17430.  7.5.13  Logical Iterated Data Record (LIDATA)
  17431.  
  17432.  ----------------------///---------------------///-----------
  17433.  |     |          |           |           |           |     |
  17434.  | REC |  Record  |  Segment  |  Iterated |  Iterated | CHK |
  17435.  | TYP |  Length  |   Index   |    Data   |   Data    | SUM |
  17436.  | A2H |          |           |   Offset  |   Block   |     |
  17437.  |     |          |           |           |           |     |
  17438.  ----------------------///---------------------///-----------
  17439.                                           |           |
  17440.                                           +-repeated--+
  17441.  
  17442.  The LIDATA record provides contiguous data from which the linker may
  17443.  construct a portion of an 8086 memory image.
  17444.  
  17445.  
  17446.  Segment Index
  17447.  
  17448.  The Segment Index field, which must be nonzero, specifies an index that
  17449.  is relative to the SEGDEF records that precede the LIDATA record.
  17450.  
  17451.  
  17452.  Iterated Data Offset
  17453.  
  17454.  The Iterated Data Offset field specifies an offset that is relative to
  17455.  the base of the LSEG specified by the segment index. It also defines the
  17456.  relative location of the first byte in the iterated data block. Successive
  17457.  data bytes in the iterated data block occupy successively higher locations
  17458.  of memory.
  17459.  
  17460.  
  17461.  Iterated Data Block
  17462.  
  17463.  This repeated field is a structure specifying the repeated data bytes.
  17464.  It has the following format:
  17465.  
  17466.  -----------------------------///-----
  17467.  |          |            |           |
  17468.  |  Repeat  |   Block    |           |
  17469.  |   Count  |   Count    |  Content  |
  17470.  |          |            |           |
  17471.  |          |            |           |
  17472.  -----------------------------///-----
  17473.  
  17474.  ───────────────────────────────────────────────────────────────────────────
  17475.  Note
  17476.    The linker cannot handle LIDATA records whose iterated Data Blocks
  17477.    are larger than 512 bytes.
  17478.  ───────────────────────────────────────────────────────────────────────────
  17479.  
  17480.  
  17481.  Repeat Count
  17482.  
  17483.  The Repeat Count field specifies the number of times to repeat the Content
  17484.  portion of this iterated data block. The value of the Repeat Count field
  17485.  must be nonzero.
  17486.  
  17487.  
  17488.  Block Count
  17489.  
  17490.  The Block Count field specifies the number of iterated data blocks in
  17491.  the Content portion of this iterated data block. If the Block Count field
  17492.  has a value of zero, the Content portion of the iterated data block is
  17493.  interpreted as data bytes. If the field is nonzero, the Content portion
  17494.  is interpreted as that number of iterated data blocks.
  17495.  
  17496.  
  17497.  Content
  17498.  
  17499.  The Content field may be interpreted in one of two ways, depending on
  17500.  the value of the previous Block Count field.
  17501.  
  17502.  If the Block Count field is zero, this field is a 1-byte count followed
  17503.  by the indicated number of data bytes. But if the Block Count field is
  17504.  nonzero, the Content field is interpreted as the first byte of another
  17505.  iterated data block.
  17506.  
  17507.  
  17508.  7.5.14  Fixupp Record (FIXUPP)
  17509.  
  17510.  -----------------------///-----------
  17511.  |     |           |           |     |
  17512.  | REC |  Record   |  Thread   | CHK |
  17513.  | TYP |  Length   |    or     | SUM |
  17514.  | 9CH |           |   Fixup   |     |
  17515.  |     |           |           |     |
  17516.  -----------------------///-----------
  17517.                    |           |
  17518.                    +----rpt----+
  17519.  
  17520.  The FIXUPP record specifies zero or more fixups. Each fixup requests
  17521.  a modification (fixup) to a Location within the previous data record.
  17522.  A data record may be followed by more than one FIXUPP record that refers
  17523.  to it. Each fixup is specified by a Fixup field that specifies four kinds
  17524.  of data: a Location, a mode, a target, and a frame. The frame and target
  17525.  may be specified completely within the Fixup field, or by reference to a
  17526.  preceding Thread field.
  17527.  
  17528.  A Thread field specifies a default target or frame that subsequently
  17529.  may be referred to. Eight threads are provided--four for frame
  17530.  specification and four for target specification. Once a thread has
  17531.  specified a target or frame, any Fixup fields that follow (in the same
  17532.  or following FIXUPP records) may refer to that target or frame until
  17533.  another Thread field with the same type (target or frame) and thread
  17534.  number (0-3) appears (in the same or in another FIXUPP record).
  17535.  
  17536.  
  17537.  Thread
  17538.  
  17539.  The Thread field has the following format:
  17540.  
  17541.  -----------///-----
  17542.  |     |           |
  17543.  | TRD |   Index   |
  17544.  | DAT |           |
  17545.  |     |           |
  17546.  -----------///-----
  17547.        |           |
  17548.        +conditional+
  17549.  
  17550.  The TRD DAT (Thread Data) field is a byte with the following internal
  17551.  structure:
  17552.  
  17553.  ---------------------------------
  17554.  |   |   |   |   |   |   |   |   |
  17555.  | 0 | D | 0 |  Method   | THRED |
  17556.  |   |   |   |   |   |   |   |   |
  17557.  ---------------------------------
  17558.  
  17559.  The D field is one bit and defines the type of thread being used. If D=0,
  17560.  this bit defines a target thread, and if D=1, it defines a frame thread.
  17561.  
  17562.  Method is a 3-bit field containing a number between 0 and 3 (if D=0) or a
  17563.  number between 0 and 6 (if D=1).
  17564.  
  17565.  If D=0, then Method = (0, 1, 2, 4, 5, 6)mod 4, where 0, 1, 2, 4, 5, 6
  17566.  indicate methods T0, T1, T2, T4, T5, and T6 of specifying a target. Thus,
  17567.  Method indicates the kind of index or frame number required to specify
  17568.  the target, without indicating whether the target is specified by a primary
  17569.  or secondary method.
  17570.  
  17571.  If D=1, then Method = 0, 1, 2, 4, 5, corresponding to methods F0, F1,
  17572.  F2, F4, F5 of specifying a frame. Here, Method indicates the kind (if any)
  17573.  of index required to specify the frame.
  17574.  
  17575.  The THRED field contains a number between 0 and 3, inclusive, and
  17576.  associates a thread number to the frame or target defined by the
  17577.  Thread field.
  17578.  
  17579.  The Index field contains a segment index, group index, or external
  17580.  index depending on the specification in the Method field. If Method
  17581.  specifies F4 or F5, this field will not be present.
  17582.  
  17583.  
  17584.  Fixup
  17585.  
  17586.  The Fixup field has the following format:
  17587.  
  17588.  -----------------------///---------///---------///-----
  17589.  |           |     |           |           |           |
  17590.  |   LOCAT   | FIX |   Frame   |  Target   |  Target   |
  17591.  |           | DAT |   Datum   |   Datum   |   Dis-    |
  17592.  |           |     |           |           | Placement |
  17593.  |           |     |           |           |           |
  17594.  -----------------------///---------///---------///-----
  17595.                    |           |           |           |
  17596.                    +conditional+conditional+conditional+
  17597.  
  17598.  The LOCAT field is a byte pair with the following format:
  17599.  
  17600.  -----------------------------------------------------------------
  17601.  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
  17602.  | 1 | M | 0 |    LOC    |  D a t a   R e c o r d   O f f s e t  |
  17603.  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
  17604.  -----------------------------------------------------------------
  17605.  |                               |                               |
  17606.  +------------lo byte------------+------------hi byte------------+
  17607.  
  17608.  M is a 1-bit field that specifies the mode of the fixups: self-
  17609.  relative (if M=0) or segment-relative (if M=1).
  17610.  
  17611.  ───────────────────────────────────────────────────────────────────────────
  17612.  Note
  17613.    Self-relative fixups may not be applied to LIDATA records.
  17614.  ───────────────────────────────────────────────────────────────────────────
  17615.  
  17616.  LOC is a 3-bit field indicating that the byte(s) in the preceding data
  17617.  record to be fixed up are a lobyte (if LOC=0), an offset (if LOC=1), a
  17618.  base (if LOC=2), a pointer (if LOC=3), a hibyte (if LOC=4), or a "loader-
  17619.  resolved" offset (if LOC=5). Any other values in LOC are invalid.
  17620.  
  17621.  The Data Record Offset field contains a number between 0 and 1023,
  17622.  inclusive, that gives the relative position of the lowest order byte
  17623.  of Location (the actual bytes being fixed up) within the preceding data
  17624.  record. The Data Record Offset value is relative to the first byte in
  17625.  the data fields in the data records.
  17626.  
  17627.  ───────────────────────────────────────────────────────────────────────────
  17628.  Note
  17629.    If the preceding data record is an LIDATA record, it is possible for the
  17630.    Data Record Offset value to designate a location within a Repeat Count
  17631.    field or a Block Count field of the Iterated Data Block field. Such a
  17632.    reference is an error. The linker's action on such a malformed record
  17633.    is undefined.
  17634.  ───────────────────────────────────────────────────────────────────────────
  17635.  
  17636.  The FIX DAT field is a byte with the following format:
  17637.  
  17638.  ---------------------------------
  17639.  |   |   |   |   |   |   |   |   |
  17640.  | F |   Frame   | T | P | TARGT |
  17641.  |   |   |   |   |   |   |   |   |
  17642.  ---------------------------------
  17643.  
  17644.  F is a 1-bit subfield that specifies whether the frame for this Fixup
  17645.  is specified by a thread (if F=1) or explicitly (if F=0).
  17646.  
  17647.  The Frame field contains a number that is interpreted in one of two
  17648.  ways, as indicated by the F bit. If F is zero, the Frame field contains a
  17649.  number between 0 and 5, inclusive, corresponding to methods F0,...,F5 for
  17650.  specifying a frame. If F=1, then the Frame field contains a thread number
  17651.  (0-3). It specifies the frame most recently defined by a Thread field
  17652.  that defined a frame thread with the same thread number. (Note that the
  17653.  Thread field may appear in the same FIXUPP record, or in an earlier one.)
  17654.  
  17655.  T is a 1-bit field that specifies whether the target specified for
  17656.  this fixup is defined by reference to a thread (T=1), or is given
  17657.  explicitly in the Fixup field (T=0).
  17658.  
  17659.  P is a 1-bit field that indicates whether the Target is specified by a
  17660.  primary method (requires a target displacement, if P=0) or by a secondary
  17661.  method (requires no target displacement, if P=1). Since a target thread
  17662.  does not have a primary/secondary attribute, the P bit is the only field
  17663.  that contains the target specification attribute.
  17664.  
  17665.  TARGT is interpreted as a 2-bit field. When T=0, it provides a number
  17666.  between 0 and 3, inclusive, corresponding to methods T0, T1, T2 or T4, T5,
  17667.  T6, depending on the value of P (where P is interpreted as the high-order
  17668.  bit of T0, T1, T2, T4, T5, or T6). When a thread specifies the target
  17669.  (if T=1), then the TARGET field specifies a thread number (0-3).
  17670.  
  17671.  The Frame Datum field is the "referent" portion of a frame specification,
  17672.  and is a segment index, group index, or external index. The Frame Datum
  17673.  field is present only when the frame is not specified by a thread (if F=0)
  17674.  or explicitly by methods F4, F5, or F6.
  17675.  
  17676.  The Target Datum field is the "referent" portion of a target specification,
  17677.  and is a segment index, group index, or external index. The Target Datum
  17678.  field is present only when a thread does not specify the target (if T=0).
  17679.  
  17680.  The Target Displacement field is the 2-byte displacement required by
  17681.  primary methods of specifying targets. This field is present if P=0.
  17682.  
  17683.  ───────────────────────────────────────────────────────────────────────────
  17684.  Note
  17685.    All these methods are described in Section 7.3, "Conceptual Framework
  17686.    for Fixups."
  17687.  ───────────────────────────────────────────────────────────────────────────
  17688.  
  17689.  
  17690.  7.5.15  Module End Record (MODEND)
  17691.  
  17692.  -----------------------------///-----------
  17693.  |     |           |     |           |     |
  17694.  | REC |  Record   | MOD |   START   | CHK |
  17695.  | TYP |  Length   | TYP |   ADDRS   | SUM |
  17696.  | 8AH |           |     |           |     |
  17697.  |     |           |     |           |     |
  17698.  -----------------------------///-----------
  17699.                          |           |
  17700.                          +conditional+
  17701.  
  17702.  The MODEND record serves two purposes. It denotes the end of a module
  17703.  and indicates whether the module that just ended specifies an entry point
  17704.  to begin execution. If it does not, the linker specifies the execution
  17705.  address.
  17706.  
  17707.  
  17708.  MOD TYP
  17709.  
  17710.  The MOD TYP field specifies the attributes of the module. The bit
  17711.  allocation and associated meanings are as follows:
  17712.  
  17713.  ---------------------------------
  17714.  |   |   |   |   |   |   |   |   |
  17715.  | MATTR | 0 | 0 | 0 | 0 | 0 | 1 |
  17716.  |   |   |   |   |   |   |   |   |
  17717.  ---------------------------------
  17718.  
  17719.  MATTR is a 2-bit field that specifies the following module attributes:
  17720.  
  17721.  MATTR   Module Attribute
  17722.  ───────────────────────────────────────────────────────────────────────────
  17723.  0       Non-main module with no START ADDRS
  17724.  1       Non-main module with START ADDRS
  17725.  2       Main module with no START ADDRS
  17726.  3       Main module with START ADDRS
  17727.  
  17728.  The START ADDRS field (present only if MATTR is 1 or 3) has the following
  17729.  format:
  17730.  
  17731.  -----------///---------///-----------------
  17732.  |     |           |           |           |
  17733.  | END |   Frame   |  Target   |  Target   |
  17734.  | DAT |   Datum   |   Datum   |   Dis-    |
  17735.  |     |           |           | Placement |
  17736.  |     |           |           |           |
  17737.  -----------///---------///-----------------
  17738.        |           |           |           |
  17739.        +conditional+conditional+conditional+
  17740.  
  17741.  The starting address of a module has all the attributes of any other
  17742.  logical reference found in a module. The mapping of a logical starting
  17743.  address to a physical starting address is done in the same manner as
  17744.  mapping any other logical address to a physical address, as specified in
  17745.  the discussion of fixups and the FIXUPP record. The fields of the START
  17746.  ADDRS field have the same semantics as the FIX DAT, Frame Datum, Target
  17747.  Datum, and Target Displacement fields in the FIXUPP record. Only primary
  17748.  fixup methods are allowed. Frame method F4 is not allowed.
  17749.  
  17750.  
  17751.  7.5.16  Comment Record (COMENT)
  17752.  
  17753.  -----------------------------------///-----------
  17754.  |     |           |           |           |     |
  17755.  | REC |  Record   |  Comment  |           | CHK |
  17756.  | TYP |  Length   |   Type    |  Comment  | SUM |
  17757.  | 88H |           |           |           |     |
  17758.  |     |           |           |           |     |
  17759.  -----------------------------------///-----------
  17760.  
  17761.  The COMENT record allows translators to include comments in object text.
  17762.  
  17763.  
  17764.  Comment Type
  17765.  
  17766.  The Comment Type field indicates the type of comment that this record
  17767.  carries, allowing you to structure comments for processes that selectively
  17768.  act on comments.
  17769.  
  17770.  The format of the Comment Type field is as follows:
  17771.  
  17772.  --------------------------------------------------------
  17773.  | N | N |   |   |   |   |   |   |          Comment     |
  17774.  | P | L | 0 | 0 | 0 | 0 | 0 | 0 |           Class      |
  17775.  --------------------------------------------------------
  17776.  
  17777.  The NP (NOPURGE) bit, if set to 1, indicates that this comment cannot be
  17778.  purged by object file utility programs that can delete Comment records.
  17779.  
  17780.  The NL (NOLIST) bit, if set to 1, indicates that the text in the Comment
  17781.  field should not appear in the listing file of object file utility programs
  17782.  that can list object Comment records.
  17783.  
  17784.  The Comment Class field is a byte defined as follows:
  17785.  
  17786. ╓┌───────────────────┌───────────────────────────────────────────────────────╖
  17787.  Value               Meaning
  17788.  ───────────────────────────────────────────────────────────────────────────
  17789.  Value               Meaning
  17790.  ───────────────────────────────────────────────────────────────────────────
  17791.  0                   Language Translator Comment (obsolete)
  17792.  
  17793.                      If the comment field contains one of the strings
  17794.                      "MS PASCAL" or "FORTRAN 77," then the comment record
  17795.                      enables the dsallocation switch on the Microsoft
  17796.                      linker.
  17797.  
  17798.  156(9CH)            DOS Version
  17799.  
  17800.                      The Comment field contains a 2-byte integer
  17801.                      that specifies the DOS level number.
  17802.  
  17803.  157(9DH)            Memory Model
  17804.  
  17805.                      Indicates the memory model of the object module.
  17806.                      The Comment field contains a single byte with the
  17807.                      values S, M, L, or H, for SMALL, MEDIUM, LARGE, or
  17808.                      HUGE, respectively. This Comment record is used
  17809.                      only by the Microsoft XENIX linker.
  17810.  Value               Meaning
  17811.                     only by the Microsoft XENIX linker.
  17812.  
  17813.  158(9EH)            Force Segment Ordering
  17814.  
  17815.                      Causes the linker to use a special segment ordering
  17816.                      for executable files. This comment record has the
  17817.                      same effect as giving the dosseg switch to Microsoft
  17818.                      language versions of the linker.
  17819.  
  17820.  159(9FH)            Library Specifier
  17821.  
  17822.  129(81H)            Library Specifier (obsolete)
  17823.  
  17824.                      Specifies a library to add to the Microsoft linker's
  17825.                      library search list. The Comment field contains the
  17826.                      name of the library. Note that unlike all other name
  17827.                      specifications, the library name is not prefixed with
  17828.                      its length but is determined by the record length.
  17829.                      The nodefaultlibrarysearch switch causes the linker
  17830.                      to ignore these comment records. The 159(9FH) class
  17831.  Value               Meaning
  17832.                     to ignore these comment records. The 159(9FH) class
  17833.                      record is ignored by XENIX versions of the
  17834.                      Microsoft linker.
  17835.  
  17836.  161(A1H)            Microsoft Extensions
  17837.  
  17838.                      Indicates that the object module contains extensions
  17839.                      to the original Microsoft adaptation of the Intel
  17840.                      Relocatable Object Module Format, such as the COMDEF
  17841.                      and LOCSYM records.
  17842.  
  17843.  
  17844.  
  17845.  Comment
  17846.  
  17847.  The Comment field provides the commentary information.
  17848.  
  17849.  
  17850.  7.6  Microsoft Type Representations for Communal Variables
  17851.  
  17852.  
  17853.  ───────────────────────────────────────────────────────────────────────────
  17854.  Note
  17855.    Object modules not containing the COMENT record from the Microsoft
  17856.    Extensions class can represent communal variable definitions only with
  17857.    the obsolete method described here. Also, Microsoft language linkers
  17858.    earlier than version 3.05 can recognize this method only. The newer
  17859.    method uses the Communal Variable Definitions (COMDEF) record.
  17860.  ───────────────────────────────────────────────────────────────────────────
  17861.  
  17862.  A communal variable is defined in the object text by an EXTDEF record
  17863.  and the TYPDEF record to which it refers.
  17864.  
  17865.  The TYPDEF record of a communal variable has the following format:
  17866.  
  17867.  -------------------------///-----------
  17868.  | REC | Record |   |    Eight   | CHK |
  17869.  | TYP | Length | 0 |    Leaf    | SUM |
  17870.  | 8EH |        |   | Descriptor |     |
  17871.  -------------------------///-----------
  17872.  
  17873.  The Eight Leaf Descriptor field has the following format:
  17874.  
  17875.  ---------///------
  17876.  | E |    Leaf    |
  17877.  | N | Descriptor |
  17878.  ---------///------
  17879.  
  17880.  The EN bitfield specifies whether the next eight leaves in the Leaf
  17881.  Descriptor field are EASY (if EN = 0) or NICE (if EN = l). This byte
  17882.  is always zero for TYPDEFs of communal variables.
  17883.  
  17884.  The Leaf Descriptor field has one of the following two formats. The
  17885.  format for communal variables in the default data segment (NEAR variables)
  17886.  is as follows:
  17887.  
  17888.  ------------------///-----///-----
  17889.  | NEAR | VAR |  Length  |  VAR   |
  17890.  | 62H  | TYP |    In    | SUBTYP |
  17891.  |      |     |   Bits   |        |
  17892.  ------------------///------///----
  17893.                          |        |
  17894.                          +--------+
  17895.                          (optional)
  17896.  
  17897.  The VARTYP (Variable Type) field may be either SCALAR (7BH), STRUCT
  17898.  (79H), or ARRAY (77H). The linker ignores the VAR SUBTYP field (if one
  17899.  exists). The format for communal variables not in the default data segment
  17900.  (FAR variables) is as follows:
  17901.  
  17902.  -----------------///-------///----
  17903.  | FAR | VAR |  Number  | Element |
  17904.  | 61H | TYP |    of    |  Type   |
  17905.  |     | 77H | Elements |  Index  |
  17906.  -----------------///-------///----
  17907.  
  17908.  The VARTYP field must be ARRAY (77H). The Length in Bits field specifies
  17909.  the Number of Elements, and the Element Type Index is an index to a
  17910.  previously defined TYPDEF record whose format is that of a NEAR communal
  17911.  variable.
  17912.  
  17913.  The format for the Length in Bits or Number of Elements fields is the
  17914.  same as the format of the Communal Length field of the COMDEF record.
  17915.  
  17916.  
  17917.  Link-Time Semantics
  17918.  
  17919.  All EXTDEF records referencing a TYPDEF record of one of the previously
  17920.  described formats are treated as communal variables. All others are
  17921.  treated as externally defined symbols for which a matching PUBDEF
  17922.  record is expected.
  17923.  
  17924.  For more information, see "Link-Time Semantics" in Section 7.5.8,
  17925.  "Communal Names Definition Record (COMDEF)."
  17926.  
  17927.  
  17928.  
  17929.  Chapter 8  Programming Hints
  17930.  
  17931.  ───────────────────────────────────────────────────────────────────────────
  17932.  
  17933.  8.1  Introduction
  17934.  
  17935.  8.2  Interrupts
  17936.  
  17937.  8.3  System Calls
  17938.  
  17939.  8.4  Device Management
  17940.  
  17941.  8.5  Memory Management
  17942.  
  17943.  8.6  Process Management
  17944.  
  17945.  8.7  File and Directory Management
  17946.  
  17947.        8.7.1  Locking Files
  17948.  
  17949.  8.8  Miscellaneous
  17950.  
  17951.  
  17952.  
  17953.  8.1  Introduction
  17954.  
  17955.  
  17956.  This chapter describes recommended MS-DOS 3.3 programming procedures.
  17957.  By using these programming hints, you can ensure compatibility with future
  17958.  versions of MS-DOS.
  17959.  
  17960.  The hints are organized in the following categories:
  17961.  
  17962.      ■ Interrupts
  17963.  
  17964.      ■ System Calls
  17965.  
  17966.      ■ Device Management
  17967.  
  17968.      ■ Memory Management
  17969.  
  17970.      ■ Process Management
  17971.  
  17972.      ■ File and Directory Management
  17973.  
  17974.      ■ Miscellaneous
  17975.  
  17976.  
  17977.  8.2  Interrupts
  17978.  
  17979.  
  17980.      ■ Never explicitly issue Interrupt 22H (Terminate Process Exit
  17981.        Address).
  17982.  
  17983.        Only the DOS should do this. To change the terminate address, use
  17984.        Function 35H (Get Interrupt Vector) to get the current address and
  17985.        save it, then use Function 25H (Set Interrupt Vector) to change the
  17986.        Interrupt 22H entry in the vector table to point to the new terminate
  17987.        address.
  17988.  
  17989.      ■ Use Interrupt 24H (Critical-Error-Handler Address) with care. The
  17990.        Interrupt 24H handler must preserve the ES register.
  17991.  
  17992.        An Interrupt 24H handler can issue only the system calls 01H-0CH.
  17993.        Making any other calls destroys the MS-DOS stack and prevents
  17994.        successful use of the Retry or Ignore options.
  17995.  
  17996.        When using the Retry or Ignore options, you must preserve the SS,
  17997.        SP, DS, BX, CX, and DX registers.
  17998.  
  17999.      ■ When an Interrupt 24H (Critical-Error-Handler Address) is received,
  18000.        always IRET back to MS-DOS with one of the standard responses.
  18001.  
  18002.        Programs that do not IRET from Interrupt 24H leave the system in an
  18003.        unpredictable state until a function call other than 01H-0CH is made.
  18004.        The Ignore option may leave incorrect or invalid data in internal
  18005.        system buffers.
  18006.  
  18007.      ■ Avoid trapping Interrupt 23H (CONTROL-C Handler Address) and
  18008.        Interrupt 24H (Critical-Error-Handler Address). Don't rely on
  18009.        trapping errors via Interrupt 24H as part of a copy protection
  18010.        scheme.
  18011.  
  18012.        These methods might not be included in future releases of MS-DOS.
  18013.  
  18014.      ■ A user program must never issue Interrupt 23H (CONTROL-C Handler
  18015.        Address).
  18016.  
  18017.        Only MS-DOS may issue Interrupt 23H.
  18018.  
  18019.      ■ Save any registers that your program uses before issuing Interrupt
  18020.        25H (Absolute Disk Read) or Interrupt 26H (Absolute Disk Write).
  18021.  
  18022.        These interrupts destroy all registers except for the segment
  18023.        registers.
  18024.  
  18025.        Avoid writing or reading an interrupt vector directly to or
  18026.        from memory.
  18027.  
  18028.      ■ Use Functions 25H and 35H (Set Interrupt Vector and Get Interrupt
  18029.        Vector) to set and get values in the interrupt table.
  18030.  
  18031.  
  18032.  8.3  System Calls
  18033.  
  18034.  
  18035.      ■ Use new system calls.
  18036.  
  18037.        Avoid using system calls that have been superseded by new calls
  18038.        unless the program must maintain backward compatibility with MS-DOS
  18039.        versions before 2.0. See Section 1.9, "Old System Calls", for a list
  18040.        of these new calls.
  18041.  
  18042.      ■ Avoid using functions 01H-0CH and 26H (Create New PSP).
  18043.  
  18044.        Use the new "tools" approach for reading and writing on standard
  18045.        input and output. Use Function 4BH (Load and Execute Program)
  18046.        instead of 26H to execute a child process.
  18047.  
  18048.      ■ Use file-sharing calls if more than one process is in effect.
  18049.  
  18050.        For more information, see File Sharing, in Section 1.5.2, "File-
  18051.        Related Function Requests."
  18052.  
  18053.      ■ Use networking calls where appropriate.
  18054.  
  18055.        Some forms of IOCtl can only be used with Microsoft Networks.
  18056.        For more information, and a list of these calls, see Section 1.6,
  18057.        "Microsoft Networks,"
  18058.  
  18059.      ■ When selecting a disk with Function 0EH (Select Disk), treat the
  18060.        value returned in AL with care.
  18061.  
  18062.        The value in AL specifies the maximum number of logical drives;
  18063.        it does not specify which drives are valid.
  18064.  
  18065.  
  18066.  8.4  Device Management
  18067.  
  18068.      ■ Use installable device drivers.
  18069.  
  18070.        MS-DOS provides a modular device driver structure for the BIOS,
  18071.        allowing you to configure and install device drivers at boot time.
  18072.        Block device drivers transmit a block of data at a time, while
  18073.        character device drivers transmit a byte of data at a time.
  18074.  
  18075.        Examples of both types of device drivers are given in Chapter 2,
  18076.        "MS-DOS Device Drivers."
  18077.  
  18078.      ■ Use buffered I/O.
  18079.  
  18080.        The device drivers can handle streams of data up to 64K bytes.
  18081.        To improve performance when sending a large amount of output to
  18082.        the screen, you can send it with one system call.
  18083.  
  18084.      ■ Programs that use direct console I/O via Function 06H and 07H (Direct
  18085.        Console I/O and Direct Console Input) and that want to read CONTROL-C
  18086.        as data should ensure that CONTROL-C checking is off.
  18087.  
  18088.        The program should ensure that CONTROL-C checking is off by using
  18089.        Function 33H (CONTROL-C Check).
  18090.  
  18091.      ■ Be compatible with international support.
  18092.  
  18093.        To provide support for international character sets, MS-DOS
  18094.        recognizes all possible byte values as significant characters
  18095.        in filenames and data streams. MS-DOS versions before 2.0 ignored
  18096.        the high bit in the MS-DOS filename.
  18097.  
  18098.  
  18099.  8.5  Memory Management
  18100.  
  18101.  
  18102.      ■ Use memory management.
  18103.  
  18104.        MS-DOS keeps track of allocated memory by writing a memory control
  18105.        block at the beginning of each area of memory. Programs should use
  18106.        Functions 48H (Allocate Memory), 49H (Free Allocated Memory), and
  18107.        4AH (Set Block) to release unneeded memory.
  18108.  
  18109.        This allows for future compatibility. For more information, see
  18110.        Section 1.3, "Memory Management."
  18111.  
  18112.      ■ Use only allocated memory.
  18113.  
  18114.        Don't directly access memory that was not provided as a result
  18115.        of a system call. Do not use fixed addressing, use only relative
  18116.        references.
  18117.  
  18118.        A program that uses memory that has not been allocated to it may
  18119.        destroy other memory control blocks or cause other applications
  18120.        to fail.
  18121.  
  18122.  
  18123.  8.6  Process Management
  18124.  
  18125.  
  18126.      ■ Use Function 4BH (Load and Execute Program, or EXEC) to load and
  18127.        execute programs.
  18128.  
  18129.        EXEC is the preferred call to use when loading programs and program
  18130.        overlays. Using the EXEC call instead of hard-coding information
  18131.        about how to load an .exe file (or always assuming that your file is
  18132.        a .com file) isolates your program from changes in .exe file formats
  18133.        and future releases of MS-DOS.
  18134.  
  18135.      ■ Use Function 31H (Keep Process), instead of Interrupt 27H (Terminate
  18136.        But Stay Resident).
  18137.  
  18138.        Function 31H allows programs that are greater than 64K bytes to
  18139.        terminate and stay resident.
  18140.  
  18141.      ■ Programs should terminate using Function 4CH (End Process).
  18142.  
  18143.        Programs that terminate by one of the following must ensure that the
  18144.        CS register contains the segment address of the PSP:
  18145.  
  18146.        ■ A long jump to offset 0 in the PSP
  18147.  
  18148.        ■ Issuing an Interrupt 20H with CS:0 pointing at the PSP
  18149.  
  18150.        ■ Issuing an Interrupt 21H with AH=0, CS:0 pointing at the PSP
  18151.  
  18152.        ■ A long call to location 50H in the PSP with AH=0
  18153.  
  18154.  
  18155.  8.7  File and Directory Management
  18156.  
  18157.  
  18158.      ■ Use the MS-DOS file management system.
  18159.  
  18160.        Using the MS-DOS file system ensures program compatibility with
  18161.        future MS-DOS versions through compatible disk formats and consistent
  18162.        internal storage.
  18163.  
  18164.      ■ Use file handles instead of FCBs.
  18165.  
  18166.        A handle is a 16-bit number that MS-DOS returns when a file is opened
  18167.        or created using Functions 3CH, 3DH, 5AH, or 5BH (Create Handle, Open
  18168.        Handle, Create Temporary File, or Create New File). The MS-DOS file-
  18169.        related function requests that use handles are listed in Table 1.5
  18170.        in Chapter 1, "System Calls."
  18171.  
  18172.        Although the default maximum number of open files is 20, this limit
  18173.        can be raised to 64K by Function 67H (Set Handle Count). For more
  18174.        information on this system call, see Chapter 1, "System Calls."
  18175.  
  18176.        You should use these calls instead of the old file-related
  18177.        functions that use FCBs (file control blocks). This is because a
  18178.        file operation can simply pass its handle rather than maintaining
  18179.        FCB information. If you must use FCBs, be sure the program closes
  18180.        them and does not move them around in memory.
  18181.  
  18182.      ■ Close files that have changed in length before issuing an Interrupt
  18183.        20H (Program Terminate), Function 00H (Terminate Program), Function
  18184.        4CH (End Process), or Function 0DH (Reset Disk).
  18185.  
  18186.        If you do not close a changed file, its length will not be recorded
  18187.        correctly in the directory.
  18188.  
  18189.      ■ Close files when they are no longer needed.
  18190.  
  18191.        Closing unneeded files increases efficiency in a networking
  18192.        environment.
  18193.  
  18194.      ■ If a program does use FCBs, that program should not close an FCB file
  18195.        and then continue writing to it. This practice will not work in a
  18196.        network environment, and is not recommended under any circumstances.
  18197.  
  18198.      ■ Change disks only if all files on the disk are closed.
  18199.  
  18200.        If you don't close all the files, any information in internal system
  18201.        buffers may be written incorrectly to a changed disk.
  18202.  
  18203.  
  18204.  8.7.1  Locking Files
  18205.  
  18206.      ■ Programs should not rely on being denied access to a locked region.
  18207.  
  18208.        To determine the status of a region, first, attempt to lock it,
  18209.        then examine its error code.
  18210.  
  18211.      ■ Programs should not close a file with a locked region or terminate
  18212.        with an open file that contains a locked region.
  18213.  
  18214.        The result of this procedure is undefined. Programs that might be
  18215.        terminated by an Interrupt 23H or Interrupt 24H (CONTROL-C Handler
  18216.        Address or Critical-Error-Handler Address) should trap these
  18217.        interrupts and unlock any locked regions before exiting.
  18218.  
  18219.  
  18220.  8.8  Miscellaneous
  18221.  
  18222.  
  18223.      ■ Avoid timing dependencies.
  18224.  
  18225.        Various machines use CPUs of different speeds. Also, programs that
  18226.        rely upon the speed of the clock for timing are not dependable in a
  18227.        networking environment.
  18228.  
  18229.      ■ Use the documented interface to the operating system. If either the
  18230.        hardware or media change, the operating system can use the features
  18231.        without modification.
  18232.  
  18233.        Don't use the ROM support provided by the OEM (Original Equipment
  18234.        Manufacturer).
  18235.  
  18236.        Don't directly address the video memory.
  18237.  
  18238.        Don't use undocumented function calls, interrupts, or features.
  18239.  
  18240.        These items may change or may not exist in future MS-DOS versions.
  18241.        If you do use these features, you will make your program highly non-
  18242.        portable.
  18243.  
  18244.      ■ Use the .exe format rather than the .com format.
  18245.  
  18246.        .Exe files are relocatable; .com files are direct memory images that
  18247.        load at a specific place and have no room for additional control
  18248.        information. .Exe files have headers that can be expanded for
  18249.        compatibility with future MS-DOS versions.
  18250.  
  18251.      ■ Use the environment to pass information to applications.
  18252.  
  18253.        The environment allows a parent process to pass information to a
  18254.        child process. The command.com file is usually the parent process
  18255.        to every application, so it can easily pass default drive and path
  18256.        information to the application.
  18257.  
  18258.  
  18259.  
  18260.  INDEX
  18261.  
  18262.  
  18263.  Symbols
  18264.  ──────────────────────────────────────────────────────────────────────────
  18265.  80186 microprocessor
  18266.  80286 microprocessor
  18267.  8086 microprocessor
  18268.  8086 object language
  18269.  8086 object module format. See Object Module Formats (OMF)
  18270.  
  18271.  
  18272.  A
  18273.  ──────────────────────────────────────────────────────────────────────────
  18274.  Absolute Disk Read (Interrupt 25H)
  18275.  Absolute Disk Write (Interrupt 26H)
  18276.  Absolute segment, LSEG
  18277.  ACBP byte, SEG ATTR
  18278.  Address mode
  18279.  Alignment attribute
  18280.  Alignment subfield, SEG ATTR
  18281.  Allocate Memory (Function 48H)
  18282.  Application
  18283.      Frame Number, protected-mode
  18284.  Archive bit
  18285.  Array, character
  18286.  ASCII character set
  18287.  ASCIZ string
  18288.  Assign list
  18289.  Attribute byte
  18290.  Attribute field
  18291.  Attribute, LSEG
  18292.      Alignment
  18293.      Combination
  18294.      SEG ATTR field, SEGDEF
  18295.  Attribute
  18296.      primary
  18297.      secondary
  18298.      Target
  18299.  AUTOEXEC file
  18300.  Auxiliary Input (Function 03H)
  18301.  Auxiliary Output (Function 04H)
  18302.  
  18303.  
  18304.  B
  18305.  ──────────────────────────────────────────────────────────────────────────
  18306.  base, definition
  18307.  Big subfield, SEG ATTR
  18308.  BIN format file
  18309.  Binary line number
  18310.  BIOS Parameter ^Block (<BPB)
  18311.  BIOS Parameter Block (BPB)
  18312.  Bit 8
  18313.  Bit 9
  18314.  Bitfield
  18315.  Block Count subfield, Iterated Data Block
  18316.  Block devices
  18317.      device drivers
  18318.      disk drives
  18319.      example
  18320.      installation
  18321.  Boot sector
  18322.  BPB pointer
  18323.  Buffered Keyboard Input (Function 0AH)
  18324.  BUILD BPB
  18325.  Build BPB
  18326.  Busy bit
  18327.  Byte, representation
  18328.  
  18329.  
  18330.  C
  18331.  ──────────────────────────────────────────────────────────────────────────
  18332.  C language
  18333.  CALL instruction
  18334.  Cancel Assign-List Entry (Function 5FH, Code 04H)
  18335.  Canonic Frame
  18336.  Canonic Frame, definition
  18337.  Carry flag
  18338.  Case-Mapping
  18339.  Change
  18340.  Change Directory Entry (Function 56H)
  18341.  Character array
  18342.  Character device driver, example
  18343.  Character devices
  18344.  Character set
  18345.      definition
  18346.  Check Keyboard Status (Function 0BH)
  18347.  CHKSUM field, SAMREC
  18348.  Class Name, definition
  18349.  CLOCK device
  18350.  Close
  18351.  Close File (Function 10H)
  18352.  Cluster
  18353.  Code page
  18354.      definition
  18355.  Code segment, CS
  18356.  Combination attribute
  18357.  Combination subfield, SEG ATTR
  18358.  COMDEF record
  18359.      field
  18360.          CHKSUM
  18361.          Communal Length, repeated
  18362.          Communal Name, repeated
  18363.          Data Segment Type, repeated
  18364.          Record Length
  18365.          RECTYP
  18366.          Type Index, repeated
  18367.      length fields, format
  18368.      order with respect to COMENT
  18369.      purpose
  18370.      schematic
  18371.  COMENT record
  18372.      field
  18373.          CHKSUM
  18374.          Comment
  18375.          Comment Type
  18376.          Record Length
  18377.          RECTYP
  18378.      order with respect to COMDEF
  18379.      order with respect to LOCSYM
  18380.      purpose
  18381.      schematic
  18382.      subfield of Comment Type
  18383.          Comment Class
  18384.  Command code field
  18385.  Command processor
  18386.  Command.com
  18387.  Commands, utility, NLS
  18388.  Comment class subfield, Comment Type
  18389.  Comment field, COMENT
  18390.  Comment record
  18391.  Comment Record (COMENT)
  18392.  Comment Type field, COMENT
  18393.      bit settings
  18394.      definition
  18395.      format
  18396.  Commit File (Function 68H)
  18397.  Common blocks, FORTRAN
  18398.  Communal Length field, COMDEF
  18399.  Communal Name field, COMDEF
  18400.  Communal Name, ordering with External Name
  18401.  Communal Names Definition Record (COMDEF)
  18402.  Communal names definition record. See COMDEF record
  18403.  Communal variable
  18404.      FAR
  18405.      HUGE
  18406.      NEAR
  18407.      similarity to FORTRAN common block
  18408.      uninitialized public variable
  18409.  Compatibility, ensuring
  18410.  Complete Name, definition
  18411.  Computer language
  18412.      C
  18413.      FORTRAN
  18414.  COMSPEC
  18415.  Con device
  18416.  config.sys 1130
  18417.  config.sys file 1114
  18418.  Content subfield, Iterated Data Block
  18419.  Control blocks
  18420.  Control information
  18421.  CONTROL-C
  18422.  CONTROL-C Address (Interrupt 23H)
  18423.  CONTROL-C Handler Address (Interrupt 23H)
  18424.  Country code, current
  18425.  Country code
  18426.      definition
  18427.  Country-dependent information, NLS
  18428.  Country-dependent information
  18429.      case conversion tables
  18430.      collating sequence, character sorting
  18431.      currency
  18432.      date
  18433.      DBCS environmental vector
  18434.      keyboard support
  18435.      time
  18436.      valid single-byte characters
  18437.  Country.sys file
  18438.  Create
  18439.  Create File (Function 16H)
  18440.  Create New File (Function 5BH)
  18441.  Create Temporary File (Function 5AH)
  18442.  Critical Error Handler Address (Interrupt 24H)
  18443.  CS register
  18444.  
  18445.  
  18446.  D
  18447.  ──────────────────────────────────────────────────────────────────────────
  18448.  DAT field, LEDATA
  18449.  Data Record
  18450.  Data Segment Type field, COMDEF
  18451.  Data segment
  18452.      DS
  18453.      ES
  18454.      FAR
  18455.      NEAR
  18456.  Delete Directory Entry (Function 41H)
  18457.  Delete File (Function 13H)
  18458.  Descriptor, Group Component, GRPDEF
  18459.  Device control
  18460.  Device drivers
  18461.      block
  18462.      creating
  18463.      example
  18464.      installable
  18465.      installing
  18466.      non-resident
  18467.      preserving registers
  18468.      resident
  18469.  Device Handles
  18470.  Device header
  18471.  Device interrupt routine
  18472.  Device management, programming hints
  18473.  Device strategy routine
  18474.  Device-related function requests
  18475.  Direct Console Input (Function 07H)
  18476.  Direct Console I/O (Function 06H)
  18477.  Directory Entry
  18478.  Directory-Related Function Requests
  18479.  Directory-related function requests
  18480.  Disk allocation
  18481.  Disk Directory
  18482.  Disk formats
  18483.      IBM
  18484.      standard MS-DOS
  18485.  Disk Transfer Address (DTA)
  18486.  Dispatch table
  18487.  Display Character (Function 02H)
  18488.  Display String (Function 09H)
  18489.  Done bit
  18490.  DS register
  18491.  Duplicate File Handle (Function 45H)
  18492.  
  18493.  
  18494.  E
  18495.  ──────────────────────────────────────────────────────────────────────────
  18496.  Eight Leaf Descriptor field, TYPDEF
  18497.      format
  18498.      subfield
  18499.          EN
  18500.          Leaf Descriptor
  18501.  Element Type Index subfield, Leaf Descriptor
  18502.  EN subfield, Eight Leaf Descriptor
  18503.  End address
  18504.  End Process (Function 4CH)
  18505.  Enumerated Data Offset field, LEDATA
  18506.  Error bit
  18507.  Error codes
  18508.  Error Handling
  18509.  Error handling
  18510.  ES register
  18511.  EXE device drivers
  18512.  .exe files
  18513.  exe files
  18514.  EXE format file
  18515.  EXE loader
  18516.  EXTDEF record
  18517.      field
  18518.          CHKSUM
  18519.          External Name, repeated
  18520.          Record Length
  18521.          RECTYP
  18522.          Type Index, repeated
  18523.      purpose
  18524.      schematic
  18525.  Extended error codes
  18526.  Extended FCB
  18527.  Extensions class, Microsoft
  18528.  External Index
  18529.  External indices
  18530.  External Name field, EXTDEF
  18531.  External Name
  18532.      mapping
  18533.      referenced in FIXUPP record
  18534.  External Names Definition Record (EXTDEF)
  18535.  External names definition record. See EXTDEF record
  18536.  
  18537.  
  18538.  F
  18539.  ──────────────────────────────────────────────────────────────────────────
  18540.  FAR data segment
  18541.  FAR subfield, Leaf Descriptor
  18542.  FAR variable format, Leaf Descriptor
  18543.  FAT
  18544.  FAT ID byte
  18545.  FAT <ID byte
  18546.  FBVAL, definition
  18547.  FCB
  18548.  File Allocation Table
  18549.  File and directory management, programming hints
  18550.  File attributes
  18551.  File Control Block
  18552.      definition
  18553.      extended
  18554.      fields
  18555.      format
  18556.      opened
  18557.      unopened
  18558.  File locking, programming hints
  18559.  Filename
  18560.  File-related function requests
  18561.  File-sharing function requests
  18562.  Find First File (Function 4EH)
  18563.  Find Next File (Function 4FH)
  18564.  FIX DAT subfield, Fixup
  18565.      internal structure
  18566.      schematic
  18567.  Fixup field, FIXUPP
  18568.      data type
  18569.          Frame
  18570.          Location
  18571.          Mode
  18572.          Target
  18573.      definition
  18574.      schematic
  18575.      subfield
  18576.          LOCAT
  18577.  Fixup mode
  18578.      segment-relative
  18579.      self-relative
  18580.  FIXUP record
  18581.  Fixup
  18582.      definition
  18583.      Frame
  18584.      Location
  18585.  FIXUPP record
  18586.  FIXUPP Record (FIXUPP)
  18587.  FIXUPP record
  18588.      External Name referenced in
  18589.      field
  18590.          CHKSUM
  18591.          Fixup, repeated
  18592.          Frame Datum, conditional
  18593.          Record Length
  18594.          RECTYP
  18595.          Target Datum, conditional
  18596.          Thread, repeated
  18597.      purpose
  18598.      schematic
  18599.      subfield of FIX DAT, Fixup
  18600.          F
  18601.          Frame
  18602.          P
  18603.          T
  18604.          TARGT
  18605.      subfield of Fixup
  18606.          Frame Datum, conditional
  18607.          Target Datum, conditional
  18608.          Target Displacement, conditional
  18609.      subfield of LOCAT, Fixup
  18610.          Data Record Offset
  18611.          LOC
  18612.          M (mode)
  18613.      subfield of Thread
  18614.          Index, conditional
  18615.          TRD DAT
  18616.      subfield of TRD DAT, Thread
  18617.          D
  18618.          Method
  18619.          THRED
  18620.  Fixup
  18621.      segment-relative
  18622.      self-relative
  18623.      Target
  18624.  Flush
  18625.  Flush Buffer, Read Keyboard (Function 0CH)
  18626.  Force Duplicate File Handle (Function 46H)
  18627.  Format
  18628.  FORTRAN, common blocks
  18629.  FORTRAN language
  18630.  FOVAL, definition
  18631.  Frame Datum field, FIXUPP
  18632.  Frame Datum subfield, Fixup
  18633.      External Index
  18634.      Group Index
  18635.      Segment Index
  18636.  Frame Datum subfield, START ADDRS
  18637.  Frame Number
  18638.  Frame Number, conditional
  18639.  
  18640.  Fr
  18641.      Frame Number
  18642.      nomenclature
  18643.      specifying
  18644.      specifying, FIXUPP
  18645.  Frames
  18646.      Thread Number, FIXUPP
  18647.  Free Allocated Memory (Function 49H)
  18648.  Function
  18649.  Function
  18650.  Function Requests
  18651.      alphabetic order
  18652.      calling
  18653.  Function requests
  18654.      definition
  18655.  Function Requests
  18656.      definition
  18657.      device-related
  18658.      Directory-related
  18659.      directory-related
  18660.      file-related
  18661.      file-sharing
  18662.      Function 00H
  18663.      Function 01H
  18664.      Function 02H
  18665.      Function 03H
  18666.      Function 04H
  18667.      Function 05H
  18668.      Function 06H
  18669.      Function 07H
  18670.      Function 08H
  18671.      Function 09H
  18672.      Function 0AH
  18673.      Function 0BH
  18674.      Function 0CH
  18675.      Function 0DH
  18676.      Function 0EH
  18677.      Function 0FH
  18678.      Function 10H
  18679.      Function 11H
  18680.      Function 12H
  18681.      Function 13H
  18682.      Function 14H
  18683.      Function 15H
  18684.      Function 16H
  18685.      Function 17H
  18686.      Function 19H
  18687.      Function 1AH
  18688.      Function 1BH
  18689.      Function 1CH
  18690.  Function requests
  18691.      Function 25H
  18692.  Function Requests
  18693.      Function 25H
  18694.  Function requests
  18695.      Function 35H
  18696.  Function Requests
  18697.      Function 40H
  18698.      Function 41H
  18699.      Function 42H
  18700.      Function 43H
  18701.      Function 44H, Code 08H
  18702.      Function 44H, Code 09H
  18703.      Function 44H, Code 0AH
  18704.      Function 44H, Code 0BH
  18705.      Function 44H, Code 0CH
  18706.      Function 44H, Code 0DH
  18707.      Function 44H, Codes 00H and 01H
  18708.      Function 44H, Codes 02H and 03H
  18709.      Function 44H, Codes 04H and 05H
  18710.      Function 44H, Codes 06H and 07H
  18711.      Function 44H, Codes 0EH and 0FH
  18712.      Function 45H
  18713.  Function requests
  18714.      Function 46H
  18715.  Function Requests
  18716.      Function 47H
  18717.      Function 48H
  18718.      Function 49H
  18719.      Function 4AH
  18720.      Function 4BH, Code 00H
  18721.      Function 4BH, Code 03H
  18722.      Function 4CH
  18723.      Function 4DH
  18724.      Function 4EH
  18725.      Function 4FH
  18726.      Function 54H
  18727.      Function 56H
  18728.      Function 57H
  18729.      Function 58H
  18730.      Function 59H
  18731.      Function 5AH
  18732.      Function 5BH
  18733.      Function 5CH, Code 00H
  18734.      Function 5CH, Code 01H
  18735.      Function 5EH, Code 00H
  18736.      Function 5EH, Code 02H
  18737.      Function 5FH, Code 02H
  18738.      Function 5FH, Code 03H
  18739.      Function 5FH, Code 04H
  18740.      Function 62H
  18741.      Function 65H
  18742.      Function 66H
  18743.      Function 67H
  18744.      Function 68H
  18745.      Handling errors
  18746.      memory management
  18747.      National Language Support
  18748.      Network-related
  18749.      network-related
  18750.      numeric order
  18751.      process management
  18752.      standard character I/O
  18753.      system-management
  18754.  
  18755.  
  18756.  G
  18757.  ──────────────────────────────────────────────────────────────────────────
  18758.  Generic IOCtl for devices (Function 44H, Code 0DH)
  18759.  Generic IOCtl for handles (Function 44H, Code 0CH)
  18760.  Generic IOCtl Function
  18761.  Get
  18762.  Get Assign List Entry (Function 5FH, Code 02H)
  18763.  Get Current Directory (Function 47H)
  18764.  Get Current Disk (Function 19H)
  18765.  Get Default Drive Data (Function 1BH)
  18766.  Get Drive Data (Function 1CH)
  18767.  Get Extended Country Information (Function 65H)
  18768.  Get Extended Error (Function 59H)
  18769.  Get Interrupt Vector (Function 35H)
  18770.  Get Machine Name (Function 5EH, Code 00H)
  18771.  Get PSP (Function 62H)
  18772.  Get Return Code Child Process (Function 4DH)
  18773.  Get Verify State (Function 54H)
  18774.  Get/Set Allocation Strategy (Function 58H)
  18775.  Get/Set Date/Time of File (Function 57H)
  18776.  Get/Set File Attributes (Function 43H)
  18777.  Get/Set Global Code Page (Function 66H)
  18778.  Get/Set IOCtl Drive Map (Function 44H, Codes 0EH and 0FH)
  18779.  Get/Set Logical Drive Map Function
  18780.  Group Component Descriptor field, GRPDEF
  18781.  Group, definition
  18782.  Group definition record. See GRPDEF record
  18783.  Group Definition Record (GRPDEF)
  18784.  Group Index
  18785.  Group Index subfield, Line Number Base
  18786.  Group Index subfield, Public Base
  18787.  Group Name Index field, GRPDEF
  18788.  GRPDEF record
  18789.      definition
  18790.      field
  18791.          CHKSUM
  18792.          Group Component Descriptor, repeated
  18793.          Group Name Index
  18794.          Record Length
  18795.          RECTYP
  18796.      schematic
  18797.  
  18798.  
  18799.  H
  18800.  ──────────────────────────────────────────────────────────────────────────
  18801.  Handles
  18802.      definition
  18803.      device
  18804.  Handling errors
  18805.  Header
  18806.  hibyte, definition
  18807.  Hidden files
  18808.  High-Level Language
  18809.  HUGE communal variable
  18810.  
  18811.  
  18812.  I
  18813.  ──────────────────────────────────────────────────────────────────────────
  18814.  IBM disk format
  18815.  Index fields
  18816.  Index Number
  18817.  Index subfield, Thread
  18818.      External Index
  18819.      Group Index
  18820.      Segment Index
  18821.  Index
  18822.      definition
  18823.  Indices
  18824.  Indices, external
  18825.  Init
  18826.  INIT code
  18827.  Installable device drivers
  18828.  Instruction Pointer (IP)
  18829.  Instruction
  18830.      CALL
  18831.      JUMP
  18832.      SHORT-JUMP
  18833.  Internal stack
  18834.  Interrupt entry point
  18835.  Interrupt handlers
  18836.  Interrupt routines
  18837.  Interrupt-handling
  18838.  Interrupts
  18839.      21H
  18840.      Address of handlers
  18841.      alphabetic order
  18842.      definition
  18843.      Interrupt 20H
  18844.      Interrupt 21H
  18845.      Interrupt 22H
  18846.      Interrupt 23H
  18847.      Interrupt 24H
  18848.      Interrupt 25H
  18849.      Interrupt 26H
  18850.      Interrupt 27H
  18851.      issuing
  18852.      numeric order
  18853.      programming hints
  18854.      Vector table
  18855.  I/O Control for Devices (Function 44H)
  18856.  IOCtl
  18857.  IOCtl bit
  18858.  IOCtl Block (Function 44H, Codes 4 and 5)
  18859.  IOCtl Character (Function 44H, Codes 2 and 3)
  18860.  IOCtl Data (Function 44H, Codes 0 and 1)
  18861.  IOCtl Is Changeable (Function 44H, Code 08H)
  18862.  IOCtl Is Redirected Block (Function 44H, Code 09H)
  18863.  IOCtl Is Redirected Handle (Function 44H, Code 0AH)
  18864.  IOCtl Retry (Function 44H, Code 0BH)
  18865.  IOCtl Status (Function 44H, Codes 6 and 7)
  18866.  io.sys file 1368
  18867.  IP. See Instruction Pointer (IP)
  18868.  Iterated Data Block field, LIDATA
  18869.  Iterated Data Offset field, LIDATA
  18870.  
  18871.  
  18872.  J
  18873.  ──────────────────────────────────────────────────────────────────────────
  18874.  JUMP instruction
  18875.  
  18876.  
  18877.  K
  18878.  ──────────────────────────────────────────────────────────────────────────
  18879.  Keep
  18880.  Keyboard layouts, national, NLS
  18881.  
  18882.  
  18883.  L
  18884.  ──────────────────────────────────────────────────────────────────────────
  18885.  Language
  18886.      C
  18887.      FORTRAN
  18888.  Leaf Descriptor subfield, Eight Leaf Descriptor
  18889.      format
  18890.          FAR variable
  18891.          NEAR variable
  18892.      subfield
  18893.          NEAR
  18894.          VARTYP
  18895.  LEDATA record
  18896.      field
  18897.          DAT, repeated
  18898.          Enumerated Data Offset
  18899.          Segment Index
  18900.      schematic
  18901.  LEDATA
  18902.      field
  18903.          CHKSUM
  18904.          Record Length
  18905.          RECTYP
  18906.      purpose
  18907.  Length fields, COMDEF, format
  18908.  Length in Bits subfield, Leaf Descriptor
  18909.  Length of Record Field
  18910.  LHEADR record
  18911.      field
  18912.          CHKSUM
  18913.          L-module Name
  18914.          Record Length
  18915.          RECTYP
  18916.      schematic
  18917.  LIDATA record
  18918.      field
  18919.          CHKSUM
  18920.          Iterated Data Block, repeated
  18921.          Iterated Data Offset
  18922.          Record Length
  18923.          RECTYP
  18924.          Segment Index
  18925.      purpose
  18926.      schematic
  18927.      subfield of Iterated Data Block
  18928.          Block Count
  18929.          Content
  18930.          Repeat Count
  18931.  Line Number Base field, LINNUM
  18932.  Line number, binary
  18933.  Line Number field, LINNUM
  18934.  Line Number Offset field, LINNUM
  18935.  Line Numbers Record (LINNUM)
  18936.  LINK
  18937.  Linker, Microsoft
  18938.  Linker, Microsoft
  18939.  Link-time semantics
  18940.  LINNUM record
  18941.      field
  18942.          CHKSUM
  18943.          Line Number Base
  18944.          Line Number Offset, repeated
  18945.          Line Number, repeated
  18946.          Record Length
  18947.          RECTYP
  18948.      purpose
  18949.      schematic
  18950.      subfield of Line Number Base
  18951.          Group Index
  18952.          Segment Index
  18953.  List of Names Record (LNAMES)
  18954.  L-module Header Record (LHEADR)
  18955.  L-module Name
  18956.  LNAMES record
  18957.      field
  18958.          CHKSUM
  18959.          Name, repeated
  18960.          Record Length
  18961.          RECTYP
  18962.      schematic
  18963.  Load and Execute Program (Function 4BH, Code 00H)
  18964.  Load module
  18965.  Load Overlay (Function 4BH, Code 03H)
  18966.  Loadsize
  18967.  lobyte, definition
  18968.  Local Base field, LOCSYM
  18969.  Local buffering
  18970.  Local Name field, LOCSYM
  18971.  Local Offset field, LOCSYM
  18972.  Local symbol
  18973.  Local Symbols Record (LOCSYM)
  18974.  LOCAT subfield, Fixup
  18975.      internal structure
  18976.      schematic
  18977.  Location
  18978.      types
  18979.          base
  18980.          hibyte
  18981.          lobyte
  18982.          offset
  18983.          pointer
  18984.  Lock (Function 5CH, Code 00H)
  18985.  LOCSYM record
  18986.      field
  18987.          CHKSUM
  18988.          Local Base
  18989.          Local Name, repeated
  18990.          Local Offset, repeated
  18991.          Record Length
  18992.          RECTYP
  18993.          Type Index, repeated
  18994.      order with respect to COMENT
  18995.      purpose
  18996.      schematic
  18997.  Logical Enumerated Data Record (LEDATA)
  18998.  Logical Iterated Data Record (LIDATA)
  18999.  Logical sector
  19000.  Logical sector numbers
  19001.  Logical Segment. See LSEG
  19002.  LSEG
  19003.      absolute
  19004.          Combination attribute
  19005.      Alignment attribute
  19006.          absolute segment
  19007.          relocatable segment
  19008.      canonic Frame
  19009.      Class name
  19010.      Combination attribute
  19011.          absolute segment
  19012.          relocatable segment
  19013.      combining
  19014.      Complete name
  19015.      definition
  19016.      Overlay Name
  19017.      relocatable
  19018.          byte-aligned
  19019.          Combination attribute
  19020.          page-aligned
  19021.          paragraph-aligned
  19022.          word-aligned
  19023.      Segment Name
  19024.  
  19025.  
  19026.  M
  19027.  ──────────────────────────────────────────────────────────────────────────
  19028.  Make Assign-List Entry (Function 5FH, Code 03H)
  19029.  Mapping
  19030.      logical to physical starting address
  19031.  MAS. See Memory Address Space (MAS)
  19032.  MATTR subfield, MOD TYP
  19033.  Maxalloc
  19034.  Media <Check
  19035.  Media descriptor byte
  19036.  Media, determining
  19037.  Memory address
  19038.  Memory Address Space (MAS)
  19039.  Memory control block
  19040.  Memory image,
  19041.  Memory image, LSEGs in
  19042.  Memory image, relocatable
  19043.  Memory management function requests
  19044.  Memory management, programming hints
  19045.  Memory model
  19046.      huge
  19047.      large
  19048.      medium
  19049.      small
  19050.  Microprocessor
  19051.      80186
  19052.      80286
  19053.      8086
  19054.  Microsoft Extensions class
  19055.  Microsoft linker
  19056.  Microsoft linker
  19057.  Microsoft Networks
  19058.  Microsoft Networks Manager's Guide
  19059.  Microsoft Networks User's Guide
  19060.  Minalloc
  19061.  MOD TYP field, MODEND
  19062.      MATTR subfield
  19063.      module attributes
  19064.  Mode, address
  19065.  Mode
  19066.      fixup
  19067.          segment-relative
  19068.          self-relative
  19069.  MODEND record
  19070.      field
  19071.          CHKSUM
  19072.          MOD TYP
  19073.          Record Length
  19074.          RECTYP
  19075.          START ADDRS, conditional
  19076.      purpose
  19077.      schematic
  19078.      subfield of START ADDRS
  19079.          Frame Datum, conditional
  19080.          Target Datum, conditional
  19081.          Target Displacement, conditional
  19082.  Module, definition
  19083.  Module End Record (MODEND)
  19084.  Module header record, definition
  19085.  Module
  19086.      record ordering in
  19087.  Move File Pointer (Function 42H)
  19088.  MS-DOS, 8086 object language
  19089.  MS-DOS initialization
  19090.  MS-DOS memory map
  19091.  MS-DOS User's Reference
  19092.  msdos.sys file 1356
  19093.  msdos.sys file 1368
  19094.  Multitasking
  19095.  
  19096.  
  19097.  N
  19098.  ──────────────────────────────────────────────────────────────────────────
  19099.  Name field
  19100.  Name field, SAMREC
  19101.  Name Indices
  19102.  National keyboard layouts, NLS
  19103.  National Language Support Function Requests
  19104.  National Language Support (NLS)
  19105.      restrictions
  19106.      unsupported features
  19107.  National Language Support system calls
  19108.  NEAR data segment
  19109.  NEAR subfield, Leaf Descriptor
  19110.  NEAR variable format, Leaf Descriptor
  19111.  Network-related Function Requests
  19112.  Network-related function requests
  19113.  Non IBM format bit
  19114.  Non-destructive Read No Wait
  19115.  NUL device
  19116.  Number field, SAMREC
  19117.  Number of Elements subfield, Leaf Descriptor
  19118.  
  19119.  
  19120.  O
  19121.  ──────────────────────────────────────────────────────────────────────────
  19122.  Object language,
  19123.  Object Module Formats
  19124.  Object Module Formats (OMF)
  19125.  Object module
  19126.      restrictions
  19127.  offset, definition
  19128.  Offset subfield, SEG ATTR
  19129.  Old system calls
  19130.  OMF. See Object Module Formats (OMF)
  19131.  Open
  19132.  Open File (Function 0FH)
  19133.  Opened FCB
  19134.  Operating system
  19135.      MS-DOS
  19136.      PC-DOS
  19137.      XENIX
  19138.  Overlay Name, definition
  19139.  
  19140.  
  19141.  P
  19142.  ──────────────────────────────────────────────────────────────────────────
  19143.  Parameter block
  19144.  Parse
  19145.  Path command
  19146.  PC-DOS, 8086 object language
  19147.  Physical Segment. See PSEG
  19148.  Pointer to Next Device field
  19149.  Predefined device handles
  19150.  Print Character (Function 05H)
  19151.  Printer Setup (Function 5EH, Code 02H
  19152.  Process management function requests
  19153.  Process management, programming hints
  19154.  Processor. See Microprocessor
  19155.  Program
  19156.  Program End Process (Interrupt 20H)
  19157.  Program segment
  19158.  Program Segment Prefix
  19159.  Programming hints
  19160.      device management
  19161.      file and directory management
  19162.      file locking
  19163.      interrupts
  19164.      memory management
  19165.      miscellaneous
  19166.      process management
  19167.      recommendations
  19168.      system calls
  19169.  Programming interfaces, NLS
  19170.  Prompt command
  19171.  Protected-mode
  19172.      application Frame Number
  19173.  PSEG
  19174.      definition
  19175.  PUBDEF record
  19176.  PUBDEF record. See also
  19177.  PUBDEF record
  19178.      field
  19179.          Public Base, repeated
  19180.          Public Name, repeated
  19181.          Public Offset, repeated
  19182.          Record Length
  19183.          RECTYP
  19184.          Type Index, repeated
  19185.      purpose
  19186.      schematic
  19187.      subfield of Public Base
  19188.          Frame Number, conditional
  19189.      subfield, Public Base
  19190.          Frame Number, conditional
  19191.          Group Index
  19192.          Segment Index
  19193.  Public Base field, PUBDEF
  19194.  Public Name field, PUBDEF
  19195.  Public names definition record. See PUBDEF record
  19196.  Public Names Definition Record (PUBDEF)
  19197.  Public Offset field, PUBDEF
  19198.  Public symbol
  19199.  Public variable
  19200.  
  19201.  
  19202.  R
  19203.  ──────────────────────────────────────────────────────────────────────────
  19204.  Random
  19205.  Read
  19206.  Read Keyboard and Echo (Function 01H)
  19207.  Read Keyboard (Function 08H)
  19208.  Read Only Memory
  19209.  Read or Write
  19210.  Record format
  19211.      abbreviation
  19212.      bitfields
  19213.      conditional field
  19214.      repeated field
  19215.  Record formats
  19216.  Record format
  19217.      sample (SAMREC)
  19218.      SAMREC (sample record)
  19219.          CHKSUM field
  19220.          Name field
  19221.          Number field
  19222.          Record Length field
  19223.      SAMREC(sample record)
  19224.          RECTYP field
  19225.      title
  19226.  Record Length field, SAMREC
  19227.  Record order
  19228.      definition
  19229.      semantic rules
  19230.      syntax
  19231.  Record Size
  19232.  Record
  19233.      COMDEF
  19234.      COMENT
  19235.      comment
  19236.      Data
  19237.      EXTDEF
  19238.      FIXUP
  19239.      FIXUPP
  19240.      GRPDEF
  19241.      LEDATA
  19242.      LHEADR
  19243.      LIDATA
  19244.      LINNUM
  19245.      LNAMES
  19246.      LOCSYM
  19247.      MODEND
  19248.      PUBDEF
  19249.      RECTYP(record type)
  19250.      SAMREC (sample record)
  19251.      SEGDEF
  19252.      symbol definition
  19253.          COMDEF
  19254.          EXTDEF
  19255.          PUBDEF
  19256.      THEADR
  19257.      TYPDEF
  19258.  RECTYP(record type)field
  19259.  Reference self-relative
  19260.  Reference
  19261.      segment-relative
  19262.  References
  19263.      WIRTH:CACM, Nov. 1977)
  19264.  Register
  19265.      CS
  19266.      DS
  19267.      ES
  19268.  Registers, treatment of
  19269.  Register
  19270.      SS
  19271.  Relocatable memory image
  19272.  Relocatable segment, LSEG
  19273.  Relocation information
  19274.  Relocation item offset value to a word in the load
  19275.  Relocation table
  19276.  Remove
  19277.  Rename File (Function 17H)
  19278.  Repeat Count subfield, Iterated Data Block
  19279.  request header
  19280.  Request packet
  19281.  Reset Disk (Function 0DH)
  19282.  Resident device drivers
  19283.  ROM
  19284.  Root directory
  19285.  
  19286.  
  19287.  S
  19288.  ──────────────────────────────────────────────────────────────────────────
  19289.  SAMREC (sample record)
  19290.      schematic
  19291.  Search for First Entry (Function 11H)
  19292.  Search for Next Entry (Function 12H)
  19293.  Sector count
  19294.  SEG ATTR field, SEGDEF
  19295.  SEGDEF record
  19296.      definition
  19297.      field
  19298.          CHKSUM
  19299.          Class Name Index
  19300.          Overlay Name Index
  19301.          Record Length
  19302.          RECTYP
  19303.          SEG ATTR
  19304.          Segment Name Index
  19305.      schematic
  19306.      subfield of SEG ATTR
  19307.          Alignment
  19308.          Big
  19309.          Combination
  19310.          Offset, conditional
  19311.  SEGDEF recrod
  19312.      field
  19313.          Segment Length
  19314.  Segment addressing
  19315.  Segment definition record. See SEGDEF record
  19316.  Segment Definition Record (SEGDEF)
  19317.  Segment Index
  19318.  Segment Index field, LEDATA
  19319.  Segment Index field, LIDATA
  19320.  Segment Index subfield, Group Component Descriptor
  19321.  Segment Index subfield, Line Number Base
  19322.  Segment Index subfield, Public Base
  19323.  Segment Length field, SEGDEF
  19324.  Segment Name, definition
  19325.  Segment Name Index field, SEGDEF
  19326.  Segment
  19327.      absolute, LSEG
  19328.      attribute
  19329.          Alignment
  19330.          Combination
  19331.      logical (LSEG)
  19332.      physical (PSEG)
  19333.  Segment-relative fixup
  19334.  Segment-relative reference
  19335.  Segment
  19336.      relocatable, LSEG
  19337.  Select Disk (Function 0EH)
  19338.  Self-relative fixup
  19339.  Self-relative reference
  19340.  Semantic rules, record ordering
  19341.  Semantics, link-time
  19342.  Sequential Read (Function 14H)
  19343.  Sequential Write (Function 15H)
  19344.  Set
  19345.  Set Block (Function 4AH)
  19346.  Set command
  19347.  Set Disk Transfer Address (Function 1AH)
  19348.  Set Handle Count(Function 67H)
  19349.  Set Interrupt Vector (Function 25H)
  19350.  Set/Reset
  19351.  SHORT-JUMP instruction
  19352.  SS register
  19353.  Stack segment, SS
  19354.  Standard character I/O function requests
  19355.  START ADDRS field, MODEND
  19356.      Format
  19357.  Start sector
  19358.  Start segment value the relocation item offset
  19359.  static request header
  19360.  Status
  19361.  Status field
  19362.  Strategy entry point
  19363.  Strategy routines
  19364.  Subfield OFFH
  19365.  Subfield
  19366.      Comment Type
  19367.          Comment Class
  19368.      Eight Leaf Descriptor
  19369.          EN
  19370.          Leaf Descriptor
  19371.      Fixup
  19372.          Frame Datum
  19373.          Target Datum
  19374.          Target Displacement
  19375.      Frame Number, conditional
  19376.      Group Component Descriptor
  19377.          Segment Index
  19378.      Iterated Data Block
  19379.          Block Count
  19380.          Content
  19381.          Repeat Count
  19382.      Leaf Descriptor
  19383.          Element Type Index
  19384.          FAR
  19385.          Length in Bits
  19386.          NEAR
  19387.          Number of Elements
  19388.          VAR SUBTYP
  19389.          VARTYP
  19390.      Line Number Base, LINNUM
  19391.          Group Index
  19392.          Segment Index
  19393.      MOD TYP
  19394.          MATTR
  19395.      Public Base
  19396.          Group INdex
  19397.      SEG ATTR
  19398.          Alignment
  19399.          Big
  19400.          Combination
  19401.      Segment Index
  19402.      START ADDRS
  19403.          Frame Datum
  19404.          Target Datum
  19405.          Target Displacement
  19406.      Thread
  19407.          Index
  19408.          TRD DAT
  19409.  Superseded system calls
  19410.  Symbol definition
  19411.  Symbol definition record
  19412.      COMDEF
  19413.      EXTDEF
  19414.      PUBDEF
  19415.  Symbol
  19416.      local
  19417.      public
  19418.  Syntax, record ordering
  19419.  Sysinit
  19420.  System call
  19421.      National Language Support
  19422.  System calls
  19423.      definition
  19424.      programming hints
  19425.      replacements for old
  19426.  System Calls
  19427.      superseded calls
  19428.  System calls
  19429.      types of
  19430.  System files
  19431.  System prompt
  19432.  System-management function requests
  19433.  
  19434.  
  19435.  T
  19436.  ──────────────────────────────────────────────────────────────────────────
  19437.  Target Datum field, FIXUPP
  19438.  Target Datum subfield, Fixup
  19439.      External Index
  19440.      Group Index
  19441.      Segment Index
  19442.  Target Datum subfield, START ADDRS
  19443.  Target Displacement subfield, Fixup
  19444.  Target Displacment subfield, START ADDRS
  19445.  Target
  19446.      definition
  19447.      nomenclature
  19448.      specification attribute
  19449.      specifying
  19450.      specifying, FIXUPP
  19451.      Thread Number, FIXUPP
  19452.  Terminate But Stay Resident (Interrupt 27H)
  19453.  Terminate Process Exit Address (Interrupt 22H)
  19454.  Terminate Program (Function 00H)
  19455.  THEADR record
  19456.      field
  19457.          CHKSUM
  19458.          Record Length
  19459.          RECTYP
  19460.          T-module Name
  19461.      schematic
  19462.  Thread Data subfield. See TRD DAT subfield, Thread
  19463.  Thread field, FIXUPP
  19464.      data type
  19465.          Frame
  19466.          Target
  19467.      definition
  19468.  Thread Number, THRED
  19469.  T-module, definition
  19470.  T-module Header Record (THEADR)
  19471.  T-Module Name
  19472.  Transfer address
  19473.  TRD DAT subfield, Thread
  19474.      D subfield
  19475.      internal structure
  19476.      Method subfield
  19477.      schematic
  19478.      THRED subfield
  19479.  TYPDEF record
  19480.      communal variable
  19481.      field
  19482.          CHKSUM
  19483.          Eight Leaf Descriptor
  19484.          Record Length
  19485.          RECTYP
  19486.      subfield of Eight Leaf Descriptor
  19487.          EN
  19488.      subfield of Leaf Descriptor
  19489.          Element Type Index
  19490.          FAR
  19491.          Length in Bits
  19492.          NEAR
  19493.          Number of Elements
  19494.          VAR SUBTYP, optional
  19495.          VARTYP
  19496.  Type Index field, COMDEF
  19497.  Type Index field, EXTDEF
  19498.  Type Index field, LOCSYM
  19499.  Type Index field, PUBDEF
  19500.  Type-ahead buffer
  19501.  
  19502.  
  19503.  U
  19504.  ──────────────────────────────────────────────────────────────────────────
  19505.  Unit code field
  19506.  Unlock (Function 5CH, Code 01H)
  19507.  Unopened FCB
  19508.  User Stack
  19509.  User stack
  19510.  Utility commands, NLS
  19511.  
  19512.  
  19513.  V
  19514.  ──────────────────────────────────────────────────────────────────────────
  19515.  VAR SUBTYP subfield, Leaf Descriptor
  19516.  Variable
  19517.      communal
  19518.          FAR
  19519.          HUGE
  19520.          NEAR
  19521.      public
  19522.  VARTYP subfield, Leaf Descriptor
  19523.      ARRAY
  19524.      SCALAR
  19525.      STRUCT
  19526.  Vector table
  19527.  Volume ID
  19528.  Volume label
  19529.  
  19530.  
  19531.  W
  19532.  ──────────────────────────────────────────────────────────────────────────
  19533.  Wildcard
  19534.  Wildcard characters
  19535.  Write Handle (Function 40H)
  19536.  
  19537.  
  19538.  X
  19539.  ──────────────────────────────────────────────────────────────────────────
  19540.  XENIX, 8086 object language
  19541.