home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft_Programmers_Library.7z / MPL / msdos / petern.txt < prev   
Encoding:
Text File  |  2013-11-08  |  1.2 MB  |  24,155 lines

Text Truncated. Only the first 1MB is shown below. Download the file for the complete contents.
  1.  The New Peter Norton Programmer's Guide to the IBM(R) PC and PS/2(R)
  2.  
  3.  
  4.  ════════════════════════════════════════════════════════════════════════════
  5.  
  6.  The New Peter Norton Programmer's Guide to the IBM(R) PC and PS/2(R)
  7.  
  8.  By Peter Norton and Richard Wilton
  9.  
  10.  ════════════════════════════════════════════════════════════════════════════
  11.  
  12.  PUBLISHED BY
  13.  Microsoft Press
  14.  A Division of Microsoft Corporation
  15.  16011 NE 36th Way, Box 97017, Redmond, Washington 98073-9717
  16.  
  17.  First edition copyright (C) 1985 by Peter Norton
  18.  Second edition revisions copyright (C) 1988 by Microsoft Press
  19.  All rights reserved. No part of the contents of this book may be reproduced
  20.  or transmitted in any form or by any means without the written permission of
  21.  the publisher.
  22.  
  23.  Library of Congress Cataloging in Publication Data
  24.  
  25.  Norton, Peter, 1943- .
  26.  The new Peter Norton programmer's guide to the IBM PC and PS/2 :
  27.  the ultimate reference guide to the entire family of IBM Personal
  28.  Computers / Peter Norton and Richard Wilton.
  29.  
  30.          p.        cm.
  31.  
  32.  Includes index.
  33.  
  34.  1. IBM microcomputers--Programming.  2. IBM Personal Computer.
  35.  3. IBM Personal System/2 (Computer system)  I. Wilton, Richard, 1953- .
  36.  II. Title.  III. Title: Programmer's guide to the IBM Personal Computers.
  37.  QA76.8.I1015N67    1988    88-21104
  38.  005.265--dc19                CIP
  39.  ISBN 1-55615-131-4
  40.  
  41.  Printed and bound in the United States of America.
  42.  
  43.  1 2 3 4 5 6 7 8 9  FGFG  3 2 1 0 9 8
  44.  
  45.  Distributed to the book trade in the United States by Harper & Row.
  46.  
  47.  Distributed to the book trade in Canada by General Publishing Company, Ltd.
  48.  
  49.  Distributed to the book trade outside the United States and Canada by
  50.  Penguin Books Ltd.
  51.  
  52.  Penguin Books Ltd., Harmondsworth, Middlesex, England
  53.  Penguin Books Australia Ltd., Ringwood, Victoria, Australia
  54.  Penguin Books N.Z. Ltd., 182-190 Wairau Road, Auckland 10, New Zealand
  55.  
  56.  British Cataloging in Publication Data available
  57.  
  58.  Microsoft(R), Flight Simulator(R), and GW-BASIC(R) are registered trademarks
  59.  of Microsoft Corporation.
  60.  
  61.  IBM(R), PC/AT(R), Personal System/2(R), and PS/2(R) are registered
  62.  trademarks, and Micro Channel(TM), PCjr(TM), and PC/XT(TM) are trademarks of
  63.  International Business Machines Corporation.
  64.  
  65.  Norton Utilities(TM) is a trademark of Peter Norton.
  66.  
  67.  ────────────────────────────────────────────────────────────────────────────
  68.  Project Editor: Megan E. Sheppard
  69.  Technical Editors: Bob Combs and Jim Johnson
  70.  ────────────────────────────────────────────────────────────────────────────
  71.  
  72.  
  73.  
  74.  ────────────────────────────────────────────────────────────────────────────
  75.  Contents
  76.  
  77.    Introduction
  78.  
  79.     1       Anatomy of the PCs and PS/2s
  80.     2       The Ins and Outs
  81.     3       The ROM Software
  82.     4       Video Basics
  83.     5       Disk Basics
  84.     6       Keyboard Basics
  85.     7       Clocks, Timers, and Sound Generation
  86.     8       ROM BIOS Basics
  87.     9       ROM BIOS Video Services
  88.    10       ROM BIOS Disk Services
  89.    11       ROM BIOS Keyboard Services
  90.    12       Miscellaneous Services
  91.    13       ROM BIOS Services Summary
  92.    14       DOS Basics
  93.    15       DOS Interrupts
  94.    16       DOS Functions: Version 1
  95.    17       DOS Functions: Versions 2.0 and Later
  96.    18       DOS Functions Summary
  97.    19       Program Building
  98.    20       Programming Languages
  99.  
  100.    Appendix A: Installable Device Drivers
  101.    Appendix B: Hexadecimal Arithmetic
  102.    Appendix C: About Characters
  103.    Appendix D: DOS Version 4
  104.  
  105.    Index
  106.  
  107.  
  108.  
  109.  ────────────────────────────────────────────────────────────────────────────
  110.  Introduction
  111.  
  112.    The world of personal computers has come a long way in the few years since
  113.    the original edition of this book appeared, yet the goal of this book
  114.    remains a simple but ambitious one: to help you master the principles of
  115.    programming the IBM personal computer family. From the time that the first
  116.    IBM Personal Computer (known simply as "the PC") was introduced in the
  117.    fall of 1981, it was clear that it was going to be a very important
  118.    computer. Later, as PC sales zoomed beyond the expectations of everyone
  119.    (IBM included) and as the original model was joined by a sibling or two,
  120.    the PC became recognized as the standard for serious desktop computers.
  121.    From the original PC, a whole family of computers──a family with many
  122.    branches──has evolved. And at the same time the importance of the PC
  123.    family has also grown.
  124.  
  125.    The success and significance of the PC family has made the development of
  126.    programs for it very important. However, the fact that each member of the
  127.    family differs in details and characteristics from its relatives has also
  128.    made the development of programs for the family increasingly complex.
  129.  
  130.    This book is about the knowledge, skills, and concepts that are needed to
  131.    create programs for the PC family──not only for one member of the family
  132.    (though you might perhaps cater to the peculiarities and quirks of one
  133.    member) but for the family as a whole──in a way that is universal enough
  134.    that your programs should work not only on all the present family members,
  135.    but on future members as well.
  136.  
  137.    This book is for anyone involved in the development of programs for the PC
  138.    family. It is for programmers, but not only for programmers. It is for
  139.    anyone who is involved in or needs to understand the technical details and
  140.    working ideas that are the basis for PC program development, including
  141.    anyone who manages programmers, anyone who plans or designs PC programs,
  142.    and anyone who uses PC programs and wants to understand the details behind
  143.    them.
  144.  
  145.  
  146.  Some Comments on Philosophy
  147.  
  148.    One of the most important elements of this book is the discussion of
  149.    programming philosophy. You will find throughout this book explanations of
  150.    the ideas underlying IBM's design of the PC family and of the principles
  151.    of sound PC programming, viewed from experience.
  152.  
  153.    If this book were to provide you with only facts──tabulations of technical
  154.    information──it would not serve you well. That's why we've interwoven with
  155.    the technical discussion an explanation of what the PC family is all
  156.    about, of the principles that tie the various family members together, and
  157.    of the techniques and methods that can help you produce programs that will
  158.    endure and prosper along with the PC family.
  159.  
  160.  
  161.  How to Use This Book
  162.  
  163.    This book is both a reading book and a reference book, and you can
  164.    approach it in at least two ways. You may want to read it as you would any
  165.    other book, from front to back, digging in where the discussion is useful
  166.    to you and quickly glancing through the material you don't yet need. This
  167.    approach provides a grand overview of the workings (and the ideas behind
  168.    the workings) of PC programs. You can also use this book as a pure
  169.    reference, and dip into specific chapters for specific information. We've
  170.    provided a detailed table of contents at the beginning of each chapter and
  171.    an extensive index to help you find what you need.
  172.  
  173.    When you use this book as a random-access reference to the details of PC
  174.    programming, you'll find that much of the material is intricately
  175.    interrelated. To help you understand the interrelationships, we have
  176.    repeated some details when it was practical to do so and have referred you
  177.    to other sections when such repetition was less practical.
  178.  
  179.  What's New in This Edition
  180.  
  181.    As you might guess, this edition of the Programmer's Guide has been
  182.    brought up to date for the new generation of IBM personal computers: the
  183.    Personal System/2 computers, or PS/2s.
  184.  
  185.    In some ways this book is more complex and more detailed than the
  186.    original. There's a good reason for this: The newer members of the PC and
  187.    PS/2 family are more complicated computers, and the later versions of DOS
  188.    are more complicated and have more features than their predecessors. It
  189.    was inevitable that this revised version of the Programmer's Guide would
  190.    reflect this greater complexity in the hardware, the ROM BIOS, and DOS.
  191.  
  192.    Still, you'll find that a few members of the extended PC family aren't
  193.    covered in this book. The PCjr, the XT/286, and the PC Convertible are
  194.    used relatively infrequently, and the PS/2 Model 70 was released too
  195.    recently to be included. Nevertheless, each of these machines is similar
  196.    to one of the PCs or PS/2s whose innards we will examine in detail, so
  197.    this book should be a useful guide even if you are programming a Model 70
  198.    or one of the less widely used PCs.
  199.  
  200.    Here are some of the changes you'll find in this new edition:
  201.  
  202.    New video subsystems. Since the original edition appeared, IBM's Enhanced
  203.    Graphics Adapter (EGA) became a de facto hardware standard for PC
  204.    programmers and users. Then the PS/2s introduced two new video subsystems,
  205.    the Multi-Color Graphics Array (MCGA) and the Video Graphics Array (VGA).
  206.    These new video subsystems receive extensive coverage in Chapters 4 and
  207.    9.
  208.  
  209.    New keyboards. IBM supports a new, extended keyboard with later versions
  210.    of the PC/AT and with all PS/2s. Chapters 6 and 11 have been expanded to
  211.    cover the new hardware.
  212.  
  213.    A new focus on C programming. For better or worse, the most recent
  214.    versions of DOS have been strongly influenced by the C programming
  215.    language. This influence is even more apparent in such operating
  216.    environments as Microsoft Windows, UNIX, and OS/2──all of which were
  217.    designed by C programmers. For this reason you'll find new examples of C
  218.    programming in several different chapters. Of course, we haven't abandoned
  219.    Pascal and BASIC──in fact, Chapter 20 examines each of these programming
  220.    languages.
  221.  
  222.    A new perspective on DOS. DOS has evolved into a mature operating system
  223.    whose design can now be viewed with the clarity of hindsight. The past
  224.    several years of working with DOS have helped us view this immensely
  225.    popular operating system with a practical perspective born of experience.
  226.    Our discussions of DOS emphasize which of its features are obsolescent and
  227.    which are pointers to the future.
  228.  
  229.    Despite these changes, the direction and philosophy of this book remain
  230.    the same. When you write a program for a PC or PS/2, you can actually
  231.    program for an entire family of computers. Each member of the family──the
  232.    PC, the PC/XT, the PC/AT, and all PS/2s──has hardware and software
  233.    components that are identical or similar to those in other members of the
  234.    family. When you keep this big picture in mind, you'll be able to write
  235.    programs that take advantage of the capabilities of the different PC and
  236.    PS/2 models without sacrificing portability.
  237.  
  238.  
  239.  Other Resources
  240.  
  241.    One book, of course, can't provide you with all the knowledge that you
  242.    might possibly need. We've made this book as rich and complete as we
  243.    reasonably can, but there will always be a need for other kinds of
  244.    information. Here are some of the places you might look for material to
  245.    supplement what you find here.
  246.  
  247.    For detailed technical information about the PC family, the ultimate
  248.    source is IBM's series of technical reference manuals. Specific technical
  249.    reference manuals exist for the original PC, for the XT, for the AT, and
  250.    for PS/2 models 30, 50, 60, and 80. In addition, the detailed IBM BIOS
  251.    Interface Technical Reference Manual summarizes the capabilities of the
  252.    Basic Input/Output System in all members of the extended PC family. You
  253.    should know a few things about using these model-specific manuals:
  254.  
  255.    ■  Information specific to one model is not differentiated from general
  256.       information for the whole PC family. To be sure of the differences, you
  257.       should use common sense, compare the different manuals, and consult
  258.       this book.
  259.  
  260.    ■  Remember that each new model in the PC family adds new features. If you
  261.       turn to the manual for a later model, you will find information on a
  262.       wide variety of features; if you turn to the manual for an earlier
  263.       model, you'll avoid being distracted by features that do not apply to
  264.       all models in the family.
  265.  
  266.    There is also an IBM Options and Adapters Technical Reference Manual for
  267.    the various options and adapters used by the PC family, such as different
  268.    disk drives or display screens. Technical information about this kind of
  269.    equipment is gathered into this manual, which is updated periodically.
  270.    (The updates are available by subscription.) Little of the information in
  271.    this technical reference manual is of use to programmers, but you might
  272.    find some parts of interest.
  273.  
  274.    IBM also publishes technical reference manuals for special extensions to
  275.    the PC, such as PC Network.
  276.  
  277.    Perhaps the most important of the IBM technical reference manuals is the
  278.    series for DOS. These manuals contain a wealth of detailed technical
  279.    information which we have summarized in this book.
  280.  
  281.    A number of other sources can provide information to supplement the IBM
  282.    manuals:
  283.  
  284.    ■  For a somewhat broader perspective on the IBM Personal Computer──one
  285.       that is not focused on programming──see Peter Norton's Inside the IBM
  286.       Personal Computer, published by Robert J. Brady Company.
  287.  
  288.    ■  For a broader perspective on DOS, see the third edition of Van
  289.       Wolverton's Running MS-DOS, and The MS-DOS Encyclopedia, both published
  290.       by Microsoft Press.
  291.  
  292.    Because this book covers the subject of PC programming in a broad fashion,
  293.    it can provide you with only a few key details about individual
  294.    programming languages. For details on particular programming languages and
  295.    the many specific compilers for those languages, you will need more books
  296.    than we could begin to list or recommend.
  297.  
  298.    With these introductory remarks completed, it's time to plunge into the
  299.    task of mastering the principles of programming the PC family!
  300.  
  301.  
  302.  
  303.  ────────────────────────────────────────────────────────────────────────────
  304.  Chapter 1  Anatomy of the PCs and PS/2s
  305.  
  306.    The Microprocessor
  307.      The 8088 Microprocessor
  308.      The 8086 Microprocessor
  309.      The 80286 Microprocessor
  310.      The 80386 Microprocessor
  311.      The Math Coprocessor
  312.  
  313.    The Support Chips
  314.      The Programmable Interrupt Controller
  315.      The DMA Controller
  316.      The Clock Generator
  317.      The Programmable Interval Timer
  318.      Video Controllers
  319.      Input/Output Controllers
  320.  
  321.    Linking the Parts: The Bus
  322.      The Address Bus
  323.      The Data Bus
  324.      Micro Channel Architecture
  325.  
  326.    Memory
  327.      CPU Address Space
  328.      The System Memory Map
  329.  
  330.    Design Philosophy
  331.  
  332.    From the programmer's point of view, all members of the PC family consist
  333.    of a processor, memory chips, and several smart, or programmable, circuit
  334.    chips. All the main circuit components that make the computer work are
  335.    located on the system board; other important parts are located on
  336.    expansion boards, which can be plugged into the system board.
  337.  
  338.    The system board (Figures 1-1 through 1-3) contains the microprocessor,
  339.    which is tied to at least 64 KB of memory; some built-in ROM programs,
  340.    such as BASIC and the ROM BIOS; and several very important support chips.
  341.    Some of these chips control external devices, such as the disk drive or
  342.    the display screen, and others help the microprocessor perform its tasks.
  343.  
  344.    In this section, we discuss each major chip and give a few important
  345.    technical specifications. These chips are frequently known by more than
  346.    one name. For example, some peripheral input/output hardware is supervised
  347.    by a chip known as the 8255. This chip is also referred to as the 8255A
  348.    and the 8255A-5. The suffixes A and 5 refer to revision numbers and to
  349.    parts rated for operation at different speeds. For programming purposes,
  350.    any Intel chip part number that starts with 8255 is identical to any other
  351.    chip whose part number starts with 8255, regardless of the suffix.
  352.    However, when you replace one of these chips on a circuit board, note the
  353.    suffix. If the suffixes are different, the part may not operate at the
  354.    proper speed.
  355.  
  356.  
  357.  The Microprocessor
  358.  
  359.    In all PCs, the microprocessor is the chip that runs programs. The
  360.    microprocessor, or central processing unit (CPU), carries out a variety of
  361.    computations, numeric comparisons, and data transfers in response to
  362.    programs stored in memory.
  363.  
  364.    The CPU controls the computer's basic operation by sending and receiving
  365.    control signals, memory addresses, and data from one part of the computer
  366.    to another along a group of interconnecting electronic pathways called a
  367.    bus. Located along the bus are input and output (I/O) ports that connect
  368.    the various memory and support chips to the bus. Data passes through these
  369.    I/O ports while it travels to and from the CPU and the other parts of the
  370.    computer.
  371.  
  372.    In the IBM PCs and PS/2s, the CPU always belongs to the Intel 8086 family
  373.    of microprocessors. (See Figure 1-4.) We'll point out the similarities
  374.    and differences between the different microprocessors as we describe them.
  375.  
  376.    ┌────────────────────────────────────────────────────────────────────────┐
  377.    │ Figure 1-1 can be found on p.3 of the printed version of the book.     │
  378.    └────────────────────────────────────────────────────────────────────────┘
  379.  
  380.    Figure 1-1.  The IBM PC system board.
  381.  
  382.    ┌────────────────────────────────────────────────────────────────────────┐
  383.    │ Figure 1-2 can be found on p.4 of the printed version of the book.     │
  384.    └────────────────────────────────────────────────────────────────────────┘
  385.  
  386.    Figure 1-2.  The PC/AT system board.
  387.  
  388.    ┌────────────────────────────────────────────────────────────────────────┐
  389.    │ Figure 1-3 can be found on p.5 of the printed version of the book.     │
  390.    └────────────────────────────────────────────────────────────────────────┘
  391.  
  392.    Figure 1-3.  The PS/2 Model 60 system board.
  393.  
  394.    Model                                Microprocessor
  395.    ──────────────────────────────────────────────────────────────────────────
  396.    PC                                   8088
  397.    PC/XT                                8088
  398.    PC/AT                                80286
  399.    PS/2 Models 25, 30                   8086
  400.    PS/2 Models 50, 60                   80286
  401.    PS/2 Model 80                        80386
  402.    ──────────────────────────────────────────────────────────────────────────
  403.  
  404.    Figure 1-4.  Microprocessors used in IBM PCs and PS/2s.
  405.  
  406.  The 8088 Microprocessor
  407.  
  408.    The 8088 is the 16-bit microprocessor that controls the standard IBM
  409.    personal computers, including the original PC, the PC/XT, the Portable PC,
  410.    and the PCjr. Almost every bit of data that enters or leaves the computer
  411.    passes through the CPU to be processed.
  412.  
  413.    Inside the 8088, 14 registers provide a working area for data transfer and
  414.    processing. These internal registers, forming an area 28 bytes in size,
  415.    are able to temporarily store data, memory addresses, instruction
  416.    pointers, and status and control flags. Through these registers, the 8088
  417.    can access 1 MB (megabyte), or more than one million bytes, of memory.
  418.  
  419.  The 8086 Microprocessor
  420.  
  421.    The 8086 is used in the PS/2 models 25 and 30 (and also in many IBM PC
  422.    clones). The 8086 differs from the 8088 in only one minor respect: It uses
  423.    a full 16-bit data bus instead of the 8-bit bus that the 8088 uses. (The
  424.    difference between 8-bit and 16-bit buses is discussed on page 12.)
  425.    Virtually anything that you read about the 8086 also applies to the 8088;
  426.    for programming purposes, consider them identical.
  427.  
  428.  The 80286 Microprocessor
  429.  
  430.    The 80286 is used in the PC/AT and in the PS/2 models 50 and 60. Although
  431.    fully compatible with the 8086, the 80286 supports extra programming
  432.    features that let it execute programs much more quickly than the 8086.
  433.    Perhaps the most important enhancement to the 80286 is its support for
  434.    multitasking.
  435.  
  436.    Multitasking is the ability of a CPU to perform several tasks at a time──
  437.    such as printing a document and calculating a spreadsheet──by quickly
  438.    switching its attention among the controlling programs.
  439.  
  440.    The 8088 used in a PC or PC/XT can support multitasking with the help of
  441.    sophisticated control software. However, an 80286 can do a much better job
  442.    of multitasking because it executes programs more quickly and addresses
  443.    much more memory than the 8088. Moreover, the 80286 was designed to
  444.    prevent tasks from interfering with each other.
  445.  
  446.    The 80286 can run in either of two operating modes: real mode or protected
  447.    mode. In real mode, the 80286 is programmed exactly like an 8086. It can
  448.    access the same 1 MB range of memory addresses as the 8086. In protected
  449.    mode, however, the 80286 reserves a predetermined amount of memory for an
  450.    executing program, preventing that memory from being used by any other
  451.    program. This means that several programs can execute concurrently without
  452.    the risk of one program accidentally changing the contents of another
  453.    program's memory area. An operating system using 80286 protected mode can
  454.    allocate memory among several different tasks much more effectively than
  455.    can an 8086-based operating system.
  456.  
  457.  The 80386 Microprocessor
  458.  
  459.    The PS/2 Model 80 uses the 80386, a faster, more powerful microprocessor
  460.    than the 80286. The 80386 supports the same basic functions as the 8086
  461.    and offers the same protected-mode memory management as the 80286.
  462.    However, the 80386 offers two important advantages over its predecessors:
  463.  
  464.    ■  The 80386 is a 32-bit microprocessor with 32-bit registers. It can
  465.       perform computations and address memory 32 bits at a time instead of 16
  466.       bits at a time.
  467.  
  468.    ■  The 80386 offers more flexible memory management than the 80286 and
  469.       8086.
  470.  
  471.    We'll say more about the 80386 in Chapter 2.
  472.  
  473.  The Math Coprocessor
  474.  
  475.    The 8086, 80286, and 80386 can work only with integers. To perform
  476.    floating-point computations on an 8086-family microprocessor, you must
  477.    represent floating-point values in memory and manipulate them using only
  478.    integer operations. During compilation, the language translator represents
  479.    each floating-point computation as a long, slow series of integer
  480.    operations. Thus, "number-crunching" programs can run very slowly──a
  481.    problem if you have a large number of calculations to perform.
  482.  
  483.    A good solution to this problem is to use a separate math coprocessor that
  484.    performs floating-point calculations. Each of the 8086-family
  485.    microprocessors has an accompanying math coprocessor: The 8087 math
  486.    coprocessor is used with an 8086 or 8088; the 80287 math coprocessor is
  487.    used with an 80286; and the 80387 math coprocessor is used with an 80386.
  488.    (See Figure 1-5.) Each PC and PS/2 is built with an empty socket on its
  489.    motherboard into which you can plug a math coprocessor chip.
  490.  
  491.    From a programmer's point of view, the 8087, 80287, and 80387 math
  492.    coprocessors are fundamentally the same: They all perform arithmetic with
  493.    a higher degree of precision and with much greater speed than is usually
  494.    achieved with integer software emulation. In particular, programs that use
  495.    math coprocessors to perform trigonometric and logarithmic operations can
  496.    run up to 10 times faster than their counterparts that use integer
  497.    emulation.
  498.  
  499.    Programming these math coprocessors in assembly language can be an
  500.    exacting process. Most programmers rely on high-level language translators
  501.    or commercial subroutine libraries when they write programs to run with
  502.    the math coprocessors. The techniques of programming the math coprocessors
  503.    directly are too specialized to cover in this book.
  504.  
  505. ╓┌─┌────────────────────┌────────────────────┌────────────────────┌─────────┌
  506.                            Approximate Range                                Si
  507.    Data Type            (from)               (to)                 Bits      (d
  508.    ───────────────────────────────────────────────────────────────────────────
  509.    Word integer         -32,768              +32,767              16
  510.    Short integer        -2 x 10E9            +2 x 10E9            32
  511.    Long integer         -9 x 10E18           +9 x 10E18           64
  512.    Packed decimal       -99...99             +99...99             80
  513.    Short real           8.43 x 10E-37        3.37 x 10E38         32
  514.    Long real            4.19 x 10E-307       1.67 x 10E308        64        15
  515.    Temporary real       3.4 x 10E-4932       1.2 x 10E4932        80
  516.    ───────────────────────────────────────────────────────────────────────────
  517.  
  518.  
  519.    Figure 1-5.  The range of numeric data types supported by the 8087,
  520.    80287, and 80387 math coprocessors.
  521.  
  522.  
  523.  The Support Chips
  524.  
  525.    The microprocessor cannot control the entire computer without some
  526.    help──nor should it. By delegating certain control functions to other
  527.    chips, the CPU is free to attend to its own work. These support chips
  528.    can be responsible for such processes as controlling the flow of
  529.    information throughout the internal circuitry (as the interrupt
  530.    controller and the DMA controller are) and controlling the flow of
  531.    information to or from a particular device (such as a video display or
  532.    disk drive) attached to the computer. These so-called device controllers
  533.    are often mounted on a separate board that plugs into one of the PC's
  534.    expansion slots.
  535.  
  536.    Many support chips in the PCs and PS/2s are programmable, which means
  537.    they can be manipulated to perform specialized tasks. Although direct
  538.    programming of these chips is generally not a good idea, the following
  539.    descriptions will point out which chips are safe to program directly and
  540.    which aren't. Because this book does not cover direct hardware control,
  541.    you should look in the IBM technical manuals as well as in the chip
  542.    manufacturers' technical literature for details about programming
  543.    individual chips.
  544.  
  545.  The Programmable Interrupt Controller
  546.  
  547.    In a PC or PS/2, one of the CPU's essential tasks is to respond to
  548.    hardware interrupts. A hardware interrupt is a signal generated by a
  549.    component of the computer, indicating that component's need for CPU
  550.    attention. For example, the system timer, the keyboard, and the disk
  551.    drive controllers all generate hardware interrupts at various times. The
  552.    CPU responds to each interrupt by carrying out an appropriate
  553.    hardware-specific activity, such as incrementing a time-of-day counter
  554.    or processing a keystroke.
  555.  
  556.    Each PC and PS/2 has a programmable interrupt controller (PIC) circuit
  557.    that monitors interrupts and presents them one at a time to the CPU. The
  558.    CPU responds to these interrupts by executing a special software routine
  559.    called an interrupt handler. Because each hardware interrupt has its own
  560.    interrupt handler in the ROM BIOS or in DOS, the CPU can recognize and
  561.    respond specifically to the hardware that generates each interrupt. In
  562.    the PC, PC/XT, and PS/2 models 25 and 30, the PIC can handle 8 different
  563.    hardware interrupts. In the PC/AT and PS/2 models 50, 60, and 80, two
  564.    PICs are chained together to allow a total of 15 different hardware
  565.    interrupts to be processed.
  566.  
  567.    Although the programmable interrupt controller is indeed programmable,
  568.    hardware interrupt management is not a concern in most programs. The ROM
  569.    BIOS and DOS provide nearly all of the services you'll need for managing
  570.    hardware interrupts. If you do plan to work directly with the PIC, we
  571.    suggest you examine the ROM BIOS listings in the IBM technical reference
  572.    manuals for samples of actual PIC programming.
  573.  
  574.  The DMA Controller
  575.  
  576.    Some parts of the computer are able to transfer data to and from the
  577.    computer's memory without passing through the CPU. This operation is
  578.    called direct memory access, or DMA, and it is handled by a chip known
  579.    as the DMA controller. The main purpose of the DMA controller is to
  580.    allow disk drives to read or write data without involving the
  581.    microprocessor. Because disk I/O is relatively slow compared to CPU
  582.    speeds, DMA speeds up the computer's overall performance quite a bit.
  583.  
  584.  The Clock Generator
  585.  
  586.    The clock generator supplies the multiphase clock signals that
  587.    coordinate the microprocessor and the peripherals. The clock generator
  588.    produces a high-frequency oscillating signal. For example, in the
  589.    original IBM PC, this frequency was 14.31818 megahertz (MHz, or million
  590.    cycles per second); in the newer machines, the frequency is higher.
  591.    Other chips that require a regular timing signal obtain it from the
  592.    system clock generator by dividing the base frequency by a constant to
  593.    obtain the frequency they need to accomplish their tasks. For example,
  594.    the IBM PC's 8088 is driven at 4.77 MHz, one-third of the base
  595.    frequency. The PC's internal bus and the programmable interval timer
  596.    (discussed shortly) use a frequency of 1.193 MHz, running at a quarter
  597.    of the 8088 rate and one-twelfth of the base rate.
  598.  
  599.  The Programmable Interval Timer
  600.  
  601.    The programmable interval timer generates timing signals at regular
  602.    intervals controlled by software. The chip can generate timing signals
  603.    on three different channels at once (four channels in the PS/2 models
  604.    50, 60, and 80).
  605.  
  606.    The timer's signals are used for various system tasks. One essential
  607.    timer function is to generate a clock-tick signal that keeps track of
  608.    the current time of day. Another of the timer's output signals can be
  609.    used to control the frequency of tones produced with the computer's
  610.    speaker. See Chapter 7 for more information about programming the
  611.    system timer.
  612.  
  613.  Video Controllers
  614.  
  615.    The many video subsystems available with the PCs and PS/2s present a
  616.    variety of programmable control interfaces to the video hardware. For
  617.    example, all PC and PS/2 video subsystems have a cathode ray tube (CRT)
  618.    controller circuit to coordinate the timing signals that control the
  619.    video display.
  620.  
  621.    Although the video control circuits can be programmed in application
  622.    software, all video subsystems have different programming interfaces.
  623.    Fortunately, all PCs and PS/2s are equipped with basic video control
  624.    routines in the ROM BIOS. We'll describe these routines in Chapter 9.
  625.  
  626.  Input/Output Controllers
  627.  
  628.    PCs and PS/2s have several input/output subsystems with specialized
  629.    control circuitry that provides an interface between the CPU and the
  630.    actual I/O hardware. For example, the keyboard has a dedicated
  631.    controller chip that transforms the electrical signals generated by
  632.    keystrokes into 8-bit codes that represent the individual keys. All disk
  633.    drives have separate controller circuitry that directly controls the
  634.    drive; the CPU communicates with the controller through a consistent
  635.    interface. The serial and parallel communications ports also have
  636.    dedicated input/output controllers.
  637.  
  638.    You rarely need to worry about programming these hardware controllers
  639.    directly because the ROM BIOS and DOS provide services that take care of
  640.    these low-level functions. If you need to know the details of the
  641.    interface between the CPU and a hardware I/O controller, see the IBM
  642.    technical reference manuals and examine the ROM BIOS listings in the PC
  643.    and PC/AT manuals.
  644.  
  645.  
  646.  Linking the Parts: The Bus
  647.  
  648.    As we mentioned, the PC family of computers links all internal control
  649.    circuitry by means of a circuit design known as a bus. A bus is simply a
  650.    shared path on the main circuit board to which all the controlling parts
  651.    of the computer are attached. When data is passed from one component to
  652.    another, it travels along this common path to reach its destination.
  653.    Every microprocessor, every control chip, and every byte of memory in
  654.    the computer is connected directly or indirectly to the bus. When a new
  655.    adapter is plugged into one of the expansion slots, it is actually
  656.    plugged directly into the bus, making it an equal partner in the
  657.    operation of the entire unit.
  658.  
  659.    Any information that enters or leaves a computer system is temporarily
  660.    stored in at least one of several locations along the bus. Data is
  661.    usually placed in main memory, which in the PC family consists of
  662.    thousands or millions of 8-bit memory cells (bytes). But some data may
  663.    end up in a port or register for a short time while it waits for the CPU
  664.    to send it to its proper location. Generally, ports and registers hold
  665.    only 1 or 2 bytes of information at a time and are usually used as
  666.    stopover sites for data being sent from one place to another. (Ports and
  667.    registers are described in Chapter 2.)
  668.  
  669.    Whenever a memory cell or port is used as a storage site, its location
  670.    is known by an address that uniquely identifies it. When data is ready
  671.    to be transferred, its destination address is first transmitted along
  672.    the address bus; the data follows along behind on the data bus. So the
  673.    bus carries more than data: It carries power and control information,
  674.    such as timing signals (from the system clock) and interrupt signals, as
  675.    well as the addresses of the thousands or millions of memory cells and
  676.    the many devices attached to the bus. To accommodate these four
  677.    different functions, the bus is divided into four parts: the power
  678.    lines, the control bus, the address bus, and the data bus. We're going
  679.    to discuss the subjects of address and data buses in greater detail
  680.    because they move information in a way that helps to explain some of the
  681.    unique properties of the PC family.
  682.  
  683.  The Address Bus
  684.  
  685.    The address bus in the PC, PC/XT, and PS/2 models 25 and 30 uses 20
  686.    signal lines to transmit the addresses of the memory cells and devices
  687.    attached to the bus. (Memory addressing is discussed more fully on page
  688.    13 and in Chapter 3.) Because two possible values (either 1 or 0) can
  689.    travel along each of the 20 address lines, these computers can specify
  690.    2^20 addresses──the limit of the addressing capability of the 8088 and
  691.    8086 microprocessors. This amounts to more than a million possible
  692.    addresses.
  693.  
  694.    The 80286 used in the PC/AT can address 2^24 bytes of memory, so the AT
  695.    has a 24-line address bus. The bus in the 80286-based PS/2 models 50 and
  696.    60 also supports 24-bit memory addressing; in the 80386-based PS/2 Model
  697.    80, the bus has 32-bit addressing capability.
  698.  
  699.  The Data Bus
  700.  
  701.    The data bus works with the address bus to carry data throughout the
  702.    computer. The PC's 8088-based system uses a data bus that has 8 signal
  703.    lines, each of which carries a single binary digit (bit); data is
  704.    transmitted across this 8-line bus in 8-bit (1-byte) units. The 80286
  705.    microprocessor of the AT uses a 16-bit data bus and therefore passes
  706.    data in 16-bit (1-word) units.
  707.  
  708.    The 8088, being a 16-bit microprocessor, can work with 16 bits of data
  709.    at a time, exactly like its relative the 80286. Although the 8088 can
  710.    work with 16-bit numbers internally, the size of its data bus allows the
  711.    8088 to pass data only 8 bits at a time. This has led some people to
  712.    comment that the 8088 is not a true 16-bit microprocessor. Rest assured
  713.    that it is, even though it is less powerful than the 80286. The 16-bit
  714.    data bus of the 80286 does help it move data around more efficiently
  715.    than the 8088, but the real difference in speed between the 8088 and the
  716.    AT comes from the AT's faster clock rate and its more powerful internal
  717.    organization.
  718.  
  719.    There is an important practical reason why so many computers, including
  720.    the older members of the PC family, use the 8088 with its 8-bit data
  721.    bus, rather than the 8086 with its 16-bit bus. The reason is simple
  722.    economics. A variety of 8-bit circuitry elements are available in large
  723.    quantities at low prices. When the PC was being designed, 16-bit
  724.    circuitry was more expensive and was less readily available. The use of
  725.    the 8088, rather than the 8086, was important not only to hold down the
  726.    cost of the PC, but also to avoid a shortage of parts. The price of
  727.    16-bit circuitry elements has decreased significantly since then,
  728.    however, and it has become economically feasible to use the more
  729.    efficient 80286 with its 16-bit bus. Furthermore, the 80286 is able to
  730.    use a mixture of 8-bit parts and 16-bit parts, thereby maintaining
  731.    compatibility within the PC family.
  732.  
  733.  Micro Channel Architecture
  734.  
  735.    The PS/2 models 50, 60, and 80 introduced a new bus hardware design that
  736.    IBM calls Micro Channel architecture. Both the Micro Channel bus in the
  737.    PS/2s and the earlier PC and PC/AT bus accomplish the same task of
  738.    communicating addresses and data to plug-in adapters. The Micro Channel
  739.    bus hardware is designed to run at higher speeds than its predecessors
  740.    as well as to allow for more flexible adapter hardware designs. The
  741.    Micro Channel differs from the PC and PC/AT bus design both in its
  742.    physical layout and in its signal specifications, so an adapter that can
  743.    be used with one bus is incompatible with the other.
  744.  
  745.    The differences between the original PC bus, the PC/AT bus, and the
  746.    Micro Channel bus are important in operating system software but not in
  747.    applications programs. Although all programs rely implicitly on the
  748.    proper functioning of the address and data buses, very few programs are
  749.    actually concerned with programming the bus directly. We'll come back to
  750.    the Micro Channel architecture only when we describe PS/2 ROM BIOS
  751.    services that work specifically with it.
  752.  
  753.  
  754.  Memory
  755.  
  756.    So far, we've discussed the CPU, the support chips, and the bus, but
  757.    we've only touched on memory. We've saved our discussion of memory for
  758.    the end of this chapter because memory chips, unlike the other chips
  759.    we've discussed, don't control or direct the flow of information through
  760.    a computer system; they merely store information until it is needed.
  761.  
  762.    The number and storage capacity of memory chips that exist inside the
  763.    computer determine the amount of memory we can use for programs and
  764.    data. Although this may vary from one computer to another, all PCs and
  765.    PS/2s come with at least 40 KB of read-only memory (ROM)──with space for
  766.    more──and between 64 KB and 2 MB of random-access memory (RAM). Both ROM
  767.    and RAM capacities can be augmented by installing additional memory
  768.    chips in empty sockets on the motherboard as well as by installing a
  769.    memory adapter in one of the system expansion slots. But this is only
  770.    the physical view of memory. A program sees memory not as a set of
  771.    individual chips, but as a set of thousands or millions of 8-bit
  772.    (1-byte) storage cells, each with a unique address.
  773.  
  774.    Programmers must also think of memory in this way──not in terms of how
  775.    much physical memory there is, but in terms of how much addressable
  776.    memory there is. The 8088 and 8086 can address up to 1 MB (1024 KB, or
  777.    exactly 1,048,576 bytes) of memory. In other words, that's the maximum
  778.    number of addresses, and therefore the maximum number of individual
  779.    bytes of information, the processors can refer to. Memory addressing is
  780.    discussed in more detail in Chapter 2.
  781.  
  782.  CPU Address Space
  783.  
  784.    Each byte is referred to by a 20-bit numeric address. In the 8086 memory
  785.    scheme, the addresses are 20 bits "wide" because they must travel along
  786.    the 20-bit address bus. This gives the 8086 an address space with
  787.    address values that range from 00000H through FFFFFH (0 through
  788.    1,048,576 in decimal notation). If you have trouble understanding hex
  789.    notation, you might want to take a quick look at Appendix B.
  790.  
  791.    Similarly, the 80286's 24-bit addressing scheme lets it use extended
  792.    address values in the range 000000H through FFFFFFH, or 16 MB. The 80386
  793.    can use extended 32-bit addresses, so its maximum address value is
  794.    FFFFFFFFH; that is, the 80386 can directly address up to 4,294,967,296
  795.    bytes, or four gigabytes (GB), of memory. This is enough memory for most
  796.    practical purposes, even for the most prolific programmer.
  797.  
  798.    Although the 80286 and 80386 can address more than 1 MB of memory, any
  799.    program compatible with the 8086 and with DOS must limit itself to
  800.    addresses that lie in the 1 MB range available to the 8086. When the IBM
  801.    PC first appeared in 1981, 1 MB seemed like a lot of memory, but large
  802.    business-applications programs, memory-resident utility programs, and
  803.    system software required for communications and networking can easily
  804.    fill up the entire 8086 address space.
  805.  
  806.    One way to work around the 1 MB limit is with the LIM
  807.    (Lotus-Intel-Microsoft) Expanded Memory Specification (EMS). The EMS is
  808.    based on special hardware and software that map additional RAM into the
  809.    8086 address space in 16 KB blocks. The EMS hardware can map a number of
  810.    different 16 KB blocks into the same 16 KB range of 8086 addresses.
  811.    Although the blocks must be accessed separately, the EMS lets up to 2048
  812.    different 16 KB blocks map to the same range of 8086 addresses. That's
  813.    up to 32 MB of expanded memory.
  814.  
  815.    ────────────────────────────────────────────────────────────────────────
  816.    NOTE:
  817.      Don't confuse EMS "expanded" memory with the "extended" memory located
  818.      above the first megabyte of 80286 or 80386 memory. Although many
  819.      memory expansion adapters can be configured to serve as either
  820.      expanded or extended memory (or both), these two memory configurations
  821.      are very different from both a hardware and software point of view.
  822.    ────────────────────────────────────────────────────────────────────────
  823.  
  824.  The System Memory Map
  825.  
  826.    On the original IBM PC, the 1 MB address space of the 8088 was split
  827.    into several functional areas. (See Figure 1-6.) This memory map has
  828.    been carried forward for compatibility in all subsequent PC and PS/2
  829.    models.
  830.  
  831.                 ┌────────────────────────────────────┐
  832.                 │   PC/AT and PS/2 extended memory   │
  833.                 └────────────────────────────────────┘
  834.    100000H ────┌────────────────────────────────────┐
  835.                 │      Reserved for ROM BIOS         │
  836.     E0000H ────├────────────────────────────────────┤
  837.                 │    Reserved for installable ROM    │
  838.     C0000H ────├────────────────────────────────────┤
  839.                 │           Video buffers            │
  840.     A0000H ────└────────────────────────────────────┘
  841.                 ┌────────────────────────────────────┐──┐
  842.                 │      Transient portion of DOS      │  │
  843.                 ├────────────────────────────────────┤  │
  844.                 │                                    │  │
  845.                 │       Transient Program Area       │  │
  846.                 │      (user programs and data)      │  │
  847.                 ├────────────────────────────────────┤  │
  848.                 │       Resident portion of DOS      │  ├── System
  849.                 ├────────────────────────────────────┤  │   RAM
  850.                 │  Data area for ROM BIOS and BASIC  │  │
  851.     00500H ────├────────────────────────────────────┤  │
  852.                 │       Data area for ROM BIOS       │  │
  853.     00400H ────├────────────────────────────────────┤  │
  854.                 │          Interrupt vectors         │  │
  855.     00000H ────└────────────────────────────────────┘──┘
  856.  
  857.    Figure 1-6.  An outline of memory usage in PCs and PS/2s.
  858.  
  859.    Some of the layout of the PC and PS/2 memory map is a consequence of the
  860.    design of the 8086 microprocessor. For example, the 8086 always maintains
  861.    a list of interrupt vectors (addresses of interrupt handling routines) in
  862.    the first 1024 bytes of RAM. Similarly, all 8086-based microcomputers have
  863.    ROM memory at the high end of the 1 MB address space, because the 8086,
  864.    when first powered up, executes the program that starts at address FFFF0H.
  865.  
  866.    The rest of the memory map follows this general division between RAM at
  867.    the bottom of the address space and ROM at the top. A maximum of 640 KB of
  868.    RAM can exist between addresses 00000H and 9FFFFH. (This is the memory
  869.    area described by the DOS CHKDSK program.) Subsequent memory blocks are
  870.    reserved for video RAM (A0000H through BFFFFH), installable ROM modules
  871.    (C0000H through DFFFFH), and permanent ROM (E0000H through FFFFFH). We'll
  872.    explore each of these memory areas in greater detail in the chapters that
  873.    follow.
  874.  
  875.  
  876.  Design Philosophy
  877.  
  878.    Before leaping into the following chapters, we should discuss the design
  879.    philosophy behind the PC family. This will help you understand what is
  880.    (and what isn't) important or useful to you.
  881.  
  882.    Part of the design philosophy of the IBM personal computer family centers
  883.    around a set of ROM BIOS service routines (see Chapters 8 through 13)
  884.    that provide essentially all the control functions and operations that IBM
  885.    considers necessary. The basic philosophy of the PC family is: Let the ROM
  886.    BIOS do it; don't mess with direct control. In our judgment, this is a
  887.    sound idea that has several beneficial results. Using the ROM BIOS
  888.    routines encourages good programming practices, and it avoids some of the
  889.    kludgy tricks that have been the curse of many other computers. It also
  890.    increases the chances of your programs working on every member of the PC
  891.    family. In addition, it gives IBM more flexibility in making improvements
  892.    and additions to the line of PC computers. However, it would be naive for
  893.    us to simply say to you, "Don't mess with direct control of the hardware."
  894.    For good reasons or bad, you may want or may need to have your programs
  895.    work as directly with the computer hardware as possible, doing what is
  896.    colorfully called "programming down to the bare metal."
  897.  
  898.    Still, as the PC family has evolved, programmers have had the opportunity
  899.    to work with increasingly powerful hardware and system software. The newer
  900.    members of the PC family provide faster hardware and better system
  901.    software, so direct programming of the hardware does not necessarily
  902.    result in significantly faster programs. For example, with an IBM PC
  903.    running DOS, the fastest way to display text on the video display is to
  904.    use assembly-language routines that bypass DOS and directly program the
  905.    video hardware. Video screen output is many times slower if you route it
  906.    through DOS. Contrast this with a PC/AT or PS/2 running OS/2, where the
  907.    best way to put text on the screen is to use the operating system output
  908.    functions. The faster hardware and the efficient video output services in
  909.    OS/2 make direct programming unnecessary.
  910.  
  911.    As you read the programming details we present in this book, keep in mind
  912.    that you can often obtain a result or accomplish a programming task
  913.    through several means, including direct hardware programming, calling the
  914.    ROM BIOS, or using a DOS service. You must always balance portability,
  915.    convenience, and performance as you weigh the alternatives. The more you
  916.    know about what the hardware, the ROM BIOS, and the operating system can
  917.    do, the better your programs can use them.
  918.  
  919.  
  920.  
  921.  ────────────────────────────────────────────────────────────────────────────
  922.  Chapter 2  The Ins and Outs
  923.  
  924.    How the 8086 Communicates
  925.      The 8086 Data Formats
  926.  
  927.    How the 8086 Addresses Memory
  928.      Segmented Addresses
  929.      80286 and 80386 Protected-Mode Addresses
  930.      Address Compatibility
  931.  
  932.    The 8086 Registers
  933.      The Scratch-Pad Registers
  934.      The Segment Registers
  935.      The Offset Registers
  936.      The Flags Register
  937.      Addressing Memory Through Registers
  938.      Rules for Using Registers
  939.  
  940.    How the 8086 Uses I/O Ports
  941.  
  942.    How the 8086 Uses Interrupts
  943.      Software Interrupts
  944.      Hardware Interrupts
  945.  
  946.    Generally speaking, the more you know about how your computer works, the
  947.    more effective you'll be at writing programs for it. High-level
  948.    programming languages, such as BASIC and C, are not designed to include
  949.    every possible function that you might need while programming──though
  950.    admittedly, some are better than others. At some point, you will want to
  951.    go deeper into your system and use some of the routines the languages
  952.    themselves use, or perhaps go even deeper and program at the hardware
  953.    level.
  954.  
  955.    Although some languages provide limited means to talk directly to memory
  956.    (as with PEEK and POKE in BASIC) or even to some of the chips (as with
  957.    BASIC's INP and OUT statements), most programmers eventually resort to
  958.    assembly language, the basic language from which all other languages and
  959.    operating systems are built. The 8086 assembly language, like all other
  960.    assembly languages, is composed of a set of symbolic instructions, as
  961.    shown in Figure 2-1. An assembler translates these instructions and the
  962.    data associated with them into a binary form, called machine language,
  963.    that can reside in memory and be processed by the 8086 to accomplish
  964.    specific tasks.
  965.  
  966. ╓┌─┌──────────────────┌──────────────────────────────────────────────────────╖
  967.    Mnemonic           Full Name
  968.    Mnemonic           Full Name
  969.    ──────────────────────────────────────────────────────────────────────────
  970.    Instructions recognized by all 8086-family microprocessors
  971.    AAA                ASCII Adjust After Addition
  972.    AAD                ASCII Adjust After Division
  973.    AAM                ASCII Adjust After Multiplication
  974.    AAS                ASCII Adjust After Subtraction
  975.    ADC                ADd with Carry
  976.    ADD                ADD
  977.    AND                AND
  978.    CALL               CALL
  979.    CBW                Convert Byte to Word
  980.    CLC                CLear Carry flag
  981.    CLD                CLear Direction flag
  982.    CLI                CLear Interrupt flag
  983.    CMC                CoMplement Carry flag
  984.    CMP                CoMPare
  985.    CMPS               CoMPare String
  986.    CMPSB              CoMPare String (Bytes)
  987.    CMPSW              CoMPare String (Words)
  988.    CWD                Convert Word to Doubleword
  989.    Mnemonic           Full Name
  990.    ──────────────────────────────────────────────────────────────────────────
  991.   CWD                Convert Word to Doubleword
  992.    DAA                Decimal Adjust After Addition
  993.    DAS                Decimal Adjust After Subtraction
  994.    DEC                DECrement
  995.    DIV                Unsigned DIVide
  996.    ESC                ESCape
  997.    HLT                HaLT
  998.    IDIV               Integer DIVide
  999.    IMUL               Integer MULtiply
  1000.    IN                 INput from I/O port
  1001.    INC                INCrement
  1002.    INT                INTerrupt
  1003.    INTO               INTerrupt on Overflow
  1004.    IRET               Interrupt RETurn
  1005.    JA                 Jump if Above
  1006.    JAE                Jump if Above or Equal
  1007.    JB                 Jump if Below
  1008.    JBE                Jump if Below or Equal
  1009.    JC                 Jump if Carry
  1010.    Mnemonic           Full Name
  1011.    ──────────────────────────────────────────────────────────────────────────
  1012.   JC                 Jump if Carry
  1013.    JCXZ               Jump if CX Zero
  1014.    JE                 Jump if Equal
  1015.    JG                 Jump if Greater than
  1016.    JGE                Jump if Greater than or Equal
  1017.    JL                 Jump if Less than
  1018.    JLE                Jump if Less than or Equal
  1019.    JMP                JuMP
  1020.    JNA                Jump if Not Above
  1021.    JNAE               Jump if Not Above or Equal
  1022.    JNB                Jump if Not Below
  1023.    JNBE               Jump if Not Below or Equal
  1024.    JNC                Jump if No Carry
  1025.    JNE                Jump if Not Equal
  1026.    JNG                Jump if Not Greater than
  1027.    JNGE               Jump if Not Greater than or Equal
  1028.    JNL                Jump if Not Less than
  1029.    JNLE               Jump if Not Less than or Equal
  1030.    JNO                Jump if Not Overflow
  1031.    Mnemonic           Full Name
  1032.    ──────────────────────────────────────────────────────────────────────────
  1033.   JNO                Jump if Not Overflow
  1034.    JNP                Jump if Not Parity
  1035.    JNS                Jump if Not Sign
  1036.    JNZ                Jump if Not Zero
  1037.    JO                 Jump if Overflow
  1038.    JP                 Jump if Parity
  1039.    JPE                Jump if Parity Even
  1040.    JPO                Jump if Parity Odd
  1041.    JS                 Jump if Sign
  1042.    JZ                 Jump if Zero
  1043.    LAHF               Load AH with Flags
  1044.    LDS                Load pointer using DS
  1045.    LEA                Load Effective Address
  1046.    LES                Load pointer using ES
  1047.    LOCK               LOCK bus
  1048.    LODS               LOaD String
  1049.    LODSB              LOaD String (Bytes)
  1050.    LODSW              LOaD String (Words)
  1051.    LOOP               LOOP
  1052.    Mnemonic           Full Name
  1053.    ──────────────────────────────────────────────────────────────────────────
  1054.   LOOP               LOOP
  1055.    LOOPE              LOOP while Equal
  1056.    LOOPNE             LOOP while Not Equal
  1057.    LOOPNZ             LOOP while Not Zero
  1058.    LOOPZ              LOOP while Zero
  1059.    MOV                MOVe data
  1060.    MOVS               MOVe String
  1061.    MOVSB              MOVe String (Bytes)
  1062.    MOVSW              MOVe String (Words)
  1063.    MUL                MULtiply
  1064.    NEG                NEGate
  1065.    NOP                No OPeration
  1066.    NOT                NOT
  1067.    OR                 OR
  1068.    OUT                OUTput to I/O port
  1069.    POP                POP
  1070.    POPF               POP Flags
  1071.    PUSH               PUSH
  1072.    PUSHF              PUSH Flags
  1073.    Mnemonic           Full Name
  1074.    ──────────────────────────────────────────────────────────────────────────
  1075.   PUSHF              PUSH Flags
  1076.    RCL                Rotate through Carry Left
  1077.    RCR                Rotate through Carry Right
  1078.    REP                REPeat
  1079.    REPE               REPeat while Equal
  1080.    REPNE              REPeat while Not Equal
  1081.    REPNZ              REPeat while Not Zero
  1082.    REPZ               REPeat while Zero
  1083.    RET                RETurn
  1084.    ROL                ROtate Left
  1085.    ROR                ROtate Right
  1086.    SAHF               Store AH into Flags
  1087.    SAL                Shift Arithmetic Left
  1088.    SAR                Shift Arithmetic Right
  1089.    SBB                SuBtract with Borrow
  1090.    SCAS               SCAn String
  1091.    SCASB              SCAn String (Bytes)
  1092.    SCASW              SCAn String (Words)
  1093.    SHL                SHift Left
  1094.    Mnemonic           Full Name
  1095.    ──────────────────────────────────────────────────────────────────────────
  1096.   SHL                SHift Left
  1097.    SHR                SHift Right
  1098.    STC                SeT Carry flag
  1099.    STD                SeT Direction flag
  1100.    STI                SeT Interrupt flag
  1101.    STOS               STOre String
  1102.    STOSB              STOre String (Bytes)
  1103.    STOSW              STOre String (Words)
  1104.    SUB                SUBtract
  1105.    TEST               TEST
  1106.    WAIT               WAIT
  1107.    XCHG               eXCHanGe
  1108.    XLAT               transLATe
  1109.    XOR                eXclusive OR
  1110.  
  1111.    Instructions recognized by the 80286 and 80386 only:
  1112.    ARPL               Adjust RPL field of selector
  1113.    BOUND              Check array index against BOUNDs
  1114.    CLTS               CLear Task-Switched flag
  1115.    Mnemonic           Full Name
  1116.    ──────────────────────────────────────────────────────────────────────────
  1117.   CLTS               CLear Task-Switched flag
  1118.    ENTER              Establish stack frame
  1119.    INS                INput String from I/O port
  1120.    LAR                Load Access Rights
  1121.    LEAVE              Discard stack frame
  1122.    LGDT               Load Global Descriptor Table register
  1123.    LIDT               Load Interrupt Descriptor Table register
  1124.    LLDT               Load Local Descriptor Table register
  1125.    LMSW               Load Machine Status Word
  1126.    LSL                Load Segment Limit
  1127.    LTR                Load Task Register
  1128.    OUTS               OUTput String to I/O port
  1129.    POPA               POP All general registers
  1130.    PUSHA              PUSH All general registers
  1131.    SGDT               Store Global Descriptor Table register
  1132.    SIDT               Store Interrupt Descriptor Table register
  1133.    SLDT               Store Local Descriptor Table register
  1134.    SMSW               Store Machine Status Word
  1135.    STR                Store Task Register
  1136.    Mnemonic           Full Name
  1137.    ──────────────────────────────────────────────────────────────────────────
  1138.   STR                Store Task Register
  1139.    VERR               VERify a segment selector for Reading
  1140.    VERW               VERify a segment selector for Writing
  1141.  
  1142.    Instructions recognized by the 80386 only:
  1143.    BSF                Bit Scan Forward
  1144.    BSR                Bit Scan Reverse
  1145.    BT                 Bit Test
  1146.    BTC                Bit Test and Complement
  1147.    BTR                Bit Test and Reset
  1148.    BTS                Bit Test and Set
  1149.    CDQ                Convert Doubleword to Quadword
  1150.    CMPSD              CoMPare String (Doublewords)
  1151.    CWDE               Convert Word to Doubleword in EAX
  1152.    LFS                Load pointer using FS
  1153.    LGS                Load pointer using GS
  1154.    LSS                Load pointer using SS
  1155.    LODSD              LOaD String (Doublewords)
  1156.    MOVSD              MOVe String (Doublewords)
  1157.    Mnemonic           Full Name
  1158.    ──────────────────────────────────────────────────────────────────────────
  1159.   MOVSD              MOVe String (Doublewords)
  1160.    MOVSX              MOVe with Sign-eXtend
  1161.    MOVZX              MOVe with Zero-eXtend
  1162.    SCASD              SCAn String (Doublewords)
  1163.    SETA               SET byte if Above
  1164.    SETAE              SET byte if Above or Equal
  1165.    SETB               SET byte if Below
  1166.    SETBE              SET byte if Below or Equal
  1167.    SETC               SET byte if Carry
  1168.    SETE               SET byte if Equal
  1169.    SETG               SET byte if Greater
  1170.    SETGE              SET byte if Greater or Equal
  1171.    SETL               SET byte if Less
  1172.    SETLE              SET byte if Less or Equal
  1173.    SETNA              SET byte if Not Above
  1174.    SETNAE             SET byte if Not Above or Equal
  1175.    SETNB              SET byte if Not Below
  1176.    SETNBE             SET byte if Not Below or Equal
  1177.    SETNC              SET byte if No Carry
  1178.    Mnemonic           Full Name
  1179.    ──────────────────────────────────────────────────────────────────────────
  1180.   SETNC              SET byte if No Carry
  1181.    SETNE              SET byte if Not Equal
  1182.    SETNG              SET byte if Not Greater
  1183.    SETNGE             SET byte if Not Greater or Equal
  1184.    SETNL              SET byte if Not Less
  1185.    SETNLE             SET byte if Not Less or Equal
  1186.    SETNO              SET byte if Not Overflow
  1187.    SETNP              SET byte if Not Parity
  1188.    SETNS              SET byte if Not Sign
  1189.    SETNZ              SET byte if Not Zero
  1190.    SETO               SET byte if Overflow
  1191.    SETP               SET byte if Parity
  1192.    SETPE              SET byte if Parity Even
  1193.    SETPO              SET byte if Parity Odd
  1194.    SETS               SET byte if Sign
  1195.    SETZ               SET byte if Zero
  1196.    SHLD               SHift Left (Doubleword)
  1197.    SHRD               SHift Right (Doubleword)
  1198.    STOSD              STOre String (Doublewords)
  1199.    Mnemonic           Full Name
  1200.    ──────────────────────────────────────────────────────────────────────────
  1201.   STOSD              STOre String (Doublewords)
  1202.    ──────────────────────────────────────────────────────────────────────────
  1203.  
  1204.  
  1205.    Figure 2-1.  The instruction set used with the 8086, 80286, and 80386.
  1206.  
  1207.    ──────────────────────────────────────────────────────────────────────────
  1208.    NOTE:
  1209.      Although this chapter discusses the details of 8086 programming,
  1210.      remember that we're implicitly talking about the 8088, 80286, and 80386
  1211.      as well. Information pertaining exclusively to the 80286 or 80386 will
  1212.      be noted.
  1213.    ──────────────────────────────────────────────────────────────────────────
  1214.  
  1215.    The operations that the 8086 instructions can perform break down into only
  1216.    a few categories. They can do simple, four-function integer arithmetic.
  1217.    They can move data around. They can, using only slightly clumsy methods,
  1218.    manipulate individual bits. They can test values and take logical action
  1219.    based on the results. And last but not least, they can interact with the
  1220.    circuitry around them. The size of each instruction varies, but generally
  1221.    the most basic and often-used instructions are the shortest.
  1222.  
  1223.    Assembly-language programming can be carried out on one of two levels: to
  1224.    create interface routines that will tie high-level programs to the
  1225.    lower-level DOS and ROM-BIOS routines; or to create full-fledged
  1226.    assembly-language programs that are faster and smaller than equivalent
  1227.    high-level programs, or that perform exotic tasks at the hardware level,
  1228.    perhaps accomplishing a feat that is accomplished nowhere else. Either
  1229.    way, to understand how to use assembly language, you must understand how
  1230.    8086-family microprocessors process information and how they work with the
  1231.    rest of the computer. The rest of this chapter describes how the
  1232.    microprocessor and the computer's other parts communicate.
  1233.  
  1234.  
  1235.  How the 8086 Communicates
  1236.  
  1237.    The 8086, 80286, and 80386 interact with the circuitry around them in
  1238.    three ways: through direct and indirect memory access, through
  1239.    input/output (I/O) ports, and with signals called interrupts.
  1240.  
  1241.    The microprocessor uses memory by reading or writing values at memory
  1242.    locations that are identified with numeric addresses. The memory locations
  1243.    can be accessed in two ways: through the direct memory access (DMA)
  1244.    controller or through the microprocessor's internal registers. The disk
  1245.    drives and the serial communications ports can directly access memory
  1246.    through the DMA controller. All other devices transfer data to and from
  1247.    memory by way of the microprocessor's registers.
  1248.  
  1249.    Input/Output ports are the microprocessor's general means of communicating
  1250.    with any computer circuitry other than memory. Like memory locations, I/O
  1251.    ports are identified by number, and data can be read from or written to
  1252.    any port. I/O port assignment is unique to the design of any particular
  1253.    computer. Generally, all members of the IBM PC family use the same port
  1254.    specifications, with just a few variations among the different models.
  1255.    (See page 37.)
  1256.  
  1257.    Interrupts are the means by which the circuitry outside the microprocessor
  1258.    reports that something (such as a keystroke) has happened and requests
  1259.    that some action be taken. Although interrupts are essential to the
  1260.    microprocessor's interaction with the hardware around it, the concept of
  1261.    an interrupt is useful for other purposes as well. For example, a program
  1262.    can use the INT instruction to generate a software interrupt that requests
  1263.    a service from DOS or from the system ROM BIOS. Interrupts are quite
  1264.    important when programming the PC family, so we'll devote a special
  1265.    section to them at the end of this chapter.
  1266.  
  1267.  The 8086 Data Formats
  1268.  
  1269.    Numeric data. The 8086 and 80386 are able to work with only four simple
  1270.    numeric data formats, all of which are integer values. The formats are
  1271.    founded on two building blocks: the 8-bit byte and the 16-bit (2-byte)
  1272.    word. Both of these basic units are related to the 16-bit processing
  1273.    capacity of the 8086. The byte is the more fundamental unit; and when the
  1274.    8086 and 80286 address memory, bytes are the basic unit addressed. In a
  1275.    single byte, these microprocessors can work with unsigned positive numbers
  1276.    ranging in value from 0 through 255 (that is, 2^8 possibilities). If the
  1277.    number is a signed value, one of the 8 bits represents the sign, so only 7
  1278.    bits represent the value. Thus a signed byte can represent values ranging
  1279.    from -128 through +127. (See Figure 2-2.)
  1280.  
  1281.    The 8086 and 80286 can also operate on 16-bit signed and unsigned values,
  1282.    or words. Words are stored in memory in two adjacent bytes, with the low-
  1283.    order byte preceding the high-order byte. (See the discussion of
  1284.    "back-words storage" on page 24.)
  1285.  
  1286.                                      Range
  1287.    Size        Signed?      Dec                     Hex
  1288.    ──────────────────────────────────────────────────────────────────────────
  1289.     8          No           0 through 255           00H through FFH
  1290.  
  1291.     8          Yes          -128 through 0 through  80H through 00H through
  1292.                             +127                    7FH
  1293.  
  1294.    16          No           0 through 65,535        0000H through FFFFH
  1295.  
  1296.    16          Yes          -32,768 through 0       8000H through 0000H
  1297.                             through +32,767         through 7FFFH
  1298.  
  1299.    32          No           0 through 4,294,967,295 00000000H through
  1300.                                                     FFFFFFFFH
  1301.  
  1302.    32          Yes          -2,147,483,648 through  00000000H through
  1303.                             +2,147,483,647          00000000H through
  1304.                                                     7FFFFFFFH
  1305.    ──────────────────────────────────────────────────────────────────────────
  1306.  
  1307.    Figure 2-2.  The six data formats used in the 8086 family. (Only the 80386
  1308.    supports 32-bit formats.)
  1309.  
  1310.    A word interpreted as an unsigned, positive number can have 2^16 different
  1311.    values ranging from 0 through 65,535. As a signed number, the value can
  1312.    range from -32,768 through +32,767.
  1313.  
  1314.    The 80386 differs from its predecessors in that it can also work with
  1315.    32-bit integer values, or doublewords. A doubleword represents a signed or
  1316.    unsigned 4-byte integer with any of 2^32 (or 4,294,967,295) different
  1317.    values.
  1318.  
  1319.    Character data. Character data is stored in the standard ASCII format,
  1320.    with each character occupying 1 byte. The 8086 family knows nothing about
  1321.    ASCII characters and treats them as arbitrary bytes, with one exception:
  1322.    The instruction set accommodates decimal addition and subtraction
  1323.    performed on binary coded decimal (BCD) characters. The actual arithmetic
  1324.    is done in binary, but the combination of the AF flag (see page 33) and a
  1325.    few special instructions makes it practical to work on decimal characters
  1326.    and get decimal results, which can easily be converted to ASCII.
  1327.  
  1328.    ──────────────────────────────────────────────────────────────────────────
  1329.    Back-Words Storage
  1330.      While the PC's memory is addressed in units of individual 8-bit bytes,
  1331.      many operations involve 16-bit words. In memory, a 16-bit word is stored
  1332.      in any two adjacent 8-bit bytes. The least-significant byte of the word
  1333.      is stored in the lower memory location, and the most significant byte is
  1334.      stored in the higher memory location. From some points of view, storing
  1335.      a word this way is the opposite of what you might expect. Due to the
  1336.      backward appearance of this storage scheme, it is sometimes whimsically
  1337.      called "back-words" storage.
  1338.  
  1339.      ─── Higher addresses ───────
  1340.      ┌───────┬───────┐
  1341.      │  9C   │  E6   │                   Value of word is E69CH
  1342.      └───────┴───────┘
  1343.  
  1344.      ─── Higher addresses ───────
  1345.      ┌───────┬───────┬───────┬───────┐
  1346.      │  4A   │  5B   │  00   │  12   │   Value of doubleword is 12005B4AH
  1347.      └───────┴───────┴───────┴───────┘
  1348.  
  1349.      If you are working with bytes and words in memory, you should take care
  1350.      not to be confused by back-words storage. The source of the confusion
  1351.      has mostly to do with how you write data. For example, if you are
  1352.      writing a word value in hex, you write it like this: ABCD. The order of
  1353.      significance is the same as if you are writing a decimal number: The
  1354.      most significant digit is written first. But a word is stored in memory
  1355.      with the lowest address location first. So, in memory, the number ABCD
  1356.      appears as CDAB, with the bytes switched.
  1357.    ──────────────────────────────────────────────────────────────────────────
  1358.  
  1359.    See Appendix C for more information on ASCII and the PC family's extended
  1360.    ASCII character set.
  1361.  
  1362.  
  1363.  How the 8086 Addresses Memory
  1364.  
  1365.    The 8086 is a 16-bit microprocessor and cannot therefore work directly
  1366.    with numbers larger than 16 bits. Theoretically, this means that the 8086
  1367.    should be able to access only 64 KB of memory. But, as we noted in the
  1368.    previous chapter, it can in fact access much more than that──1024 KB to be
  1369.    exact. This is possible because of the 20-bit addressing scheme used with
  1370.    the 8086, which expands the full range of memory locations that the 8086
  1371.    can work with from 2^16 (65,536) to 2^20 (1,048,576). But the 8086 is
  1372.    still limited by its 16-bit processing capacity. To access the 20-bit
  1373.    addresses, it must use an addressing method that fits into the 16-bit
  1374.    format.
  1375.  
  1376.  Segmented Addresses
  1377.  
  1378.    The 8086 divides the addressable memory space into segments, each of which
  1379.    contains 64 KB of memory. Each segment begins at a paragraph address──that
  1380.    is, a byte location that is evenly divisible by 16. To access individual
  1381.    bytes or words, you use an offset that points to an exact byte location
  1382.    within a particular segment. Because offsets are always measured relative
  1383.    to the beginning of a segment, they are also called relative addresses or
  1384.    relative offsets.
  1385.  
  1386.    Together, a segment and an offset form a segmented address that can
  1387.    designate any byte in the 8086's 1 MB address space. The 8086 converts a
  1388.    given 32-bit segmented address into a 20-bit physical address by using the
  1389.    segment value as a paragraph number and adding the offset value to it. In
  1390.    effect, the 8086 shifts the segment value left by 4 bits and then adds the
  1391.    offset value to create a 20-bit address.
  1392.  
  1393.    Figure 2-3 shows how this is done for a segment value of 1234H and an
  1394.    offset of 4321H. The segmented address is written as 1234:4321, with
  1395.    4-digit hexadecimal values and with a colon separating the segment and
  1396.    offset.
  1397.  
  1398.       1234:4321
  1399.    shift│    │
  1400.     left│    │
  1401.         │    │
  1402.             │
  1403.      12340   │
  1404.      +4321──┘
  1405.      ─────
  1406.      16661
  1407.  
  1408.    Figure 2-3.  Decoding an 8086 segmented address. The segment value 1234H
  1409.    is shifted left 4 bits (one hex digit) and added to the offset 4321H to
  1410.    give the 20-bit physical address 16661H.
  1411.  
  1412.    On the 8086, there's obviously a great deal of overlap in the range of
  1413.    values that can be expressed as segmented addresses. Any given physical
  1414.    address can be represented by up to 2^12 different segmented addresses.
  1415.    For example, the physical address 16661H could be represented not only as
  1416.    1234:4321, but also as 1666:0001, 1665:0011, 1664:0021, and so on.
  1417.  
  1418.  80286 and 80386 Protected-Mode Addresses
  1419.  
  1420.    The 80286 also uses segmented addresses, but when the 80286 runs in
  1421.    protected mode, the addresses are decoded differently than on an 8086 or
  1422.    in 80286 real mode. The 80286 decodes protected-mode segmented addresses
  1423.    through a table of segment descriptors. The "segment" part of a segmented
  1424.    address is not a paragraph value, but a "selector" that represents an
  1425.    index into a segment descriptor table (Figure 2-4). Each descriptor in
  1426.    the table contains a 24-bit base address that indicates the actual start
  1427.    of a segment in memory. The resulting address is the sum of the 24-bit
  1428.    base address and the 16-bit offset specified in the segmented address.
  1429.    Thus, in protected mode the 80286 can access up to 2^24 bytes of memory;
  1430.    that is, physical addresses are 24 bits in size.
  1431.  
  1432.    This table-driven addressing scheme gives the 80286 a great deal of
  1433.    control over memory usage. In addition to a 24-bit base address, each
  1434.    segment descriptor specifies a segment's attributes (executable code,
  1435.    program data, read-only, and so on), as well as a privilege level that
  1436.    lets an operating system restrict access to the segment. This ability to
  1437.    specify segment attributes and access privileges is of great use to a
  1438.    multitasking operating system like OS/2.
  1439.  
  1440.    The 80386 supports both 8086 and 80286 protected-mode addressing. The
  1441.    80386 enhances the protected-mode addressing scheme by allowing 32-bit
  1442.    segment base addresses and 32-bit offsets. Thus a single segmented
  1443.    address, consisting of a 16-bit selector and a 32-bit offset, can specify
  1444.    any of 2^32 different physical addresses.
  1445.  
  1446.                           0038:4321
  1447.                             │    │
  1448.      │            │         │    │
  1449.      ├────────────┤         │    │
  1450.      │            │ 28      │    │
  1451.      ├────────────┤         │    │
  1452.      │            │ 30      │    │
  1453.      ├────────────┤         │    │
  1454.    ┌─┤   012340   │ 38 ────┘    │
  1455.    │ ├────────────┤              │
  1456.    │ │            │ 40           │
  1457.    │ ├────────────┤              │
  1458.    │ │            │              │
  1459.    │                             │
  1460.    └────────────────── 012340   │
  1461.                         + 4321 ─┘
  1462.                         ──────
  1463.                         016661
  1464.  
  1465.    Figure 2-4.  Decoding an 80286 protected-mode segmented address. The
  1466.    segment selector 38H indicates an entry in a segment descriptor table. The
  1467.    segment descriptor contains a 24-bit segment base address which is added
  1468.    to the offset 4321H to give the 24-bit physical address 016661H.
  1469.  
  1470.    The 80386 also provides a "virtual 8086" addressing mode, in which
  1471.    addressing is the same as the usual 8086 16-bit addressing, but with the
  1472.    physical addresses corresponding to the 1 MB 8086 address space mapped
  1473.    anywhere in the 4 gigabyte (GB) 80386 address space. This lets an
  1474.    operating system execute several different 8086 programs, each in its own
  1475.    1 MB, 8086-compatible address space.
  1476.  
  1477.  Address Compatibility
  1478.  
  1479.    The different addressing schemes used by the 80286 and 80386 are generally
  1480.    compatible (except, of course, for 32-bit addressing on the 80386).
  1481.    However, if you are writing an 8086 program that you intend to convert for
  1482.    use in protected mode, be careful to use segments in an orderly fashion.
  1483.    Although it's possible to specify a physical 8086 address with many
  1484.    different segment-offset combinations, you will find it easier to convert
  1485.    8086 programs to 80286 protected-mode addressing if you keep your segment
  1486.    values as constant as possible.
  1487.  
  1488.    For example, imagine that your program needs to access an array of
  1489.    160-byte strings of characters, starting at physical address B8000H. A
  1490.    poor way to access each string would be to exploit the fact that the
  1491.    strings are each 10 paragraphs long by using a different segment value to
  1492.    locate the start of each string:
  1493.  
  1494.      B800:0000H (physical address B8000H)
  1495.      B80A:0000H (physical address B80A0H)
  1496.      B814:0000H (physical address B8140H)
  1497.      B81E:0000H (physical address B81E0H)
  1498.  
  1499.    A better way to accomplish the same addressing would be to keep a constant
  1500.    segment value and change the offset value:
  1501.  
  1502.      B800:0000H (physical address B8000H)
  1503.      B800:00A0H (physical address B80A0H)
  1504.      B800:0140H (physical address B8140H)
  1505.      B800:01E0H (physical address B81E0H)
  1506.  
  1507.    Although the result is the same on an 8086 and in real mode on an 80286,
  1508.    you'll find that the second method is much better suited to 80286
  1509.    protected mode, where each different segment selector designates a
  1510.    different segment descriptor.
  1511.  
  1512.  
  1513.  The 8086 Registers
  1514.  
  1515.    The 8086 was designed to execute instructions and perform arithmetic and
  1516.    logical operations as well as receive instructions and pass data to and
  1517.    from memory. To do this, it uses a variety of 16-bit registers.
  1518.  
  1519.    There are fourteen registers in all, each with a special use. Four
  1520.    scratch-pad registers are used by programs to temporarily hold the
  1521.    intermediate results and operands of arithmetic and logical operations.
  1522.    Four segment registers hold segment values. Five pointer and index
  1523.    registers hold the offsets that are used with the values in the segment
  1524.    registers to locate data in memory. Finally, one flags register contains
  1525.    nine 1-bit flags that are used to record 8086 status information and
  1526.    control 8086 operations. (See Figure 2-5.)
  1527.  
  1528.                                          Scratch-pad registers
  1529.  
  1530.                            7                      0 7                      0
  1531.                            ╓──┬──┬──┬──┬──┬──┬──┬──╥──┬──┬──┬──┬──┬──┬──┬──╖
  1532.    AX (accumulator)        ║          AH           ║          AL           ║
  1533.                            ╟──┼──┼──┼──┼──┼──┼──┼──╫──┼──┼──┼──┼──┼──┼──┼──╢
  1534.    BX (base)               ║          BH           ║          BL           ║
  1535.                            ╟──┼──┼──┼──┼──┼──┼──┼──╫──┼──┼──┼──┼──┼──┼──┼──╢
  1536.    CX (count)              ║          CH           ║          CL           ║
  1537.                            ╟──┼──┼──┼──┼──┼──┼──┼──╫──┼──┼──┼──┼──┼──┼──┼──╢
  1538.    DX (data)               ║          DH           ║          DL           ║
  1539.                            ╙──┴──┴──┴──┴──┴──┴──┴──╨──┴──┴──┴──┴──┴──┴──┴──╜
  1540.  
  1541.                                             Segment registers
  1542.  
  1543.                            15                                              0
  1544.                            ╓──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──╖
  1545.    CS (code segment)       ║                                               ║
  1546.                            ╟──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──╢
  1547.    DS (data segment)       ║                                               ║
  1548.                            ╟──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──╢
  1549.    SS (stack segment)      ║                                               ║
  1550.                            ╟──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──╢
  1551.    ES (extra segment)      ║                                               ║
  1552.                            ╙──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──╜
  1553.  
  1554.                                            Offset registers
  1555.  
  1556.                            15                                              0
  1557.                            ╓──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──╖
  1558.    IP (instruction pointer)║                                               ║
  1559.                            ╟──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──╢
  1560.    SP (stack pointer)      ║                                               ║
  1561.                            ╟──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──╢
  1562.    BP (base pointer)       ║                                               ║
  1563.                            ╟──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──╢
  1564.    SI (source index)       ║                                               ║
  1565.                            ╟──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──╢
  1566.    DI (destination index)  ║                                               ║
  1567.                            ╙──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──╜
  1568.  
  1569.                                             Flags register
  1570.  
  1571.                            15                                              0
  1572.                            ╓──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──╖
  1573.                     Flags  ║           │OF│DF│IF│TF│SF│ZF│  │AF│  │PF│  │CF║
  1574.                            ╙──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──╜
  1575.  
  1576.    Figure 2-5.  The 8086 registers and flags.
  1577.  
  1578.  The Scratch-Pad Registers
  1579.  
  1580.    When a computer is processing data, a great deal of the microprocessor's
  1581.    time is spent transferring data to and from memory. This access time can
  1582.    be greatly reduced by keeping frequently used operands and results inside
  1583.    the 8086. Four 16-bit registers, usually called the scratch-pad or data
  1584.    registers, are designed for this purpose.
  1585.  
  1586.    The scratch-pad registers are known as AX, BX, CX, and DX. Each of them
  1587.    can also be subdivided and separately used as two 8-bit registers. The
  1588.    high-order 8-bit registers are known as AH, BH, CH, and DH, and the low-
  1589.    order 8-bit registers are known as AL, BL, CL, and DL.
  1590.  
  1591.    The scratch-pad registers are used mostly as convenient temporary working
  1592.    areas, particularly for arithmetic operations. Addition and subtraction
  1593.    can be done in memory without using the registers, but the registers are
  1594.    faster.
  1595.  
  1596.    Although these registers are available for any kind of scratch-pad work,
  1597.    each also has some special uses:
  1598.  
  1599.    ■  The AX (accumulator) register is the main register used to perform
  1600.       arithmetic operations. (Although addition and subtraction can be
  1601.       performed in any of the scratch-pad or offset registers, multiplication
  1602.       and division must be done in AX or AL.)
  1603.  
  1604.    ■  The BX (base) register can be used to point to the beginning of a
  1605.       translation table in memory. It can also be used to hold the offset
  1606.       part of a segmented address.
  1607.  
  1608.    ■  The CX (count) register is used as a repetition counter for loop
  1609.       control and repeated data moves. For example, the LOOP instruction in
  1610.       assembly language uses CX to count the number of loop iterations.
  1611.  
  1612.    ■  The DX register is used to store data for general purposes, although
  1613.       it, too, has certain specialized functions. For example, DX contains
  1614.       the remainder of division operations performed in AX.
  1615.  
  1616.  The Segment Registers
  1617.  
  1618.    As we discussed earlier, the complete address of a memory location
  1619.    consists of a 16-bit segment value and a 16-bit offset within the segment.
  1620.    Four registers, called CS, DS, ES, and SS, are used to identify four
  1621.    specific segments of memory. Five offset registers, which we'll discuss
  1622.    shortly, can be used to store the relative offsets of the data within each
  1623.    of the four segments.
  1624.  
  1625.    Each segment register is used for a specific type of addressing:
  1626.  
  1627.    ■  The CS register identifies the code segment, which contains the program
  1628.       that is being executed.
  1629.  
  1630.    ■  The DS and ES registers identify data segments where data used in a
  1631.       program is stored.
  1632.  
  1633.    ■  The SS register identifies the stack segment. (See page 32 for more
  1634.       information about stacks.)
  1635.  
  1636.    Programs rarely use four separate segments to address four different 64 KB
  1637.    areas of memory. Instead, the four segments specified in CS, DS, ES, and
  1638.    SS usually refer to overlapping or identical areas in memory. In effect,
  1639.    the different segment registers identify areas of memory used for
  1640.    different purposes.
  1641.  
  1642.    For example, Figure 2-6 shows how the values in the segment registers
  1643.    correspond to the memory used in a hypothetical DOS program. The values in
  1644.    the segment registers are chosen to correspond to the start of each
  1645.    logically different area of memory, even though the 64 KB areas of memory
  1646.    identified by each segment overlap each other. (See Chapter 20 for more
  1647.    about segments and the memory layout of DOS programs.)
  1648.  
  1649.    All 8086 instructions that use memory have an implied use of a particular
  1650.    segment register for the operation being performed. For example, the MOV
  1651.    instruction, because it acts on data, uses the DS register. The JMP
  1652.    instruction, which affects the flow of a program, automatically uses the
  1653.    CS register.
  1654.  
  1655.    This means that you can address any 64 KB segment in memory by placing its
  1656.    paragraph address in the appropriate segment register. For example, to
  1657.    access data in the video buffer used by IBM's Color Graphics Adapter, you
  1658.    place the paragraph address of the start of the buffer in a segment
  1659.    register and then use the MOV instruction to transfer data to or from the
  1660.    buffer.
  1661.  
  1662.                ┌─────────────────────┐        ───┐
  1663.       SS=2919H │       Stack         │ 29190H     ├─ 2 KB
  1664.                ├─────────────────────┤        ───┤
  1665.                │                     │            │
  1666.       DS=2419H │    Program data     │            ├─ 20KB
  1667.                │                     │ 24190H     │
  1668.                ├─────────────────────┤        ───┤
  1669.                │                     │            │
  1670.       CS=2019H │   Executable code   │            ├─ 16 KB
  1671.                │                     │ 20190H     │
  1672.                └─────────────────────┘        ───┘
  1673.    Segment registers              Physical addresses
  1674.  
  1675.    Figure 2-6.  Segment usage in a typical DOS program. Each segment register
  1676.    contains the starting paragraph of a different area of memory.
  1677.  
  1678.    mov ax,0B800h                   ; move the segment value into DS
  1679.    mov ds,ax
  1680.    mov al,[0000]                   ; copy the byte at B800:0000
  1681.                                    ; into AL
  1682.  
  1683.    In interpreted BASIC you can use this method with the DEF SEG statement:
  1684.  
  1685.    DEF SEG = &HB800                ' move the segment value into DS
  1686.    X = PEEK(0000)                  ' copy the byte at B800:0000 into X
  1687.  
  1688.  The Offset Registers
  1689.  
  1690.    Five offset registers are used with the segment registers to contain
  1691.    segmented addresses. One register, called the instruction pointer (IP),
  1692.    contains the offset of the current instruction in the code segment; two
  1693.    registers, called the stack registers, are intimately tied to the stack;
  1694.    and the remaining two registers, called the index registers, are used to
  1695.    address strings of data.
  1696.  
  1697.    The instruction pointer (IP), also called the program counter (PC),
  1698.    contains the offset within the code segment where the current program is
  1699.    executing. It is used with the CS register to track the location of the
  1700.    next instruction to be executed.
  1701.  
  1702.    Programs do not have direct access to the IP register, but a number of
  1703.    instructions, such as JMP and CALL, change the IP value implicitly.
  1704.  
  1705.    The stack registers, called the stack pointer (SP) and the base pointer
  1706.    (BP), provide offsets into the stack segment. SP gives the location of the
  1707.    current top of the stack. Programs rarely change the value in SP directly.
  1708.    Instead, they rely on PUSH and POP instructions to update SP implicitly.
  1709.    BP is the register generally used to access the stack segment directly.
  1710.    You'll see BP used quite often in the assembly-language examples that
  1711.    appear in Chapters 8 through 20.
  1712.  
  1713.    The index registers, called the source index (SI) and the destination
  1714.    index (DI), can be used for general-purpose addressing of data. Also, all
  1715.    string move and comparison instructions use SI and DI to address data
  1716.    strings.
  1717.  
  1718.  The Flags Register
  1719.  
  1720.    The fourteenth and last register, called the flags register, is really a
  1721.    collection of individual status and control bits called flags. The flags
  1722.    are maintained in a register, so they can be either saved and restored as
  1723.    a coordinated set or inspected as ordinary data. Normally, however, the
  1724.    flags are set and tested as independent items──not as a set.
  1725.  
  1726.    There are nine 1-bit flags in the 8086's 16-bit flags register, leaving 7
  1727.    bits unused. (The 80286 and 80386 use some of the unused flags to support
  1728.    protected-mode operation.) The flags can be logically divided into two
  1729.    groups: six status flags, which record processor status information
  1730.    (usually indicating what happened with a comparison or arithmetic
  1731.    operation), and three control flags, which direct some of the 8086
  1732.    instructions. Be prepared to see a variety of notations for the flags,
  1733.    including distinct names for whether they are set (1) or clear (0). The
  1734.    terms used in Figures 2-7 and 2-8 are the most common.
  1735.  
  1736.    ──────────────────────────────────────────────────────────────────────────
  1737.    The Stack
  1738.      The stack is a built-in feature of the 8086. It provides programs with a
  1739.      place to store and keep track of work in progress. The most important
  1740.      use of the stack is to keep a record of where subroutines were invoked
  1741.      from and what parameters were passed to them. The stack can also be used
  1742.      for temporary working storage, although this is less fundamental and
  1743.      less common.
  1744.  
  1745.      The stack gets its name from an analogy to a spring-loaded stack of
  1746.      plates in a cafeteria: New data is "pushed" onto the top of the stack
  1747.      and old data is "popped" off. A stack always operates in
  1748.      last-in-first-out (LIFO) order. This means that when the stack is used
  1749.      to keep track of where to return to a program, the most recent calling
  1750.      program is returned to first. This way, a stack maintains the orderly
  1751.      workings of programs, subroutines, and interrupt handlers, no matter how
  1752.      complex their operation.
  1753.  
  1754.      A stack is used from the bottom (highest address) to the top (lowest
  1755.      address) so that when data is pushed onto the top of the stack, it is
  1756.      stored at the memory addresses just below the current top of the stack.
  1757.      The stack grows downward so that as data is added, the location of the
  1758.      top of the stack moves to lower and lower addresses, decreasing the
  1759.      value of SP each time. You need to keep this in mind when you access the
  1760.      stack, which you are likely to do in assembly-language interface
  1761.      routines.
  1762.  
  1763.      Any part of any program can create a new stack space at any time, but
  1764.      this is not usually done. Normally, when a program is run, a single
  1765.      stack is created for it and used throughout the operation of the
  1766.      program.
  1767.  
  1768.      There is no simple way to estimate the size of stack that a program
  1769.      might need, and the 8086's design does not provide any automatic way of
  1770.      detecting when stack space is in short supply or exhausted. This can
  1771.      make programmers nervous about the amount of space that should be set
  1772.      aside for a stack. A conservative estimate of how much stack space to
  1773.      maintain is about 2 KB (2048 bytes), the default amount allocated by
  1774.      many high-level language compilers.
  1775.  
  1776.                                               ┌──────┐─── Bottom of stack
  1777.                                         :1008 │ 5E00 │
  1778.            ┌──────┐─── Bottom of stack       ├──────┤
  1779.      :1008 │ 5E00 │                     :1006 │ 4D00 │
  1780.            ├──────┤                           ├──────┤
  1781.      :1006 │ 4D00 │                     :1004 │ 3C00 │─── Old top of stack
  1782.            ├──────┤                           ├──────┤
  1783.      :1004 │ 3C00 │─── Top of stack    :1002 │ 2B00 │─── Top of stack
  1784.            ├──────┤     (SP=1004)             ├──────┤     (SP=1002)
  1785.      :1002 │      │                     :1000 │      │
  1786.            ├──────┤                           └────┘
  1787.      :1000 │      │                             ║  ║
  1788.            └──────┘                             PUSH
  1789.      a. Stack before a PUSH             b. Stack after a PUSH
  1790.      ──────────────────────             ─────────────────────
  1791.  
  1792.                                ┌──────┐─── Bottom of stack
  1793.                          :1008 │ 5E00 │
  1794.                                ├──────┤
  1795.                          :1006 │ 4D00 │
  1796.                                ├──────┤
  1797.                          :1004 │ 3C00 │─── Top of stack
  1798.                                ├──────┤     (SP=1004)
  1799.                          :1002 │      │
  1800.                                ├──────┤
  1801.                          :1000 │      │
  1802.                                └─║──║─┘
  1803.                                    
  1804.                                  POP
  1805.                          c. Stack after a POP
  1806.                          ────────────────────
  1807.  
  1808.    ──────────────────────────────────────────────────────────────────────────
  1809.  
  1810.    Code        Name                     Use
  1811.    ──────────────────────────────────────────────────────────────────────────
  1812.    CF          Carry flag               Indicates an arithmetic carry
  1813.    OF          Overflow flag            Indicates signed arithmetic overflow
  1814.    ZF          Zero flag                Indicates zero result, or equal
  1815.                                         comparison
  1816.    SF          Sign flag                Indicates negative result/comparison
  1817.    PF          Parity flag              Indicates even number of 1 bits
  1818.    AF          Auxiliary carry flag     Indicates adjustment needed in
  1819.                                         binary-coded decimal (BCD) arithmetic
  1820.                                         operations
  1821.    ──────────────────────────────────────────────────────────────────────────
  1822.  
  1823.    Figure 2-7.  The six status flags in the 8086's flags register.
  1824.  
  1825.    Code        Name                     Use
  1826.    ──────────────────────────────────────────────────────────────────────────
  1827.    DF          Direction flag           Controls increment direction in
  1828.                                         string operations (CMPS, LODS, MOVS,
  1829.                                         SCAS, STOS)
  1830.    IF          Interrupt flag           Controls whether interrupts are
  1831.                                         enabled
  1832.    TF          Trap flag                Controls single-step operation (used
  1833.                                         by DEBUG) by generating an interrupt
  1834.                                         at the end of every instruction
  1835.    ──────────────────────────────────────────────────────────────────────────
  1836.  
  1837.    Figure 2-8.  The three control flags in the 8086's flags register.
  1838.  
  1839.  Addressing Memory Through Registers
  1840.  
  1841.    We've seen that memory is always addressed by a combination of a segment
  1842.    value and a relative offset. The segment value always comes from one of
  1843.    the four segment registers.
  1844.  
  1845.    In contrast, the relative offset can be specified in many different ways.
  1846.    (See Figure 2-9.) For each machine instruction that accesses memory, the
  1847.    8086 computes an effective address by combining one, two, or three of the
  1848.    following:
  1849.  
  1850.    ■  The value in BX or BP
  1851.  
  1852.    ■  The value in SI or DI
  1853.  
  1854.    ■  A relative-offset value, called a displacement, that is part of the
  1855.       instruction itself
  1856.  
  1857. ╓┌─┌──────────────────┌───────────────────────────┌──────────────────┌───────
  1858.    Name               Effective Address           Example            Comments
  1859.    ───────────────────────────────────────────────────────────────────────────
  1860.    Immediate          Value "addressed" is part   mov ax,1234h       Stores 12
  1861.                       of the 8086 instruction
  1862.  
  1863.    Direct             Specified as part of the    mov ax,[1234h]     Copies th
  1864.                       8086 instruction                               into AX.
  1865.                                                                      register
  1866.  
  1867.    Register indirect  Contained in BX, SI, DI, or mov ax,[bx]        Copies th
  1868.                       BP                                             offset co
  1869.                                                                      AX. The d
  1870.                                                                      register
  1871.    Name               Effective Address           Example            Comments
  1872.    ───────────────────────────────────────────────────────────────────────────
  1873.                                                                     register
  1874.                                                                      [DI] is D
  1875.                                                                      default i
  1876.  
  1877.    Based              The sum of a displacement   mov ax,[bx+2]      Copies th
  1878.                       (part of the instruction)   or mov ax,2[bx]    past the
  1879.                       and the value in BX or BP                      BX into A
  1880.                                                                      segment r
  1881.                                                                      DS; for [
  1882.                                                                      SS.
  1883.  
  1884.    Indexed            The sum of a displacement   mov ax,[si+2]      Copies th
  1885.                       and the value in SI or DI   or mov ax,2[si]    past the
  1886.                                                                      SI into A
  1887.                                                                      segment r
  1888.    Based indexed      The sum of a displacement,  mov ax,[bp+si+2]   The offse
  1889.                       the value in SI or DI, and  or mov ax,2[bp+si] values in
  1890.                       the value in BX or BP       or                 When BX i
  1891.                                                   mov ax,2[bp][si]   segment r
  1892.    Name               Effective Address           Example            Comments
  1893.    ───────────────────────────────────────────────────────────────────────────
  1894.                                                  mov ax,2[bp][si]   segment r
  1895.                                                                      BP is use
  1896.                                                                      SS.
  1897.  
  1898.    String addressing  Source string: register     movsb              Copies th
  1899.                       indirect using SI                              memory at
  1900.                       Destination string:                            ES:[DI].
  1901.                       register indirect using DI
  1902.    ───────────────────────────────────────────────────────────────────────────
  1903.  
  1904.  
  1905.    Figure 2-9.  8086 Addressing Modes. In assembly language, some
  1906.    instructions can be specified in several different ways.
  1907.  
  1908.    Each of the various ways of forming an effective address has its uses. You
  1909.    can use the Immediate and Direct methods when you know the offset of a
  1910.    particular memory location in advance. You must use one of the remaining
  1911.    methods when you can't tell what an address will be until your program
  1912.    executes. In the chapters ahead, you'll see examples of most of the
  1913.    different 8086 addressing modes.
  1914.  
  1915.    The notation used in specifying 8086 addresses is straightforward.
  1916.    Brackets, [ ], are used to indicate that the enclosed item specifies a
  1917.    relative offset. This is a key element of memory addressing: Without
  1918.    brackets, the actual value stored in the register is used in whatever
  1919.    operation is specified.
  1920.  
  1921.  Rules for Using Registers
  1922.  
  1923.    It is important to know that various rules apply to the use of registers,
  1924.    and it is essential to be aware of these rules when writing assembly-
  1925.    language interface routines. Because the rules and conventions of usage
  1926.    vary by circumstance and by programming language, exact guidelines are not
  1927.    always available, but the general rules that follow will apply in most
  1928.    cases. (You will find additional guidance, and working models to copy, in
  1929.    the examples in Chapters 8 through 20.) Keep in mind, though, that the
  1930.    following rules are general, not absolute.
  1931.  
  1932.    Probably the most useful rule for using the registers is simply to use
  1933.    them for what they are designed for. The idea that each of the 8086
  1934.    registers has certain special uses may seem somewhat quirky, particularly
  1935.    to a programmer who is accustomed to working with a CPU that has a less
  1936.    specialized set of registers (such as the 68000, for example). On the
  1937.    8086, using the registers for their natural functions leads to cleaner,
  1938.    more efficient source code and ultimately to more reliable programs.
  1939.  
  1940.    For example, the segment registers are designed to contain segment values,
  1941.    so don't use them for anything else. (In 80286 protected mode you can't
  1942.    use them for anything else anyway without generating an error condition.)
  1943.    The BP register is intended for stack addressing; if you use it for
  1944.    anything else, you'll have to do some fancy footwork when you need to
  1945.    address values in the stack segment.
  1946.  
  1947.    Particular rules apply to the four segment registers (CS, DS, ES, and SS).
  1948.    The CS register should be changed only through intersegment jumps and
  1949.    subroutine calls.
  1950.  
  1951.    Most programmers use the DS register to point to a default data segment
  1952.    that contains the data most frequently used in a program. This means that
  1953.    the value in the DS register is usually initialized at the beginning of a
  1954.    program and then left alone. Should it be necessary to use DS to address a
  1955.    different segment, its original value is saved, the new segment is
  1956.    accessed, and then the original value is restored. In contrast, most
  1957.    people use the ES register as needed to access arbitrary segments in
  1958.    memory.
  1959.  
  1960.    The stack segment (SS) and stack pointer (SP) registers should usually be
  1961.    updated implicitly, either by PUSH and POP instructions or by CALL and RET
  1962.    instructions that save subroutine return addresses on the stack. When DOS
  1963.    loads a program into memory to be executed, it initializes SS and SP to
  1964.    usable values. In .COM programs, SS:SP points to the end of the program's
  1965.    default segment; in .EXE programs, SS:SP is determined explicitly by the
  1966.    size and location of the program's stack segment. In either case, it's
  1967.    rare that you need to change SS or SP explicitly.
  1968.  
  1969.    If you need to discard a number of values from the stack or reserve
  1970.    temporary storage space on top of the stack, you can increment or
  1971.    decrement SP directly:
  1972.  
  1973.    add sp,8                        ; discard four words (8 bytes)
  1974.                                    ; from stack
  1975.    sub sp,6                        ; add three empty words (6 bytes)
  1976.                                    ; to top of stack
  1977.  
  1978.    If you need to move the stack to a different location in memory, you must
  1979.    generally update both SS and SP at the same time:
  1980.  
  1981.    cli                             ; disable interrupts
  1982.    mov ss,NewStackSeg              ; update SS from a memory variable
  1983.    mov sp,NewStackPtr              ; update SP from a memory variable
  1984.    sti                             ; re-enable interrupts
  1985.  
  1986.    Be careful when you change SS and SP explicitly. If you modify SS but fail
  1987.    to update SP, SS will be specifying a new stack segment while SP will be
  1988.    pointing somewhere inside another stack segment──and that's asking for
  1989.    trouble the next time you use the stack.
  1990.  
  1991.    It's hard to be explicit about the use of the other registers. In general,
  1992.    most programmers try to minimize memory accesses by keeping the
  1993.    intermediate results of lengthy computations in registers. This is because
  1994.    it takes longer to perform a computation on a value stored in memory than
  1995.    on a value stored in a register. Of course, the 8086 has only so many
  1996.    registers to work with, so you may find yourself running out of registers
  1997.    before you run out of variables.
  1998.  
  1999.  
  2000.  How the 8086 Uses I/O Ports
  2001.  
  2002.    The 8086-family microprocessors communicate with and control many parts of
  2003.    the computer through the use of input and output (I/O) ports. The I/O
  2004.    ports are doorways through which information passes as it travels to or
  2005.    from an I/O device, such as a keyboard or a printer. Most of the support
  2006.    chips we described in Chapter 1 are accessed through I/O ports; in fact,
  2007.    each chip may use several port addresses for different purposes.
  2008.  
  2009.    Each port is identified by a 16-bit port number, which can range from 00H
  2010.    through FFFFH (65,535). The CPU identifies a particular port by the port's
  2011.    number.
  2012.  
  2013.    As it does when accessing memory, the CPU uses the data and address buses
  2014.    as conduits for communication with the ports. To access a port, the CPU
  2015.    first sends a signal on the system bus to notify all I/O devices that the
  2016.    address on the bus is that of a port. The CPU then sends the port address.
  2017.    The device with the matching port address responds.
  2018.  
  2019.    The port number addresses a memory location that is associated with an I/O
  2020.    device but is not part of main memory. In other words, an I/O port number
  2021.    is not the same as a memory address. For example, I/O port 3D8H has
  2022.    nothing to do with memory address 003D8H. To access an I/O port, you don't
  2023.    use data-transfer instructions like MOV and STOS. Instead, you use the
  2024.    instructions IN and OUT, which are reserved for I/O port access.
  2025.  
  2026.    ──────────────────────────────────────────────────────────────────────────
  2027.    NOTE:
  2028.      Many high-level programming languages provide functions that access I/O
  2029.      ports. The BASIC functions INP and OUT, and the C functions inp and
  2030.      outp, are typical examples.
  2031.    ──────────────────────────────────────────────────────────────────────────
  2032.  
  2033.    The uses of specific I/O ports are determined by the hardware designers.
  2034.    Programs that make use of I/O ports need to be aware of the port numbers,
  2035.    as well as their use and meaning. Port number assignments differ slightly
  2036.    among the PC family members, but, in general, IBM has reserved the same
  2037.    ranges of I/O port numbers for the same input/output devices in all PCs
  2038.    and PS/2s. (See Figure 2-10.) For details on how each I/O port is used,
  2039.    see the descriptions of the various input/output devices in the IBM
  2040.    technical reference manuals.
  2041.  
  2042. ╓┌─┌──────────────────────────────────────────────┌───────────────┌──────────
  2043.    Description                                    I/O Port        Comment
  2044.                                                   Numbers
  2045.    ───────────────────────────────────────────────────────────────────────────
  2046.    Programmable Interrupt Controller (master)     20H─3FH
  2047.  
  2048.    System timer                                   40H─5FH
  2049.  
  2050.    Keyboard controller                            60H─6FH         On PS/2 Mode
  2051.                                                                   are reserved
  2052.                                                                   control and
  2053.  
  2054.    System control port B                          61H             PS/2 models
  2055.  
  2056.    Real-time clock, NMI mask                      70H─7FH         On PC, PC/XT
  2057.                                                                   30, NMI mask
  2058.  
  2059.    System control port A                          92H             PS/2 models
  2060.    Description                                    I/O Port        Comment
  2061.                                                   Numbers
  2062.    ───────────────────────────────────────────────────────────────────────────
  2063.   System control port A                          92H             PS/2 models
  2064.  
  2065.    Programmable Interrupt Controller (slave)      A0H─BFH         On PS/2 Mode
  2066.  
  2067.    Real-time clock                                B0H─BFH,        PS/2 Model 3
  2068.                                                   E0H─EFH
  2069.  
  2070.    Clear math coprocessor busy                    F0H
  2071.  
  2072.    Reset math coprocessor                         F1H
  2073.  
  2074.    Math coprocessor                               F8H─FFH
  2075.  
  2076.    Fixed-disk controller                          1F0H─1F8H
  2077.  
  2078.    Game control adapter                           200H─207H
  2079.  
  2080.    Parallel printer 3                             278H─27BH
  2081.    Description                                    I/O Port        Comment
  2082.                                                   Numbers
  2083.    ───────────────────────────────────────────────────────────────────────────
  2084.   Parallel printer 3                             278H─27BH
  2085.  
  2086.    Serial communications 2                        2F8H─2FFH
  2087.  
  2088.    Fixed-disk controller                          320H─32FH       PC/XT and PS
  2089.  
  2090.    PC network                                     360H─363H,
  2091.                                                   368H─36BH
  2092.  
  2093.    Parallel printer 2                             378H─37BH
  2094.  
  2095.    Monochrome Display Adapter                     3B0H─3BBH       Also used by
  2096.                                                                   monochrome v
  2097.  
  2098.    Parallel printer 1                             3BCH─3BFH
  2099.  
  2100.    Enhanced Graphics Adapter (EGA),               3C0H─3CFH
  2101.    Video Graphics Array (VGA)
  2102.    Description                                    I/O Port        Comment
  2103.                                                   Numbers
  2104.    ───────────────────────────────────────────────────────────────────────────
  2105.   Video Graphics Array (VGA)
  2106.  
  2107.    Color Graphics Adapter (CGA),                  3D0H─3DFH       Also used by
  2108.    Multi-Color Graphics Array (MCGA)                              color video
  2109.  
  2110.    Diskette controller                            3F0H─3F7H
  2111.  
  2112.    Serial communications 1                        3F8H─3FFH
  2113.    ───────────────────────────────────────────────────────────────────────────
  2114.  
  2115.  
  2116.    Figure 2-10.  PC and PS/2 input/output port assignments. This table lists
  2117.    the most frequently used I/O ports. For a complete list, see the IBM
  2118.    Technical Reference manuals.
  2119.  
  2120.  
  2121.  How the 8086 Uses Interrupts
  2122.  
  2123.    An interrupt is an indication to the microprocessor that its immediate
  2124.    attention is needed. The 8086-family microprocessors can respond to
  2125.    interrupts from either hardware or software. A hardware device can
  2126.    generate an interrupt signal that is processed by the programmable
  2127.    interrupt controller (PIC) and passed to the microprocessor; in software,
  2128.    the INT instruction generates an interrupt. In both cases, the
  2129.    microprocessor stops processing and executes a memory-resident subroutine
  2130.    called an interrupt handler. After the interrupt handler has performed its
  2131.    task, the microprocessor resumes processing at the point the interrupt
  2132.    occurred.
  2133.  
  2134.    The 8086 supports 256 different interrupts, each identified by a number
  2135.    between 00H and FFH (decimal 255). The segmented addresses of the 256
  2136.    interrupt handlers are stored in an interrupt vector table that starts at
  2137.    0000:0000H (that is, at the very beginning of available memory). Each
  2138.    interrupt vector is 4 bytes in size, so you can locate the address of any
  2139.    interrupt handler by multiplying the interrupt number by 4. You can also
  2140.    replace an existing interrupt handler with a new one by storing the new
  2141.    handler's segmented address in the appropriate interrupt vector.
  2142.  
  2143.  Software Interrupts
  2144.  
  2145.    Probably the most familiar type of interrupts are generated by the INT
  2146.    instruction. Consider what happens when the CPU executes the following
  2147.    instruction:
  2148.  
  2149.    INT 12H
  2150.  
  2151.    The CPU pushes the current contents of the flags register, the CS (code
  2152.    segment) register, and the IP (instruction pointer) register onto the
  2153.    stack. Then it transfers control to the interrupt handler corresponding to
  2154.    interrupt number 12H, using the segmented address stored at 0000:0048H.
  2155.    The CPU then executes the interrupt 12H handler, which responds
  2156.    appropriately to interrupt 12H. The interrupt handler terminates with an
  2157.    IRET instruction that pops CS:IP and the flags back into the registers,
  2158.    thus transferring control back to the interrupted program.
  2159.  
  2160.  Hardware Interrupts
  2161.  
  2162.    The microprocessor responds to a hardware interrupt in much the same way
  2163.    it responds to a software interrupt: by transferring control to an
  2164.    interrupt handler. The important difference lies in the way the interrupt
  2165.    is signalled.
  2166.  
  2167.    Devices such as the system timer, the hard disk, the keyboard, and the
  2168.    serial communications ports can generate interrupt signals on a set of
  2169.    reserved interrupt request (IRQ) lines. These lines are monitored by the
  2170.    PIC circuit, which assigns interrupt numbers to them. When a particular
  2171.    hardware interrupt occurs, the PIC places the corresponding interrupt
  2172.    number on the system data bus where the microprocessor can find it.
  2173.  
  2174.    The PIC also assigns priorities to the various interrupt requests. For
  2175.    example, the highest-priority PIC interrupt in all PCs and PS/2s is the
  2176.    timer-tick interrupt, which is signalled on interrupt request line 0
  2177.    (IRQ0) and is assigned interrupt 08H by the PIC. When a system timer
  2178.    generates a timer- tick interrupt, it does so by signalling on IRQ0; the
  2179.    PIC responds by signalling the CPU to execute interrupt 08H. If a
  2180.    lower-priority hardware interrupt request occurs while the timer-tick
  2181.    interrupt is being processed, the PIC delays the lower-priority interrupt
  2182.    until the timer interrupt handler signals that it has finished its
  2183.    processing.
  2184.  
  2185.    When you coldboot the computer, the system start-up routines assign
  2186.    interrupt numbers and priorities to the hardware interrupts by
  2187.    initializing the PIC. In 8088- and 8086-based machines (PCs, PC/XTs, PS/2
  2188.    models 25 and 30), interrupt numbers 08H through 0FH are assigned to
  2189.    interrupt request levels 0 through 7 (IRQ0 through IRQ7). In PC/ATs and
  2190.    PS/2 models 50, 60, and 80, an additional eight interrupt lines (IRQ8
  2191.    through IRQ15) are assigned interrupt numbers 70H through 77H.
  2192.  
  2193.    One hardware interrupt bypasses the PIC altogether. This is the
  2194.    non-maskable interrupt (NMI), which is assigned interrupt number 02H in
  2195.    the 8086 family. The NMI is used by devices that require absolute,
  2196.    "now-or-never" priority over all other CPU functions. In particular, when
  2197.    a hardware memory error occurs, the computer's RAM subsystem generates an
  2198.    NMI. This causes the CPU to pass control to an interrupt 02H handler; the
  2199.    default handler in the PC family resides in ROM and issues the "PARITY
  2200.    CHECK" message you see when a memory error occurs.
  2201.  
  2202.    When you debug a program on any member of the PC family, remember that
  2203.    hardware interrupts are occurring all the time. For example, the system
  2204.    timer-tick interrupt (interrupt 08H) occurs roughly 18.2 times per second.
  2205.    The keyboard and disk-drive controllers also generate interrupts. Each
  2206.    time these hardware interrupts occur, the 8086 uses the current stack to
  2207.    save CS:IP and the flags register. If your stack is too small, or if you
  2208.    are manipulating SS and SP when a hardware interrupt occurs, the 8086 may
  2209.    damage valuable data when it saves CS:IP and the flags.
  2210.  
  2211.    If you look back at our example of updating SS and SP on page 36, you'll
  2212.    see that we explicitly disable hardware interrupts by executing the CLI
  2213.    instruction prior to updating SS. This prevents a hardware interrupt from
  2214.    occurring between the two MOV instructions while SS:SP is pointing
  2215.    nowhere. (Actually, this is a problem only in very early releases of the
  2216.    8088; the chip was later redesigned to prevent this problem by disabling
  2217.    interrupts during the instruction that follows a data move into SS.)
  2218.  
  2219.    We'll talk in more detail about how PCs and PS/2s use interrupts in
  2220.    Chapters 3 and 8.
  2221.  
  2222.  
  2223.  
  2224.  ────────────────────────────────────────────────────────────────────────────
  2225.  Chapter 3  The ROM Software
  2226.  
  2227.    The Start-Up ROM
  2228.  
  2229.    The ROM BIOS
  2230.      Interrupt Vectors
  2231.      Key Low-Memory Addresses
  2232.      The ROM Version and Machine-ID Markers
  2233.  
  2234.    The ROM BASIC
  2235.  
  2236.    The ROM Extensions
  2237.  
  2238.    Comments
  2239.  
  2240.    It takes software to make a computer go. And getting a computer going and
  2241.    keeping it going is much easier if some of that software is permanently
  2242.    built into the computer. That's what the ROM programs are all about. ROM
  2243.    stands for read-only memory──memory permanently recorded in the circuitry
  2244.    of the computer's ROM chips, that can't be changed, erased, or lost.
  2245.  
  2246.    PCs and PS/2s come with a substantial amount of ROM that contains the
  2247.    programs and data needed to start and operate the computer and its
  2248.    peripheral devices. The advantage of having a computer's fundamental
  2249.    programs stored in ROM is that they are right there──built into the
  2250.    computer──and there is no need to load them into memory from disk the way
  2251.    that DOS must be loaded. Because they are permanent, the ROM programs are
  2252.    very often the foundation upon which other programs (including DOS) are
  2253.    built.
  2254.  
  2255.    There are four elements to the ROM in IBM's PC family: the start-up
  2256.    routines, which do the work of getting the computer started; the ROM
  2257.    BIOS──an acronym for Basic Input/Output System──which is a collection of
  2258.    machine-language routines that provide support services for the continuing
  2259.    operation of the computer; the ROM BASIC, which provides the core of the
  2260.    BASIC programming language; and the ROM extensions, which are programs
  2261.    that are added to the main ROM when certain optional equipment is added to
  2262.    the computer. We'll be examining each of these four major elements
  2263.    throughout the rest of this chapter.
  2264.  
  2265.    The ROM programs occupy addresses F000:0000H through F000:FFFFH in the
  2266.    PC/XT/AT family and the PS/2 models 25 and 30, and E000:0000H through
  2267.    F000:FFFFH in the other PS/2s. However, the routines themselves are not
  2268.    located at any specific addresses in ROM as they are in other computers.
  2269.    The address of a particular ROM routine varies among the different members
  2270.    of the PC/XT/AT and PS/2 families.
  2271.  
  2272.    Although the exact addresses of the ROM routines can vary, IBM provides a
  2273.    consistent interface to the ROM software by using interrupts. Later in
  2274.    this book we'll show you exactly how to use interrupts to execute the ROM
  2275.    routines.
  2276.  
  2277.  
  2278.  The Start-Up ROM
  2279.  
  2280.    The first job the ROM programs have is to supervise the start-up of the
  2281.    computer. Unlike other aspects of the ROM, the start-up routines have
  2282.    little to do with programming the PC family──but it is still worthwhile to
  2283.    understand what they do.
  2284.  
  2285.    The start-up routines perform several tasks:
  2286.  
  2287.    ■  They run a quick reliability test of the computer (and the ROM
  2288.       programs) to ensure everything is in working order.
  2289.  
  2290.    ■  They initialize the chips and the standard equipment attached to the
  2291.       computer.
  2292.  
  2293.    ■  They set up the interrupt-vector table.
  2294.  
  2295.    ■  They check to see what optional equipment is attached.
  2296.  
  2297.    ■  They load the operating system from disk.
  2298.  
  2299.    The following paragraphs discuss these tasks in greater detail.
  2300.  
  2301.    The reliability test, part of a process known as the Power On Self Test
  2302.    (POST), is an important first step in making sure the computer is ready.
  2303.    All POST routines are quite brief except for the memory tests, which can
  2304.    be annoyingly lengthy in computers that contain a large amount of memory.
  2305.  
  2306.    The initialization process is slightly more complex. One routine sets the
  2307.    default values for interrupt vectors. These default values either point to
  2308.    the standard interrupt handlers located inside the ROM BIOS, or they point
  2309.    to do-nothing routines in the ROM BIOS that may later be superseded by the
  2310.    operating system or by your own interrupt handlers. Another initialization
  2311.    routine determines what equipment is attached to the computer and then
  2312.    places a record of it at standard locations in low memory. (We'll be
  2313.    discussing this equipment list in more detail later in the chapter.) How
  2314.    this information is acquired varies from model to model──for example, in
  2315.    the PC it is taken mostly from the settings of two banks of switches
  2316.    located on the computer's system board; in the PC/AT and the PS/2s, the
  2317.    ROM BIOS reads configuration information from a special nonvolatile memory
  2318.    area whose contents are initialized by special setup programs supplied by
  2319.    IBM. The POST routines learn about the computer's hardware by a logical
  2320.    inspection and test. In effect, the initialization program shouts to each
  2321.    possible option, "Are you there?", and listens for a response.
  2322.  
  2323.    No matter how it is acquired, the status information is recorded and
  2324.    stored in the same way for every model so that your programs can examine
  2325.    it. The initialization routines also check for new equipment and
  2326.    extensions to ROM. If they find any, they momentarily turn control over to
  2327.    the ROM extensions so that they can initialize themselves. The
  2328.    initialization routines then continue executing the remaining start-up
  2329.    routines (more on this later in the chapter).
  2330.  
  2331.    The final part of the start-up procedure, after the POST tests, the
  2332.    initialization process, and the incorporation of ROM extensions, is called
  2333.    the bootstrap loader. It's a short routine that loads a program from disk.
  2334.    In essence, the ROM bootstrap loader attempts to read a disk boot program
  2335.    from a disk. If the boot program is successfully read into memory, the ROM
  2336.    loader passes control of the computer to it. The disk boot program is
  2337.    responsible for loading another, larger disk program, which is usually a
  2338.    disk operating system such as DOS, but can be a self-contained and
  2339.    self-loading program, such as Microsoft Flight Simulator. If the ROM
  2340.    bootstrap loader cannot read a disk's boot program, it either activates
  2341.    the built-in ROM BASIC or displays an error message if the disk boot
  2342.    program contains an error. As soon as either of these two events occurs,
  2343.    the system start-up procedure is finished and the other programs take
  2344.    over.
  2345.  
  2346.  
  2347.  The ROM BIOS
  2348.  
  2349.    The ROM BIOS is the part of ROM that is in active use whenever the
  2350.    computer is at work. The role of the ROM BIOS is to provide the
  2351.    fundamental services that are needed for the operation of the computer.
  2352.    For the most part, the ROM BIOS controls the computer's peripheral
  2353.    devices, such as the display screen, keyboard, and disk drives. When we
  2354.    use the term BIOS in its narrowest sense, we are referring to the device
  2355.    control programs──the programs that translate a simple command, such as
  2356.    read-something-from-the-disk, into all the steps needed to actually
  2357.    perform the command, including error detection and correction. In the
  2358.    broadest sense, the BIOS includes not only routines needed to control the
  2359.    PC's devices, but also routines that contain information or perform tasks
  2360.    that are fundamental to other aspects of the computer's operation, such as
  2361.    keeping track of the time of day.
  2362.  
  2363.    Conceptually, the ROM BIOS programs lie between programs that are
  2364.    executing in RAM (including DOS) and the hardware. In effect, this means
  2365.    that the BIOS works in two directions in a two-sided process. One side
  2366.    receives requests from programs to perform the standard ROM BIOS
  2367.    input/output services. A program invokes these services with a combination
  2368.    of an interrupt number (which indicates the subject of the service
  2369.    request, such as printer services) and a service number (which indicates
  2370.    the specific service to be performed). The other side of the ROM BIOS
  2371.    communicates with the computer's hardware devices (display screen, disk
  2372.    drives, and so on), using whatever detailed command codes each device
  2373.    requires. This side of the ROM BIOS also handles any hardware interrupts
  2374.    that a device generates to get attention. For example, whenever you press
  2375.    a key, the keyboard generates an interrupt to let the ROM BIOS know.
  2376.  
  2377.    Of all the ROM software, the BIOS services are probably the most
  2378.    interesting and useful to programmers──as a matter of fact, we have
  2379.    devoted six chapters to the BIOS services in Chapters 8 through 13. Since
  2380.    we deal with them so thoroughly later on, we'll skip any specific
  2381.    discussion of what the BIOS services do and instead focus on how the BIOS
  2382.    as a whole keeps track of the computer's input and output processes.
  2383.  
  2384.  Interrupt Vectors
  2385.  
  2386.    The IBM PC family, like all computers based on the Intel 8086 family of
  2387.    microprocessors, is controlled largely through the use of interrupts,
  2388.    which can be generated by hardware or software. The BIOS service routines
  2389.    are no exception; each is assigned an interrupt number that you must call
  2390.    when you want to use the service.
  2391.  
  2392.    When an interrupt occurs, control of the computer is turned over to an
  2393.    interrupt-handling subroutine that is often stored in the system's ROM (a
  2394.    BIOS service routine is nothing more than an interrupt handler). The
  2395.    interrupt handler is called by loading its segment and offset addresses
  2396.    into registers that control program flow: the CS (code segment) register
  2397.    and the IP (instruction pointer) register──together known as the CS:IP
  2398.    register pair. Segment addresses that locate interrupt handlers are called
  2399.    interrupt vectors.
  2400.  
  2401.    During the system start-up process, the BIOS sets the interrupt vectors to
  2402.    point to the interrupt handlers in ROM. The interrupt vector table starts
  2403.    at the beginning of RAM, at address 0000:0000H. (See Chapter 2 for more
  2404.    about interrupts and interrupt vectors.) Each entry in the table is stored
  2405.    as a pair of words, with the offset portion first and the segment portion
  2406.    second. The interrupt vectors can be changed to point to a new interrupt
  2407.    handler simply by locating the vector and changing its value.
  2408.  
  2409.    As a general rule, PC-family interrupts can be divided into six
  2410.    categories: microprocessor, hardware, software, DOS, BASIC, and general
  2411.    use.
  2412.  
  2413.    Microprocessor interrupts, often called logical interrupts, are designed
  2414.    into the microprocessor. Four of them (interrupts 00H, 01H, 03H, and 04H)
  2415.    are generated by the microprocessor itself, and another (interrupt 02H,
  2416.    the nonmaskable interrupt) is activated by a signal generated by certain
  2417.    hardware devices, such as the 8087 math coprocessor.
  2418.  
  2419.    Hardware interrupts are built into the PC hardware. In PCs, XTs, and PS/2
  2420.    models 25 and 30, interrupt numbers 08H through 0FH are used for hardware
  2421.    interrupts; in ATs and PS/2 models 50, 60, and 80, interrupt numbers 08H
  2422.    through 0FH and 70H through 77H are reserved for hardware interrupts. (See
  2423.    Chapter 2 for more about hardware interrupts.)
  2424.  
  2425.    ──────────────────────────────────────────────────────────────────────────
  2426.    The Part DOS Plays
  2427.      The ROM bootstrap loader's only function is to read a bootstrap program
  2428.      from a disk and transfer control to it. On a bootable DOS disk, the disk
  2429.      bootstrap program verifies that DOS is stored on the disk by looking for
  2430.      two hidden files named IBMBIO.COM and IBMDOS.COM. If it finds them, it
  2431.      loads them into memory along with the DOS command interpreter,
  2432.      COMMAND.COM. During this loading process, optional parts of DOS, such as
  2433.      installable device drivers, may also be loaded.
  2434.  
  2435.      The IBMBIO.COM file contains extensions to the ROM BIOS. These
  2436.      extensions can be changes or additions to the basic I/O operations and
  2437.      often include corrections to the existing ROM BIOS, new routines for new
  2438.      equipment, or customized changes to the standard ROM BIOS routines.
  2439.      Because they are part of disk software, the IBMBIO.COM routines provide
  2440.      a convenient way to modify the ROM BIOS. All that is necessary, besides
  2441.      the new routine, is that the interrupt vectors for the previous ROM BIOS
  2442.      routines be changed to point to the location in memory where the new
  2443.      disk BIOS routines are placed. Whenever new devices are added to the
  2444.      computer, their support programs can be included in the IBMBIO.COM file
  2445.      or as installable device drivers, eliminating the need to replace ROM
  2446.      chips. See Appendix A for more on device drivers.
  2447.  
  2448.      You can think of the ROM BIOS routines as the lowest-level system
  2449.      software available, performing the most fundamental and primitive I/O
  2450.      operations. The IBMBIO.COM routines, being extensions of the ROM BIOS,
  2451.      are essentially on the same low level, also providing basic functions.
  2452.      By comparison, the IBMDOS.COM routines are more sophisticated; think of
  2453.      them as occupying the next level up, with applications programs on top.
  2454.  
  2455.      The IBMDOS.COM file contains the DOS service routines. The DOS services,
  2456.      like the BIOS services, can be called by programs through a set of
  2457.      interrupts whose vectors are placed in the interrupt-vector table in low
  2458.      memory. One of the DOS interrupts, interrupt 21H (decimal 33), is
  2459.      particularly important because when invoked, it gives you access to a
  2460.      rather large group of DOS functions. The DOS functions provide more
  2461.      sophisticated and efficient control over the I/O operations than the
  2462.      BIOS routines do, especially with regard to disk file operations. All
  2463.      standard disk processes──formatting diskettes; reading and writing data;
  2464.      opening, closing, and deleting files; performing directory searches──are
  2465.      included in the DOS functions and provide the foundation for many
  2466.      higher-level DOS programs, such as FORMAT, COPY, and DIR. Your programs
  2467.      can use the DOS services when they need more control of I/O operations
  2468.      than programming languages allow, and when you are reluctant to dig all
  2469.      the way down to the BIOS level. The DOS services are a very important
  2470.      part of this book, and we have devoted five chapters to them. (See
  2471.      Chapters 14 through 18.)
  2472.  
  2473.      The COMMAND.COM file is the third and most important part of DOS, at
  2474.      least from a utilitarian standpoint. This file contains the routines
  2475.      that interpret the commands you type in through the keyboard in the DOS
  2476.      command mode. By comparing your input to a table of command names, the
  2477.      COMMAND.COM program can differentiate between internal commands that are
  2478.      part of the COMMAND.COM file, such as RENAME or ERASE, and external
  2479.      commands, such as the DOS utility programs (like DEBUG) or one of your
  2480.      own programs. The command interpreter acts by executing the required
  2481.      routines for internal commands or by searching for the requested
  2482.      programs on disk and loading them into memory. The whole subject of the
  2483.      COMMAND.COM file and how it works is intriguing and well worth
  2484.      investigating──as are the other DOS programs. We recommend you read the
  2485.      DOS Technical Reference Manual or Inside the IBM PC for additional
  2486.      information.
  2487.    ──────────────────────────────────────────────────────────────────────────
  2488.  
  2489.    Software interrupts incorporated into the PC design are part of the ROM
  2490.    BIOS programs. ROM BIOS routines invoked by these interrupts cannot be
  2491.    changed, but the vectors that point to them can be changed to point to
  2492.    different routines. Reserved interrupt numbers are 10H through 1FH
  2493.    (decimal 16 through 31) and 40H through 5FH (decimal 64 through 95).
  2494.  
  2495.    DOS interrupts are always available when DOS is in use. Many programs and
  2496.    programming languages use the services provided by DOS through the DOS
  2497.    interrupts to handle basic operations, especially disk I/O. DOS interrupt
  2498.    numbers are 20H through 3FH (decimal 32 through 63).
  2499.  
  2500.    BASIC interrupts are assigned by BASIC itself and are always available
  2501.    when BASIC is in use. The reserved interrupt numbers are 80H through F0H
  2502.    (decimal 128 through 240).
  2503.  
  2504.    General-use interrupts are available for temporary use in your programs.
  2505.    The reserved interrupt numbers are 60H through 66H (decimal 96 through
  2506.    102).
  2507.  
  2508.    Most of the interrupt vectors used by the ROM BIOS, DOS, and BASIC contain
  2509.    the addresses of interrupt handlers. A few interrupt vectors, however,
  2510.    point to tables of useful information. For example, interrupt 1EH contains
  2511.    the address of a table of diskette drive initialization parameters; the
  2512.    interrupt 1FH vector points to a table of bit patterns used by the ROM
  2513.    BIOS to display text characters; and interrupts 41H and 46H point to
  2514.    tables of fixed-disk parameters. These interrupt vectors are used for
  2515.    convenience, not for interrupts. If you tried to execute interrupt 1EH,
  2516.    for instance, you'd probably crash the system because the interrupt 1EH
  2517.    vector points to data, not to executable code.
  2518.  
  2519.    The interrupt vectors are stored at the lowest memory locations; the very
  2520.    first location in memory contains the vector for interrupt number 00H, and
  2521.    so on. Because each vector is two words in length, you can find a
  2522.    particular interrupt's location in memory by multiplying its interrupt
  2523.    number by 4. For example, the vector for interrupt 05H, the print-screen
  2524.    service interrupt, would be at byte offset 20 (5 x 4 = 20); that is, at
  2525.    address 0000:0014H. You can examine the interrupt vectors by using DEBUG.
  2526.    For example, you could examine the interrupt 05H vector with DEBUG in the
  2527.    following way:
  2528.  
  2529.    DEBUG
  2530.    D 0000:0014 L 4
  2531.  
  2532.    DEBUG will show 4 bytes, in hex, like this:
  2533.  
  2534.    54 FF 00 F0
  2535.  
  2536.    Converted to a segment and offset address and allowing for "back-words"
  2537.    storage, the interrupt vector for the entry point in ROM of the
  2538.    print-screen service routine (interrupt 05H) is F000:FF54H. (Of course,
  2539.    this address may be different in different members of the PC and PS/2
  2540.    families.) The same DEBUG instruction finds any other interrupt vector
  2541.    just as easily.
  2542.  
  2543.    Figure 3-1 lists the main interrupts and their vector locations. These
  2544.    are the interrupts that programmers will probably find most useful.
  2545.    Details are available for most of these interrupts in Chapters 8 through
  2546.    18. Interrupts that are not mentioned in this list are, for the most part,
  2547.    reserved for future development by IBM.
  2548.  
  2549. ╓┌─┌───────────┌────────────┌────────────────────────────────────────────────╖
  2550.    Interrupt   Offset in    Use
  2551.    Hex   Dec   Segment
  2552.                0000
  2553.    ──────────────────────────────────────────────────────────────────────────
  2554.    00H   0     0000         Generated by CPU when division by zero is
  2555.                             attempted
  2556.    01H   1     0004         Used to single-step through programs (as with
  2557.                             DEBUG)
  2558.    02H   2     0008         Nonmaskable interrupt (NMI)
  2559.    03H   3     000C         Used to set break-points in programs (as with
  2560.                             DEBUG)
  2561.    04H   4     0010         Generated when arithmetic result overflows
  2562.    05H   5     0014         Invokes print-screen service routine in ROM BIOS
  2563.    08H   8     0020         Generated by hardware clock tick
  2564.    Interrupt   Offset in    Use
  2565.    Hex   Dec   Segment
  2566.                0000
  2567.    ──────────────────────────────────────────────────────────────────────────
  2568.   08H   8     0020         Generated by hardware clock tick
  2569.    09H   9     0024         Generated by keyboard action
  2570.    0EH   14    0038         Signals diskette attention (e.g. to signal
  2571.                             completion)
  2572.    0FH   15    003C         Used in printer control
  2573.    10H   16    0040         Invokes video display services in ROM BIOS
  2574.    11H   17    0044         Invokes equipment-list service in ROM BIOS
  2575.    12H   18    0048         Invokes memory-size service in ROM BIOS
  2576.    13H   19    004C         Invokes disk services in ROM BIOS
  2577.    14H   20    0050         Invokes communications services in ROM BIOS
  2578.    15H   21    0054         Invokes system services in ROM BIOS
  2579.    16H   22    0058         Invokes standard keyboard services in ROM BIOS
  2580.    17H   23    005C         Invokes printer services in ROM BIOS
  2581.    18H   24    0060         Activates ROM BASIC language
  2582.    19H   25    0064         Invokes bootstrap start-up routine in ROM BIOS
  2583.    1AH   26    0068         Invokes time and date services in ROM BIOS
  2584.    1BH   27    006C         Interrupt by ROM BIOS for Ctrl-Break
  2585.    Interrupt   Offset in    Use
  2586.    Hex   Dec   Segment
  2587.                0000
  2588.    ──────────────────────────────────────────────────────────────────────────
  2589.   1BH   27    006C         Interrupt by ROM BIOS for Ctrl-Break
  2590.    1CH   28    0070         Interrupt generated at each clock tick
  2591.    1DH   29    0074         Points to table of video control parameters
  2592.    1EH   30    0078         Points to diskette drive parameter table
  2593.    1FH   31    007C         Points to CGA video graphics characters
  2594.    20H   32    0080         Invokes program-terminate service in DOS
  2595.    21H   33    0084         Invokes all function-call services in DOS
  2596.    22H   34    0088         Address of DOS program-terminate routine
  2597.    23H   35    008C         Address of DOS keyboard-break handler
  2598.    24H   36    0090         Address of DOS critical-error handler
  2599.    25H   37    0094         Invokes absolute disk-read service in DOS
  2600.    26H   38    0098         Invokes absolute disk-write service in DOS
  2601.    27H   39    009C         Ends program, but keeps it in memory under DOS
  2602.    2FH   47    00BC         DOS Multiplex interrupt
  2603.    41H   65    0104         Points to fixed-disk drive parameter table
  2604.    43H   67    010C         Points to video graphics characters (EGA, PS/2s)
  2605.    67H   103   019CH        Invokes LIM Expanded Memory Manager
  2606.    Interrupt   Offset in    Use
  2607.    Hex   Dec   Segment
  2608.                0000
  2609.    ──────────────────────────────────────────────────────────────────────────
  2610.   67H   103   019CH        Invokes LIM Expanded Memory Manager
  2611.    ──────────────────────────────────────────────────────────────────────────
  2612.  
  2613.  
  2614.    Figure 3-1.  Important interrupts used in the IBM personal computer
  2615.    family.
  2616.  
  2617.    Changing Interrupt Vectors
  2618.  
  2619.    The main programming interest in interrupt vectors is not to read them but
  2620.    to change them to point to a new interrupt-handling routine. To do this,
  2621.    you must write a routine that performs a different function than the
  2622.    standard ROM BIOS or DOS interrupt handlers perform, store the routine in
  2623.    RAM, and then assign the routine's address to an existing interrupt in the
  2624.    table.
  2625.  
  2626.    A vector can be changed byte by byte on an assembly-language level, or by
  2627.    using a programming-language instruction like the POKE statement in BASIC.
  2628.    In some cases, there may be a danger of an interrupt occurring in the
  2629.    middle of a change to the vector. If you are not concerned about this, go
  2630.    ahead and use the POKE method. Otherwise, there are two ways to change
  2631.    a vector while minimizing the likelihood of interrupts: by suspending
  2632.    interrupts during the process, or by using a DOS interrupt specially
  2633.    designed to change vectors.
  2634.  
  2635.    The first method requires that you use assembly language to suspend
  2636.    interrupts while you change the interrupt vector. You can use the clear
  2637.    interrupts instruction (CLI), which suspends all interrupts until a
  2638.    subsequent STI (set interrupts) instruction is executed. By temporarily
  2639.    disabling interrupts with CLI you ensure that no interrupts can occur
  2640.    while you update an interrupt vector.
  2641.  
  2642.    ──────────────────────────────────────────────────────────────────────────
  2643.    NOTE:
  2644.      CLI does not disable the nonmaskable interrupt (NMI). If your
  2645.      application is one of the rare ones that needs to supply its own NMI
  2646.      handler, the program should temporarily disable the NMI while changing
  2647.      the NMI interrupt vector. (See PC or PS/2 technical reference manuals
  2648.      for details.)
  2649.    ──────────────────────────────────────────────────────────────────────────
  2650.  
  2651.    The following example demonstrates how to update an interrupt vector with
  2652.    interrupts temporarily disabled. This example uses two MOV instructions to
  2653.    copy the segment and offset address of an interrupt handler from DS:DX
  2654.    into interrupt vector 60H:
  2655.  
  2656.    xor     ax,ax                   ; zero segment register ES
  2657.    mov     es,ax
  2658.    cli                             ; disable interrupts
  2659.    mov     word ptr es:[180h],dx   ; update vector offset
  2660.    mov     word ptr es:[182h],ds   ; update vector segment
  2661.    sti                             ; enable interrupts
  2662.  
  2663.    The second method of updating an interrupt vector is to let DOS do it for
  2664.    you using DOS interrupt 21H, service 25H (decimal 37), which was designed
  2665.    for this purpose. There are two very important advantages to letting DOS
  2666.    set interrupts for you. One advantage is that DOS takes on the task of
  2667.    putting the vector into place in the safest possible way. The other
  2668.    advantage is more far-reaching. When you use DOS service 25H to change an
  2669.    interrupt vector, you allow DOS to track changes to any interrupt vectors
  2670.    it may itself be using. This is particularly important for programs that
  2671.    might run in the DOS "compatibility box" in OS/2. Using a DOS service to
  2672.    set an interrupt vector instead of setting it yourself is only one of many
  2673.    ways that you can reduce the risk that a program will be incompatible with
  2674.    new machines or new operating-system environments.
  2675.  
  2676.    The following example demonstrates how to use interrupt 21H, service 25H
  2677.    to update the vector for interrupt 60H from values stored in a memory
  2678.    variable:
  2679.  
  2680.    mov     dx,seg Int60Handler     ; copy new segment to DS
  2681.    mov     ds,dx
  2682.    mov     dx,offset Int60Handler  ; store offset address in DX
  2683.    mov     al,60h                  ; interrupt number
  2684.    mov     ah,25h                  ; DOS set-interrupt function number
  2685.    int     21h                     ; DOS function-call interrupt
  2686.  
  2687.    This example shows, in the simplest possible way, how to use the DOS
  2688.    service. However, it glosses over an important and subtle difficulty: You
  2689.    have to load one of the addresses that you're passing to DOS into the DS
  2690.    (data segment) register──which effectively blocks normal access to data
  2691.    through the DS register. Getting around that problem requires you to
  2692.    preserve the contents of the DS register. Here is one way this can be
  2693.    done. In this example, taken from the Norton Utilities programs, the
  2694.    interrupt 09H vector is updated with the address of a special interrupt
  2695.    handler:
  2696.  
  2697.    push    ds                      ; save current data segment
  2698.    mov     dx,offset PGROUP:XXX    ; store handler's offset in DX
  2699.    push    cs                      ; move handler's code segment...
  2700.    pop     ds                      ; ...into DS
  2701.    mov     ah,25h                  ; request set-interrupt function
  2702.    mov     al,9                    ; change interrupt number 9
  2703.    int     21h                     ; DOS function-call interrupt
  2704.    pop     ds                      ; restore original data segment
  2705.  
  2706.  Key Low-Memory Addresses
  2707.  
  2708.    Much of the operation of the PCs and PS/2s is controlled by data stored in
  2709.    low-memory locations, particularly in the two adjacent 256-byte areas
  2710.    beginning at segments 40H and 50H (addresses 0040:0000H and 0050:0000H).
  2711.    The ROM BIOS uses the 256 bytes from 0040:0000H through 0040:00FFH as a
  2712.    data area for its keyboard, video, disk, printer, and communications
  2713.    routines. The 256 bytes between 0050:0000H and 0050:00FFH are used
  2714.    primarily by BASIC, although a few ROM BIOS status variables are located
  2715.    there as well.
  2716.  
  2717.    Data is loaded into these areas by the BIOS during the start-up process.
  2718.    Although the control data is supposed to be the private reserve of the
  2719.    BIOS, DOS, and BASIC, your programs are allowed to inspect or even change
  2720.    it. Even if you do not intend to use the information in these control
  2721.    areas, it is worth studying because it reveals a great deal about what
  2722.    makes the PC family tick.
  2723.  
  2724.    The ROM BIOS Data Area
  2725.  
  2726.    Some memory locations in the BIOS data area are particularly interesting.
  2727.    Most of them contain data vital to the operation of various ROM BIOS and
  2728.    DOS service routines. In many instances, your programs can obtain
  2729.    information stored in these locations by invoking a ROM BIOS interrupt; in
  2730.    all cases, they can access the information directly. You can easily check
  2731.    out the values at these locations on your own computer, using either DEBUG
  2732.    or BASIC. To use DEBUG, type a command of this form:
  2733.  
  2734.    DEBUG
  2735.    D XXXX:YYYY L 1
  2736.  
  2737.    XXXX represents the segment part of address you want to examine. (This
  2738.    would be either 0040H or 0050H, depending on the data area that interests
  2739.    you.) YYYY represents the offset part of the address. The L 1 tells DEBUG
  2740.    to display one byte. To see two or more bytes, type the number of bytes
  2741.    (in hex) you want to see after the L instruction. For example, the BIOS
  2742.    keeps track of the current video mode number in the byte at 0040:0049H. To
  2743.    inspect this byte with DEBUG, you would type
  2744.  
  2745.    DEBUG
  2746.    D 0040:0049 L 1
  2747.  
  2748.    To display the data with BASIC, use a program of the following form,
  2749.    making the necessary substitutions for segment (&H0040 or &H0050),
  2750.    number.of.bytes, and offset (the offset part of the address you want to
  2751.    inspect):
  2752.  
  2753.    10 DEF SEG = segment
  2754.    20 FOR I = 0 TO number.of.bytes - 1
  2755.    30   VALUE = PEEK(offset + I)
  2756.    40   IF VALUE < 16 THEN PRINT "0";    ' needed for leading zero
  2757.    50   PRINT HEX$ (VALUE);" ";
  2758.    60 NEXT I
  2759.  
  2760.    The following pages describe useful low-memory addresses.
  2761.  
  2762.    0040:0010H (a 2-byte word). This word holds the equipment-list data that
  2763.    is reported by the equipment-list service, interrupt 11H (decimal 17). The
  2764.    format of this word, shown in Figure 3-2, was established for the PC and
  2765.    XT; certain parts may appear in a different format in later models.
  2766.  
  2767.    0040:0013H (a 2-byte word). This word contains the usable memory size in
  2768.    KB. BIOS interrupt service 12H (decimal 18) is responsible for reporting
  2769.    the value in this word.
  2770.  
  2771.    0040:0017H (2 bytes of keyboard status bits). These bytes are actively
  2772.    used to control the interpretation of keyboard actions by the ROM BIOS
  2773.    routines. Changing these bytes actually changes the meaning of keystrokes.
  2774.    You can freely change the first byte, at address 0040:0017H, but it is not
  2775.    a good idea to change the second byte. See pages 137 and 138 for the bit
  2776.    settings of these 2 bytes.
  2777.  
  2778. ╓┌─┌──────────────────┌─────────────────┌────────────────────────────────────╖
  2779.                   Bit
  2780.    F E D C B A 9 8    7 6 5 4 3 2 1 0   Meaning
  2781.    ──────────────────────────────────────────────────────────────────────────
  2782.    X X . . . . . .    . . . . . . . .   Number of printers installed
  2783.    . . X . . . . .    . . . . . . . .   (Reserved)
  2784.    . . . X . . . .    . . . . . . . .   1 if game adapter installed
  2785.    . . . . X X X .    . . . . . . . .   Number of RS-232 serial ports
  2786.    . . . . . . . X    . . . . . . . .   (Reserved)
  2787.    . . . . . . . .    X X . . . . . .   +1 = number of diskette drives:
  2788.                                           00 = 1 drive; 01 = 2 drives;
  2789.                                           10 = 3 drives;
  2790.                                           11 = 4 drives (see bit 0)
  2791.    . . . . . . . .    . . X X . . . .   Initial video mode:
  2792.                                           01 = 40-column color;
  2793.                                           10 = 80-column color,
  2794.                                           11 = 80-column monochrome;
  2795.                   Bit
  2796.    F E D C B A 9 8    7 6 5 4 3 2 1 0   Meaning
  2797.    ──────────────────────────────────────────────────────────────────────────
  2798.                                          11 = 80-column monochrome;
  2799.                                           00 = none of the above
  2800.    . . . . . . . .    . . . . X X . .   For PC with 64 KB motherboard:
  2801.                                           Amount of system board RAM
  2802.                                           (11 = 64 KB, 10 = 48 KB,
  2803.                                           01 = 32 KB, 00 = 16 KB)
  2804.                                         For PC/AT: Not used
  2805.                                         For PS/2s: Bit 3: Not used;
  2806.                                           Bit 2: 1 = pointing device
  2807.                                         installed
  2808.    . . . . . . . .    . . . . . . X .   1 if math coprocessor installed
  2809.    . . . . . . . .    . . . . . . . X   1 if any diskette drives present (if
  2810.                                         so, see bits 7 and 6)
  2811.    ──────────────────────────────────────────────────────────────────────────
  2812.  
  2813.  
  2814.    Figure 3-2.  The coding of the equipment-list word at address 0040:0010H.
  2815.  
  2816.    0040:001AH (a 2-byte word). This word points to the current head of the
  2817.    BIOS keyboard buffer at 0040:001EH, where keystrokes are stored until they
  2818.    are used.
  2819.  
  2820.    0040:001CH (a 2-byte word). This word points to the current tail of the
  2821.    BIOS keyboard buffer.
  2822.  
  2823.    0040:001EH (32 bytes, used as sixteen 2-byte entries). This keyboard
  2824.    buffer holds up to 16 keystrokes until they are read via the BIOS services
  2825.    through interrupt 16H (decimal 22). As this is a circular queue buffer,
  2826.    two pointers indicate the head and tail. It is not wise to manipulate this
  2827.    data.
  2828.  
  2829.    0040:003EH (1 byte). This byte indicates if a diskette drive needs to be
  2830.    recalibrated before seeking to a track. Bits 0 through 3 correspond to
  2831.    drives 0 through 3. If a bit is clear, recalibration is needed. Generally,
  2832.    you will find that a bit is clear if there was any problem with the most
  2833.    recent use of a drive. For example, the recalibration bit will be clear if
  2834.    you try to request a directory (DIR) on a drive with no diskette, and then
  2835.    type A in response to the following display:
  2836.  
  2837.    Not ready reading drive A
  2838.    Abort, Retry, Fail?
  2839.  
  2840.    0040:003FH (1 byte). This byte returns the diskette motor status. Bits 0
  2841.    through 3 correspond to drives 0 through 3. If the bit is set, the
  2842.    diskette motor is running.
  2843.  
  2844.    0040:0040H (1 byte). This byte is used by the ROM BIOS to ensure that the
  2845.    diskette drive motor is turned off. The value in this byte is decremented
  2846.    with every tick of the system clock (that is, about 18.2 times per
  2847.    second). When the value reaches 0, the BIOS turns off the drive motor.
  2848.  
  2849.    0040:0041H (1 byte). This byte contains the status code reported by the
  2850.    ROM BIOS after the most recent diskette operation. (See Figure 3-3.)
  2851.  
  2852.    0040:0042H (7 bytes). These 7 bytes hold diskette controller status
  2853.    information.
  2854.  
  2855.    Beginning at 0040:0049H is a 30-byte area used for video control. This is
  2856.    the first of two areas in segment 40H that the ROM BIOS uses to track
  2857.    critical video information.
  2858.  
  2859.    Value              Meaning
  2860.    ──────────────────────────────────────────────────────────────────────────
  2861.    00H                No error
  2862.    01H                Invalid diskette command requested
  2863.    02H                Address mark on diskette not found
  2864.    03H                Write-protect error
  2865.    04H                Sector not found; diskette damaged or not formatted
  2866.    06H                Diskette change line active
  2867.    08H                DMA diskette error
  2868.    09H                Attempt to DMA across 64 KB boundary
  2869.    0CH                Media type not found
  2870.    10H                Cyclical redundancy check (CRC) error in data
  2871.    20H                Diskette controller failed
  2872.    40H                Seek operation failed
  2873.    80H                Diskette timed out (drive not ready)
  2874.    ──────────────────────────────────────────────────────────────────────────
  2875.  
  2876.    Figure 3-3.  Diskette status codes in the ROM BIOS data area at
  2877.    0040:0041H.
  2878.  
  2879.    Although programs can safely inspect any of this data, you should modify
  2880.    the data only when you bypass the ROM BIOS video services and program the
  2881.    video hardware directly. In such cases, you should update the video
  2882.    control data to reflect the true status of the video hardware.
  2883.  
  2884.    0040:0049H (1 byte). The value in this byte specifies the current video
  2885.    mode. (See Figure 3-4.) This is the same video-mode number used in the
  2886.    ROM BIOS video services. (See Chapter 9 for more on these services and
  2887.    page 72 for general information concerning video modes.)
  2888.  
  2889.    We've already shown how to use DEBUG to determine the current video mode
  2890.    by inspecting the byte at 0040:0049H. BASIC programs can use the following
  2891.    instructions to read this byte and determine the video mode:
  2892.  
  2893.    DEF SEG = &H40                  ' set BASIC data segment to 40H
  2894.    VIDEO.MODE = PEEK(&H49)         ' look at location 0040:0049H
  2895.  
  2896.    0040:004AH (a 2-byte word). This word indicates the number of characters
  2897.    that can be displayed in each row of text on the screen.
  2898.  
  2899.    0040:004CH (a 2-byte word). This word indicates the number of bytes
  2900.    required to represent one screenful of video data.
  2901.  
  2902.    Number             Description
  2903.    ──────────────────────────────────────────────────────────────────────────
  2904.    00H                40 x 25 16-color text
  2905.                       (CGA composite color burst disabled)
  2906.    01H                40 x 25 16-color text
  2907.    02H                80 x 25 16-color text
  2908.                       (CGA composite color burst disabled)
  2909.    03H                80 x 25 16-color text
  2910.    04H                320 x 200 4-color graphics
  2911.    05H                320 x 200 4-color graphics
  2912.                       (CGA composite color burst disabled)
  2913.    06H                640 x 200 2-color graphics
  2914.    07H                80 x 25 monochrome text
  2915.    0DH                320 x 200 16-color graphics
  2916.    0EH                640 x 200 16-color graphics
  2917.    0FH                640 x 350 monochrome graphics
  2918.    10H                640 x 350 16-color graphics
  2919.    11H                640 x 480 2-color graphics
  2920.    12H                640 x 480 16-color graphics
  2921.    13H                320 x 200 256-color graphics
  2922.    ──────────────────────────────────────────────────────────────────────────
  2923.  
  2924.    Figure 3-4.  BIOS video mode numbers stored at address 0040:0049H.
  2925.  
  2926.    0040:004EH (a 2-byte word). This word contains the starting byte offset
  2927.    into video display memory of the current display page. In effect, this
  2928.    address indicates which page is in use by giving the offset to that page.
  2929.  
  2930.    0040:0050H (eight 2-byte words). These words give the cursor locations for
  2931.    eight separate display pages, beginning with page 0. The first byte of
  2932.    each word gives the character column and the second byte gives the row.
  2933.  
  2934.    0040:0060H (a 2-byte word). These 2 bytes indicate the size of the cursor,
  2935.    based on the range of cursor scan lines. The first byte gives the ending
  2936.    scan line, the second byte the starting scan line.
  2937.  
  2938.    0040:0062H (1 byte). This byte holds the current display page number.
  2939.  
  2940.    0040:0063H (a 2-byte word). This word stores the port address of the
  2941.    hardware CRT controller chip.
  2942.  
  2943.    0040:0065H (1 byte). This byte contains the current setting of the CRT
  2944.    mode register on the Monochrome Display Adapter and the Color Graphics
  2945.    Adapter.
  2946.  
  2947.    0040:0066H (1 byte). This byte contains the current setting of the Color
  2948.    Graphics Adapter's CRT color register. This byte ends the first block of
  2949.    ROM BIOS video control data.
  2950.  
  2951.    0040:0067H (5 bytes). The original IBM PC BIOS used the 5 bytes starting
  2952.    at 0040:0067H for cassette tape control. In PS/2 models 50, 60, and 80,
  2953.    which don't support a cassette interface, the 4 bytes at 0040:0067H can
  2954.    contain the address of a system reset routine that overrides the usual
  2955.    BIOS startup code. (See the BIOS technical reference manual for details.)
  2956.  
  2957.    0040:006CH (4 bytes stored as one 4-byte number). This area is used as a
  2958.    master clock count, which is incremented once for each timer tick. It is
  2959.    treated as if it began counting from 0 at midnight. When the count reaches
  2960.    the equivalent of 24 hours, the ROM BIOS resets the count to 0 and sets
  2961.    the byte at 0040:0070H to 1. DOS or BASIC calculates the current time from
  2962.    this value and sets the time by putting the appropriate count in this
  2963.    field.
  2964.  
  2965.    0040:0070H (1 byte). This byte indicates that a clock rollover has
  2966.    occurred. When the clock count passes midnight (and is reset to 0), the
  2967.    ROM BIOS sets this byte to 1, which means that the date should be
  2968.    incremented.
  2969.  
  2970.    ──────────────────────────────────────────────────────────────────────────
  2971.    NOTE:
  2972.      This byte is set to 1 at midnight and is not incremented. There is no
  2973.      indication if two midnights pass before the clock is read.
  2974.    ──────────────────────────────────────────────────────────────────────────
  2975.  
  2976.    0040:0071H (1 byte). The ROM BIOS sets bit 7 of this byte to indicate that
  2977.    the Ctrl-Break key combination was pressed.
  2978.  
  2979.    0040:0072H (a 2-byte word). This word is set to 1234H after the initial
  2980.    power-up memory check. When a warm boot is instigated from the keyboard
  2981.    (via Ctrl-Alt-Del), the memory check will be skipped if this location is
  2982.    already set to 1234H.
  2983.  
  2984.    0040:0074H (4 bytes). These 4 bytes are used by various members of the PC
  2985.    family for diskette and fixed-disk drive control. See the IBM BIOS
  2986.    Interface Technical Reference Manual for details.
  2987.  
  2988.    0040:0078H (4 bytes). These bytes control time-out values for the parallel
  2989.    printers. (In the PS/2, only the first 3 bytes are used for this purpose.)
  2990.  
  2991.    0040:007CH (4 bytes). These bytes contain time-out values for up to four
  2992.    RS-232 serial ports.
  2993.  
  2994.    0040:0080H (a 2-byte word). This word points to the start of the keyboard
  2995.    buffer area.
  2996.  
  2997.    0040:0082H (a 2-byte word). This word points to the end of the keyboard
  2998.    buffer area.
  2999.  
  3000.    The next 7 bytes are used by the ROM BIOS in the EGA and PS/2s for video
  3001.    control:
  3002.  
  3003.    0040:0084H (1 byte). The value of this byte is one less than the number of
  3004.    character rows displayed on the screen. The BIOS can refer to this value
  3005.    to determine how many character rows of data to erase when the screen is
  3006.    cleared or how many rows to print when Shift-PrtSc is pressed.
  3007.  
  3008.    0040:0085H (2 bytes). This word indicates the height, in scan lines, of
  3009.    characters on the screen.
  3010.  
  3011.    0040:0087H (4 bytes). These 4 bytes are used by the BIOS video support
  3012.    routines to indicate the amount of video RAM available, the initial
  3013.    settings of the EGA configuration switches, and other miscellaneous video
  3014.    status information.
  3015.  
  3016.    0040:008BH (11 bytes). The ROM BIOS uses this data area for control and
  3017.    status information regarding the diskette and fixed-disk drives.
  3018.  
  3019.    0040:0098H (9 bytes). This data area is used by the PC/AT and PS/2 BIOS to
  3020.    control certain functions of the real-time clock.
  3021.  
  3022.    0040:00A8H (4 bytes). In the EGA and PS/2 BIOS, these bytes contain the
  3023.    segmented address of a table of video parameters and overrides for default
  3024.    ROM BIOS video configuration values. The actual contents of the table
  3025.    vary, depending on which video hardware you are using. The IBM ROM BIOS
  3026.    Interface Technical Reference Manual describes this table in detail.
  3027.  
  3028.    0050:0000H (1 byte). This byte is used by the ROM BIOS to indicate the
  3029.    status of a print-screen operation. Three possible hex values are stored
  3030.    in this location:
  3031.  
  3032.    ──────────────────────────────────────────────────────────────────────────
  3033.    00H            Indicates OK status
  3034.    01H            Indicates a print-screen operation is currently in progress
  3035.    FFH            Indicates an error occurred during a print-screen operation
  3036.    ──────────────────────────────────────────────────────────────────────────
  3037.  
  3038.    0050:0004H (1 byte). This byte is used by DOS when a single-diskette
  3039.    system mimics a two-diskette system. The value indicates whether the one
  3040.    physical drive is acting as drive A or drive B. These values are used:
  3041.  
  3042.    ──────────────────────────────────────────────────────────────────────────
  3043.    00H            Acting as drive A
  3044.    01H            Acting as drive B
  3045.    ──────────────────────────────────────────────────────────────────────────
  3046.  
  3047.    0050:0010H (a 2-byte word). This area is used by ROM BASIC to hold its
  3048.    default data segment (DS) value.
  3049.  
  3050.    BASIC lets you set your own data segment value with the DEF SEG = value
  3051.    statement. (The offset into the segment is specified by the PEEK or POKE
  3052.    function.) You can also reset the data segment to its default setting by
  3053.    using the DEF SEG statement without a value. Although BASIC does not give
  3054.    you a simple way to find the default value stored in this location, you
  3055.    can get it by using this little routine:
  3056.  
  3057.    DEF SEG = &H50
  3058.    DATA.SEGMENT = PEEK(&H11) * 256 + PEEK(&H10)
  3059.  
  3060.    ──────────────────────────────────────────────────────────────────────────
  3061.    NOTE:
  3062.      BASIC administers its own internal data based on the default data
  3063.      segment value. Attempting to change this value is likely to sabotage
  3064.      BASIC's operation.
  3065.    ──────────────────────────────────────────────────────────────────────────
  3066.  
  3067.    0050:0012H (4 bytes). In some versions of ROM BASIC, these 4 bytes contain
  3068.    the segment and offset address of BASIC's clock-tick interrupt handler.
  3069.  
  3070.    ──────────────────────────────────────────────────────────────────────────
  3071.    NOTE:
  3072.      In order to perform better, BASIC runs the system clock at four times
  3073.      the standard rate, so BASIC must replace the ROM BIOS clock interrupt
  3074.      routine with its own. The standard BIOS interrupt routine is invoked by
  3075.      BASIC at the normal rate; that is, once for every four fast ticks.
  3076.      There's more about this on page 146.
  3077.    ──────────────────────────────────────────────────────────────────────────
  3078.  
  3079.    0050:0016H (4 bytes). This area contains the address of ROM BASIC's
  3080.    break-key handling routine.
  3081.  
  3082.    0050:001AH (4 bytes). This area contains the address of ROM BASIC's
  3083.    diskette error-handling routine.
  3084.  
  3085.    The Intra-Application Communications Area
  3086.  
  3087.    In the PC/XT/AT family, the 16 bytes starting at 0040:00F0H are reserved
  3088.    as an intra-application communication area (ICA). This data area provides
  3089.    an area of RAM at a known address that an application can use for sharing
  3090.    data among separate program modules. In the PS/2 BIOS, however, the ICA is
  3091.    no longer documented.
  3092.  
  3093.    Few applications actually use the ICA because the amount of RAM is so
  3094.    small and because the data within the ICA can be unexpectedly modified
  3095.    when more than one program uses it. If you do write a program that uses
  3096.    the ICA, we recommend that you include a checksum and also a signature so
  3097.    that you can ensure that the data in the ICA is yours and that it has not
  3098.    been changed by another program.
  3099.  
  3100.    ──────────────────────────────────────────────────────────────────────────
  3101.    WARNING:
  3102.      The ICA is definitely located in the 16 bytes from 0040:00F0H through
  3103.      0040:00FFH. A typographic error in some editions of the IBM PC Technical
  3104.      Reference Manual places it at 0050:0000H through 0050:00FFH. This is
  3105.      incorrect.
  3106.    ──────────────────────────────────────────────────────────────────────────
  3107.  
  3108.    The BIOS Extended Data Area
  3109.  
  3110.    The PS/2 ROM BIOS start-up routines allocate an additional area of RAM for
  3111.    their own use. The BIOS routines use this extended data area for transient
  3112.    data storage. For example, the BIOS routines that support the
  3113.    pointing-device (mouse) controller hardware use part of the extended data
  3114.    area for temporary storage.
  3115.  
  3116.    You can determine the starting address of the extended data area by using
  3117.    a system service available through ROM BIOS interrupt 15H. (See Chapter
  3118.    12.) The first byte in the extended data area contains the size of the
  3119.    data area in KB.
  3120.  
  3121.  The ROM Version and Machine-ID Markers
  3122.  
  3123.    Because the BIOS programs are fixed in memory, they can't be easily
  3124.    changed when additions or corrections are needed. This means that ROM
  3125.    programs must be tested very carefully before they are frozen onto memory
  3126.    chips. Although there is a good chance for serious errors to exist in a
  3127.    system's ROM programs, IBM has a fine track record; so far, only small and
  3128.    relatively unimportant errors have been found in the PC family's ROM
  3129.    programs, and IBM has done well to correct errors by revising the BIOS.
  3130.  
  3131.    The different versions of ROM software could present a small challenge to
  3132.    programmers who discover that the differences affect the operating
  3133.    characteristics of their programs. But an even greater challenge for
  3134.    programmers is that the PC, XT, AT, and PS/2s each have a slightly
  3135.    different set of ROM BIOS routines.
  3136.  
  3137.    To ensure that programs can work with the appropriate ROM programs and the
  3138.    right computer, IBM has supplied two identifying markers that are
  3139.    permanently available at the end of memory in the system ROM. One marker
  3140.    identifies the ROM release date, which can be used to identify the BIOS
  3141.    version, and the other gives the machine model. These markers are always
  3142.    present in IBM's own machines and you'll also find them supplied by the
  3143.    manufacturers of a few PC compatibles. The following paragraphs describe
  3144.    these markers in detail.
  3145.  
  3146.    The ROM release date can be found in an 8-byte storage area from
  3147.    F000:FFF5H to F000:FFFCH (2 bytes before the machine ID byte). It consists
  3148.    of ASCII characters in the common American date format; for example,
  3149.    06/01/83 stands for June 1, 1983. This release marker is a common feature
  3150.    of the IBM personal computers, but is present in only a few IBM
  3151.    compatibles. For example, the Compaq Portable I does not have it, but the
  3152.    Panasonic Senior Partner does.
  3153.  
  3154.    You can look at the release date with DEBUG by using the following
  3155.    command:
  3156.  
  3157.    DEBUG
  3158.    D F000:FFF5 L 8
  3159.  
  3160.    Or you can let your program look at the bytes using this technique:
  3161.  
  3162.    10 DEF SEG = &HF000
  3163.    20 FOR I = 0 TO 7
  3164.    30   PRINT CHR$(PEEK(&HFFF5 + I));
  3165.    40 NEXT
  3166.    50 END
  3167.  
  3168.    The model ID is a byte located at F000:FFFEH. This byte identifies which
  3169.    model of PC or PS/2 you are using. (See Figure 3-5.) In addition, a ROM
  3170.    BIOS service in the PC/AT and PS/2s returns more detailed identification
  3171.    information, including the submodel byte listed in the figure. (See
  3172.    Chapter 12.)
  3173.  
  3174. ╓┌─┌──────────────────┌────────┌────────┌────────┌─────────┌─────────────────╖
  3175.    Machine            Date     Model    Submodel BIOS      Revision Notes
  3176.    ──────────────────────────────────────────────────────────────────────────
  3177.    PC                 04/24/81 FFH              00
  3178.                       10/19/81 FFH              01        Some BIOS bugs
  3179.                                                            fixed
  3180.                       10/27/82 FFH              02        Upgrade of PC BIOS
  3181.                                                            to XT level
  3182.    PC/XT              11/08/82 FEH              00
  3183.                       01/10/86 FBH      00       01        256/640 KB system
  3184.                                                            board
  3185.                       05/09/86 FBH      00       02
  3186.    PC/AT              01/10/84 FCH              00        6 MHz 80286
  3187.                       06/10/85 FCH      00       01
  3188.                       11/15/85 FCH      01       00        8 MHz 80286
  3189.    PS/2 Model 25      06/26/87 FAH      01       00
  3190.    PS/2 Model 30      09/02/86 FAH      00       00
  3191.                       12/12/86 FAH      00       01
  3192.    PS/2 Model 50      02/13/87 FCH      04       00
  3193.    PS/2 Model 60      02/13/87 FCH      05       00
  3194.    Machine            Date     Model    Submodel BIOS      Revision Notes
  3195.    ──────────────────────────────────────────────────────────────────────────
  3196.   PS/2 Model 60      02/13/87 FCH      05       00
  3197.    PS/2 Model 80      03/30/87 F8H      00       00        16 MHz 80386
  3198.    PS/2 Model 80      10/07/87 F8H      01       00        20 MHz 80386
  3199.    PCjr               06/01/83 FDH              00
  3200.    PC Convertible     09/13/85 F9H      00       00
  3201.    PC/XT Model        04/21/86 FCH      02       00
  3202.    286
  3203.    ──────────────────────────────────────────────────────────────────────────
  3204.  
  3205.  
  3206.    Figure 3-5.  Machine and ROM BIOS version identification.
  3207.  
  3208.    It is possible that IBM-compatible computers can be identified in the same
  3209.    way, but we do not know of any reliable published information. You may
  3210.    need to rely on improvised methods to identify non-IBM compatibles.
  3211.  
  3212.    You can examine the machine ID byte with DEBUG by using the following
  3213.    command:
  3214.  
  3215.    DEBUG
  3216.    D F000:FFFE L 1
  3217.  
  3218.    A BASIC program can inspect this byte using techniques such as this:
  3219.  
  3220.    10 DEF SEG = &HF000
  3221.    20 MODEL = PEEK(&HFFFE)
  3222.    30 IF MODEL < &HF8 THEN PRINT "I'm not an IBM computer" : STOP
  3223.    40 ON (MODEL - &HF7) GOTO 100,110,120,130,140,150,160,170
  3224.    100 PRINT "I'm a PS/2 Model 80" : STOP
  3225.    110 PRINT "I'm a PC convertible" : STOP
  3226.    120 PRINT "I'm a PS/2 Model 30" : STOP
  3227.    130 PRINT "I'm a PC/XT" : STOP
  3228.    140 PRINT "I'm an 80286-based machine (PC/AT, PS/2 Model 50 or 60)" :
  3229.               STOP
  3230.    150 PRINT "I'm a PCjr" : STOP
  3231.    160 PRINT "I'm a PC/XT" : STOP
  3232.    170 PRINT "I'm a PC" : STOP
  3233.  
  3234.  
  3235.  The ROM BASIC
  3236.  
  3237.    Now we move on to the third element of ROM: the ROM BASIC. The ROM BASIC
  3238.    acts in two ways. First, it provides the core of the BASIC language, which
  3239.    includes most of the commands and the underlying foundation──such as
  3240.    memory management──that BASIC uses. The disk versions of interpreted
  3241.    BASIC, which are found in the program files BASIC.COM and BASICA.COM, are
  3242.    essentially supplements to ROM BASIC, and they rely on ROM BASIC to get
  3243.    much of their work done. The second role of ROM BASIC is to provide what
  3244.    IBM calls "cassette" BASIC──the BASIC that is activated when you start up
  3245.    your computer without a disk.
  3246.  
  3247.    Whenever you use any of the interpreted, disk-based BASICs, the ROM BASIC
  3248.    programs are also used──although there's nothing to make you aware of it.
  3249.    On the other hand, compiled BASIC programs don't make use of the ROM
  3250.    BASIC.
  3251.  
  3252.  
  3253.  The ROM Extensions
  3254.  
  3255.    The fourth element of the ROM has more to do with the PC's design than
  3256.    with the actual contents of its memory. The PC was designed to allow for
  3257.    installable extensions to the built-in software in ROM. The additional ROM
  3258.    is usually located on a plug-in adapter such as the Enhanced Graphics
  3259.    Adapter or a fixed-disk controller card. Computers in the PC/XT/AT family
  3260.    also have empty sockets on their system boards to accommodate additional
  3261.    ROM chips. Because the original ROM BIOS could not include support
  3262.    programs for future hardware, ROM extensions are obviously a necessary and
  3263.    helpful addition.
  3264.  
  3265.    Several memory areas are reserved for ROM extensions. Addresses C000:0000H
  3266.    through C000:7FFFH are reserved for video adapter ROM. The area between
  3267.    C800:0000H and D000:FFFFH can be used by nonvideo adapters. (For example,
  3268.    the IBM XT fixed-disk adapter occupies addresses starting at C800:0000H.)
  3269.    Finally, ROM extensions on chips placed onto the system board of a PC, XT,
  3270.    or AT occupy the address range E000:0000H through E000:FFFFH. In the PS/2
  3271.    models 50, 60, and 80, you cannot add ROM chips to the system board. The
  3272.    system ROM in these computers occupies the entire address range between
  3273.    E000:0000H and F000:FFFFH.
  3274.  
  3275.  
  3276.  Comments
  3277.  
  3278.    As the PC family has evolved, the amount and complexity of the ROM
  3279.    software has increased to accommodate the greater sophistication of the
  3280.    computer hardware. The source code listings in the PC, XT, and AT
  3281.    technical reference manuals consist of tens of thousands of
  3282.    assembly-language instructions. Despite the size of the ROM BIOS, a browse
  3283.    through the source code can be fun and enlightening.
  3284.  
  3285.    We have made every effort in this book to point out when and how to use
  3286.    the ROM BIOS routines. We recommend that you read Chapters 8 through 13
  3287.    before you begin your own exploration of the ROM BIOS.
  3288.  
  3289.  
  3290.  
  3291.  ────────────────────────────────────────────────────────────────────────────
  3292.  Chapter 4  Video Basics
  3293.  
  3294.    The Video Subsystems
  3295.      Memory and the Video Subsystems
  3296.      Creating the Screen Image
  3297.  
  3298.    The Video Display Modes
  3299.      Video Mode Control
  3300.      Display Resolution
  3301.  
  3302.    The Use of Color
  3303.      Color-Suppressed Modes
  3304.      Color in Text and Graphics Modes
  3305.  
  3306.    Inside the Display Memory
  3307.      Display Pages in Text Modes
  3308.      Display Pages in Graphics Modes
  3309.      Displaying Characters in Text and Graphics Modes
  3310.  
  3311.    Controlling the Video Display
  3312.      Direct Hardware Control
  3313.  
  3314.    Compatibility Considerations
  3315.  
  3316.    To many people, the video display is the computer. Programs are often
  3317.    judged by their display quality and visual design alone. In this chapter,
  3318.    you'll see what kinds of video display output the IBM PC family can
  3319.    produce. More importantly, we'll describe how to manipulate the video
  3320.    displays to get the effects you want.
  3321.  
  3322.  
  3323.  The Video Subsystems
  3324.  
  3325.    Every PC and PS/2 has a video subsystem responsible for producing the
  3326.    image that appears on the screen. At the heart of the video subsystem is
  3327.    the special-purpose circuitry that must be programmed to generate the
  3328.    electrical signals that control the video display. Most members of the
  3329.    PC/XT/AT family require you to install a display adapter, a special video
  3330.    circuit board that plugs into one of the computer's expansion slots. On
  3331.    the other hand, all PS/2s are equipped with built-in video circuitry and,
  3332.    therefore, require no display adapter.
  3333.  
  3334.    The video circuitry consists of a group of interrelated components that
  3335.    control signal timing, colors, and the generation of text characters. All
  3336.    IBM video subsystems have a video buffer, a block of dedicated memory that
  3337.    holds the text or graphics information displayed on the screen. The video
  3338.    subsystem performs the unique task of translating the raw data in the
  3339.    video buffer into the signals that drive the video display.
  3340.  
  3341.    The various video subsystems used in PCs and PS/2s all evolved from the
  3342.    two video adapters originally released by IBM for the PC: the Monochrome
  3343.    Display Adapter (MDA) and the Color Graphics Adapter (CGA). IBM later
  3344.    released its Enhanced Graphics Adapter (EGA), a more powerful successor to
  3345.    the MDA and CGA.
  3346.  
  3347.    When the PS/2s appeared, IBM introduced two more video subsystems: the
  3348.    Multi-Color Graphics Array (MCGA), built into the PS/2 models 25 and 30,
  3349.    and the Video Graphics Array (VGA), built into the PS/2 models 50, 60, and
  3350.    80. At the same time the PS/2s appeared, IBM introduced a VGA adapter that
  3351.    can be used in the PC/XT/AT family as well as in the PS/2 Model 30.
  3352.  
  3353.    We'll be discussing all five of these IBM subsystems──MDA, CGA, EGA, MCGA,
  3354.    and VGA──in this chapter. Although clear differences in hardware design
  3355.    exist between the various video subsystems, their strong family
  3356.    resemblance should encourage you to consider what they have in common
  3357.    before worrying about the differences between them.
  3358.  
  3359.    Most of the five video subsystems can be programmed into two fundamentally
  3360.    different modes, called text mode and graphics mode by IBM. (The lone
  3361.    exception is the MDA, which operates only in text mode.) In text mode you
  3362.    can display only text characters, though many of these characters are
  3363.    suitable for producing simple line drawings. (See Appendix C for more on
  3364.    characters.) Graphics mode is mainly used for complex drawings but you can
  3365.    also use it to draw text characters in a variety of shapes and sizes.
  3366.  
  3367.    The CGA can operate in both text and graphics modes to produce drawings
  3368.    and characters in several formats and colors. By contrast, the MDA can
  3369.    operate only in text mode, using a stored set of ASCII alphanumeric and
  3370.    graphics characters and displaying them in only one color. The MDA works
  3371.    only with the IBM Monochrome Monitor (or its equivalent) while the CGA
  3372.    must be connected to either a direct-drive or a composite color monitor.
  3373.    (See page 74 for more on monitors.) Many business and professional users
  3374.    prefer a monochrome display to a color display because a monochrome screen
  3375.    is easier on the eyes and less expensive than an equivalent color display.
  3376.    But in choosing monochrome, they sacrifice color, a valuable asset for any
  3377.    computer display.
  3378.  
  3379.    The MDA's most obvious drawback is its inability to display images in
  3380.    graphics mode. For this reason, PC/XT/AT users who prefer a monochrome
  3381.    display, yet need to view graphics, must turn to an EGA or to a non-IBM
  3382.    adapter like the Hercules Graphics Card, which emulates the MDA's text
  3383.    mode but supports a monochrome graphics mode as well.
  3384.  
  3385.    Roughly two-thirds of all PCs are equipped with the standard MDA and
  3386.    therefore have no graphics or color capability. While there are real
  3387.    advantages to using color and graphics, most PCs get along nicely without
  3388.    either. Although the clear trend is toward higher-performance video
  3389.    subsystems that can display graphics as well as text, keep in mind as you
  3390.    plan computer applications that many PCs display text only.
  3391.  
  3392.    The best way to understand the video capabilities of the PCs and PS/2s is
  3393.    to cover the features that their various video subsystems have in common.
  3394.    As we go along, we'll point out the differences and improvements that
  3395.    distinguish the newer and more complicated subsystems (EGA, MCGA, and VGA)
  3396.    from their predecessors (MDA and CGA).
  3397.  
  3398.  Memory and the Video Subsystems
  3399.  
  3400.    The video buffer memory is connected directly to the display circuitry so
  3401.    that the data in the video buffer can be repeatedly read out of the buffer
  3402.    and displayed. However, the video buffer is also logically (to the CPU) a
  3403.    part of the computer's main memory address space. A full 128 KB of the
  3404.    memory address space is set aside for use as video buffers, at addresses
  3405.    A000:0000H through B000:FFFFH, but the two original display adapters use
  3406.    only two small parts of this memory area. The Monochrome Display Adapter
  3407.    (MDA) provides 4 KB of display memory located at segment B000H. The
  3408.    original CGA provides 16 KB of display memory located at segment B800H.
  3409.  
  3410.    With the other IBM video subsystems, the address at which video memory is
  3411.    located isn't fixed──it depends on how the subsystem is configured. For
  3412.    example, when an EGA is used with a monochrome display, its text-mode
  3413.    video buffer is placed at B000H, just as with an MDA. When an EGA is
  3414.    attached to a color display, its video buffer can be addressed at B800H.
  3415.    And when you use an EGA in non-CGA graphics modes, the starting buffer
  3416.    address is A000H. Like the EGA, the MCGA and the VGA also support this
  3417.    chameleon-like method of buffer addressing.
  3418.  
  3419.  Creating the Screen Image
  3420.  
  3421.    You can describe the screen display created by IBM video subsystems as a
  3422.    memory-mapped display, because each address in the display memory
  3423.    corresponds to a specific location on the screen. (See Figure 4-1.) The
  3424.    display circuitry repeatedly reads information from memory and places it
  3425.    on the screen. The information can be changed as quickly as the computer
  3426.    can write new information from your programs into memory. The display
  3427.    circuitry translates the stream of bits it receives from memory into
  3428.    bursts of light at particular locations on the screen.
  3429.  
  3430.                     ┌─────────────────────────────────────────┐
  3431.                     │ ┌─────────────────────────────────────┐ │
  3432.                     │ │        Pixels or   │ │
  3433.                     │ │                         characters  │ │
  3434.                     │ │                         on screen   │ │
  3435.                     │ │                                     │ │
  3436.                     │ │                                     │ │
  3437.                     │ │                                     │ │
  3438.                     │ │                                     │ │
  3439.                     │ │                                     │ │
  3440.                     │ │                                     │ │
  3441.                     │ └─────────────────────────────────────┘ │
  3442.                     └─────────────────────────────────────────┘
  3443.                                          
  3444.                                        ║  ║
  3445.    ┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬
  3446.    │▓│▓│ │▓│▓│▓│ │ │▓│ │▓│▓│▓│▓│ │▓│▓│▓│▓│ │▓│▓│▓│ │ │ │ │ │ │ │ │ │ │ │ │ │ │
  3447.    └─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴
  3448.                              Successive locations in RAM
  3449.  
  3450.    Figure 4-1.  The memory-mapped display.
  3451.  
  3452.    These dots of light are called pixels and are produced by an electron beam
  3453.    striking the phosphorescent surface of the CRT. The electron beam is
  3454.    produced by an electron gun that scans the screen line by line. As the gun
  3455.    moves across and down the screen in a fixed path called a raster scan, the
  3456.    video subsystem generates video control signals that turn the beam on and
  3457.    off, matching the pattern of the bits in memory.
  3458.  
  3459.    The video circuitry refreshes the screen between 50 and 70 times a second
  3460.    (depending on the video mode), making the changing images appear clear and
  3461.    steady. At the end of each screen-refresh cycle, the electron beam must
  3462.    move from the bottom right corner to the top left corner of the screen to
  3463.    begin a new cycle. This movement is called the vertical retrace. During
  3464.    the retrace, the beam is blanked and no pixels are written to the screen.
  3465.  
  3466.    The vertical retrace period (about 1.25 milliseconds) is important to
  3467.    programmers for one main reason, which requires some explanation. The
  3468.    special dual-ported design of the video memory gives the CPU and the
  3469.    display-refresh circuitry equal access to the display memory. This allows
  3470.    the CPU and the display circuitry to access video memory at the same time.
  3471.  
  3472.    This causes a problem on the Color Graphics Adapter (CGA). If the CPU
  3473.    happens to read or write to the video buffer at the same time the display
  3474.    circuitry is copying data out of the buffer to display onscreen, a "snow"
  3475.    effect may briefly appear on the screen. However, if you instruct the CPU
  3476.    to access memory only during vertical retrace, when the display circuitry
  3477.    is not accessing the video buffer, then snow can be eliminated. A program
  3478.    running on a CGA can test the value of bit 3 in the adapter's I/O port at
  3479.    3DAH. This bit is set on at the beginning of vertical retrace and then set
  3480.    off at the end. During this 1.25-millisecond pause, you can have your
  3481.    programs write as much data as possible to the video display memory. At
  3482.    the end of the retrace, the display circuitry can write this data to the
  3483.    screen without snow.
  3484.  
  3485.    This technique is useful for any application that directly accesses data
  3486.    in the video buffer in text mode on a CGA. Fortunately, the hardware
  3487.    design of all other IBM video subsystems avoids this access conflict and
  3488.    makes this specialized programming technique unnecessary.
  3489.  
  3490.  
  3491.  The Video Display Modes
  3492.  
  3493.    Originally, there were eight video modes defined for the IBM personal
  3494.    computers: seven on the CGA and one on the MDA. The more sophisticated
  3495.    EGA, MCGA, and VGA introduced several new modes plus variations on the
  3496.    original eight. As a result, among the five IBM video subsystems are 12
  3497.    text and graphics modes and, depending how you count them, seven or eight
  3498.    variations──and that's not counting the extra modes available with non-IBM
  3499.    video hardware and with defunct IBM systems like the PCjr. There's plenty
  3500.    of variety when you're working with IBM video subsystems.
  3501.  
  3502.    Despite the perplexing proliferation of video modes, what is striking
  3503.    about the different modes is not their differences but their similarities
  3504.    (Figure 4-2): All video modes are related in resolution and in video
  3505.    buffer organization to the original MDA and CGA modes.
  3506.  
  3507.    The MDA's 80-column, 25-row monochrome text mode is supported on the EGA
  3508.    and VGA. Similarly, the CGA's two text modes (40 x 25 and 80 x 25 16-color
  3509.    modes) are also supported on the EGA, MCGA, and VGA. Don't let the
  3510.    redundant mode numbers in Figure 4-2 confuse you: The difference between
  3511.    mode 0 and mode 1, for example, is that the composite color signal on the
  3512.    CGA is modified for composite monochrome monitors in mode 0. (See page
  3513.    74 for more on monitors.) With all other monitors and in all other video
  3514.    subsystems, modes 0 and 1 are the same, as are modes 2 and 3 and modes 4
  3515.    and 5.
  3516.  
  3517. ╓┌─┌────────────┌─────────────┌────────────┌─────────────┌────────────┌──────
  3518.    BIOS Mode Number
  3519.    Hex          Dec           Type         Resolution    Colors       Video Su
  3520.    ───────────────────────────────────────────────────────────────────────────
  3521.    00H,01H      0, 1          Text         40 x 25       16           CGA, EGA
  3522.    02H,03H      2, 3          Text         80 x 25       16           CGA, EGA
  3523.    04H,05H      4, 5          Graphics     320 x 200     4            CGA, EGA
  3524.    06H          6             Graphics     640 x 200     2            CGA, EGA
  3525.    07H          7             Text         80 x 25       Mono         MDA, EGA
  3526.    08H,09H,0AH  8, 9, 10                                              (PCjr on
  3527.    0BH,0CH      11, 12                                                (Used in
  3528.                                                                       BIOS)
  3529.    0DH          13            Graphics     320 x 200     16           EGA,VGA
  3530.    BIOS Mode Number
  3531.    Hex          Dec           Type         Resolution    Colors       Video Su
  3532.    ───────────────────────────────────────────────────────────────────────────
  3533.   0DH          13            Graphics     320 x 200     16           EGA,VGA
  3534.    0EH          14            Graphics     640 x 200     16           EGA,VGA
  3535.    0FH          15            Graphics     640 x 350     Mono         EGA,VGA
  3536.    10H          16            Graphics     640 x 350     16           EGA,VGA
  3537.    11H          17            Graphics     640 x 480     2            MCGA,VGA
  3538.    12H          18            Graphics     640 x 480     16           VGA
  3539.    13H          19            Graphics     320 x 200     256          MCGA,VGA
  3540.    ───────────────────────────────────────────────────────────────────────────
  3541.  
  3542.  
  3543.    Figure 4-2.  Video modes available on IBM video subsystems.
  3544.  
  3545.    The evolutionary pattern is the same for graphics modes. The CGA supports
  3546.    two graphics modes, a 320 x 200 pixel, 4-color mode and a 640 x 200,
  3547.    2-color mode. These same two modes are supported on the EGA, MCGA, and
  3548.    VGA. The EGA introduced three new graphics modes with more colors and
  3549.    better resolution than the original CGA graphics modes: the 320 x 200,
  3550.    16-color; 640 x 200, 16-color; and 640 x 350, 16-color modes. The EGA also
  3551.    introduced a 640 x 350 monochrome graphics mode that could be used only
  3552.    with an MDA-compatible monochrome display.
  3553.  
  3554.    When the PS/2s appeared, their video subsystems supported the same modes
  3555.    as did the MDA, CGA, and EGA──but again, a few new graphics modes were
  3556.    introduced. The MCGA in the PS/2 models 25 and 30 followed the CGA
  3557.    tradition: It supported all CGA modes, plus new 640 x 480, 2-color and 320
  3558.    x 200, 256-color graphics modes. The VGA in the other PS/2 models strongly
  3559.    resembles the EGA. It provides all the EGA's text and graphics modes, the
  3560.    two new MCGA graphics modes, and one more graphics mode not supported by
  3561.    the other subsystems──a 640 x 480, 16-color mode.
  3562.  
  3563.    How do you know which mode to use in a program? Clearly, if broad
  3564.    compatibility is a concern, the MDA and CGA modes are the least common
  3565.    denominator. If you need more colors or better graphics resolution than
  3566.    the CGA modes provide, you can turn to one of the EGA, MCGA, or VGA
  3567.    graphics modes. Of course, if your program requires an EGA or a VGA to
  3568.    run, users who have only a CGA will be out of luck.
  3569.  
  3570.    Many commercial software vendors solve this problem by distributing
  3571.    installable video output routines along with their products. Before you
  3572.    can use a package like Microsoft Windows or Lotus 1-2-3, for example, you
  3573.    must run a special installation program that binds output routines for
  3574.    your particular video hardware to the software application. This approach
  3575.    is more work for both the people who write software and the people who use
  3576.    it, but it is a good way to make applications deliver the best possible
  3577.    video performance without stumbling over the diversity of video hardware
  3578.    and video modes.
  3579.  
  3580.  Video Mode Control
  3581.  
  3582.    Before we get into the details about resolution and color in video modes,
  3583.    let's consider how you select which video mode to use. The most efficient
  3584.    way to set up a video mode is to use assembly language to call the ROM
  3585.    BIOS. ROM BIOS interrupt 10H (decimal 16), service 00H, provides a way to
  3586.    select a video mode using the mode numbers listed in Figure 4-2. (See
  3587.    Chapter 9 for more details on this.)
  3588.  
  3589.    ──────────────────────────────────────────────────────────────────────────
  3590.    Monitors
  3591.      The type of video display, or monitor, that might be used has an
  3592.      important effect on program design. Many monitors cannot produce color
  3593.      or graphics, and a few produce such a poor quality image that you can
  3594.      use only the 40-column text display format. The many kinds of monitors
  3595.      that can be used with the PC family of computers can be broken down into
  3596.      five basic types.
  3597.  
  3598.      Direct-drive monochrome monitors. These monitors are designed to work
  3599.      with the Monochrome Display Adapter (MDA), although you can also use
  3600.      them with an Enhanced Graphics Adapter (EGA). The green IBM Monochrome
  3601.      Display is reminiscent of IBM's 3270 series of mainframe computer
  3602.      terminals; it's no surprise that many business users are comfortable
  3603.      with the combination of an MDA and a green monochrome display.
  3604.  
  3605.      Composite monochrome monitors. These monitors are still among the most
  3606.      widely used and least expensive monitors available. They connect to the
  3607.      composite video output on the Color Graphics Adapter (CGA) and provide a
  3608.      fairly clear one-color image (usually green or amber). Don't confuse the
  3609.      composite monochrome monitor with the direct-drive monochrome monitor.
  3610.      The composite monochrome monitor can be attached only to the CGA,
  3611.      whereas the direct-drive monochrome monitor must be used with an MDA or
  3612.      EGA.
  3613.  
  3614.      Composite color monitors and TV sets. Composite color monitors use a
  3615.      single combined signal such as the composite video output of the CGA.
  3616.      The composite color monitor produces color and graphics but has
  3617.      limitations: An 80-column display is often unreadable; only certain
  3618.      color combinations work well; and graphics resolution is low in quality,
  3619.      so graphics must be kept simple by using low-resolution graphics modes.
  3620.  
  3621.      Although the standard television set (color or black-and-white) is
  3622.      technically a composite monitor, it usually produces an even
  3623.      lower-quality image than the dedicated composite monitor. Text displays
  3624.      must be in 40-column mode to ensure that the display is readable. TVs
  3625.      are connected to the composite video output of the CGA, but the
  3626.      composite signal must be converted by an RF adapter before going into
  3627.      the TV.
  3628.  
  3629.      RGB color monitors. The RGB monitors are considered the best of both
  3630.      worlds. They combine the high-quality text display of the monochrome
  3631.      monitors with high-resolution graphics and color. RGB stands for
  3632.      red-green-blue, and RGB monitors are so named because they use separate
  3633.      red, green, and blue color signals, unlike the composite monitors, which
  3634.      use only one composite signal. The image and color quality of an RGB
  3635.      monitor is much better than that available through any screen that
  3636.      connects to the composite video output.
  3637.  
  3638.      Variable-frequency monitors. One of the problems created by the
  3639.      proliferation of different video subsystems is that some subsystems
  3640.      produce color and timing signals with different frequencies or different
  3641.      encodings than other subsystems. For example, you cannot use a
  3642.      PS/2-compatible monitor with a CGA because the color information in the
  3643.      monitor drive signals is encoded differently by a CGA than it is by a
  3644.      PS/2 video subsystem (MCGA or VGA).
  3645.  
  3646.      Monitor manufacturers addressed this problem by designing
  3647.      variable-frequency RGB monitors that can be used with a wide range of
  3648.      signal frequencies and with more than one type of color signal encoding.
  3649.      For example, NEC's MultiSync monitors can adjust to the different signal
  3650.      frequencies generated by the CGA, the EGA, and the PS/2 video
  3651.      subsystems. These monitors also have a switch that lets you adapt them
  3652.      either to the digital color signal encoding used by the CGA and EGA or
  3653.      to the analog color signals used by the PS/2 subsystems.
  3654.  
  3655.      Many people use variable-frequency monitors because they anticipate the
  3656.      need to upgrade their video subsystems at some time in the future, and
  3657.      they don't want to be stuck with an incompatible monitor.
  3658.    ──────────────────────────────────────────────────────────────────────────
  3659.  
  3660.    Many programming languages also offer high-level commands that select
  3661.    video modes for you. For example, BASIC gives you control over the video
  3662.    modes through the SCREEN statement but refers to them in its own way,
  3663.    using different mode numbers than the ROM BIOS routines. You can also
  3664.    control some of the video modes through the DOS MODE command. (See Figure
  3665.    4-3.)
  3666.  
  3667.    BIOS Mode Number         BASIC Statement to      DOS Statement to
  3668.    Hex          Dec         Change Mode             Change Mode
  3669.    ──────────────────────────────────────────────────────────────────────────
  3670.    00H          0           SCREEN 0,0: WIDTH 40    MODE BW40
  3671.    01H          1           SCREEN 0,1:WIDTH 40     MODE CO40
  3672.    02H          2           SCREEN 0,0:WIDTH 80     MODE BW80
  3673.    03H          3           SCREEN 0,1:WIDTH 80     MODE CO80
  3674.    04H          4           SCREEN 1,0              n/a
  3675.    05H          5           SCREEN 1,1              n/a
  3676.    06H          6           SCREEN 2                n/a
  3677.    07H          7           n/a                     MODE MONO
  3678.    ──────────────────────────────────────────────────────────────────────────
  3679.  
  3680.    Figure 4-3.  The BASIC and DOS commands used to change video modes.
  3681.  
  3682.  Display Resolution
  3683.  
  3684.    Video images consist of a large number of closely spaced pixels. The
  3685.    display resolution is defined by the number of pixel rows, or scan lines,
  3686.    from top to bottom and the number of pixels from left to right in each
  3687.    scan line. The horizontal and vertical resolution is limited by the
  3688.    capabilities of the video monitor as well as the display circuitry inside
  3689.    the computer. The video modes available on the different subsystems were
  3690.    carefully designed so that the horizontal and vertical resolution in each
  3691.    mode is within the limits imposed by the hardware.
  3692.  
  3693.    The MDA's single text mode has 720 x 350 pixel resolution; that is, the
  3694.    screen has 350 scan lines, each of which contains 720 pixels. Because 25
  3695.    rows of 80 characters of text are displayed in this mode, each character
  3696.    is 9 pixels wide (720 ÷ 80) and 14 pixels high (350 ÷ 25). The CGA's text
  3697.    modes are a bit lower resolution, because the CGA's pixel resolution is
  3698.    only 640 x 200. Thus the 25 rows of 80-character text on a CGA consist of
  3699.    characters that are only 8 pixels wide (640 ÷ 80) and 8 pixels high (200 ÷
  3700.    25). That's why text looks sharper on an MDA screen than on a CGA.
  3701.  
  3702.    The trend in the newer IBM video subsystems is to provide better vertical
  3703.    resolution. For example, the EGA's 80 x 25 text mode has 640 x 350 pixel
  3704.    resolution, so text characters are 8 x 14 pixels. On the MCGA, the default
  3705.    80 x 25 text mode has 640 x 400 resolution (8 x 16 characters), and on the
  3706.    VGA the same text mode has 720 x 400 resolution, so characters are each 9
  3707.    pixels wide and 16 pixels high. From a program's point of view, the 80 x
  3708.    25 text mode is the same on the CGA, the MCGA, and the VGA──it's display
  3709.    mode 3 in all cases──but a user sees much higher resolution when using a
  3710.    VGA or MCGA than when using one of the older subsystems.
  3711.  
  3712.    You see the same trend towards better resolution when you examine the
  3713.    graphics modes available with the newer video subsystems. The VGA's 640 x
  3714.    480, 16-color mode has more than twice as many pixels on the screen as the
  3715.    original CGA's 640 x 200 graphics mode. It's ironic that this CGA mode was
  3716.    known as a "high-resolution" mode when the CGA was new.
  3717.  
  3718.  
  3719.  The Use of Color
  3720.  
  3721.    A variety of colors is available in every video mode except of course on a
  3722.    monochrome display. You may have noticed that among the various modes
  3723.    there are substantial differences in the number of colors available. In
  3724.    this section, we will describe the color options for the video modes.
  3725.  
  3726.    Colors for the video display screens are produced by combinations of four
  3727.    elements: three color components──red, green, and blue──plus an intensity,
  3728.    or brightness, component. Text and graphics modes use the same colors and
  3729.    intensity options, but they combine them in different ways to produce
  3730.    their colored displays. The text modes, whose basic unit is a character
  3731.    composed of several pixels, use an entire byte to set the color, the
  3732.    intensity, and the blinking characteristics of the character and its
  3733.    background. In graphics modes, each pixel is represented by a group of 1
  3734.    through 8 bits whose value determines the color and brightness of the
  3735.    displayed pixel.
  3736.  
  3737.    In 16-color text and graphics modes, the four basic color and brightness
  3738.    components can be combined in 16 ways. Colors are specified by a group of
  3739.    4 bits. Each bit designates whether a particular color component is on or
  3740.    off. The result is 16 color combinations that correspond to the 16 4-bit
  3741.    binary numbers. (See Figure 4-4.)
  3742.  
  3743.    In some video modes, the data in the video buffer consists of 4-bit
  3744.    attribute values that correspond exactly to the 16 possible color
  3745.    combinations on the screen. In other video modes, the attribute values do
  3746.    not directly specify colors. For example, on the EGA, each attribute value
  3747.    designates one of 16 palette registers, each of which contains a color
  3748.    value. (See Figure 4-5.) It is the palette color values that determine
  3749.    the color combinations displayed on the screen.
  3750.  
  3751.    Intensity Red       Green    Blue      Binary    Hex       Description
  3752.    ───────────────────────────────────────────────────────────────────────────
  3753.    0         0         0        0         0000B     00H       Black
  3754.    0         0         0        1         0001B     01H       Blue
  3755.    0         0         1        0         0010B     02H       Green
  3756.    0         0         1        1         0011B     03H       Cyan (blue-green
  3757.    0         1         0        0         0100B     04H       Red
  3758.    0         1         0        1         0101B     05H       Magenta
  3759.    0         1         1        0         0110B     06H       Brown (or dark
  3760.                                                               yellow)
  3761.    0         1         1        1         0111B     07H       Light gray (or
  3762.                                                               ordinary white)
  3763.    1         0         0        0         1000B     08H       Dark gray (black
  3764.                                                               many screens)
  3765.    1         0         0        1         1001B     09H       Light blue
  3766.    1         0         1        0         1010B     0AH       Light green
  3767.    1         0         1        1         1011B     0BH       Light cyan
  3768.    1         1         0        0         1100B     0CH       Light red
  3769.    1         1         0        1         1101B     0DH       Light magenta
  3770.    1         1         1        0         1110B     0EH       Yellow (or light
  3771.                                                               yellow)
  3772.    1         1         1        1         1111B     0FH       Bright white
  3773.    ───────────────────────────────────────────────────────────────────────────
  3774.  
  3775.    Figure 4-4.  Default colors available in 16-color text and graphics modes.
  3776.  
  3777.    ┌──────────────────────────────────── ┌─────────────┐
  3778.    │ 0110 1010 1010 0111 0101 0101 1101  │▒▒▒▒▒▒▒▒▒▒▒▒▒│
  3779.    │                └─┬┘                 ├─────────────┤
  3780.    │                  │                  │▒▒▒▒▒▒▒▒▒▒▒▒▒│
  3781.    │                  │                  ├─────────────┤
  3782.    │                  │                  │▒▒▒▒▒▒▒▒▒▒▒▒▒│
  3783.    │                  │                  ├─────────────┤
  3784.    │                  │                  │▒▒▒▒▒▒▒▒▒▒▒▒▒│
  3785.    │                  │                  ├─────────────┤    ┌──────────
  3786.    │                  └─────────────────│ Color value ├───│ ┌────────
  3787.    │                                     ├─────────────┤    │ │ ▒
  3788.    │                                     │▒▒▒▒▒▒▒▒▒▒▒▒▒│    │ │
  3789.    │                                     ├─────────────┤    │ │
  3790.    │                                     │▒▒▒▒▒▒▒▒▒▒▒▒▒│    │ │
  3791.                                          ├─────────────┤
  3792.                                          │▒▒▒▒▒▒▒▒▒▒▒▒▒│
  3793.               Attribute value in         └─────────────┘     Color on
  3794.                  video buffer           Pallette registers    screen
  3795.  
  3796.    Figure 4-5.  How EGA colors are specified using palette registers. Each
  3797.    attribute value in the video buffer designates a palette register whose
  3798.    contents specify a color.
  3799.  
  3800.    The use of palettes makes it possible to specify one of a broad range of
  3801.    colors using relatively few bits of data in the video buffer. Each of the
  3802.    EGA's 16 palette registers, for example, can contain one of 64 different
  3803.    6-bit color values. In this way, any 2 of 64 different colors can be used
  3804.    in a 2-color EGA video mode, any 4 out of 64 can be used in a 4-color
  3805.    mode, and any 16 of 64 can be used in a 16-color mode.
  3806.  
  3807.    All IBM video subsystems except the MDA can use palettes to display
  3808.    colors. The CGA has three built-in, 4-color palettes for use in 320 x 200,
  3809.    4-color mode. The EGA, as we have seen, has a 16-color palette in which
  3810.    each color can be selected from a set of 64 colors. The MCGA and the VGA,
  3811.    which can display an even wider range of colors, use a separate
  3812.    palette-like component, the video digital to analog converter (video DAC),
  3813.    to send color signals to the screen.
  3814.  
  3815.    The video DAC contains 256 color registers, each of which contains 6-bit
  3816.    color values for red, green, and blue. Since there are 64 possible values
  3817.    for each of the RGB components, each video DAC color register can contain
  3818.    one of 64 x 64 x 64, or 262,144 different color values. That wide range of
  3819.    colors can help you display very subtle color shades and contours.
  3820.  
  3821.    With the MCGA, the video DAC color registers serve much the same purpose
  3822.    as the palette registers do with the EGA. Attribute values in the video
  3823.    buffer designate video DAC color registers whose contents specify the
  3824.    colors that appear on the screen. Unfortunately, only one MCGA video mode
  3825.    can take full advantage of the video DAC's capabilities: 320 x 200,
  3826.    256-color mode. Only this video mode uses 8-bit attribute values that can
  3827.    specify all 256 of the video DAC's color registers. All remaining video
  3828.    modes use attribute values that have no more than 4 bits, so only the
  3829.    first 16 video DAC color registers are used.
  3830.  
  3831.    The VGA gets around this limitation (and complicates matters somewhat) by
  3832.    using a set of 16 palette registers like the EGA's, as well as a set of
  3833.    256 video DAC color registers like the MCGA's. An attribute value in the
  3834.    video buffer selects one of the 16 palette registers, whose contents
  3835.    select one of the 256 video DAC color registers──whose contents "in turn"
  3836.    determine the color displayed on the screen. (See Figure 4-6.)
  3837.  
  3838.    Specifying colors on an EGA, MCGA, or VGA is clearly more complicated than
  3839.    it is on the CGA. To simplify this process, however, the ROM BIOS loads
  3840.    the palette registers (on the EGA and VGA) and the video DAC color
  3841.    registers (on the MCGA and VGA) with color values that exactly match those
  3842.    available on the CGA. If you use CGA-compatible text and graphics modes on
  3843.    the newer subsystems and ignore the palette and video DAC registers,
  3844.    you'll see the same colors you would on a CGA.
  3845.  
  3846.    ┌──────────────────────────────────────
  3847.    │ 0110 1010 1010 0111 0101 0101 1101
  3848.    │                └─┬┘                            
  3849.    │                  │   ┌─────────────┐    │            │
  3850.    │                  │   │▒▒▒▒▒▒▒▒▒▒▒▒▒│    │            │
  3851.    │                  │   ├─────────────┤    ├─────────────┤
  3852.    │                  │   │▒▒▒▒▒▒▒▒▒▒▒▒▒│    │▒▒▒▒▒▒▒▒▒▒▒▒▒│
  3853.    │                  │   ├─────────────┤    ├─────────────┤
  3854.    │ Attribute value  │   │▒▒▒▒▒▒▒▒▒▒▒▒▒│    │▒▒▒▒▒▒▒▒▒▒▒▒▒│
  3855.    │ in video buffer  │   ├─────────────┤    ├─────────────┤
  3856.    │                  └──│    Color    ├─┐  │▒▒▒▒▒▒▒▒▒▒▒▒▒│
  3857.    │                      │   register  │ │  ├─────────────┤   ┌─────────
  3858.    │                      ├─────────────┤ │  │  RGB color  ├──│ ┌───────
  3859.    │                      │▒▒▒▒▒▒▒▒▒▒▒▒▒│ └─│    value    │   │ │ ▒
  3860.    │                      ├─────────────┤    ├─────────────┤   │ │
  3861.                           │▒▒▒▒▒▒▒▒▒▒▒▒▒│    │▒▒▒▒▒▒▒▒▒▒▒▒▒│   │ │
  3862.                           ├─────────────┤    ├─────────────┤   │ │
  3863.                           │▒▒▒▒▒▒▒▒▒▒▒▒▒│    │▒▒▒▒▒▒▒▒▒▒▒▒▒│   │ │
  3864.                           └─────────────┘    ├─────────────┤
  3865.                           Palette registers  │▒▒▒▒▒▒▒▒▒▒▒▒▒│    Color on
  3866.                                              ├─────────────┤     screen
  3867.                                              │            │
  3868.                                              │            │
  3869.                                                     
  3870.                                         Video DAC color registers
  3871.  
  3872.    Figure 4-6.  How VGA colors are specified using palette registers and the
  3873.    video DAC.
  3874.  
  3875.    For this reason it's usually best to ignore the palette and video DAC
  3876.    registers when you start developing an application. Once your application
  3877.    works properly with the CGA-compatible colors, you can add program code
  3878.    that changes the palette and/or the video DAC colors. The ROM BIOS
  3879.    provides a complete set of services that let you access the palette and
  3880.    video DAC registers. Chapter 9 covers these services in detail.
  3881.  
  3882.    In considering color, read each of the remaining sections, which discuss
  3883.    important color-related items.
  3884.  
  3885.  Color-Suppressed Modes
  3886.  
  3887.    In an effort to make the graphics modes compatible with a wide range of
  3888.    monitors, both color and monochrome, IBM included a few modes on the Color
  3889.    Graphics Adapter that do not produce color: color-suppressed modes. There
  3890.    are three color-suppressed modes: modes 0, 2, and 5. In these modes,
  3891.    colors are converted into shades of gray, or whatever color the screen
  3892.    phosphor produces. There are four gray shades in mode 5, and a variety of
  3893.    shades in modes 0 and 2. CGA's color is suppressed in the composite output
  3894.    but not in its RGB output. This inconsistency is the result of an
  3895.    unavoidable technical limitation.
  3896.  
  3897.    ──────────────────────────────────────────────────────────────────────────
  3898.    NOTE:
  3899.      For each color-suppressed mode, there is a corresponding color mode, so
  3900.      modes 0 and 1 correspond to 40-column text, modes 2 and 3 to 80-column
  3901.      text, and modes 4 and 5 to medium-resolution graphics. The fact that
  3902.      modes 4 and 5 reverse the pattern of modes 0 and 1 and modes 2 and 3,
  3903.      where the color-suppressed mode comes first, has led to a complication
  3904.      in BASIC. The burst parameter of the BASIC SCREEN statement controls
  3905.      color. The meaning of this parameter is reversed for modes 4 and 5 so
  3906.      that the statement SCREEN,1 activates color in the text modes (0, 1, 2,
  3907.      and 3) but suppresses color in the graphics modes (4 and 5). This
  3908.      inconsistency may have been a programming error at first, but it is now
  3909.      part of the official definition of the SCREEN statement.
  3910.    ──────────────────────────────────────────────────────────────────────────
  3911.  
  3912.  Color in Text and Graphics Modes
  3913.  
  3914.    Text and graphics modes use the same color-decoding circuitry, but differ
  3915.    in the way they store the color attribute data in the video buffer. In
  3916.    text modes, no matter what video subsystem you use, the foreground and
  3917.    background colors of each character are specified by two 4-bit fields in a
  3918.    single attribute byte. (See Figure 4-7.) Together, the foreground and
  3919.    background attributes describe all of a character's pixels: All foreground
  3920.    pixels are displayed with the character's foreground attribute, and all
  3921.    background pixels assume the background attribute.
  3922.  
  3923.          Bit
  3924.    7 6 5 4 3 2 1 0          Use
  3925.    ──────────────────────────────────────────────────────────────────────────
  3926.    1 . . . . . . .          Blinking of foreground character or intensity
  3927.                             component of background color
  3928.    . 1 . . . . . .          Red component of background color
  3929.    . . 1 . . . . .          Green component of background color
  3930.    . . . 1 . . . .          Blue component of background color
  3931.    . . . . 1 . . .          Intensity component of foreground color
  3932.    . . . . . 1 . .          Red component of foreground color
  3933.    . . . . . . 1 .          Green component of foreground color
  3934.    . . . . . . . 1          Blue component of foreground color
  3935.    ──────────────────────────────────────────────────────────────────────────
  3936.  
  3937.    Figure 4-7.  The coding of the color attribute byte.
  3938.  
  3939.    In graphics modes, each pixel's attribute is determined by the contents of
  3940.    a bit field in the video buffer. The size and format of a pixel's bit
  3941.    field depend on the video mode: The smallest bit fields are only 1 bit
  3942.    wide (as in 640 x 200, 2-color mode), and the largest bit fields are 8
  3943.    bits wide (as in 320 x 200, 256-color mode).
  3944.  
  3945.    The reason for having both text and graphics modes becomes clear if you
  3946.    think about how much data it takes to describe the pixels on the screen.
  3947.    In graphics modes, you need between 1 and 8 bits of data in the video
  3948.    buffer for every pixel you display. In 640 x 350, 16-color mode, for
  3949.    instance, with 4 bits per pixel, you need 640 x 350 x 4 ÷ 8 (112,000)
  3950.    bytes to represent one screenful of video data. But if you display 25 rows
  3951.    of 80 characters in a text mode with the same resolution, you need only 80
  3952.    x 25 x 2, or 4000, bytes.
  3953.  
  3954.    The tradeoff is clear: Text modes consume less memory and require less
  3955.    data manipulation than do graphics modes──but you can manipulate each
  3956.    pixel independently in graphics modes, as opposed to manipulating entire
  3957.    characters in text modes.
  3958.  
  3959.    Setting color in text modes
  3960.  
  3961.    Let's take a closer look at how you control colors in text modes. (We'll
  3962.    get back to graphics modes later in this chapter.) In text modes, each
  3963.    character position on the display screen is controlled by a pair of
  3964.    adjacent bytes in the video buffer. The first byte contains the ASCII code
  3965.    for the character that will be displayed. (See Appendix C for a chart of
  3966.    characters.) The second byte is the character's attribute byte. It
  3967.    controls how the character will appear, that is, its colors, brightness
  3968.    (intensity), and blinking.
  3969.  
  3970.    We've already mentioned two attributes that affect a character's
  3971.    appearance: color and intensity (brightness). You can assign several other
  3972.    attributes to text characters, depending on which video subsystem you're
  3973.    using. With all IBM video subsystems, text characters can blink. On
  3974.    monochrome-capable subsystems (the MDA, EGA, and VGA), characters can also
  3975.    be underlined. Also, on some non-IBM subsystems like the Hercules Graphics
  3976.    Card Plus, characters can have attributes such as overstrike and boldface.
  3977.  
  3978.    In all cases, you assign these alternate attributes by using the same
  3979.    4-bit attributes that specify color. A case in point is the blinking
  3980.    attribute. Character blinking is controlled by setting a bit in a special
  3981.    register in the video subsystem. (On the CGA, for example, this
  3982.    enable-blink bit is bit 5 of the 8-bit register mapped at input/output
  3983.    port 3D8H.) When this bit is set to 1, the high-order bit of each
  3984.    character's attribute byte is not interpreted as part of the character's
  3985.    background color specification. Instead, this bit indicates whether the
  3986.    character should blink.
  3987.  
  3988.    If you have a CGA, watch what happens when you run the following BASIC
  3989.    program:
  3990.  
  3991.    10 DEF SEG = &HB800             ' point to start of video buffer
  3992.    20 POKE 0,ASC("A")              ' store the ASCII code for A in the buffer
  3993.    30 POKE 1,&H97                  ' foreground attribute = 7 (white)
  3994.                                    ' background attribute = 9 (intense blue)
  3995.  
  3996.    You'll see a blinking white letter A on a blue background. If you add the
  3997.    following statement to the program, you'll clear the enable-blink bit and
  3998.    cause the CGA to interpret the background attribute as intense blue:
  3999.  
  4000.    40 OUT &H3D8,&H09               ' clear the "enable-blink" bit
  4001.  
  4002.    The default attribute used by DOS and BASIC is 07H, normal white (7) on
  4003.    black (0), without blinking, but you can use any combination of 4-bit
  4004.    foreground and background attributes for each character displayed in a
  4005.    text mode. If you exchange a character's foreground and background
  4006.    attributes, the character is displayed in "reverse video." If the
  4007.    foreground and background attributes are the same, the character is
  4008.    "invisible."
  4009.  
  4010.    Setting attributes in the monochrome mode
  4011.  
  4012.    The monochrome mode (mode 7) used by the Monochrome Display Adapter has a
  4013.    limited selection of attributes that take the place of color. Like the
  4014.    CGA, the MDA uses 4-bit foreground and background attributes, but their
  4015.    values are interpreted differently by the MDA attribute decoding
  4016.    circuitry.
  4017.  
  4018.    Only certain combinations of foreground and background attributes are
  4019.    recognized by the MDA. (See Figure 4-8.) Other useful combinations, like
  4020.    "invisible" (white-on-white) or a reverse-video/underlined combination,
  4021.    aren't supported by the hardware.
  4022.  
  4023.    Like the CGA, the MDA has an enable-blink bit that determines whether the
  4024.    high-order bit of each character's attribute byte controls blinking or the
  4025.    intensity of the background attribute. On the MDA, the enable-blink bit is
  4026.    bit 5 of the register at port 3B8H. As on the CGA, the enable-blink bit is
  4027.    set by the ROM BIOS when it establishes monochrome text mode 7, so you
  4028.    must explicitly clear this bit if you want to disable blinking and display
  4029.    characters with intensified background.
  4030.  
  4031.    With the EGA, MCGA, and VGA, text-mode attributes work the same as with
  4032.    the MDA and CGA. Although the enable-blink bit is not in the same hardware
  4033.    register in the newer subsystems, the ROM BIOS offers a service through
  4034.    interrupt 10H that toggles the bit on an EGA, MCGA, or VGA. (See Chapter
  4035.    9, page 178 for more information about this service.)
  4036.  
  4037. ╓┌─┌──────────┌──────────────────────────────────────────────────────────────╖
  4038.    Attribute  Description
  4039.    ──────────────────────────────────────────────────────────────────────────
  4040.    00H        Nondisplayed
  4041.  
  4042.    01H        Underlined
  4043.  
  4044.    07H        Normal (white on black)
  4045.  
  4046.    09H        High-intensity underlined
  4047.  
  4048.    0FH        High-intensity
  4049.  
  4050.    70H        White background, black foreground ("reverse video")
  4051.  
  4052.    87H       Blinking white on black (if blinking enabled)
  4053.               Dim background, normal foreground (if blinking
  4054.               disabled)
  4055.    Attribute  Description
  4056.    ──────────────────────────────────────────────────────────────────────────
  4057.              disabled)
  4058.  
  4059.    8FH       Blinking high-intensity (if blinking enabled)
  4060.               Dim background, high-intensity foreground (if blinking
  4061.               disabled)
  4062.  
  4063.    F0H        Blinking "reverse video" (if blinking enabled)
  4064.               High-intensity background, black foreground (if blinking
  4065.               disabled)
  4066.    ──────────────────────────────────────────────────────────────────────────
  4067.  
  4068.  
  4069.    Figure 4-8.  Monochrome text-mode attributes. The appearance of some
  4070.    attributes depends on the setting of the enable-blink bit at I/O port
  4071.    3B8H.
  4072.  
  4073.    Setting color in graphics modes
  4074.  
  4075.    So far, we've seen how to set color (and the monochrome equivalent of
  4076.    color) in text modes. Setting color in graphics modes is quite different.
  4077.    In graphics modes, each pixel is associated with a color. The color is set
  4078.    the same way attributes are set in text mode, but there are important
  4079.    differences. First, since each pixel is a discrete dot of color, there is
  4080.    no foreground and background──each pixel is simply one color or another.
  4081.    Second, pixel attributes are not always 4 bits in size──we've already
  4082.    mentioned that pixel attributes can range from 1 to 8 bits, depending on
  4083.    the video mode being used. These differences give graphics-mode programs a
  4084.    subtly different "feel" than they have in text modes, both to programmers
  4085.    and to users.
  4086.  
  4087.    The most important difference between text-mode and graphics-mode
  4088.    attributes, however, is this: In graphics modes you can control the color
  4089.    of each pixel. This lets you use colors much more effectively than you can
  4090.    in text modes. This isn't so obvious with the CGA and its limited color
  4091.    capabilities, but with an MCGA or VGA it's quite apparent.
  4092.  
  4093.    Let's start with the CGA. The CGA's two graphics modes are relatively
  4094.    limited in terms of color: In 320 x 200, 4-color mode, pixel attributes
  4095.    are only 2 bits wide, and you can display only four different colors at a
  4096.    time. In 640 x 200, 2-color mode, you have only 1 bit per pixel, so you
  4097.    can display only two different colors. Also, the range of colors you can
  4098.    display in CGA graphics modes is severely limited.
  4099.  
  4100.    In 320 x 200, 4-color mode, pixels can have value 0, 1, 2, or 3,
  4101.    corresponding to the 2-bit binary values 00B, 01B, 10B, and 11B. You can
  4102.    assign any one of the CGA's 16 color combinations to zero-value pixels,
  4103.    but colors for nonzero pixels are derived from one of three built-in
  4104.    palettes. (See Figure 4-9.) In 640 x 200, 2-color mode, nonzero pixels
  4105.    can be assigned any one of the 16 color combinations, but zero-value
  4106.    pixels are always black. In both modes, you can assign palette colors
  4107.    using ROM BIOS interrupt 10H services described in Chapter 9.
  4108.  
  4109.    The EGA, MCGA, and VGA are considerably more flexible in terms of color
  4110.    management, because you can assign any color combination to any palette or
  4111.    video DAC color register. Equally important is the fact that you have
  4112.    larger pixel values and therefore more colors to work with on the screen.
  4113.    The most frequently used graphics modes on the EGA and VGA are the
  4114.    16-color modes with pixels that require 4 bits to define the colors. In
  4115.    most applications, 16 colors are adequate, because you can select those 16
  4116.    colors from the entire range of color combinations the hardware can
  4117.    display (64 colors on the EGA and 262,144 colors on the MCGA and VGA).
  4118.    Again, the ROM BIOS provides services that let you assign arbitrary color
  4119.    combinations to the palette and video DAC color registers on the EGA,
  4120.    MCGA, and VGA. See Chapter 9 for details.
  4121.  
  4122.    Pixel Bits               Pixel Value             Pixel Color
  4123.    ──────────────────────────────────────────────────────────────────────────
  4124.    Mode 4, palette 0:
  4125.    0 1                      1                       Green
  4126.    1 0                      2                       Red
  4127.    1 1                      3                       Yellow or brown
  4128.  
  4129.    Mode 4, palette 1:
  4130.    0 1                      1                       Cyan
  4131.    1 0                      2                       Magenta
  4132.    1 1                      3                       White
  4133.  
  4134.    Mode 5:
  4135.    0 1                      1                       Cyan
  4136.    1 0                      2                       Red
  4137.    1 1                      3                       White
  4138.    ──────────────────────────────────────────────────────────────────────────
  4139.  
  4140.    Figure 4-9.  Palettes in CGA 320 x 200, 4-color graphics mode.
  4141.  
  4142.  
  4143.  Inside the Display Memory
  4144.  
  4145.    Now we come to the inner workings of the video buffer map. In this
  4146.    section, we'll see how the information in the video memory is related to
  4147.    the display screen.
  4148.  
  4149.    Although the video buffer memory map varies according to the video mode
  4150.    you use, a clear family resemblance exists among the video modes. In text
  4151.    modes, the video buffer map in all IBM video subsystems is the same. In
  4152.    graphics modes, there are two general layouts, a linear map based on the
  4153.    map used with the original CGA graphics modes and a parallel map that was
  4154.    first used in EGA graphics modes.
  4155.  
  4156.    Video Mode     Starting       Memory Used   Subsystem
  4157.                   Paragraph      (bytes)
  4158.                   Address (hex)
  4159.    ──────────────────────────────────────────────────────────────────────────
  4160.    00H, 01H       B800H             2000       CGA, EGA, MCGA, VGA
  4161.    02H, 03H       B800H             4000       CGA, EGA, MCGA, VGA
  4162.    04H, 05H       B800H           16,000       CGA, EGA, MCGA, VGA
  4163.    06H            B800H           16,000       CGA, EGA, MCGA, VGA
  4164.    07H            B000H             4000       MDA, EGA, VGA
  4165.    0DH            A000H           32,000       EGA, VGA
  4166.    0EH            A000H           64,000       EGA, VGA
  4167.    0FH            A000H           56,000       EGA, VGA
  4168.    10H            A000H          112,000       EGA, VGA
  4169.    11H            A000H           38,400       MCGA, VGA
  4170.    12H            A000H          153,600       VGA
  4171.    13H            A000H           64,000       MCGA, VGA
  4172.    ──────────────────────────────────────────────────────────────────────────
  4173.  
  4174.    Figure 4-10.  Video buffer addresses in IBM video modes.
  4175.  
  4176.    Before we examine the actual map of the video buffer, let's look at the
  4177.    addresses where the video buffer is located. (See Figure 4-10.) The
  4178.    breakdown is straightforward: Color text modes start at paragraph address
  4179.    B800H, and monochrome text mode starts at B000H. CGA-compatible graphics
  4180.    modes start at B800H. All other graphics modes start at A000H. The amount
  4181.    of RAM required to hold a screenful of data varies according to the number
  4182.    of characters or pixels displayed, and, in the case of graphics modes,
  4183.    with the number of bits that represent a pixel.
  4184.  
  4185.  Display Pages in Text Modes
  4186.  
  4187.    The amount of RAM physically installed in the various video subsystems is
  4188.    frequently more than enough to contain more than one screen's worth of
  4189.    video data. In video modes where this is true, all IBM video subsystems
  4190.    support multiple display pages. When you use display pages, the video
  4191.    buffer is mapped into two or more areas, and the video hardware is set up
  4192.    to selectively display any one of these areas in the map.
  4193.  
  4194.    Because only one page is displayed at any given time, you can write
  4195.    information into nondisplayed pages as well as directly to the displayed
  4196.    page. Using this technique you can build a screen on an invisible page
  4197.    while another page is being displayed and then switch to the new page when
  4198.    the appropriate time comes. Switching screen images this way makes screen
  4199.    updates seem instantaneous.
  4200.  
  4201.    The display pages are numbered 0 through 7, with page 0 starting at the
  4202.    beginning of the video buffer. Of course, the amount of available RAM may
  4203.    be insufficient to support eight full display pages; the actual number of
  4204.    pages you can use (see Figure 4-11) depends on how much video RAM is
  4205.    available and on how much memory is required for one screenful of data.
  4206.    Each page begins on an even kilobyte memory boundary. The display page
  4207.    offset addresses are shown in Figure 4-12.
  4208.  
  4209.    To select a display page, use ROM BIOS interrupt 10H, service 05H. To
  4210.    determine which page is actively displayed, use interrupt 10H, service
  4211.    0FH. (See Chapter 9 for information about these ROM BIOS services.)
  4212.  
  4213.    In any of these modes, if the pages are not actively used (actually
  4214.    displayed on the screen), then the unused part of the display memory can
  4215.    conceivably be used for data besides text or pixels, although this usage
  4216.    is neither normal nor advisable. Making any other use of this potentially
  4217.    free memory is asking for trouble in the future.
  4218.  
  4219.                                         Number of
  4220.    Video Mode  Subsystem                Pages       Notes
  4221.    ──────────────────────────────────────────────────────────────────────────
  4222.    00H, 01H    CGA, EGA, MCGA, VGA      8
  4223.    02H, 03H    CGA                      4
  4224.                EGA, MCGA, VGA           8
  4225.    04H, 05H    CGA, MCGA                1
  4226.                EGA, VGA                 2           Not fully supported by
  4227.                                                     ROM BIOS
  4228.    06H         CGA, EGA, MCGA, VGA      1
  4229.    07H         MDA                      1
  4230.                EGA, VGA                 8
  4231.    0DH         EGA, VGA                 8
  4232.    0EH         EGA, VGA                 4
  4233.    0FH         EGA, VGA                 2
  4234.    10H         EGA, VGA                 2
  4235.    11H         MCGA, VGA                1
  4236.    12H         VGA                      1
  4237.    13H         MCGA, VGA                1
  4238.    ──────────────────────────────────────────────────────────────────────────
  4239.  
  4240.    Figure 4-11.  Display pages available in IBM video subsystems.
  4241.  
  4242.    Page   40 x 25, 16-color      80 x 25, 16-color     80 x 25 Mono
  4243.    ──────────────────────────────────────────────────────────────────────────
  4244.    0      B800:0000H             B800:0000H            B000:0000H
  4245.    1      B800:0800H             B800:1000H            B000:1000H
  4246.    2      B800:1000H             B800:2000H            B000:2000H
  4247.    3      B800:1800H             B800:3000H            B000:3000H
  4248.    4      B800:2000H             B800:4000H           B000:4000H
  4249.    5      B800:2800H             B800:5000H           B000:5000H
  4250.    6      B800:3000H             B800:6000H           B000:6000H
  4251.    7      B800:3800H             B800:7000H           B000:7000H
  4252.    ──────────────────────────────────────────────────────────────────────────
  4253.  
  4254.    Figure 4-12.  Start addresses for text-mode display pages in IBM video
  4255.    subsystems.
  4256.  
  4257.  Display Pages in Graphics Modes
  4258.  
  4259.    For the EGA, the MCGA, and the VGA, the page concept is as readily
  4260.    available in graphics modes as in text modes. Obviously there is no reason
  4261.    not to have graphics pages if the memory is there to support them.
  4262.  
  4263.    The main benefit of using multiple pages for either graphics or text is to
  4264.    be able to switch instantly from one display screen to another without
  4265.    taking the time to build the display information from scratch. In theory,
  4266.    multiple pages could be used in graphics mode to produce smooth and
  4267.    fine-grained animation effects, but there aren't enough display pages to
  4268.    take the animation very far.
  4269.  
  4270.  Displaying Characters in Text and Graphics Modes
  4271.  
  4272.    As you have learned, in text modes no character images are stored in video
  4273.    memory. Instead, each character is represented in the video buffer by a
  4274.    pair of bytes containing the character's ASCII value and display
  4275.    attributes. The pixels that make up the character are drawn on the screen
  4276.    by a character generator that is part of the display circuitry. The Color
  4277.    Graphics Adapter has a character generator that produces characters in an
  4278.    8 x 8 pixel block format, while the Monochrome Display Adapter's character
  4279.    generator uses a 9 x 14 pixel block format. The larger format is one of
  4280.    the factors that makes the MDA's display output easier to read.
  4281.  
  4282.    The standard ASCII characters (01H through 7FH [decimal 1 through 127])
  4283.    represent only half of the ASCII characters available in the text modes.
  4284.    An additional 128 graphics characters (80H through FFH [decimal 128
  4285.    through 255]) are available through the same character generator. More
  4286.    than half of them can be used to make simple line drawings. A complete
  4287.    list of both the standard ASCII characters and the graphics characters
  4288.    provided by IBM is given in Appendix C.
  4289.  
  4290.    The graphics modes can also display characters, but they are produced
  4291.    quite differently. Graphics-mode characters are drawn, pixel by pixel, by
  4292.    a ROM BIOS software character generator, instead of by a hardware
  4293.    character generator. (ROM BIOS interrupt 10H provides this service; see
  4294.    Chapter 9.) The software character generator refers to a table of bit
  4295.    patterns to determine which pixels to draw for each character. The ROM of
  4296.    every PC and PS/2 contains a default table of character bit patterns, but
  4297.    you can also place a custom bit pattern table in RAM and instruct the BIOS
  4298.    to use it to display your own character set.
  4299.  
  4300.    In CGA-compatible graphics modes (640 x 200, 2-color and 320 x 200,
  4301.    4-color), the bit patterns for the second 128 ASCII characters are always
  4302.    found at the address stored in the interrupt 1FH vector at 0000:007CH. If
  4303.    you store a table of bit patterns in a buffer and then store the buffer's
  4304.    segment and offset at 0000:007CH, the ROM BIOS will use the bit patterns
  4305.    in the buffer for ASCII characters 80H through FFH (decimal 128 through
  4306.    255. In other graphics modes on the EGA, MCGA, and VGA, the ROM BIOS
  4307.    provides a service through interrupt 10H that lets you pass the address of
  4308.    a RAM-based table of character bit patterns for all 256 characters.
  4309.  
  4310.    Mapping characters in text modes
  4311.  
  4312.    In text modes, the memory map begins with the top left corner of the
  4313.    screen, using 2 bytes per screen position. The memory bytes for succeeding
  4314.    characters immediately follow in the order you would read them──from left
  4315.    to right and from top to bottom.
  4316.  
  4317.    Modes 0 and 1 are text modes with a screen format of 40 columns by 25
  4318.    rows. Each row occupies 40 x 2 = 80 bytes. A screen occupies only 2 KB in
  4319.    modes 0 and 1, which means the CGA's 16 KB memory can accommodate eight
  4320.    display pages. If the rows are numbered 0 through 24 and the columns
  4321.    numbered 0 through 39, then the offset to any screen character in the
  4322.    first display page is given by the following BASIC formula:
  4323.  
  4324.    CHARACTER.OFFSET = (ROW.NUMBER * 80) + (COLUMN.NUMBER * 2)
  4325.  
  4326.    Since the attribute byte for any character is in the memory location next
  4327.    to the ASCII character value, you can locate it by simply adding 1 to the
  4328.    character offset.
  4329.  
  4330.    Modes 2, 3, and 7 are also text modes, but with 80 columns in each row
  4331.    instead of 40. The byte layout is the same, but each row requires twice as
  4332.    many bytes, or 80 x 2 = 160 bytes. Consequently, the 80 x 25 screen format
  4333.    uses 4 KB, and the 16 KB memory can accommodate four display pages. The
  4334.    offset to any screen location in the first display page is given by the
  4335.    following BASIC formula:
  4336.  
  4337.    CHARACTER.OFFSET = (ROW.NUMBER * 160) + (COLUMN.NUMBER * 2)
  4338.  
  4339.    The beginning of each text display page traditionally starts at an even
  4340.    kilobyte boundary. Because each screen page in the text modes actually
  4341.    uses only 2000 or 4000 bytes, some unused bytes follow each page: either
  4342.    48 or 96 bytes, depending on the size of the page. So, to locate any
  4343.    screen position on any page in text mode, use the general formula shown on
  4344.    the next page.
  4345.  
  4346.    LOCATION = (SEGMENT.PARAGRAPH * 16)
  4347.               + (PAGE.NUMBER * PAGE.SIZE) + (ROW.NUMBER * ROW.WIDTH * 2)
  4348.               + (COLUMN.NUMBER * 2) + WHICH
  4349.    LOCATION  is the 20-bit address of the screen information.
  4350.    SEGMENT.PARAGRAPH  is the location of the video display memory
  4351.    (for example, B000H or B800H).
  4352.    PAGE.NUMBER  is in the range 0 through 3 or 0 through 7.
  4353.    PAGE.SIZE  is 2000 or 4000.
  4354.    ROW.NUMBER  is from 0 through 24.
  4355.    ROW.WIDTH  is 40 or 80.
  4356.    COLUMN.NUMBER  is from 0 through 39 or 0 through 79.
  4357.    WHICH  is 0 for the display character or 1 for the display attribute.
  4358.  
  4359.    Mapping pixels in graphics modes
  4360.  
  4361.    When you use a graphics mode, pixels are stored as a series of bit fields,
  4362.    with a one-to-one correlation between the bit fields in memory and the
  4363.    pixels on the screen. The actual mapping of bit fields in the video buffer
  4364.    depends on the video mode.
  4365.  
  4366.    In CGA-compatible graphics modes, the display is organized into 200 lines,
  4367.    numbered 0 through 199. Each line of pixels is represented in the video
  4368.    buffer in 80 bytes of data. In 640 x 200, 2-color mode, each bit
  4369.    represents one pixel on the screen, while in 320 x 200, 4-color mode, each
  4370.    pixel is represented by a pair of bits in the buffer. (See Figure 4-13.)
  4371.    Thus there are eight pixels to each byte in 640 x 200, 2-color mode, and
  4372.    80 x 8, or 640, pixels per row. Similarly, there are four pixels to each
  4373.    byte in 320 x 200, 4-color mode, and 80 x 4, or 320, pixels per row.
  4374.  
  4375.    The storage for the pixel rows is interleaved:
  4376.  
  4377.    ■  Pixels in even-numbered rows are stored in the first half of the video
  4378.       buffer, starting at B800:0000H.
  4379.  
  4380.    ■  Pixels in odd-numbered rows are stored starting at B800:2000H.
  4381.  
  4382.    For example, in 640 x 200, 2-color mode, the first pixel in the first row
  4383.    (in the upper-left corner of the screen) is represented by the leftmost
  4384.    bit (bit 7) in the byte at B800:0000H. The second pixel in the row is
  4385.    represented by bit 6 of the same byte. Because of the interleaved buffer
  4386.    map, however, the pixel immediately below the first pixel is represented
  4387.    in bit 7 of the byte at B800:2000H.
  4388.  
  4389.    640 x 200, 2-color mode            320 x 200, 4-color mode
  4390.  
  4391.              bit                                bit
  4392.        7 6 5 4 3 2 1 0                    7 6 5 4 3 2 1 0
  4393.     ┌───────────────────┐              ┌───────────────────┐
  4394.     │  1 0 0 0 1 1 1 1  │              │  1 1 0 0 0 1 0 1  │
  4395.     └──┼─┼─┼─┼─┼─┼─┼─┼──┘              └──┬─┬─┬─┬─┬─┬─┬─┬──┘
  4396.        │ │ │ │ │ │ │ │                    └┬┘ └┬┘ └┬┘ └┬┘
  4397.    ┌───│─│─│─│─│─│─│─│───────         ┌────│───│───│───│────────
  4398.    │┌──│─│─│─│─│─│─│─│───────         │┌───│───│───│───│────────
  4399.    ││                         ││            
  4400.    ││  ▓    ▓ ▓ ▓ ▓                ││   ▒      ▓   ▓
  4401.    ││                                 ││
  4402.    ││                                 ││
  4403.    ││                                 ││
  4404.  
  4405.    Figure 4-13.  Pixel mapping in CGA-compatible graphics modes.
  4406.  
  4407.    In all other graphics modes, the buffer map is linear, as it is in text
  4408.    modes. Pixels are stored from left to right in each byte, and one row of
  4409.    pixels immediately follows another in the video buffer. On the MCGA and
  4410.    VGA, for example, the 1-bit pixels in 640 x 480, 2-color mode and the
  4411.    8-bit pixels in 320 x 200, 256-color mode are stored starting at
  4412.    A000:0000H and proceeding linearly through the buffer.
  4413.  
  4414.    The catch is that pixel bit fields are not always mapped linearly in all
  4415.    video modes. On the EGA and VGA, the video buffer in 16-color graphics
  4416.    modes is arranged as a set of four parallel memory maps. In effect, the
  4417.    video memory is configured to have four 64 KB memory maps spanning the
  4418.    same range of addresses starting at A000:0000H. The EGA and VGA have
  4419.    special circuitry that accesses all four memory maps in parallel. Thus in
  4420.    16-color EGA and VGA graphics modes, each 4-bit pixel is stored with 1 bit
  4421.    in each memory map. (See Figure 4-14.) Another way to visualize this is
  4422.    that a 4-bit pixel value is formed by concatenating corresponding bits
  4423.    from the same address in each memory map.
  4424.  
  4425.    There is a good reason why the EGA and VGA were designed to use parallel
  4426.    memory maps in graphics modes. Consider the situation in 640 x 350,
  4427.    16-color mode: With 4 bits per pixel, you need 640 x 350 x 4 (896,000)
  4428.    bits to store one screenful of pixels. That comes out to 112,000 bytes,
  4429.    which is bigger than the 64 KB maximum size of one 8086 segment. If you
  4430.    organize the pixel data in parallel, however, you only need 112,000 ÷ 4
  4431.    (28,000) bytes in each memory map.
  4432.  
  4433.    With this variety of memory maps and pixel sizes, it's fortunate that the
  4434.    ROM BIOS provides services that let you read and write individual pixels
  4435.    regardless of the video mode. (Chapter 9 describes these services.)
  4436.    Unfortunately, these ROM BIOS pixel-manipulation services are pretty slow.
  4437.    If you're working in graphics modes, you'll probably find that the
  4438.    graphics drawing functions provided in your programming language (such as
  4439.    the PSET, LINE, and CIRCLE functions in BASIC) are the best tools for
  4440.    creating graphics-mode screens.
  4441.  
  4442.                ┌───────────────────┐
  4443.    Parallel    │  1 0 1 1 0 1 0 1  │ Map 3
  4444.    memory      └──┬─┬─┬─┬─┬─┬─┬─┬──┘
  4445.    maps        ┌──┴─┴─┴─┴─┴─┴─┴─┴──┐
  4446.                │  1 0 0 0 0 0 0 0  │ Map 2
  4447.                └──┬─┬─┬─┬─┬─┬─┬─┬──┘
  4448.                ┌──┴─┴─┴─┴─┴─┴─┴─┴──┐
  4449.                │  1 0 1 1 0 1 1 1  │ Map 1
  4450.                └──┬─┬─┬─┬─┬─┬─┬─┬──┘
  4451.                ┌──┴─┴─┴─┴─┴─┴─┴─┴──┐
  4452.                │  1 0 1 1 0 0 0 1  │ Map 0
  4453.                └──┬─┬─┬─┬─┬─┬─┬─┬──┘
  4454.         ┌─────────┘ │ │┌┘ └┐│ │ └─────────┐
  4455.         │    ┌──────Pixel values─────┐    │
  4456.         │    │    ┌───┘│   │└───┐    │    │
  4457.       ┌─┴┐ ┌─┴┐ ┌─┴┐ ┌─┴┐ ┌┴─┐ ┌┴─┐ ┌┴─┐ ┌┴─┐
  4458.       1111 0000 1011 1011 0000 1010 0010 1011
  4459.         │    │    └───┐│   │┌───┘    │    │
  4460.         │    └──────┐ │└┐ ┌┘│ ┌──────┘    │
  4461.         └─────────┐ │ │ │ │ │ │ ┌─────────┘
  4462.               ┌───│─│─│─│─│─│─│─│───────
  4463.               │┌──│─│─│─│─│─│─│─│───────
  4464.               ││         
  4465.               ││  ▒  ▓ ▓  ▓ ▓ ▓
  4466.               ││
  4467.  
  4468.    Figure 4-14.  Pixel mapping in 16-color EGA and VGA graphics modes.
  4469.  
  4470.  
  4471.  Controlling the Video Display
  4472.  
  4473.    In general, control of the display screen, like most other computer
  4474.    operations, can be done in four ways:
  4475.  
  4476.    ■  By using the programming-language services (for example, BASIC's SCREEN
  4477.       statement)
  4478.  
  4479.    ■  By using the DOS services (see Chapters 16 and 17)
  4480.  
  4481.    ■  By using the ROM BIOS video services (see Chapter 9)
  4482.  
  4483.    ■  By direct manipulation of the hardware via memory or I/O ports
  4484.  
  4485.    The video services available through programming languages, DOS, and the
  4486.    ROM BIOS automatically place screen output data in the video buffer, with
  4487.    each type of service offering varying levels of control. The ROM BIOS
  4488.    services are particularly powerful, providing nearly all the functions
  4489.    needed to generate display-screen output, control the cursor, and
  4490.    manipulate screen information. (All video services are fully described in
  4491.    Chapter 9.) For maximum control over the video display, you also have the
  4492.    option of bypassing the software services and placing data directly in the
  4493.    video buffer──when you feel you have good reason to.
  4494.  
  4495.    ──────────────────────────────────────────────────────────────────────────
  4496.    About the Cursor
  4497.      A blinking cursor is a feature of the text modes that is used to
  4498.      indicate the active location on the display screen. The cursor is
  4499.      actually a group of scan lines that fill the entire width of the
  4500.      character box. The size of the character-box varies with the video
  4501.      hardware and video mode: The Monochrome Display Adapter uses a
  4502.      9-pixels-wide-by-14-scan-lines-high format; the Color Graphics Adapter
  4503.      uses an 8-pixels-by-8-scan-lines format; the EGA's default text-mode
  4504.      character box is 8 pixels wide by 14 scan lines high; and the VGA's is 9
  4505.      by 16. The higher-resolution video subsystems use character boxes with
  4506.      more scan lines, so their text-mode characters appear sharper and more
  4507.      detailed, as you'll see in Appendix C.
  4508.  
  4509.      The default cursor format uses two scan lines near the bottom of the
  4510.      character box but may be changed to display any number of scan lines
  4511.      within the character box. Since the blinking cursor used in text modes
  4512.      is a hardware-created feature, software has only limited control over
  4513.      it.
  4514.  
  4515.      You can change the size of the cursor as well as its location on the
  4516.      screen using the services provided by the ROM BIOS. Interrupt 10H,
  4517.      service 01H lets you set the size of the cursor, whereas service 02H
  4518.      lets you move the cursor to any character position on the screen. The
  4519.      ROM BIOS also provides a service (interrupt 10H, service 03H) that
  4520.      reports the current size and location of the cursor.
  4521.  
  4522.      So far, we've been talking about the text-mode cursor. In graphics modes
  4523.      there is no hardware-generated cursor, but the ROM BIOS routines keep
  4524.      track of a logical cursor location that tells you the active screen
  4525.      location. As in text modes, you can use ROM BIOS services 02H and 03H to
  4526.      keep track of the graphics-mode cursor location.
  4527.  
  4528.      To create a cursor in graphics modes, many programs, including BASIC,
  4529.      simulate the block cursor by using a distinctive background color at the
  4530.      cursor location or by using the ASCII block characters.
  4531.    ──────────────────────────────────────────────────────────────────────────
  4532.  
  4533.    Before opting for direct video output, you should know that it does
  4534.    interfere with windowing systems and more advanced multitasking operating
  4535.    environments. All the same, many important programs for the PC family
  4536.    generate direct video output──so many, in fact, that this has become a
  4537.    standard and accepted way of creating output. So, even though in the long
  4538.    run it's probably not wise to place output directly in the video buffer,
  4539.    everyone seems to be doing it.
  4540.  
  4541.    Basically, you can't mix programs that write directly into the display
  4542.    memory and windowing systems because two programs would be fighting over
  4543.    the control of the same memory and messing up each other's data. But
  4544.    because so many programs now generate direct video output, multitasking
  4545.    operating systems like OS/2 go to great lengths to accommodate programs
  4546.    that write directly to the display memory. A system like OS/2 can make
  4547.    this accommodation simply by keeping a separate copy of the program's
  4548.    display memory; when the program is running, the copy is moved into the
  4549.    display buffer, and when the program is stopped, a fresh copy of the
  4550.    display buffer is made. This technique allows OS/2 to run programs that
  4551.    work directly with the display memory, but at a cost: First, computing and
  4552.    memory overhead go up; second, the program can't run in the background
  4553.    simultaneously with other programs; and third, the display information
  4554.    can't be "windowed"; that is, it can't be moved or adjusted in size.
  4555.  
  4556.    Programmers are faced with a conflict here: Direct output to the screen
  4557.    has the benefit of speed and power, but using ROM BIOS or higher-level
  4558.    services for screen output has the benefit of more flexibility for
  4559.    adapting to windowing systems, new video hardware, and so on. The best
  4560.    solution is to use both techniques, trading off portability whenever
  4561.    maximum performance is an absolute priority.
  4562.  
  4563.  Direct Hardware Control
  4564.  
  4565.    Much of the information we've provided in this chapter, particularly
  4566.    information on internal mapping of display memory, is meant to help you
  4567.    write video information directly into the display memory. But remember
  4568.    that direct programming has inherent risks, and you'll find it both safer
  4569.    and easier to use the highest available means to control the video
  4570.    display. Lower-level means, particularly direct manipulation, can be very
  4571.    disruptive.
  4572.  
  4573.    More important, it's not always easy to write "well-behaved" programs that
  4574.    access video hardware directly. There are several reasons for this. One is
  4575.    simply that there is a lot of different video hardware to worry about.
  4576.    Apart from the five IBM video subsystems we've discussed here, many
  4577.    non-IBM video adapters and built-in video subsystems exist in non-IBM
  4578.    computers. If you write a program that programs a particular IBM video
  4579.    subsystem directly, the program probably won't be portable to a different
  4580.    IBM subsystem or to non-IBM hardware.
  4581.  
  4582.    We've already mentioned another reason to avoid direct video hardware
  4583.    programming: Multitasking or windowing operating systems must work
  4584.    overtime to accommodate programs that directly access video hardware. Of
  4585.    course, the designers of newer PC and PS/2 operating environments are well
  4586.    aware of the need for good video performance, so modern operating systems
  4587.    generally offer faster and more flexible video output services than do
  4588.    older systems, such as DOS. Direct hardware programming offers little
  4589.    advantage if the operating system's video I/O services are fast enough.
  4590.  
  4591.    Also, direct video hardware control can get you into trouble with the ROM
  4592.    BIOS if you aren't careful. The ROM BIOS keeps track of the video hardware
  4593.    status in a set of variables in the data area in segment 40H. (See Chapter
  4594.    3 for a list of ROM BIOS video status variables.) If you program the
  4595.    video hardware directly, you must be careful to update the ROM BIOS status
  4596.    variables accordingly.
  4597.  
  4598.    For example, the simple routine we presented earlier for resetting the CGA
  4599.    enable-blink bit bypasses a ROM BIOS status variable. To update the
  4600.    enable-blink bit without causing the ROM BIOS to lose track of the video
  4601.    hardware state, you would update the ROM BIOS status variable at
  4602.    0040:0065H:
  4603.  
  4604.    10 DEF SEG = &HB800             ' (same as before)
  4605.    20 POKE 0,ASC("A")
  4606.    30 POKE 1,&H97
  4607.    40 DEF SEG = &H0040             ' address the BIOS data area
  4608.    50 POKE &H0065,(PEEK(&H0065) AND NOT &H20) ' update BIOS status variable
  4609.    60 OUT &H3D8,PEEK(&H0065)       ' update hardware register
  4610.  
  4611.    If you program carefully, controlling the video hardware directly can be
  4612.    very rewarding. You can maximize the speed of your video output as well as
  4613.    take full advantage of hardware capabilities such as smooth,
  4614.    pixel-by-pixel panning or hardware-generated interrupts. But when you
  4615.    write such a program, keep the pitfalls in mind.
  4616.  
  4617.  
  4618.  Compatibility Considerations
  4619.  
  4620.    If you want your program to run on a wide variety of PCs and PS/2s, you
  4621.    must design compatibility into the program. As the various IBM video
  4622.    subsystems have evolved, programmers have developed several approaches to
  4623.    compatibility. These include
  4624.  
  4625.    ■  Installable programs
  4626.  
  4627.    ■  Self-installing programs
  4628.  
  4629.    ■  Hardware-independent programming environments
  4630.  
  4631.    We've already mentioned how many software vendors provide video
  4632.    compatibility by distributing software that has its video output routines
  4633.    in separate, installable modules: Before the software can be used, the
  4634.    video routines must be linked to the rest of the application. This lets
  4635.    you write programs that take full advantage of each video subsystem's
  4636.    capabilities without sacrificing compatibility.
  4637.  
  4638.    However, the installation process can be cumbersome, both for a programmer
  4639.    who must write the installation program and for an end-user who must
  4640.    install video routines properly. You can eliminate the installation
  4641.    process if you make your application self-installing. The key to doing
  4642.    this is to incorporate a routine in your program that identifies which
  4643.    video subsystem the program is running on. The program can then tailor its
  4644.    own video output to the capabilities and limitations of the video
  4645.    hardware.
  4646.  
  4647.    You can use several different programming techniques to identify the video
  4648.    subsystem. In PS/2s, ROM BIOS offers a service that reports the video
  4649.    hardware configuration (see Chapter 9), but in the PC/XT/AT family you
  4650.    must rely on improvised hardware identification techniques documented in
  4651.    the hardware technical manuals.
  4652.  
  4653.    Once a program has determined the video hardware configuration, it can
  4654.    produce appropriate output. For example, a program running on a Monochrome
  4655.    Display Adapter can use only one video mode with monochrome attributes. If
  4656.    the same program were running on a color subsystem, it could run with
  4657.    color attributes in text modes. If the program needed to produce graphics
  4658.    output, it could select a graphics mode with the highest possible
  4659.    resolution based on its identification of the video subsystem.
  4660.  
  4661.    In the simplest case, your program can use whatever video mode is in use
  4662.    when the program starts up. ROM BIOS interrupt 10H, service 0FH reports
  4663.    the current video mode number. If you're not using an assembly-language
  4664.    interface to the ROM BIOS, however, you may find it easier simply to use
  4665.    the program on the following page to inspect the ROM BIOS status variable
  4666.    at 0040:0049H that contains the video mode number.
  4667.  
  4668.    10 DEF SEG = &H0040
  4669.    20 VIDEO.MODE = PEEK(&H0049)
  4670.  
  4671.    You can avoid video hardware dependence in your programs if you use an
  4672.    operating environment like Digital Research's GEM or Microsoft Windows.
  4673.    These environments shield your program from the idiosyncrasies of video
  4674.    hardware by providing a set of consistent, hardware-independent
  4675.    subroutines to perform video I/O. The problem, of course, is that the
  4676.    end-user must also have a copy of the operating environment to be able to
  4677.    run your program.
  4678.  
  4679.    Whatever approach you take to video compatibility, be sure to consider
  4680.    several compatibility criteria. These criteria are not completely
  4681.    consistent with each other, reflecting the internal inconsistency in the
  4682.    design of the IBM personal computer and the variety of display formats
  4683.    that can be used. Still, there are overall guidelines for compatibility,
  4684.    which we'll outline here.
  4685.  
  4686.    First, text-only display output increases compatibility. Many PCs are
  4687.    still equipped with Monochrome Display Adapters, which cannot show graphic
  4688.    output. If you are weighing a text-versus-graphics decision in the design
  4689.    of a program, there are two factors to consider. On one hand, as many
  4690.    programs have dramatically demonstrated, you can create very effective
  4691.    drawings using only standard IBM text characters. On the other hand, it is
  4692.    more and more common for computers to include graphics capability. So, in
  4693.    the future, text-only output will probably lose its importance, and you'll
  4694.    be able to use graphics in your programs without worrying about
  4695.    compatibility.
  4696.  
  4697.    Second, the less your programs depend on color, the wider the range of
  4698.    computers with which they will be compatible. This does not mean that you
  4699.    need to avoid color for compatibility; it simply means that for maximum
  4700.    compatibility, programs should use color as an enhancement rather than as
  4701.    an essential ingredient. If programs can get along without color, they
  4702.    will be compatible with computers that use monochrome displays, including
  4703.    PCs with Monochrome Display Adapters, as well as Compaq Portable computers
  4704.    with built-in monochrome displays.
  4705.  
  4706.    In general, you must weigh the advantage of broad compatibility against
  4707.    the convenience and simplicity of writing programs for a narrower range of
  4708.    displays. Our own experience and judgment tell us that far too often
  4709.    programmers err by opting for a narrower range of displays, thereby
  4710.    greatly reducing the variety of computers their programs can be used on.
  4711.    Be forewarned.
  4712.  
  4713.  
  4714.  
  4715.  ────────────────────────────────────────────────────────────────────────────
  4716.  Chapter 5  Disk Basics
  4717.  
  4718.    Disk Data Mapping
  4719.      Data Storage
  4720.      Bootable Disks
  4721.  
  4722.    DOS Disk Formats
  4723.      Diskette Formats
  4724.      Fixed-Disk Formats
  4725.  
  4726.    The Disk's Logical Structure
  4727.  
  4728.    How DOS Organizes the Disk
  4729.  
  4730.    The Logical Structure in Detail
  4731.      The Boot Sector
  4732.      The Root Directory
  4733.      The Files Area
  4734.      The File Allocation Table
  4735.  
  4736.    Comments
  4737.      Copy Protection
  4738.  
  4739.    Most computer systems have some way to store information permanently,
  4740.    whether it is on punched paper tape, bar-coded print media, magnetic disks
  4741.    or tape, or laser disks. By far the most widely used media in the PC and
  4742.    PS/2 family are diskettes (floppy disks) and fixed disks (hard disks).
  4743.    Diskettes and fixed disks come in various sizes and capacities but they
  4744.    all work in basically the same way: Information is magnetically encoded on
  4745.    their surfaces in patterns determined by the disk drive and by the
  4746.    software that controls the drive.
  4747.  
  4748.    When the PC family was introduced in 1981, it used one main type of
  4749.    storage device: the 51/4-inch diskette, which was double density, single
  4750.    sided, and soft sectored, and stored only 160 kilobytes (KB). Since then,
  4751.    higher-capacity 51/4-inch and 31/2-inch diskettes have become standard
  4752.    equipment on PCs and PS/2s, as have fixed disks with capacities from 10
  4753.    megabytes (MB) on the PC/XT to 314 MB on the PS/2 Model 80.
  4754.  
  4755.    Although the type of storage device is important, it is the way stored
  4756.    information is laid out and managed that concerns programmers most. In
  4757.    this chapter, we'll focus on how information is organized and stored on
  4758.    both diskettes and fixed disks. Much of the information provided in this
  4759.    chapter applies to RAM disks──that is, the simulation of disk storage in
  4760.    memory──as much as it does to conventional diskettes, fixed disks, and
  4761.    disk cartridges.
  4762.  
  4763.  
  4764.  Disk Data Mapping
  4765.  
  4766.    To understand how data is organized on a disk, consider the physical
  4767.    structure of the disk itself and the drive mechanism that reads from and
  4768.    writes to it. We'll start with diskettes, but both diskettes and fixed
  4769.    disks have the same basic geometry.
  4770.  
  4771.    Inside a diskette's square plastic case is a circular platter made of
  4772.    tough plastic coated with a magnetic medium. A diskette drive stores data
  4773.    on the diskette by writing and reading magnetically encoded patterns that
  4774.    represent digital data. Because both sides of the diskette are coated,
  4775.    both sides can be used to store data.
  4776.  
  4777.    A diskette drive contains a motor that rotates the diskette at a constant
  4778.    speed. The drive has two read/write heads, one for each side of the
  4779.    diskette. The heads are mounted on an arm that moves them in unison to any
  4780.    position toward or away from the center of the disk. (The original IBM PC
  4781.    came with a diskette drive that had only one read/write head and could
  4782.    access only one side of a diskette. Most PC users perceived this as
  4783.    wasteful, so single-sided diskette drives gradually went the way of the
  4784.    dinosaur.)
  4785.  
  4786.    Like the tape heads in a common tape recorder, a diskette drive's
  4787.    read/write heads can magnetize the diskette medium to store data on the
  4788.    diskette; they can also retrieve data from the diskette by decoding the
  4789.    magnetically encoded patterns in the diskette medium.
  4790.  
  4791.    The geometry of a fixed disk is similar to that of a diskette. Fixed disks
  4792.    rotate much faster than diskettes, so the platters are made of
  4793.    magnetically coated metal or glass, not flexible plastic. Also, fixed
  4794.    disks usually consist of a stack of several platters that rotate together,
  4795.    so fixed-disk drives have multiple read/write heads──one for each disk
  4796.    surface.
  4797.  
  4798.  Data Storage
  4799.  
  4800.    The way data is mapped on diskettes and fixed disks is a natural result of
  4801.    the geometry of the hardware. When a particular read/write head is held
  4802.    motionless, a ring of magnetic medium moves past it as the disk rotates.
  4803.    For each position of the read/write head, relative to the center of the
  4804.    disk, there is a corresponding ring of disk medium on which data can be
  4805.    stored. These rings are called tracks. (See Figure 5-1.)
  4806.  
  4807.    Because each disk track can store 4 KB or more of data, each track of data
  4808.    is divided into a number of smaller units called sectors. All sectors hold
  4809.    the same amount of data──typically, 512 bytes for diskettes and most fixed
  4810.    disks. The sectors and tracks are numbered sequentially, so you can locate
  4811.    any particular byte of data on a disk surface by specifying its track
  4812.    number and its sector number.
  4813.  
  4814.    Because two-sided diskettes and fixed disks have more than one disk
  4815.    surface, however, you need to think three-dimensionally to locate a byte
  4816.    of data. So the position of the read/write heads for these disks is
  4817.    described by a cylinder number. Like tracks, cylinders are numbered
  4818.    sequentially. If you think of a cylinder as a stack of tracks at a given
  4819.    position of the read/write heads, you can see that the location of a
  4820.    particular track is determined by specifying a cylinder number plus a
  4821.    read/write head.
  4822.  
  4823.    With this in mind, it's easy to make sense of the various diskette formats
  4824.    used in PC and PS/2 disk drives. (See Figure 5-2.) With the original
  4825.    single-sided IBM PC diskette drives you could use diskettes formatted with
  4826.    40 tracks, each of which contained eight sectors of data, so the capacity
  4827.    of the diskette was 40 x 8 x 512, or 160 KB. Now, with more accurate
  4828.    diskette drives and with high-density diskette media that can store more
  4829.    data per track, you can use diskettes with higher-capacity formats.
  4830.    Fixed-disk drives are mechanically more accurate than diskette drives, and
  4831.    their magnetic media are of comparatively higher density, so the number of
  4832.    tracks and the number of sectors per track are higher than for diskettes.
  4833.  
  4834.    ┌────────────────────────────────────────────────────────────────────────┐
  4835.    │ Figure 5-1 can be found on p.102 of the printed version of the book.   │
  4836.    └────────────────────────────────────────────────────────────────────────┘
  4837.  
  4838.    Figure 5-1.  One side of a diskette formatted with 40 concentric tracks
  4839.    and eight sectors per track.
  4840.  
  4841.    Manufacturers' terminology and advertising regarding these variations of
  4842.    disk format and disk-storage capacity is somewhat fuzzy. "Quad-density"
  4843.    refers to a diskette or drive that can use an 80-track diskette format.
  4844.    "High-density" and "high-capacity" generally refer to the PC/AT 1.2 MB or
  4845.    PS/2 1.44 MB diskette formats. "Double-density" diskettes can be formatted
  4846.    with eight or nine sectors per track, but they can't be used reliably with
  4847.    higher-capacity formats.
  4848.  
  4849.                                                     Sectors
  4850.    Disk                     Capacity    Cylinders   per Track    Heads
  4851.    ──────────────────────────────────────────────────────────────────────────
  4852.    51/4-inch diskette       160 KB      40           8           1
  4853.                             180 KB      40           9           1
  4854.                             320 KB      40           8           2
  4855.                             360 KB      40           9           2
  4856.                             1.2 MB      80          15           2
  4857.    31/2-inch diskette       720 KB      80           9           2
  4858.                             1.44 MB     80          18           2
  4859.    ──────────────────────────────────────────────────────────────────────────
  4860.  
  4861.    Figure 5-2.  PC and PS/2 diskette formats.
  4862.  
  4863.  Bootable Disks
  4864.  
  4865.    Regardless of their data formats, all diskettes and disks are potentially
  4866.    bootable; that is, they can contain the information necessary to get an
  4867.    operating system running at the time you start your computer. There is
  4868.    nothing special about the format of a bootable disk; it's just one that
  4869.    contains information that lets the ROM BIOS boot the operating system.
  4870.    Here's how it works.
  4871.  
  4872.    On all PC and PS/2 diskettes and fixed disks, the first sector on the
  4873.    disk──cylinder 0, head 0, sector 1──is reserved for a short bootstrap
  4874.    program. (The program has to be short because the size of a sector is only
  4875.    512 bytes.) The function of this bootstrap program is to read the bulk of
  4876.    the operating system into memory from elsewhere on the disk and then to
  4877.    transfer control to the operating system.
  4878.  
  4879.    When you start or restart your computer, the last tasks performed by the
  4880.    start-up ROM BIOS routines are reading the contents of the disk boot
  4881.    sector into memory and checking those contents for a bootstrap program.
  4882.    The BIOS does this checking by examining the last 2 bytes of the boot
  4883.    sector for a signature (55H and AAH) that indicates that the data in the
  4884.    boot sector represents a bootstrap program. If the signature value isn't
  4885.    correct, the BIOS assumes there's no bootstrap program in the boot sector
  4886.    and, therefore, that the disk isn't bootable.
  4887.  
  4888.    The bootstrap program's job is to copy the start-up program for an
  4889.    operating system from the disk into memory. There's no restriction on the
  4890.    size and location of the operating system's start-up program, so this
  4891.    stepwise transfer of control──from ROM BIOS to boot sector to operating
  4892.    system──can be used to start DOS, XENIX, OS/2, or even a stand-alone
  4893.    application.
  4894.  
  4895.  
  4896.  DOS Disk Formats
  4897.  
  4898.    The diskette formats listed in Figure 5-2 aren't the only ones you can
  4899.    use for diskettes, but because diskettes are intended to be portable, the
  4900.    number of diskette formats that DOS recognizes is limited to those in the
  4901.    list. In the earliest releases of DOS, only the 160 KB and 320 KB formats
  4902.    could be used. Later DOS versions recognize higher-capacity diskette
  4903.    formats and fixed disks in addition to the original diskette formats
  4904.    (Figure 5-3).
  4905.  
  4906.    Disk                     Capacity        DOS Version      Media Descriptor
  4907.    ──────────────────────────────────────────────────────────────────────────
  4908.    51/4-inch diskette       160 KB          1.0              FEH
  4909.                             320 KB          1.1              FFH
  4910.                             180 KB          2.0              FCH
  4911.                             360 KB          2.0              FDH
  4912.                             1.2 MB          3.0              F9H
  4913.    31/2-inch diskette       720 KB          3.2              F9H
  4914.                             1.44 MB         3.3              F0H
  4915.    Fixed disk                               2.0              F8H
  4916.    ──────────────────────────────────────────────────────────────────────────
  4917.  
  4918.    Figure 5-3.  Standard DOS disk formats. The media descriptor value is used
  4919.    by DOS to identify different disk formats.
  4920.  
  4921.  Diskette Formats
  4922.  
  4923.    Beginning with version 2.0, DOS had the potential to recognize virtually
  4924.    any physical disk format. This became possible because DOS versions 2.0
  4925.    and later provide the necessary tools to write an installable device
  4926.    driver── a machine-language routine that can configure a disk drive to
  4927.    read or write different formats or allow you to hook up a non-IBM disk
  4928.    drive to your system. (See Appendix A for more on installable device
  4929.    drivers.)
  4930.  
  4931.    Fortunately, installable diskette device drivers have not led to a
  4932.    proliferation of nonstandard, incompatible diskette formats. Instead,
  4933.    software vendors and programmers have relied on the standard DOS formats
  4934.    listed in Figure 5-3. On 51/4-inch diskettes, the 360 KB nine-sector
  4935.    format is used most frequently, while on 31/2-inch diskettes, the 720 KB
  4936.    format is most common. These are not the highest capacity formats, but
  4937.    they can be used on machines that aren't equipped with higher-capacity
  4938.    diskette drives as well as on those that are.
  4939.  
  4940.    If you're interested in creating your own diskette formats, or in
  4941.    understanding DOS diskette formats in more detail, be sure to read about
  4942.    ROM BIOS disk services in Chapter 10.
  4943.  
  4944.  Fixed-Disk Formats
  4945.  
  4946.    High-capacity fixed-disk systems present some special problems and
  4947.    opportunities. Fixed-disk formats vary much more than diskette formats do
  4948.    (Figure 5-4). Still, data is organized on fixed disks by cylinder, head,
  4949.    and sector numbers, just as it is on diskettes.
  4950.  
  4951.                                                     Sectors
  4952.    Disk                     Capacity    Cylinders   per Track    Heads
  4953.    ──────────────────────────────────────────────────────────────────────────
  4954.    Typical PC/XT            10 MB       306         17           4
  4955.    fixed disk
  4956.    PC/AT fixed disk         30 MB       733         17           5
  4957.    type 20
  4958.    PS/2 Model 30            20 MB       612         17           4
  4959.    fixed disk, type 26
  4960.    PS/2 Model 60            44 MB       732         17           7
  4961.    fixed disk, type 31
  4962.    ──────────────────────────────────────────────────────────────────────────
  4963.  
  4964.    Figure 5-4.  Some typical fixed-disk formats. All use 512 bytes per
  4965.    sector.
  4966.  
  4967.    Because the storage capacity of a fixed disk is relatively large, some PC
  4968.    users prefer to use only part of the disk space for DOS and to use other
  4969.    portions of the disk for other operating systems. To facilitate this, the
  4970.    available space on a fixed disk can be split into as many as four logical
  4971.    partitions, each of which is accessed separately. Each partition's data
  4972.    can be kept completely separate from the data in the other partitions.
  4973.    Each partition can contain its own boot sector and operating system.
  4974.  
  4975.    The first sector on a fixed disk contains a 64-byte partition table
  4976.    (Figure 5-5) and a disk bootstrap program. The partition table indicates
  4977.    where each partition is located on the disk. The table also designates one
  4978.    bootable partition. The first sector in the bootable partition is a
  4979.    partition boot sector that the ROM BIOS can use to load an operating
  4980.    system.
  4981.  
  4982.    The disk bootstrap program examines the partition table to determine which
  4983.    one of the partitions is bootable. It then reads the partition's boot
  4984.    sector from the disk into memory. The partition boot sector contains a
  4985.    bootstrap program that reads the operating system from the disk into
  4986.    memory and transfers control to it.
  4987.  
  4988.    Because bootable partitions are indicated in a table, you can select among
  4989.    fixed-disk partitions simply by updating the table and restarting the
  4990.    computer. All operating systems capable of supporting fixed disks provide
  4991.    a utility program that lets you update the partition table. (The DOS
  4992.    utility FDISK is such a program.)
  4993.  
  4994.    Offset from
  4995.    Start of Entry Size (bytes)   Meaning
  4996.    ──────────────────────────────────────────────────────────────────────────
  4997.    00H            1              Boot indicator (80H = bootable, 0 = not
  4998.                                  bootable)
  4999.    01H            1              Starting head number
  5000.    02H            2              Starting cylinder number (10 bits) and
  5001.                                  sector number (6 bits)
  5002.    04H            1              System indicator:
  5003.                                     1 = primary DOS, 12-bit FAT
  5004.                                     2 = XENIX
  5005.                                     4 = primary DOS, 16-bit FAT
  5006.                                     5 = extended DOS
  5007.                                     8 = other non-DOS
  5008.    05H            1              Ending head number
  5009.    06H            2              Ending cylinder and sector numbers
  5010.    08H            4              Starting sector (relative to beginning of
  5011.                                  disk)
  5012.    0CH            4              Number of sectors in partition
  5013.    ──────────────────────────────────────────────────────────────────────────
  5014.  
  5015.    Figure 5-5.  The format of an entry in a fixed-disk partition table. The
  5016.    table consists of four such 16-byte entries, starting at offset 1BEH in
  5017.    the disk boot sector.
  5018.  
  5019.    ──────────────────────────────────────────────────────────────────────────
  5020.    NOTE:
  5021.      Be very careful if you access a fixed disk's boot sector. The
  5022.      information contained there is intended only for use by the ROM BIOS
  5023.      bootstrap loader. Should the data in a disk's boot sector be erased or
  5024.      corrupted, the entire contents of the disk may become inaccessible.
  5025.    ──────────────────────────────────────────────────────────────────────────
  5026.  
  5027.  
  5028.  The Disk's Logical Structure
  5029.  
  5030.    Regardless of the type of disk you use, all DOS disks are logically
  5031.    formatted in the same way: The disk's sides, tracks, and sectors are
  5032.    identified numerically with the same notation, and certain sectors are
  5033.    always reserved for special programs and indexes that DOS uses to manage
  5034.    disk operations. Before we describe how DOS organizes space on a disk, we
  5035.    need to briefly cover the conventional notation used by DOS and the ROM
  5036.    BIOS to locate information.
  5037.  
  5038.    Diskette cylinder numbers start from 0 at the outside edge of the disk
  5039.    surface and increase toward the center of the disk. Read/write heads are
  5040.    also numbered from 0, but sector numbers start with 1. Any location on the
  5041.    disk can thus be described by a unique combination of cylinder, head, and
  5042.    sector numbers. This in fact is how the ROM BIOS services access disk
  5043.    data.
  5044.  
  5045.    DOS, however, does not recognize cylinders, heads, and sectors. Instead,
  5046.    DOS sees a disk as a linear sequence of logical sectors. The sequence of
  5047.    logical sectors begins with the first sector on a disk: Sector 1, cylinder
  5048.    0, head 0 (the boot sector) is DOS logical sector 0.
  5049.  
  5050.    Logical sectors are numbered from track to track in the same cylinder, and
  5051.    then are numbered from cylinder to cylinder. Thus the last sector in
  5052.    cylinder 0, head 0, is followed by the first sector in cylinder 0, head 1;
  5053.    the last sector in a cylinder is followed by the first sector in the next
  5054.    cylinder. See page 300 for information on converting DOS notation to ROM
  5055.    BIOS notation and vice versa.
  5056.  
  5057.    The use of logical sector numbers lets DOS avoid having to deal with
  5058.    cylinder, head, and sector numbers that vary among different types of
  5059.    disk-drive hardware. However, this same feature means that DOS is limited
  5060.    in the amount of disk space it can access on a particular disk drive.
  5061.    Because DOS maintains logical sector numbers as 16-bit integers, it can
  5062.    recognize, at most, 65,536 logical sectors on a disk. Because the default
  5063.    size of a disk sector is 512 bytes, the largest disk DOS can manage is
  5064.    65,536 x 512, or 32 MB. This certainly is no problem on diskettes, but
  5065.    it's an unwelcome limitation for the many PC/AT and PS/2 users who have
  5066.    fixed disks larger than 32 MB.
  5067.  
  5068.    To get around this restriction, DOS version 3.3 introduced the notion of
  5069.    the extended DOS partition. With DOS 3.3, you can use the DOS utility
  5070.    program FDISK to allocate a fixed-disk partition as an extended DOS
  5071.    partition. You can format the extended partition as one or more separate
  5072.    logical drives. Thus, for example, you could use both a primary and an
  5073.    extended DOS partition on a fixed disk, with the primary partition as
  5074.    drive C and the extended partition as drives D and E.
  5075.  
  5076.  
  5077.  How DOS Organizes the Disk
  5078.  
  5079.    When DOS formats a diskette, it erases and verifies every sector. In a
  5080.    fixed-disk partition, DOS verifies the integrity of each sector without
  5081.    erasing pre-existing data. (That is why a program like the Norton
  5082.    Utilities' Format Recover can retrieve data from a fixed disk after you
  5083.    have accidentally reformatted it.) On both diskettes and fixed disks, the
  5084.    format program reserves a certain amount of disk space to store control
  5085.    information and indexes that DOS uses to organize the data you store on
  5086.    the disk.
  5087.  
  5088.    Every DOS diskette or fixed-disk DOS partition is mapped into four
  5089.    separate areas. These areas, in the order they are stored, are the
  5090.    reserved area, the file allocation table (FAT), the root directory, and
  5091.    the files area. (See Figure 5-6.) The size of each area varies among
  5092.    formats, but the structure and the order of the areas don't vary.
  5093.  
  5094.                     ┌───────────────────┐
  5095.    Logical sector 0 │  Reserved area    │
  5096.                     ├───────────────────┤
  5097.                     │                   │
  5098.                     │ File allocation   │
  5099.                     │   table (FAT)     │
  5100.                     │                   │
  5101.                     ├───────────────────┤
  5102.                     │  Root directory   │
  5103.                     ├───────────────────┤
  5104.                     │                   │
  5105.                     │ Files area (files │
  5106.                     │and subdirectories)│
  5107.                     │                   │
  5108.                     │                   │
  5109.                     │                   │
  5110.                     └───────────────────┘
  5111.  
  5112.    Figure 5-6.  DOS disk map.
  5113.  
  5114.    The reserved area can be one or more sectors long; the first sector is
  5115.    always the disk boot sector (logical sector 0). A table within the boot
  5116.    sector specifies the size of the reserved area, the size (and number of
  5117.    copies) of the file allocation table, as well as the number of entries in
  5118.    the root directory. All diskettes have a reserved area of at least one
  5119.    sector, even if they aren't bootable.
  5120.  
  5121.    The file allocation table, or FAT, immediately follows the reserved area.
  5122.    The FAT maps the usage of all the disk space in the files area of the
  5123.    disk, including space used for files, space that hasn't been used, and
  5124.    space that is unusable due to defects in the disk medium. Because the FAT
  5125.    maps the entire usable data storage area of a disk, two identical copies
  5126.    of it are stored in case one is damaged. The size of a FAT depends on the
  5127.    size of the disk (or of the partition of a fixed disk): Larger disks
  5128.    usually require larger FATs. Figure 5-7 shows FAT sizes for several
  5129.    different disk sizes.
  5130.  
  5131.                                         Reserved                 Root
  5132.    Disk                     Capacity    Area        FAT          Directory
  5133.    ──────────────────────────────────────────────────────────────────────────
  5134.    51/4-inch diskette       360 KB      1 sector     4 sectors    7 sectors
  5135.                             1.2 MB      1           14           14
  5136.    31/2-inch diskette       720 KB      1            6            7
  5137.                             1.44 MB     1           18           14
  5138.    ──────────────────────────────────────────────────────────────────────────
  5139.  
  5140.    Figure 5-7.  Reserved area, FAT, and root-directory overhead for some
  5141.    common DOS diskette formats.
  5142.  
  5143.    The root directory is the next item on a DOS disk. It is used as a table
  5144.    of contents, identifying each file on the disk with a directory entry that
  5145.    contains several pieces of information, including the file's name, size,
  5146.    and location on the disk. The size of the root directory varies with the
  5147.    disk format. (See Figure 5-7.)
  5148.  
  5149.    The files area, which occupies the bulk of the available disk space, is
  5150.    used to store files; in DOS versions 2.0 and later, the files area may
  5151.    contain subdirectories as well as files. For both files and
  5152.    subdirectories, space in the files area is allocated as needed in chunks
  5153.    of contiguous sectors called clusters. As with the sizes of the FAT and
  5154.    the root directory, a DOS disk's cluster size varies with the format. (See
  5155.    Figure 5-8.) The number of sectors in a cluster is always a power of 2;
  5156.    generally, the cluster size is one sector for single-sided diskettes, two
  5157.    sectors for double-sided diskettes, and four or more for fixed disks.
  5158.  
  5159.    Disk                                 Capacity           Cluster Size
  5160.    ──────────────────────────────────────────────────────────────────────────
  5161.    51/4-inch diskette                   360 KB             2 sectors
  5162.                                         1.2 MB             1
  5163.    31/2-inch diskette                   720 KB             2
  5164.                                         1.44 MB            1
  5165.    Typical PC/XT fixed disk             10 MB              8
  5166.    PC/AT fixed disk, type 20            30 MB              4
  5167.    PS/2 Model 30, fixed disk, type 26   20 MB              4
  5168.    PS/2 Model 60, type 31               44 MB              4
  5169.    ──────────────────────────────────────────────────────────────────────────
  5170.  
  5171.    Figure 5-8.  Cluster size for some common DOS disk formats.
  5172.  
  5173.  
  5174.  The Logical Structure in Detail
  5175.  
  5176.    Now it's time to delve a little more deeply into each of the four sections
  5177.    of a disk: the boot sector, the root directory, the files area, and the
  5178.    FAT.
  5179.  
  5180.  The Boot Sector
  5181.  
  5182.    The boot sector on a DOS diskette or in a DOS partition on a fixed disk
  5183.    consists primarily of a short machine-language program that starts the
  5184.    process of loading DOS into memory. As we mentioned, to perform this task
  5185.    the ROM BIOS checks to see whether the disk is bootable and then proceeds
  5186.    accordingly.
  5187.  
  5188.    ──────────────────────────────────────────────────────────────────────────
  5189.    NOTE:
  5190.      A bootable disk contains the start-up programs for an operating system
  5191.      or for a stand-alone application that runs without operating-system
  5192.      support. In the case of DOS, a bootable disk contains two hidden files
  5193.      that represent the DOS start-up routines and essential low-level DOS
  5194.      functions. See Chapter 3, page 45 for details about these files.
  5195.    ──────────────────────────────────────────────────────────────────────────
  5196.  
  5197.    You can inspect the boot program by using the DOS DEBUG utility, which
  5198.    combines the ability to read data from any sector on a disk with the
  5199.    ability to disassemble──or unassemble──machine language into
  5200.    assembly-language code. If you want to learn more about the boot program
  5201.    and you aren't intimidated by DEBUG's terse command format, place a
  5202.    bootable diskette in drive A and enter the following commands to display
  5203.    the diskette's boot program:
  5204.  
  5205.    DEBUG
  5206.    L 0 0 0 1           ; load first logical sector
  5207.    U 0 L 3             ; unassemble and list first and second bytes
  5208.  
  5209.    At this point, DEBUG will display the first instruction in the boot
  5210.    program, a JMP to the address that contains the rest of the program. Use
  5211.    DEBUG's U command with the address specified in the JMP to inspect the
  5212.    rest of the boot program. For example, if the first instruction is JMP
  5213.    0036, enter
  5214.  
  5215.    U 0036          ; unassemble and list next portion of boot program
  5216.  
  5217.    For all disk formats (except diskettes formatted with eight sectors per
  5218.    track) you will find some key parameters in the boot sector, beginning
  5219.    with the 11th byte. (See Figure 5-9.) These parameters are part of the
  5220.    BIOS parameter block used by DOS to control any disk-type device. If
  5221.    you're using DEBUG to inspect the boot sector of a diskette in drive A,
  5222.    you can see a hexadecimal dump of the BIOS parameter block by entering the
  5223.    following command:
  5224.  
  5225.    D 0B L 1B
  5226.  
  5227.    Offset         Length         Description
  5228.    ──────────────────────────────────────────────────────────────────────────
  5229.    03H            8 bytes        System ID
  5230.    0BH            1 word         Number of bytes per sector
  5231.    0DH            1 byte         Number of sectors per cluster
  5232.    0EH            1 word         Number of sectors in reserved area
  5233.    10H            1 byte         Number of copies of FAT
  5234.    11H            1 word         Number of root directory entries
  5235.    13H            1 word         Total number of sectors
  5236.    15H            1 byte         DOS media descriptor
  5237.    16H            1 word         Number of sectors per FAT
  5238.    18H            1 word         Number of sectors per track
  5239.    1AH            1 word         Number of heads (sides)
  5240.    1CH            1 word         Number of hidden sectors
  5241.    ──────────────────────────────────────────────────────────────────────────
  5242.  
  5243.    Figure 5-9.  The BIOS parameter block in the boot sector.
  5244.  
  5245.  The Root Directory
  5246.  
  5247.    The root directory on a diskette or in a fixed-disk partition is created
  5248.    by the DOS FORMAT program. The root directory's size is determined by
  5249.    FORMAT, so the number of root directory entries is limited. (See Figure
  5250.    5-10.)
  5251.  
  5252.    Disk                          Capacity      Size           Number of
  5253.                                                               Entries
  5254.    ──────────────────────────────────────────────────────────────────────────
  5255.    51/4-inch diskette            180 KB         4 sectors      64
  5256.                                  360 KB         7             112
  5257.                                  1.2 MB        14             224
  5258.    31/2-inch diskette            720 KB         7             112
  5259.                                  1.44 MB       14             224
  5260.    Typical PC/XT fixed disk      10 MB         32             512
  5261.    PC/AT fixed disk, type 20     30 MB         32             512
  5262.    PS/2 Model 30, fixed disk,    20 MB         32             512
  5263.    type 26
  5264.    PS/2 Model 60, fixed disk,    44 MB         32             512
  5265.    type 31
  5266.    ──────────────────────────────────────────────────────────────────────────
  5267.  
  5268.    Figure 5-10.  Root directory sizes for some common DOS disk formats.
  5269.  
  5270.    In DOS versions 1.0 and later, which did not support subdirectories, the
  5271.    size of the root directory limited the number of files that could be
  5272.    stored on a diskette. This restriction disappeared in DOS versions 2.0 and
  5273.    later, where file names could be placed in subdirectories as well as in
  5274.    the root directory.
  5275.  
  5276.    The root directory contains a series of 32-byte directory entries. Each
  5277.    directory entry contains the name of a file, a subdirectory, or a disk
  5278.    volume label. The directory entry for a file contains such basic
  5279.    information as the file's size, its location on the disk, and the time and
  5280.    date it was most recently modified. This information is contained in the
  5281.    eight fields listed in Figure 5-11.
  5282.  
  5283.                                         Size
  5284.    Offset      Description              (bytes)     Format
  5285.    ──────────────────────────────────────────────────────────────────────────
  5286.    00H         Filename                  8          ASCII characters
  5287.    08H         Filename extension        3          ASCII characters
  5288.    0BH         Attribute                 1          Bit coded
  5289.    0CH         Reserved                 10          Unused; zeros
  5290.    16H         Time                      2          Word, coded
  5291.    18H         Date                      2          Word, coded
  5292.    1AH         Starting cluster number   2          Word
  5293.    1CH         File size                 4          Integer
  5294.    ──────────────────────────────────────────────────────────────────────────
  5295.  
  5296.    Figure 5-11.  The eight parts of a directory entry.
  5297.  
  5298.    Offset 00H: The filename
  5299.  
  5300.    The first 8 bytes in a directory entry contain the filename, stored in
  5301.    ASCII format. If the filename is less than eight characters, it is filled
  5302.    out to the right with blanks (CHR$(32)). Letters should be uppercase,
  5303.    because lowercase letters will not be properly recognized. Normally,
  5304.    blanks should not be embedded in the filename, as in AA BB. Most DOS
  5305.    command programs, such as DEL and COPY, will not recognize filenames with
  5306.    embedded blanks. BASIC works successfully with these filenames, however,
  5307.    and DOS services usually can too. (See Chapters 16 and 17.) This
  5308.    capability suggests some useful tricks, such as creating files that cannot
  5309.    easily be erased.
  5310.  
  5311.    Two codes, used to indicate special situations, may appear in the first
  5312.    byte of the filename field. When a file is deleted, DOS sets the first
  5313.    byte of the filename field in its directory entry to E5H to indicate that
  5314.    the directory entry can be reused for another filename. In DOS versions
  5315.    2.0 and later, the first byte of a directory entry can also be set to 00H
  5316.    to indicate the end of the list of directory entries.
  5317.  
  5318.    When a file is erased, only two things on the disk are affected: The first
  5319.    byte of the directory entry is set to E5H, and the file's space-allocation
  5320.    chain in the FAT is wiped out (we'll cover this in the section on the
  5321.    FAT). All other directory information about the file is retained,
  5322.    including the rest of its name, its size, and even its starting cluster
  5323.    number. The lost information can be recovered, with suitably sophisticated
  5324.    methods, provided that the directory entry has not been reused for another
  5325.    file. Be forewarned, though, that whenever a new directory entry is
  5326.    needed, DOS uses the first available entry, quickly recycling an erased
  5327.    file's entries and making recovery more problematic.
  5328.  
  5329.    Offset 08H: The filename extension
  5330.  
  5331.    Directly following the filename is the standard filename extension, stored
  5332.    in ASCII format. It is 3 bytes long and, like the filename, is padded with
  5333.    blanks if it is less than the full three-character length. While a
  5334.    filename must have at least one ordinary character in it, the extension
  5335.    can be all blanks. Generally, the rules that apply to the filename also
  5336.    apply to the filename extension.
  5337.  
  5338.    ──────────────────────────────────────────────────────────────────────────
  5339.    NOTE:
  5340.      When the directory contains a volume ID label entry, the filename and
  5341.      extension fields are treated as one combined field of 11 bytes. In this
  5342.      case, embedded blanks are permitted.
  5343.    ──────────────────────────────────────────────────────────────────────────
  5344.  
  5345.    Offset 0BH: The file attribute
  5346.  
  5347.    The third field of the directory entry is 1 byte long. The bits of the
  5348.    attribute byte are individually coded as bits 0 through 7, as shown in
  5349.    Figure 5-12, and each bit is used to categorize the directory entry.
  5350.  
  5351.          Bit
  5352.    7 6 5 4 3 2 1 0          Meaning
  5353.    ──────────────────────────────────────────────────────────────────────────
  5354.    . . . . . . . 1          Read-only
  5355.    . . . . . . 1 .          Hidden
  5356.    . . . . . 1 . .          System
  5357.    . . . . 1 . . .          Volume label
  5358.    . . . 1 . . . .          Subdirectory
  5359.    . . 1 . . . . .          Archive
  5360.    . 1 . . . . . .          Unused
  5361.    1 . . . . . . .          Unused
  5362.    ──────────────────────────────────────────────────────────────────────────
  5363.  
  5364.    Figure 5-12.  The 8 file-attribute bits.
  5365.  
  5366.    Bit 0, the low-order bit, is set to mark a file as read-only. In this
  5367.    state, the file is protected from being changed or deleted by any DOS
  5368.    operation. We should point out that many DOS services ignore this
  5369.    attribute, so even though bit 0 can provide worthwhile protection for
  5370.    data, it is not foolproof.
  5371.  
  5372.    Bit 1 marks a file as hidden and bit 2 marks a file as a system file.
  5373.    Files marked as hidden, system, or both, cannot be seen by ordinary DOS
  5374.    operations, such as the DIR command. Programs can gain access to such
  5375.    files only by using DOS services to search explicitly for hidden or system
  5376.    files. There is no particular significance to the system attribute; it
  5377.    exists to perpetuate a feature of CP/M and has absolutely nothing to do
  5378.    with DOS.
  5379.  
  5380.    ──────────────────────────────────────────────────────────────────────────
  5381.    Subdirectories
  5382.      There are two types of directories: root directories and subdirectories.
  5383.      The contents and use of each type are essentially the same (both store
  5384.      the names and locations of files on the disk) but their characteristics
  5385.      are different. The root directory has a fixed size and is stored in a
  5386.      fixed location on the disk. A subdirectory has no fixed size and can be
  5387.      stored anywhere on the disk. Any version of DOS numbered 2.0 or later
  5388.      can use subdirectories.
  5389.  
  5390.                      Root Directory
  5391.                             │
  5392.           ┌─────────────────┼────────────────────────────────┐
  5393.           │                 │                                │
  5394.        Programs    Word-processing data                Accounting data
  5395.      subdirectory     subdirectory                      subdirectory
  5396.                             │                                │
  5397.                     ┌───────┴────────┐               ┌───────┴────────┐
  5398.                     │                │               │                │
  5399.                  Letters          Reports      Current year      Prior year
  5400.                subdirectory     subdirectory   subdirectory     subdirectory
  5401.  
  5402.      A subdirectory is stored in a disk's files area, just like any other
  5403.      file. The format of directory entries in a subdirectory is identical to
  5404.      the format of entries in a root directory, but a subdirectory is not
  5405.      limited in size. Like an ordinary file, a subdirectory can grow without
  5406.      bounds as long as disk space is available to hold it.
  5407.  
  5408.      A subdirectory is always attached to a parent directory, which can be
  5409.      either the root directory or another subdirectory. When you nest
  5410.      subdirectories, one within another, they are related in the form of a
  5411.      tree structure.
  5412.  
  5413.      A parent directory has one entry for each of its subdirectories. A
  5414.      subdirectory entry is just like a filename entry, except that the
  5415.      attribute byte marks the entry as a subdirectory and the file-size field
  5416.      is set to 0. The actual size of the subdirectory can be found by tracing
  5417.      its allocation chain through the FAT.
  5418.  
  5419.      When DOS creates a subdirectory, it places two special entries in it,
  5420.      with . and . . as filenames. These act like entries for further
  5421.      subdirectories, but . actually refers to the present subdirectory and .
  5422.      . refers to its parent directory. The starting cluster number in each of
  5423.      these directory entries gives the location of the subdirectory itself or
  5424.      of its parent. When the starting cluster number is 0, the parent of the
  5425.      subdirectory is the root directory.
  5426.  
  5427.      If the size of a "normal" file is reduced, you can generally count on
  5428.      DOS to release any unused space. In the case of subdirectories, however,
  5429.      clusters of space that are no longer used (because the directory entries
  5430.      that occupied that space are erased) are not released until the entire
  5431.      subdirectory is deleted.
  5432.    ──────────────────────────────────────────────────────────────────────────
  5433.  
  5434.    Bit 3 marks a directory entry as a volume label. A volume label entry is
  5435.    properly recognized only in the root directory, and uses only a few of the
  5436.    eight fields available in the directory entry: The label itself is stored
  5437.    in the filename and extension fields, which are treated as one unified
  5438.    field for this purpose; the size and starting cluster fields are not used,
  5439.    but the date and time fields are.
  5440.  
  5441.    Bit 4, the subdirectory attribute, identifies a directory entry as a
  5442.    subdirectory. Because subdirectories are stored like ordinary data files,
  5443.    they need a supporting directory entry. All the directory fields are used
  5444.    for these entries, except the file-size field, which is zero. The actual
  5445.    size of a subdirectory can be found simply by following its space
  5446.    allocation chain in the FAT.
  5447.  
  5448.    Bit 5, the archive attribute, was created to assist in making backup
  5449.    copies of the many files that can be stored on a fixed disk. This bit is 0
  5450.    on all files that haven't changed since they were last backed up; DOS sets
  5451.    this bit to 1 whenever a file is created or modified.
  5452.  
  5453.    Offset 0CH: Reserved
  5454.  
  5455.    This 10-byte area is set aside for possible future uses. All 10 bytes are
  5456.    normally set to 0.
  5457.  
  5458.    Offset 16H: The time
  5459.  
  5460.    This field contains a 2-byte value that marks the time that the file was
  5461.    created or last changed. It is used in conjunction with the date field,
  5462.    and the two together can be treated as a single 4-byte unsigned integer.
  5463.    This 4-byte integer can be compared with those in other directory entries
  5464.    for greater-than, less-than, or equal values. The time, by itself, is
  5465.    treated as an unsigned word integer. It is based on a 24-hour clock and is
  5466.    built out of the hour, minutes, and seconds with this formula:
  5467.  
  5468.    Time=(Hourx2048)+(Minutesx32)+(Seconds÷2)
  5469.  
  5470.    The 2-byte word used to store the time is one bit too short to store all
  5471.    the seconds, so seconds are stored in units of 2 seconds from 0 through
  5472.    29; a value of 5, for example, would represent 10 seconds. The time
  5473.    11:32:10 would be stored as the value 5C05H (decimal 23557).
  5474.  
  5475.    Offset 18H: The date
  5476.  
  5477.    This field contains a 2-byte value that marks the date the file was
  5478.    created or last changed. It is used in conjunction with the time field,
  5479.    and the two together can be treated as a single 4-byte unsigned integer
  5480.    that can be compared with those in other directory entries for
  5481.    greater-than, less-than, or equal values. The date, by itself, is treated
  5482.    as an unsigned word integer that is built out of the year, month, and day
  5483.    with this formula:
  5484.  
  5485.    Date=((Year-1980)x512)+(Monthx32)+Day
  5486.  
  5487.    This formula compresses the year by subtracting 1980 from it. Thus, the
  5488.    year 1988 is calculated as a value of 8. Using this formula, a date such
  5489.    as December 12, 1988 is stored by the formula as 118CH (decimal 4492):
  5490.  
  5491.    (1988-1980)x512+12x32+12=4492
  5492.  
  5493.    Although this scheme allows for years up through 2107, the highest year
  5494.    supported by DOS is 2099.
  5495.  
  5496.    Offset 1AH: The starting cluster number
  5497.  
  5498.    The seventh field of a directory entry is a 2-byte value that gives the
  5499.    starting cluster number for the file's data space. This cluster number
  5500.    acts as the entry point into the file's space allocation chain in the FAT.
  5501.    For files with no space allocated and for volume-label entries, the
  5502.    starting cluster number is 0.
  5503.  
  5504.    Offset 1CH: The file size
  5505.  
  5506.    The last field of a directory entry gives the size of the file in bytes.
  5507.    It is coded as a 4-byte unsigned integer, which allows file sizes to grow
  5508.    very large──4,294,967,295 bytes, to be exact──large enough for all
  5509.    practical purposes.
  5510.  
  5511.    DOS uses the file size in a file's directory entry to determine the exact
  5512.    size of the file. Because a file's disk space is allocated in clusters of
  5513.    512 bytes or more, the actual disk space occupied by a file is usually
  5514.    greater than the value in the directory entry. On disk, the space between
  5515.    the end of the file and the end of the last cluster in the file is wasted.
  5516.  
  5517.  The Files Area
  5518.  
  5519.    All data files and subdirectories are stored in the files area, which
  5520.    occupies the last and largest part of each disk.
  5521.  
  5522.    DOS allocates space to files, one cluster at a time, on an as-needed
  5523.    basis. (Remember, a cluster is one or more consecutive sectors; the number
  5524.    of sectors per cluster is a fixed characteristic of each disk format.) As
  5525.    a file is being created, or as an existing file is extended, the file's
  5526.    allocated space grows. When more space is needed, DOS allocates another
  5527.    cluster to the file. In DOS versions 1 and 2, the first available cluster
  5528.    is always allocated to the file. Later versions of DOS select clusters by
  5529.    more complicated rules that we won't go into here.
  5530.  
  5531.    Under ideal conditions, a file is stored in one contiguous block of space.
  5532.    However, a file might be broken into several noncontiguous blocks,
  5533.    especially if information is added to an existing file or a new file is
  5534.    stored in the space left by an erased file. So it's not unusual for one
  5535.    file's data to be scattered throughout the disk.
  5536.  
  5537.    This file fragmentation slows access to the file's data to some degree.
  5538.    Also, it is much harder to "unerase" a file you have unintentionally
  5539.    erased if it is fragmented, simply because you have to do a lot more
  5540.    searching for the individual clusters that make up the file's data space.
  5541.    But fragmentation has no other effect, and programs generally do not need
  5542.    to be concerned about where on a disk their data is stored. To determine
  5543.    if a file is fragmented, use CHKDSK or a program such as the Norton
  5544.    Utilities.
  5545.  
  5546.    If you are concerned about diskette file fragmentation, the DOS COPY
  5547.    command lets you transfer fragmented files to a newly formatted disk. DOS
  5548.    allocates contiguous space for the copied files. This simple technique
  5549.    also works for fixed-disk files, but it is much less convenient unless you
  5550.    have an extra, newly formatted fixed disk to use. If you think that
  5551.    fixed-disk file fragmentation is slowing down a particular application,
  5552.    you can purchase any of several fixed-disk utility programs to rearrange
  5553.    fragmented fixed-disk files and make them contiguous. Most of the time,
  5554.    however, file fragmentation has little impact on the speed of your
  5555.    programs.
  5556.  
  5557.    Whether you ever look at your fragmented files or not, you should know how
  5558.    DOS uses the file allocation table (FAT) to allocate disk space and how
  5559.    the FAT forms a space allocation chain to connect all of the clusters that
  5560.    make up a file.
  5561.  
  5562.  The File Allocation Table
  5563.  
  5564.    The file allocation table (FAT) is DOS's map of how space is utilized in
  5565.    the files area of a disk. We've already discussed how space for the FAT
  5566.    itself is reserved on a diskette or in a fixed-disk partition. Now we'll
  5567.    describe how the FAT is formatted and used.
  5568.  
  5569.    For most disk formats, DOS maintains two copies of the FAT, just in case
  5570.    one of them is damaged or becomes unreadable. Curiously, the CHKDSK
  5571.    program, which tests for most errors that can occur in the FAT and in
  5572.    directories, does not even notice if the two FATs are different.
  5573.  
  5574.    The organization of the FAT is simple: There is one entry in the FAT for
  5575.    each cluster in the files area. A FAT entry can contain any of the values
  5576.    listed in Figure 5-13. If the value in a FAT entry doesn't mark an
  5577.    unused, reserved, or defective cluster, then the cluster that corresponds
  5578.    to the FAT entry is part of a file, and the value in the FAT entry itself
  5579.    indicates the next cluster in the file.
  5580.  
  5581.    This means that the space that belongs to a given file is mapped by a
  5582.    chain of FAT entries, each of which points to the next entry in the chain.
  5583.    (See Figure 5-14.) The first cluster number in the chain is the starting
  5584.    cluster number in the file's directory entry. When a file is created or
  5585.    extended, DOS allocates clusters to the file by searching the FAT for
  5586.    unused clusters (that is, clusters whose FAT entries are 0) and adding
  5587.    them to the chain. Conversely, when a file is truncated or deleted, DOS
  5588.    frees the clusters that had been allocated to the file by clearing the
  5589.    corresponding FAT entries.
  5590.  
  5591.    12-bit Value             16-bit Value            Meaning
  5592.    ──────────────────────────────────────────────────────────────────────────
  5593.    0                        0                       Unused cluster
  5594.    FF0-FF6H                 FFF0-FFF6H              Reserved cluster
  5595.    FF7H                     FFF7H                   Bad cluster
  5596.    FF8-FFFH                 FFF8-FFFFH              Last cluster in a file
  5597.    (other values)                                   Next cluster in a file
  5598.    ──────────────────────────────────────────────────────────────────────────
  5599.  
  5600.    Figure 5-13.  FAT values.
  5601.  
  5602.                 File-  Extension            Starting
  5603.                 name                        cluster
  5604.    Directory   ┌─────┬────┬─────────────────┬────┬─┐
  5605.        entry   │ALPHA│TEXT│                 │0003│ │
  5606.                └─────┴────┴─────────────────┴──┬─┴─┘
  5607.                       ┌────────────────────────┘
  5608.                       │┌─────────────┐┌─────────┐
  5609.              ──┬────┬─┴─┬────┬────┬─┴─┬────┬────┬────┬──
  5610.      FAT       │0000│0006│0000│0000│0000│0008│FFFFH│0000│
  5611.              ──┴────┴────┴────┴────┴────┴────┴─────┴────┴──
  5612.                   2    3    4    5    6    7     8    9
  5613.  
  5614.    Figure 5-14.  Disk-space allocation using the FAT.
  5615.  
  5616.    The FAT can be formatted with either 12-bit or 16-bit entries. The 12-bit
  5617.    format is used for diskettes and fixed-disk partitions with no more than
  5618.    4078 clusters. (A fixed-disk's partition table indicates whether a DOS
  5619.    partition's FAT uses 12-bit or 16-bit entries.) The entries in a 12-bit
  5620.    FAT are harder to access because they don't fit neatly into the 16-bit
  5621.    word size of the 8086 family of microprocessors, but a 12-bit FAT takes up
  5622.    less room on a diskette, where disk space is scarcer.
  5623.  
  5624.    The first two entries in the FAT are reserved for use by DOS. The first
  5625.    byte of the FAT contains the same media descriptor value that appears in
  5626.    the BIOS parameter block in the disk boot sector. The remaining bytes of
  5627.    the first two entries are filled with the value 0FFH. Because the first
  5628.    two cluster numbers (0 and 1) are reserved, cluster number 2 corresponds
  5629.    to the first cluster of available disk space in the files area.
  5630.  
  5631.    Reading the values in the FAT is simple enough for a 16-bit FAT: Multiply
  5632.    a given cluster number by 2 to find the byte offset of the corresponding
  5633.    FAT entry. In the 16-bit FAT in Figure 5-15, for example, the byte offset
  5634.    of the FAT entry for cluster 2 is 04H, and the value in that entry is
  5635.    0003; the byte offset of the FAT entry for cluster 3 is 06H, and the value
  5636.    in that entry is 0004; and so on.
  5637.  
  5638.    For a 12-bit FAT, the computation is a bit trickier, because each pair of
  5639.    FAT entries occupies 3 bytes (0 and 1 occupy the first 3 bytes, 2 and 3
  5640.    occupy the next 3 bytes, and so forth). Given any cluster number, you can
  5641.    find the FAT entry by multiplying the cluster number by 3, dividing by 2,
  5642.    and then using the whole number of the result as a displacement into the
  5643.    FAT. By grabbing a word at that address, you have the three hex digits of
  5644.    the FAT entry, plus one extraneous hex digit, which can be removed by any
  5645.    one of several quick machine-language instructions. If the cluster number
  5646.    is even, you discard the high-order digit; if it is odd, you discard the
  5647.    low-order digit. Try this on the 12-bit FAT in Figure 5-15. You'll find
  5648.    that the entries are the same as in the 16-bit FAT in Figure 5-15.
  5649.  
  5650.    (a) 16-bit FAT
  5651.  
  5652.        Reserved     Cluster Cluster Cluster Cluster Cluster Cluster Cluster Cl
  5653.                        2       3       4       5       6       7       8
  5654.     ┌──────┴─────┐  ┌──┴─┐  ┌──┴─┐  ┌──┴─┐  ┌──┴─┐  ┌──┴─┐  ┌──┴─┐  ┌──┴─┐  ┌─
  5655.     F8  FF  FF  FF  03  00  04  00  05  00  06  00  0A  00  08  00  FF  FF  23
  5656.  
  5657.  
  5658.  
  5659.    (b) 12-bit FAT
  5660.  
  5661.      Reserved    Clusters    Clusters    Clusters    Clusters
  5662.                  2 and 3     4 and 5     6 and 7     8 and 9
  5663.     ┌────┴───┐  ┌────┴───┐  ┌────┴───┐  ┌────┴───┐  ┌────┴───┐
  5664.     FO  FF  FF  03  40  00  05  60  00  0A  80  00  FF  3F  12
  5665.  
  5666.    Figure 5-15.  The first few entries in a 16-bit FAT (a) and in a 12-bit
  5667.    FAT (b).
  5668.  
  5669.    As we have said, the first two FAT entries, in both 12-bit and 16-bit
  5670.    formats, are not used to indicate the status of clusters; instead, they
  5671.    are set aside so that the very first byte of the FAT can be used as a
  5672.    media descriptor byte that indicates the format of the disk. (See Figure
  5673.    5-16.) However, you should not assume that these IDs uniquely identify
  5674.    formats: they don't necessarily. If you considered every disk format in
  5675.    use, you'd find quite a few duplications. Beware.
  5676.  
  5677.                                                     Sectors      Media
  5678.    Disk                     Capacity    Heads       per Track    Descriptor
  5679.    ──────────────────────────────────────────────────────────────────────────
  5680.    51/4-inch diskette       160 KB      1             8          FEH
  5681.                             320 KB      2             8          FFH
  5682.                             180 KB      1             9          FCH
  5683.                             360 KB      2             9          FDH
  5684.                             1.2 MB      2            15          F9H
  5685.    31/2-inch diskette       720 KB      2             9          F9H
  5686.                             1.44 MB     2            18          F0H
  5687.    Fixed disk                                                    F8H
  5688.    ──────────────────────────────────────────────────────────────────────────
  5689.  
  5690.    Figure 5-16.  DOS media descriptor values.
  5691.  
  5692.    Your programs can learn the format of a disk by reading and inspecting the
  5693.    FAT media descriptor byte. The easy way to do this is to use DOS function
  5694.    1BH (decimal 27). For more information about this function, see page 335.
  5695.  
  5696.    Special notes on the FAT
  5697.  
  5698.    Normally, programs do not look at or change a disk's FAT; they leave the
  5699.    FAT completely under the supervision of DOS. The only exceptions are
  5700.    programs that perform space-allocation functions not supported by DOS──for
  5701.    example, programs that recover erased files, such as the UnErase program
  5702.    in the Norton Utilities program set.
  5703.  
  5704.    Be aware that a FAT can be logically damaged; for example, an allocation
  5705.    chain can be circular, referring back to a previous link in the chain; or
  5706.    two chains can converge on one cluster; or a cluster can be orphaned,
  5707.    meaning that it is marked as in use even though it is not part of any
  5708.    valid allocation chain. Also, an end-of-file marker (FFFH or FFFFH) may be
  5709.    missing. The DOS programs CHKDSK and RECOVER are designed to detect and
  5710.    repair most of these problems as well as can reasonably be done.
  5711.  
  5712.    For special notes on the interaction of the space allocation chain in the
  5713.    FAT and DOS's record of a file's size, see page 117.
  5714.  
  5715.  
  5716.  Comments
  5717.  
  5718.    Although this chapter has included detailed information for direct use of
  5719.    the logical structure of the disk itself, including the boot sector, FAT,
  5720.    and directories, it is not a good idea to use these elements directly
  5721.    unless you have a compelling reason. In fact, except where such use is
  5722.    completely unavoidable, as in a copy-protection program, it's unwise to
  5723.    incorporate any knowledge of the disk format in your programs. On the
  5724.    whole, your best approach is to consider the standard hierarchy of
  5725.    operations and use the highest level of services that can satisfy your
  5726.    needs:
  5727.  
  5728.    ■  First choice: Language services (the facilities provided by your
  5729.       programming language; for example, BASIC's OPEN and CLOSE statements)
  5730.  
  5731.    ■  Second choice: DOS services (described in Chapters 16 and 17)
  5732.  
  5733.    ■  Third choice: ROM BIOS disk services (described in Chapter 10)
  5734.  
  5735.    ■  Last choice: Direct control (for example, direct programming of the
  5736.       disk-drive controller through commands issued via I/O ports)
  5737.  
  5738.    Most disk operations for the PC family can be handled quite easily with
  5739.    the services that your programming language provides. There are, however,
  5740.    two obvious circumstances that can call for more exotic methods. One,
  5741.    which we've already mentioned, occurs when your programming involves
  5742.    control of a disk on the same level exercised by DOS. This level of
  5743.    control would be called for if you were writing a program similar to DOS's
  5744.    CHKDSK or the Norton Utilities. The other circumstance involves copy
  5745.    protection. In one way or another, all diskette copy-protection schemes
  5746.    involve some type of unconventional diskette I/O. This type of control
  5747.    usually leads to the use of the ROM BIOS services, but may also lead to
  5748.    the extreme measure of directly programming the disk-drive controller
  5749.    itself.
  5750.  
  5751.  Copy Protection
  5752.  
  5753.    A variety of copy-protection schemes are commercially available. Some are
  5754.    simple, others are more complex. If you're interested in devising your own
  5755.    scheme, however, here are some things to consider.
  5756.  
  5757.    For diskettes, there are dozens of ways to approach copy protection.
  5758.    Perhaps the most common methods involve reformatting the sectors in
  5759.    certain tracks on the diskette by using the ROM BIOS format routines.
  5760.    Because DOS cannot read sectors that don't conform to its specific
  5761.    formats, the DOS COPY program can't copy a disk that has an occasional odd
  5762.    sector size interspersed with normal sectors. This DOS limitation inspired
  5763.    a number of companies to produce copy programs that can read and copy
  5764.    sectors of any size, so it is not a particularly effective means of copy
  5765.    protection.
  5766.  
  5767.    On a more advanced level, there are two special aspects of diskette copy
  5768.    protection that are worth noting. First, some of the most exotic and
  5769.    unbreakable protection schemes have been based on the discovery of
  5770.    undocumented abilities hidden in the diskette-drive controller. Second,
  5771.    some protection schemes are intentionally or unintentionally dependent
  5772.    upon the particular characteristics of different diskette drives. This
  5773.    means that a copy-protected program may function on one model of computer
  5774.    but fail to function on another model, even though the copy protection has
  5775.    not been tampered with. If you use a copy-protection scheme, keep this in
  5776.    mind.
  5777.  
  5778.    Many of the copy-protection techniques used on diskettes are not
  5779.    appropriate for fixed disks, mainly because most fixed-disk users need to
  5780.    be able to make backup copies of programs on their fixed disks. This means
  5781.    you should avoid copy-protection schemes that prevent fixed-disk backups
  5782.    by making it impossible for DOS or the ROM BIOS to read part of the disk.
  5783.    Most of the fixed-disk copy-protection schemes in use today rely on
  5784.    data-encryption techniques, which discourage software piracy without
  5785.    preventing legitimate copying.
  5786.  
  5787.    In an encrypted program, the program's executable code and data are stored
  5788.    on the disk in an encrypted, hard-to-unravel format. When you execute the
  5789.    program, a special start-up program decrypts the encrypted code and data
  5790.    so that it can be used. The start-up program might also rely on data saved
  5791.    in hidden files or subdirectories to decrypt the main program.
  5792.  
  5793.    There is no particular additional guidance that we can give you here,
  5794.    except to remind you that variety and ingenuity are the keys to successful
  5795.    copy protection.
  5796.  
  5797.  
  5798.  
  5799.  ────────────────────────────────────────────────────────────────────────────
  5800.  Chapter 6  Keyboard Basics
  5801.  
  5802.    Keyboard Operation
  5803.      Keystrokes and Scan Codes
  5804.      Communicating with the ROM BIOS
  5805.      Translating the Scan Codes
  5806.      Entering ASCII Codes Directly
  5807.  
  5808.    Keyboard Data Format
  5809.      The ASCII Keys
  5810.      The Special Keys
  5811.  
  5812.    ROM BIOS Keyboard Control
  5813.      The Insert State
  5814.      The Caps Lock State
  5815.      The Num Lock State
  5816.      The Keyboard-Hold State
  5817.      The Toggle-Key States
  5818.  
  5819.    Comments
  5820.  
  5821.    This chapter is about the IBM PC and PS/2 keyboards. The first part of
  5822.    this chapter explains how the keyboard interacts with the computer on a
  5823.    hardware and software level. In the second part, we'll describe how the
  5824.    ROM BIOS treats keyboard information and makes it available to programs.
  5825.  
  5826.    ──────────────────────────────────────────────────────────────────────────
  5827.    NOTE:
  5828.      If you plan to play around with keyboard control, we urge you to read
  5829.      the comments on page 140 first and then apply the information in this
  5830.      chapter to your programs only if you have a reason to do so (for
  5831.      example, if you are creating a keyboard-enhancer program to modify the
  5832.      operation of the keyboard; see the sidebar on page 133 for more
  5833.      information on such programs). If you have any such application in mind,
  5834.      take a look at the ROM BIOS keyboard services in Chapter 11.
  5835.    ──────────────────────────────────────────────────────────────────────────
  5836.  
  5837.    The keyboard has undergone several modifications since the IBM PC was
  5838.    released. The original IBM PC keyboard had 83 keys. The PC/AT was
  5839.    introduced with an 84-key keyboard that changed the locations of several
  5840.    keys on the 83-key keyboard and added one new key, the Sys Req key.
  5841.  
  5842.    IBM later upgraded the AT with a 101/102-key keyboard that provided extra
  5843.    function keys and a new keyboard layout. The 101/102-key keyboard became
  5844.    standard equipment in the PS/2 series. The 101/102-key layout includes two
  5845.    extra function keys (F11 and F12), a number of duplicate shift and control
  5846.    keys, and modifications to several keys and keyboard combinations found in
  5847.    the 83- and 84-key layouts (Pause, Alt-Sys Req, and Print Screen).
  5848.  
  5849.    A trend in IBM's keyboard design has been to increase the similarity
  5850.    between the PC and PS/2 keyboards and the keyboards on their mainframe
  5851.    display terminals. For example, the 101/102-key keyboard's 12 function
  5852.    keys (F1 through F12) are reminiscent of the Program Function (PF) keys on
  5853.    IBM mainframe display terminals. Similarly, the Sys Req key is like the
  5854.    Sys Req key in IBM mainframe terminals: A mainframe terminal-emulator
  5855.    program running on a PC or PS/2 could use the Sys Req key for the same
  5856.    purpose a mainframe terminal would──to switch among terminal sessions or
  5857.    to initiate a keyboard reset function.
  5858.  
  5859.    Another trend in IBM's keyboard design has been to accommodate non-English
  5860.    alphabets in the keyboard layout. The English-language version of the
  5861.    101/102-key keyboard released in the United States and United Kingdom has
  5862.    101 keys, but for other languages the same keyboard has an extra key next
  5863.    to the left Shift key, a different arrangement of keys around the Enter
  5864.    key, and a different map of ASCII characters to key locations. From a
  5865.    programmer's point of view, however, these two keyboards are so similar
  5866.    that IBM describes them together in its technical documentation──and we'll
  5867.    do the same in this chapter.
  5868.  
  5869.  
  5870.  Keyboard Operation
  5871.  
  5872.    The keyboard unit contains a dedicated microprocessor that performs a
  5873.    variety of jobs, all of which help cut down on system overhead. The main
  5874.    duty of the keyboard microprocessor is to watch the keys and report to the
  5875.    main computer whenever a key is pressed or released. If any key is pressed
  5876.    continuously, the keyboard microprocessor sends out a repeat action at
  5877.    specific intervals. The keyboard microprocessor controller also has
  5878.    limited diagnostic and error-checking capabilities and has a buffer that
  5879.    can store key actions in the rare instance that the main computer is
  5880.    temporarily unable to accept them.
  5881.  
  5882.    The PC/AT and PS/2s have sophisticated keyboard control circuitry that can
  5883.    perform several functions the original IBM PC and PC/XT keyboard cannot.
  5884.    These features include programmable typematic control, programmable
  5885.    scan-code sets, and improved hardware for error detection.
  5886.  
  5887.    On the 83-key keyboard, the typematic delay and repeat rate are built into
  5888.    the hardware: A key must be pressed for 0.5 seconds before auto-repeat
  5889.    begins, and the repeat rate is about 10 characters per second. With the
  5890.    PC/AT and PS/2 keyboards, you can modify the typematic delay and rate by
  5891.    programming the keyboard controller. The most convenient way to do this is
  5892.    through the ROM BIOS keyboard services described in Chapter 11.
  5893.  
  5894.    The keyboard controller in the PC/AT and PS/2s can also assign any of
  5895.    three different sets of scan-code values to the keys on the 84- and
  5896.    101/102-key layouts. By default, however, the ROM BIOS establishes a
  5897.    scan-code set that is compatible with that used on the 83-key keyboard.
  5898.    You will probably find use for the alternative scan-code sets only if your
  5899.    program bypasses the ROM BIOS and processes scan codes directly. (See the
  5900.    PC/AT and PS/2 technical reference manuals for details.)
  5901.  
  5902.    The improved error-detection ability of the AT and PS/2 keyboard
  5903.    controllers is largely invisible to your programs; the keyboard hardware
  5904.    and the ROM BIOS service routines are very reliable. The most common
  5905.    errors you may encounter are a full ROM BIOS keyboard buffer or a key
  5906.    combination that the PS/2 ROM BIOS cannot process. In both situations, the
  5907.    ROM BIOS generates a warning beep to inform you that something unusual has
  5908.    occurred. (For example, try holding down both pairs of Ctrl and Alt keys
  5909.    on a PS/2 keyboard.)
  5910.  
  5911.  Keystrokes and Scan Codes
  5912.  
  5913.    Each time you press or release one of the keys on the keyboard, the
  5914.    keyboard circuits transmit a sequence of one or more 8-bit numbers through
  5915.    the connector cable to the computer. This sequence, called a scan code,
  5916.    uniquely identifies the key you pressed. The keyboard produces different
  5917.    scan codes, depending on whether the key was pressed or released. Whenever
  5918.    you press a key, the scan-code byte contains a number ranging from 01H
  5919.    through 58H. When you release the key, the keyboard generates a scan code
  5920.    80H higher than the keystroke scan code by setting bit 7 of the scan-code
  5921.    byte to 1. For example, when you press the letter Z, the keyboard
  5922.    generates a scan code of 2CH; when you release it, the keyboard generates
  5923.    a scan code of ACH (2CH + 80H). The keyboard diagrams in Figures 6-1,
  5924.    6-2, and 6-3 show the standard keyboard keys and their associated scan
  5925.    codes.
  5926.  
  5927.    ┌────────────────────────────────────────────────────────────────────────┐
  5928.    │ Figure 6-1 can be found on p.128 of the printed version of the book.   │
  5929.    └────────────────────────────────────────────────────────────────────────┘
  5930.  
  5931.    Figure 6-1.  Scan codes for the 83-key keyboard (PC, PC/XT). Scan-code
  5932.    values are in hex.
  5933.  
  5934.    ┌────────────────────────────────────────────────────────────────────────┐
  5935.    │ Figure 6-2 can be found on p.128 of the printed version of the book.   │
  5936.    └────────────────────────────────────────────────────────────────────────┘
  5937.  
  5938.    Figure 6-2.  Scan codes for the 84-key keyboard (PC/AT). Scan-code values
  5939.    are in hex.
  5940.  
  5941.    ┌────────────────────────────────────────────────────────────────────────┐
  5942.    │ Figure 6-3 can be found on p.129 of the printed version of the book.   │
  5943.    └────────────────────────────────────────────────────────────────────────┘
  5944.  
  5945.    Figure 6-3.  Scan codes for the 101/102-key keyboard (PC/AT and PS/2).
  5946.    Scan-code values are in hex.
  5947.  
  5948.    If you compare the scan codes for the 83-, 84-, and 101/102-key keyboards,
  5949.    you'll see that a key generates the same scan code regardless of its
  5950.    location on the keyboard. For example, the Esc key has a scan code of 01H,
  5951.    whether it's next to the 1 key, next to the Num Lock key, or by itself in
  5952.    the upper-left corner. (The 101/102-key keyboard can actually generate
  5953.    different scan codes, but the start-up ROM BIOS suppresses this by
  5954.    configuring the keyboard to be compatible with the 83-key keyboard.)
  5955.  
  5956.    The 101/102-key layout contains duplicate shift and control keys that
  5957.    don't exist on the other keyboards. The 101/102-key keyboard distinguishes
  5958.    between duplicate keys by transmitting multiple-byte scan codes. For
  5959.    example, the two Alt shift keys have different scan codes: The left Alt
  5960.    key has a scan code of 38H, and the right Alt key has a 2-byte scan code,
  5961.    E0H 38H.
  5962.  
  5963.    ──────────────────────────────────────────────────────────────────────────
  5964.    NOTE:
  5965.      The multiple-byte scan codes for shift and control keys can vary
  5966.      depending on whether one of the shift keys (Ctrl, Alt, Shift), Num Lock,
  5967.      or Caps Lock is pressed at the same time. See IBM's PS/2 technical
  5968.      reference manuals for details.
  5969.    ──────────────────────────────────────────────────────────────────────────
  5970.  
  5971.    The 101/102-key keyboard also assigns special scan codes to certain
  5972.    keystroke combinations. The Alt-Sys Req combination is intended to be the
  5973.    same as the Sys Req key on the 84-key layout, so the 101/102-key keyboard
  5974.    transmits the same scan code, 54H. Because the Print Screen key has the
  5975.    same function as the Shift-PrtSc combination in the other keyboard
  5976.    layouts, the 101/102-key keyboard transmits a Shift key scan code (E0H
  5977.    2AH) followed by the PrtSc scan code (E0H 37H). The Pause key's scan code,
  5978.    E1H 1DH 45H, resembles the scan-code sequence for the Ctrl-Num Lock
  5979.    combination, but when you press Ctrl-Pause (that is, Ctrl-Break), the
  5980.    keyboard transmits E0H 46H E0H C6H, which is derived from the scan code
  5981.    for the Scroll Lock (Break) key on the 83- and 84-key keyboards. Figure
  5982.    6-4 lists these keystroke combinations and their associated codes.
  5983.  
  5984.    101/102-key Keyboard     84-key Keyboard         Scan Code
  5985.    Keystroke Combination    Equivalent              Transmitted
  5986.    ──────────────────────────────────────────────────────────────────────────
  5987.    Alt-Sys Req              Sys Req                 54H
  5988.    Print Screen             Shift-Print Screen      E0H 2AH
  5989.                                                     E0H 37H
  5990.    Ctrl-Break               Ctrl-Break              E0H 46H E0H C6H
  5991.    ──────────────────────────────────────────────────────────────────────────
  5992.  
  5993.    Figure 6-4.  Scan codes for special keystroke combinations on the
  5994.    101/102-key keyboard.
  5995.  
  5996.    ──────────────────────────────────────────────────────────────────────────
  5997.    NOTE:
  5998.      The "compact" keyboard available for the PS/2 Model 25 is really a
  5999.      101/102-key keyboard in disguise. The numeric keypad is mapped to a
  6000.      group of 14 keys on the main keyboard, and the Num Lock key is the shift
  6001.      state of the Scroll Lock key. However, keyboard scan codes and ROM BIOS
  6002.      processing are the same for the compact version as for the full-size
  6003.      101/102-key keyboard.
  6004.    ──────────────────────────────────────────────────────────────────────────
  6005.  
  6006.    Any program that processes keyboard scan codes must be aware of which
  6007.    machine it's running on and which keyboard is in use. Fortunately, few
  6008.    programs need to respond directly to keyboard scan codes──the ROM BIOS
  6009.    keyboard service routines translate scan codes into meaningful information
  6010.    that a program can use. The following sections describe this translation
  6011.    process more fully.
  6012.  
  6013.  Communicating with the ROM BIOS
  6014.  
  6015.    The keyboard-controller circuitry on the computer's system board monitors
  6016.    the keyboard for input. The keyboard controller generates interrupt 09H
  6017.    each time it receives a byte of data from the keyboard. The ROM BIOS
  6018.    contains an interrupt 09H handler that reads the byte from the keyboard
  6019.    controller and processes it. (I/O port 60H contains the keyboard data
  6020.    byte.) The interrupt 09H handler translates scan codes into 2-byte values
  6021.    that are generally more useful to a program than the original scan codes.
  6022.  
  6023.    The low-order byte of each 2-byte keyboard value contains the ASCII value
  6024.    corresponding to each key pressed. The high-order byte usually contains
  6025.    the corresponding keyboard scan code.
  6026.  
  6027.    Special keys, such as the function keys and the numeric-keypad keys, have
  6028.    a 0 in the low-order byte, with the keyboard scan code in the high-order
  6029.    byte. (More about this later, on page 134.)
  6030.  
  6031.    The ROM BIOS routines place the translated byte-pairs in a queue, which is
  6032.    kept in low memory in location 0040:001EH. The byte-pairs are stored there
  6033.    until they are requested by a program, such as DOS or interpreted BASIC,
  6034.    that expects to read keyboard input.
  6035.  
  6036.  Translating the Scan Codes
  6037.  
  6038.    The scan-code translation job is moderately complicated because the IBM
  6039.    keyboard recognizes two types of keys that change the meaning of a
  6040.    keystroke: shift keys and toggle keys.
  6041.  
  6042.    The shift keys
  6043.  
  6044.    Three keys──Ctrl, Shift, and Alt──are known as shift keys: They change the
  6045.    shift state, and thereby the meaning, of whatever key they are used with.
  6046.    For example, when you press Shift-C, you get a capital C; when you press
  6047.    Ctrl-C, you generate the "break" character. The ROM BIOS recognizes that
  6048.    all subsequent key actions will be influenced by that shift state as long
  6049.    as a shift key is pressed.
  6050.  
  6051.    The toggle keys
  6052.  
  6053.    In addition to the shift keys, two toggle keys also affect the keyboard's
  6054.    shift state: the Caps Lock key and the Num Lock key. When activated, Caps
  6055.    Lock reverses the shift state of the alphabet keys; it doesn't affect the
  6056.    other keys. When activated, the Num Lock key disables cursor-control
  6057.    functions on the numeric keypad. Toggle keys are activated with a single
  6058.    keystroke and remain active until released by a second keystroke.
  6059.  
  6060.    The shift-key and toggle-key status information is kept by the ROM BIOS in
  6061.    a low-memory location (0040:0017H), where you can use or change it. When
  6062.    you press a shift key or a toggle key, the ROM BIOS sets a specific bit in
  6063.    one of these two bytes. When the ROM BIOS receives the release scan code
  6064.    of a shift key, it switches the status bit back to its original shift
  6065.    state.
  6066.  
  6067.    Whenever the ROM BIOS receives a scan code for an ordinary keystroke, such
  6068.    as the letter z or a right arrow key, it first checks the shift state and
  6069.    then translates the key into the appropriate 2-byte code. (We'll discuss
  6070.    the status bytes in more detail on page 137.)
  6071.  
  6072.    The combination keys
  6073.  
  6074.    While the ROM BIOS routine is translating scan codes, it checks for Sys
  6075.    Req keystrokes and for certain shift-key combinations; specifically, it
  6076.    checks for the Ctrl-Alt-Del, Shift-PrtSc, Ctrl-Num Lock, and Ctrl-Break
  6077.    combinations. These five command-like key actions cause the ROM BIOS to
  6078.    perform a specific task immediately.
  6079.  
  6080.    Ctrl-Alt-Del causes the computer to reboot. Ctrl-Alt-Del is probably used
  6081.    more often than any other special key combination. It works dependably as
  6082.    long as the keyboard interrupt service is working. If the interrupt
  6083.    service is not working, turn the power off, wait a few seconds, then turn
  6084.    it on again; the power-on program resets all interrupt vectors and
  6085.    services.
  6086.  
  6087.    Shift-PrtSc (Print Screen on the 101/102-key keyboard) causes the ROM BIOS
  6088.    interrupt 09H handler to execute software interrupt 05H. The default
  6089.    interrupt 05H handler is also part of the ROM BIOS; it prints a "snapshot"
  6090.    of the current contents of the screen.
  6091.  
  6092.    Ctrl-Num Lock (Pause on the 101/102-key keyboard) suspends operation of a
  6093.    program until another keystroke occurs.
  6094.  
  6095.    Ctrl-Break causes the ROM BIOS to generate software interrupt 1BH and to
  6096.    set bit 7 of the byte at 0040:0071H to 1. The default DOS handler for
  6097.    interrupt 1BH simply sets a flag internal to DOS that causes DOS to
  6098.    interpret Ctrl-Break as Ctrl-C. You can override the default DOS action
  6099.    for Ctrl-Break by pointing the interrupt 1BH vector (located at
  6100.    0000:006CH) to your own interrupt handler.
  6101.  
  6102.    Sys Req (on the 84-key keyboard) and Alt-Sys Req (on the 101/102-key
  6103.    keyboard) cause the ROM BIOS to issue interrupt 15H with AH = 85H. Your
  6104.    program can provide its own interrupt 15H handler that intercepts and
  6105.    processes Sys Req keystrokes. (See Chapter 12 for details.)
  6106.  
  6107.    These are the only key combinations that are especially meaningful to the
  6108.    ROM BIOS. When an invalid combination is reported from the keyboard, the
  6109.    ROM BIOS simply ignores it and moves on to the next valid key action.
  6110.  
  6111.    Two more features of the PC keyboard should be presented before we discuss
  6112.    the details of keyboard coding: repeat key action and duplicate keys.
  6113.  
  6114.    Repeat key action
  6115.  
  6116.    The PC keyboard features automatic repeat key action, a process called
  6117.    typematic by IBM. The circuitry inside the keyboard monitors how long each
  6118.    key is pressed, and if a key is held down longer than a defined interval,
  6119.    the circuitry generates repeat key actions. This typematic action is
  6120.    reported as successive keystroke scan codes, without the intervening
  6121.    key-release codes. This makes it possible for an interrupt 09H handler to
  6122.    distinguish between actual keystrokes and typematic action. However, the
  6123.    ROM BIOS does not always distinguish between the two. The ROM BIOS
  6124.    keyboard-handling routine treats each automatic repeat key action as
  6125.    though the key were actually pressed and interprets the key accordingly.
  6126.  
  6127.    ──────────────────────────────────────────────────────────────────────────
  6128.    Keyboard-enhancer programs
  6129.      Thanks to the flexible software design of the PC, it's possible to
  6130.      create programs that customize the keyboard. Such programs are called
  6131.      keyboard-enhancer programs.
  6132.  
  6133.      Keyboard-enhancer programs monitor the scan codes that come in from the
  6134.      keyboard and respond to them in ways that aren't supported by the ROM
  6135.      BIOS or by DOS. Typically, these programs are fed instructions, called
  6136.      keyboard macros, that tell them what keystrokes to look for and what
  6137.      changes to make. The change might involve suppressing a keystroke
  6138.      (acting as if it never happened), replacing one keystroke with another,
  6139.      or replacing one keystroke with a long series of keystrokes. The most
  6140.      common use of keyboard macros is to abbreviate frequently used phrases;
  6141.      for example, you might instruct a keyboard enhancer to convert a key
  6142.      combination, such as Alt-S, into a salutation you use in your
  6143.      correspondence, such as Sincerely yours. You can also use keyboard
  6144.      macros to condense multiple-keystroke program commands to a single
  6145.      keystroke.
  6146.  
  6147.      Keyboard enhancers work by combining the powers of two special
  6148.      facilities──one that's part of DOS and one that's part of the PC's ROM
  6149.      BIOS. The DOS facility allows the enhancer program to remain resident in
  6150.      the computer's memory, quietly monitoring the operation of the computer
  6151.      while the ordinary control of the computer is turned over to a
  6152.      conventional program, such as a word processor. The ROM BIOS facility
  6153.      lets programs divert the stream of keyboard information so that it can
  6154.      be inspected and changed before it is passed on to a program. These
  6155.      programs use the DOS Terminate and Stay Resident facility to stay active
  6156.      in memory while other programs are run; then they use the ROM BIOS
  6157.      keyboard-monitoring facility to preview keyboard data and change it as
  6158.      needed.
  6159.    ──────────────────────────────────────────────────────────────────────────
  6160.  
  6161.    For example, if you press and hold the A key long enough for the keyboard
  6162.    to begin generating successive keystroke signals, then the ROM BIOS will
  6163.    create a series of As to be passed on to whatever program is reading
  6164.    keyboard data. On the other hand, when you press and hold a shift key, the
  6165.    ROM BIOS sets bits in its status bytes in segment 40H. While you hold the
  6166.    shift key down, the ROM BIOS continues to set the same bits to 1. When you
  6167.    release the key, the ROM BIOS resets the status bits. All this boils down
  6168.    to the simple fact that the ROM BIOS treats repeat key actions in a
  6169.    sensible way, acting on them or ignoring them as needed.
  6170.  
  6171.    Duplicate keys
  6172.  
  6173.    We've already described how the keyboard differentiates duplicate keys by
  6174.    assigning different scan codes to each. The ROM BIOS translates duplicate
  6175.    keys into the same ASCII character codes. For example, if you press either
  6176.    of the two asterisk keys, the ROM BIOS returns ASCII 2AH (the ASCII code
  6177.    for an asterisk); if you press either of the two Ctrl keys on a
  6178.    101/102-key keyboard, the ROM BIOS sets the appropriate bit in its
  6179.    shift-state byte.
  6180.  
  6181.    The ROM BIOS also lets programs tell the difference between duplicate
  6182.    keys, in some cases. Remember that the ROM BIOS translates each keystroke
  6183.    into a scan code as well as an ASCII code. A program that requests a
  6184.    keystroke from the ROM BIOS can inspect the scan code to determine which
  6185.    key was pressed. In the case of shift keys, a program can inspect the BIOS
  6186.    shift-state bytes at 0040:0017H and 0040:0018H to determine exactly which
  6187.    shift keys are pressed. (See the discussion of the shift-state bytes on
  6188.    pages 137 and 138.)
  6189.  
  6190.  Entering ASCII Codes Directly
  6191.  
  6192.    We should mention that the PC keyboard, in conjunction with the ROM BIOS,
  6193.    provides an alternate way to enter nearly any ASCII character code. This
  6194.    is done by holding down the Alt key and then entering the decimal ASCII
  6195.    character code from the numeric keypad on the right side of the keyboard.
  6196.    This method lets you enter any ASCII code from 01H through FFH (decimal 1
  6197.    through 255).
  6198.  
  6199.  
  6200.  Keyboard Data Format
  6201.  
  6202.    Once a keyboard action is translated, it is stored as a pair of bytes in
  6203.    the ROM BIOS buffer. We call the low-order byte the main byte and the
  6204.    high-order byte the auxiliary byte. The contents of these bytes will vary,
  6205.    depending on whether an ASCII key or a special key was pressed.
  6206.  
  6207.  The ASCII Keys
  6208.  
  6209.    When the main byte is an ASCII character value from 01H to FFH, one of two
  6210.    events has occurred: One of the standard keyboard characters was pressed,
  6211.    or an ASCII character was entered directly using the Alt-number method
  6212.    mentioned above. (See Appendix C for the complete ASCII character set.)
  6213.    For these ASCII characters, the auxiliary byte contains the scan code of
  6214.    the pressed key. (The scan code is 0 for characters entered with
  6215.    Alt-number.) Usually you can ignore this scan code. DOS does not report
  6216.    keyboard scan codes, nor do high-level programming language functions like
  6217.    getch() in C or INKEY$ in BASIC. However, a program can examine the
  6218.    auxiliary byte (scan code) to differentiate among duplicate keyboard
  6219.    characters.
  6220.  
  6221.  The Special Keys
  6222.  
  6223.    When the main byte is null (00H), it means that a special, non-ASCII key
  6224.    was pressed. The special keys include function keys, shifted function
  6225.    keys, cursor-control keys such as Home and End, and some of the Ctrl- and
  6226.    Alt-key combinations. When any of these keys are pressed by themselves or
  6227.    in combination with other keys, the auxiliary byte contains a single value
  6228.    that indicates which key was pressed. Figure 6-5 lists these values in a
  6229.    rough mixture of logical and numeric order. (For a complete breakdown of
  6230.    ROM BIOS key codes, see the IBM BIOS Interface Technical Reference
  6231.    Manual.)
  6232.  
  6233.    ──────────────────────────────────────────────────────────────────────────
  6234.    NOTE:
  6235.      With the 101/102-key keyboard, the main byte value for the gray
  6236.      cursor-control keys is E0H. This value distinguishes these keys from
  6237.      their counterparts on the numeric keypad, which have a main byte value
  6238.      of 00H.
  6239.    ──────────────────────────────────────────────────────────────────────────
  6240.  
  6241. ╓┌─┌──────────────────┌─────────────────┌────────────────────────────────────╖
  6242.             Value
  6243.    (hex)              (dec)             Keys Pressed
  6244.    ──────────────────────────────────────────────────────────────────────────
  6245.    3BH                59                F1
  6246.    3CH                60                F2
  6247.    3DH                61                F3
  6248.    3EH                62                F4
  6249.    3FH                63                F5
  6250.    40H                64                F6
  6251.    41H                65                F7
  6252.    42H                66                F8
  6253.    43H                67                F9
  6254.    44H                68                F10
  6255.    85H                133               F11
  6256.    86H                134               F12
  6257.  
  6258.    54H                84                Shift-F1
  6259.    55H                85                Shift-F2
  6260.             Value
  6261.    (hex)              (dec)             Keys Pressed
  6262.    ──────────────────────────────────────────────────────────────────────────
  6263.   55H                85                Shift-F2
  6264.    56H                86                Shift-F3
  6265.    57H                87                Shift-F4
  6266.    58H                88                Shift-F5
  6267.    59H                89                Shift-F6
  6268.    5AH                90                Shift-F7
  6269.    5BH                91                Shift-F8
  6270.    5CH                92                Shift-F9
  6271.    5DH                93                Shift-F10
  6272.    87H                135               Shift-F11
  6273.    88H                136               Shift-F12
  6274.  
  6275.    5EH                94                Ctrl-F1
  6276.    5FH                95                Ctrl-F2
  6277.    60H                96                Ctrl-F3
  6278.    61H                97                Ctrl-F4
  6279.    62H                98                Ctrl-F5
  6280.    63H                99                Ctrl-F6
  6281.             Value
  6282.    (hex)              (dec)             Keys Pressed
  6283.    ──────────────────────────────────────────────────────────────────────────
  6284.   63H                99                Ctrl-F6
  6285.    64H                100               Ctrl-F7
  6286.    65H                101               Ctrl-F8
  6287.    66H                102               Ctrl-F9
  6288.    67H                103               Ctrl-F10
  6289.    89H                137               Ctrl-F11
  6290.    8AH                138               Ctrl-F12
  6291.  
  6292.    68H                104               Alt-F1
  6293.    69H                105               Alt-F2
  6294.    6AH                106               Alt-F3
  6295.    6BH                107               Alt-F4
  6296.    6CH                108               Alt-F5
  6297.    6DH                109               Alt-F6
  6298.    6EH                110               Alt-F7
  6299.    6FH                111               Alt-F8
  6300.    70H                112               Alt-F9
  6301.    71H                113               Alt-F10
  6302.             Value
  6303.    (hex)              (dec)             Keys Pressed
  6304.    ──────────────────────────────────────────────────────────────────────────
  6305.   71H                113               Alt-F10
  6306.    8BH                139               Alt-F11
  6307.    8CH                140               Alt-F12
  6308.  
  6309.    78H                120               Alt-1
  6310.    79H                121               Alt-2
  6311.    7AH                122               Alt-3
  6312.    7BH                123               Alt-4
  6313.    7CH                124               Alt-5
  6314.    7DH                125               Alt-6
  6315.    7EH                126               Alt-7
  6316.    7FH                127               Alt-8
  6317.    80H                128               Alt-9
  6318.    81H                129               Alt-0
  6319.    82H                130               Alt-Hyphen
  6320.    83H                131               Alt-=
  6321.  
  6322.    10H                16                Alt-Q
  6323.             Value
  6324.    (hex)              (dec)             Keys Pressed
  6325.    ──────────────────────────────────────────────────────────────────────────
  6326.   10H                16                Alt-Q
  6327.    11H                17                Alt-W
  6328.    12H                18                Alt-E
  6329.    13H                19                Alt-R
  6330.    14H                20                Alt-T
  6331.    15H                21                Alt-Y
  6332.    16H                22                Alt-U
  6333.    17H                23                Alt-I
  6334.    18H                24                Alt-O
  6335.    19H                25                Alt-P
  6336.  
  6337.    1EH                30                Alt-A
  6338.    1FH                31                Alt-S
  6339.    20H                32                Alt-D
  6340.    21H                33                Alt-F
  6341.    22H                34                Alt-G
  6342.    23H                35                Alt-H
  6343.    24H                36                Alt-J
  6344.             Value
  6345.    (hex)              (dec)             Keys Pressed
  6346.    ──────────────────────────────────────────────────────────────────────────
  6347.   24H                36                Alt-J
  6348.    25H                37                Alt-K
  6349.    26H                38                Alt-L
  6350.  
  6351.    2CH                44                Alt-Z
  6352.    2DH                45                Alt-X
  6353.    2EH                46                Alt-C
  6354.    2FH                47                Alt-V
  6355.    30H                48                Alt-B
  6356.    31H                49                Alt-N
  6357.    32H                50                Alt-M
  6358.  
  6359.    0FH                15                Shift-Tab
  6360.  
  6361.    47H                71                Home
  6362.    48H                72                Up arrow
  6363.    49H                73                PgUp
  6364.  
  6365.             Value
  6366.    (hex)              (dec)             Keys Pressed
  6367.    ──────────────────────────────────────────────────────────────────────────
  6368. 
  6369.    4BH                75                Left arrow
  6370.  
  6371.    4DH                77                Right arrow
  6372.  
  6373.    4FH                79                End
  6374.  
  6375.    50H                80                Down arrow
  6376.    51H                81                PgDn
  6377.    52H                82                Insert
  6378.    53H                83                Del
  6379.  
  6380.    72H                114               Ctrl-PrtSc
  6381.    73H                115               Ctrl-Left arrow
  6382.    74H                116               Ctrl-Right arrow
  6383.    75H                117               Ctrl-End
  6384.    76H                118               Ctrl-PgDn
  6385.    77H                119               Ctrl-Home
  6386.             Value
  6387.    (hex)              (dec)             Keys Pressed
  6388.    ──────────────────────────────────────────────────────────────────────────
  6389.   77H                119               Ctrl-Home
  6390.  
  6391.    84H                132               Ctrl-PgUp
  6392.    ──────────────────────────────────────────────────────────────────────────
  6393.  
  6394.  
  6395.    Figure 6-5.  ROM BIOS auxiliary byte values for the special keys.
  6396.  
  6397.    Codes generated by the ROM BIOS for the complete set of characters and
  6398.    special keys are handled differently in different programming languages.
  6399.    BASIC, for example, takes a mixed approach to the special keys. When you
  6400.    use ordinary input statements, BASIC returns the ASCII characters and
  6401.    filters out any special keys. Some of these keys can be acted on with the
  6402.    ON KEY statement, but you can use the BASIC INKEY$ function to get
  6403.    directly to the ROM BIOS coding for keyboard characters and find out
  6404.    immediately what special key was pressed. If the INKEY$ function returns a
  6405.    1-byte string, it is reporting an ordinary or extended ASCII keyboard
  6406.    character. If INKEY$ returns a 2-byte string, the first byte in the string
  6407.    is the ROM BIOS's main byte and will always be 00H; the second byte is the
  6408.    auxiliary byte and will indicate which special key was pressed.
  6409.  
  6410.  
  6411.  ROM BIOS Keyboard Control
  6412.  
  6413.    The ROM BIOS stores keyboard status information in several portions of the
  6414.    ROM BIOS data area in segment 40H in low memory. Your programs can use
  6415.    some of the ROM BIOS status variables to check the keyboard status or to
  6416.    modify ROM BIOS keyboard processing.
  6417.  
  6418.    The two keyboard status bytes at locations 0040:0017H (shown in Figure
  6419.    6-6) and 0040:0018H (shown in Figure 6-7) are coded with individually
  6420.    meaningful bits that indicate which shift keys and toggle keys are active.
  6421.    All the standard models of the PC family have these two bytes, although
  6422.    the bits representing the Sys Req, left Alt, and left Ctrl keys are
  6423.    updated only for the keyboards that support these keys.
  6424.  
  6425.    The status byte at 0040:0017H is particularly useful because it
  6426.    establishes the state of ROM BIOS keystroke processing. Changes to this
  6427.    status byte affect the next keystroke that the ROM BIOS processes.
  6428.  
  6429.          Bit
  6430.    7 6 5 4 3 2 1 0          Meaning
  6431.    ──────────────────────────────────────────────────────────────────────────
  6432.    X . . . . . . .          Insert state: 1 = active; 0 = inactive
  6433.    . X . . . . . .          Caps Lock: 1 = active; 0 = inactive
  6434.    . . X . . . . .          Num Lock: 1 = active; 0 = inactive
  6435.    . . . X . . . .          Scroll Lock: 1 = active; 0 = inactive
  6436.    . . . . X . . .          1 = Alt pressed
  6437.    . . . . . X . .          1 = Ctrl pressed
  6438.    . . . . . . X .          1 = Left Shift pressed
  6439.    . . . . . . . X          1 = Right Shift pressed
  6440.    ──────────────────────────────────────────────────────────────────────────
  6441.  
  6442.    Figure 6-6.  The coding of the keyboard status byte at location
  6443.    0040:0017H. Bits 4─7 are toggles; their values change each time the key is
  6444.    pressed. Bits 0─3 are set only while the corresponding key i s pressed.
  6445.  
  6446.          Bit
  6447.    7 6 5 4 3 2 1 0          Meaning
  6448.    ──────────────────────────────────────────────────────────────────────────
  6449.    X . . . . . . .          1 = Ins pressed
  6450.    . X . . . . . .          1 = Caps Lock pressed
  6451.    . . X . . . . .          1 = Num Lock pressed
  6452.    . . . X . . . .          1 = Scroll Lock pressed
  6453.    . . . . X . . .          1 = Hold state active (Ctrl-Num Lock or Pause)
  6454.    . . . . . X . .          1 = Sys Req key pressed
  6455.    . . . . . . X .          1 = Left Alt key pressed
  6456.    . . . . . . . X          1 = Left Ctrl key pressed
  6457.    ──────────────────────────────────────────────────────────────────────────
  6458.  
  6459.    Figure 6-7.  The coding of the keyboard status byte at location
  6460.    0040:0018H. These bits are set only while the corresponding key is
  6461.    pressed.
  6462.  
  6463.  The Insert State
  6464.  
  6465.    The ROM BIOS keeps track of the insert state in bit 7 of byte 0040:0017H.
  6466.    However, every program we know of ignores this bit and keeps its own
  6467.    record of the insert state. This means that you should not rely on this
  6468.    status bit to tell you anything about the current state of Insert key
  6469.    processing.
  6470.  
  6471.  The Caps Lock State
  6472.  
  6473.    Some programmers force the Caps Lock state to be active by setting bit 6
  6474.    of byte 0040:0017H. This can confuse or irritate some program users, so we
  6475.    don't recommend it. However, this trick works reliably and precedent
  6476.    exists for using it. If you do you'll see that the ROM BIOS updates the
  6477.    LED indicator on the 84- and 101/102-key keyboards accordingly. This also
  6478.    occurs when you update the Num Lock or Scroll Lock states.
  6479.  
  6480.  The Num Lock State
  6481.  
  6482.    Because the Num Lock key's location on the keyboard makes it susceptible
  6483.    to inadvertent keystrokes, some programmers force the Num Lock toggle (bit
  6484.    5 of byte 0040:0017H) to a predetermined state at the beginning of a
  6485.    program. For example, clearing the Num Lock status bit before requesting
  6486.    user input from the keypad forces keypad keystrokes to be processed as
  6487.    direction keys instead of numbers, even if the Num Lock key was pressed
  6488.    accidentally. This can be particularly helpful with the 83-key keyboard
  6489.    for the IBM PC and PC/XT because this keyboard has no status LEDs and
  6490.    provides no visual indication of the Num Lock state.
  6491.  
  6492.  The Keyboard-Hold State
  6493.  
  6494.    The ROM BIOS establishes the keyboard-hold (pause) state when it detects a
  6495.    Ctrl-Num Lock or Pause keystroke. During keyboard hold, the ROM BIOS
  6496.    executes a do-nothing loop until a printable key is pressed; it doesn't
  6497.    return control of the computer to whatever program is running until this
  6498.    happens. This feature is used to suspend the operation of the computer.
  6499.  
  6500.    During keyboard hold, all hardware interrupts are handled normally. For
  6501.    example, if a disk drive generates an interrupt (signaling the completion
  6502.    of a disk operation), the disk interrupt handler receives the interrupt
  6503.    and processes it normally. But when the interrupt handler finishes
  6504.    working, it passes control back to whatever was happening when the
  6505.    interrupt took place──which is that endless do-nothing loop inside the ROM
  6506.    BIOS. So, during the keyboard hold, the computer can respond to external
  6507.    interrupts but programs are normally completely suspended. The keyboard
  6508.    BIOS continues to handle interrupts that signal key actions, and when it
  6509.    detects a normal keystroke (for example, the Spacebar or a function key,
  6510.    but not just a shift key), it ends the keyboard hold, finally returning
  6511.    control to whatever program was running.
  6512.  
  6513.    The keyboard-hold state is of no practical use in programming, except that
  6514.    it provides a standard way for users of our programs to suspend a
  6515.    program's operation.
  6516.  
  6517.    Be aware that the keyboard-hold state is not "bullet-proof." A program can
  6518.    continue working through the keyboard hold by acting on an external
  6519.    interrupt, such as the clock-tick interrupt. If a program really wanted to
  6520.    avoid being put on hold, it could set up an interrupt handler that would
  6521.    work through the hold state, or it could simply turn the hold state off
  6522.    whenever the hold state was turned on.
  6523.  
  6524.  The Toggle-Key States
  6525.  
  6526.    Notice that bits 4 through 7 in the bytes at 0040:0017H and 0040:0018H
  6527.    refer to the same keys. In the first byte, the bits show the current state
  6528.    of the toggle keys; in the second byte, they show whether or not the
  6529.    corresponding toggle key is pressed.
  6530.  
  6531.    You can read the status of any of these bits to your heart's content, but
  6532.    few, if any, are likely to be useful in your programs. With the partial
  6533.    exception of controlling the Caps Lock state, we don't think it's wise to
  6534.    change any of the shift-state bits (bits 4 through 6 of byte 0040:0017H).
  6535.    And it is potentially very disruptive to change any of the key-is-pressed
  6536.    bits (bits 0 through 3 of byte 0040:0017H or any bits in byte 0040:0018H).
  6537.  
  6538.  
  6539.  Comments
  6540.  
  6541.    If you want to gain a deeper understanding of the PC's keyboard operation,
  6542.    study the ROM BIOS program listing in the IBM technical reference manuals
  6543.    for the PC, PC/XT, or PC/AT. If you do this, be careful to avoid making a
  6544.    simple mistake that is common when anyone first studies the ROM BIOS,
  6545.    particularly the interrupts used by the ROM BIOS. The ROM BIOS provides
  6546.    two different interrupts for the keyboard: one that responds to keyboard
  6547.    hardware interrupts (interrupt 09H) and collects keyboard data into the
  6548.    low-memory buffer, and one that responds to a software interrupt
  6549.    requesting keyboard services (interrupt 16H, decimal 22) and passes data
  6550.    from the low-memory buffer to DOS and your programs. It is easy to confuse
  6551.    the operation of these two interrupts, and it is just as easy to further
  6552.    confuse them with the break-key interrupts, 1BH and 23H (decimal 27 and
  6553.    35). The table in Figure 6-8 lists the keyboard interrupts.
  6554.  
  6555.    Interrupt
  6556.    Hex   Dec          Origin of         Use
  6557.                       Interrupt
  6558.    ──────────────────────────────────────────────────────────────────────────
  6559.    09H    9           Keyboard          Signals keyboard action.
  6560.  
  6561.    16H   22           User program      Invokes standard BIOS keyboard
  6562.                                         services. (See Chapter 11.)
  6563.  
  6564.    1BH   27           ROM BIOS          Occurs when Ctrl-Break is pressed
  6565.                                         under BIOS control; a routine is
  6566.                                         invoked if you create it.
  6567.  
  6568.    23H   35           DOS               If you create it, an interrupt
  6569.                                         routine is invoked when a break-key
  6570.                                         combination is pressed under DOS
  6571.                                         control.
  6572.    ──────────────────────────────────────────────────────────────────────────
  6573.  
  6574.    Figure 6-8.  The interrupts related to keyboard action.
  6575.  
  6576.    A general theme running throughout this book advises you not to play fast
  6577.    and loose, but to play by the rules. This means, again, to write programs
  6578.    that are general to the IBM PC family rather than tied to the quirks of
  6579.    any one model, and to write programs that use portable means (such as DOS
  6580.    or ROM BIOS services) to manipulate data, instead of direct hardware
  6581.    programming. These rules apply to keyboard programming as much as they do
  6582.    to any other type of programming.
  6583.  
  6584.  
  6585.  
  6586.  ────────────────────────────────────────────────────────────────────────────
  6587.  Chapter 7  Clocks, Timers, and Sound Generation
  6588.  
  6589.    Clocks and Timers
  6590.      The CPU Clock
  6591.      System Timers
  6592.      Using the System Timer Tick
  6593.  
  6594.    The Physics of Sound
  6595.  
  6596.    How the Computer Produces Sound
  6597.      Timer-Chip Sound Control
  6598.      Direct Speaker Control
  6599.  
  6600.    Speaker Volume and Sound Quality
  6601.  
  6602.    The Real-Time Clock
  6603.      Using the Date and Time
  6604.      Setting the Alarm
  6605.  
  6606.    Clocks and timers are the heartbeat of a computer. The computer's
  6607.    essential functions of computation and data transfer take place in step
  6608.    with the pulses generated by electronic clocks. PCs and PS/2s play host to
  6609.    several clocks and timers that you should know about:
  6610.  
  6611.    ■  The system timer generates "clock-ticks" and other timing pulses at
  6612.       precisely controlled intervals.
  6613.  
  6614.    ■  The sound generator produces tones through a speaker with a wide range
  6615.       of frequencies and durations.
  6616.  
  6617.    ■  The real-time clock/calendar keeps track of the date and time and can
  6618.       also serve as an "alarm clock." (This is supported only in the PC/AT
  6619.       and PS/2s.)
  6620.  
  6621.    To understand how to use the system timer, the sound generator, and the
  6622.    real-time clock, you need to know about the basic clock and timing
  6623.    mechanisms in PCs and PS/2s. That is what we'll outline in this chapter.
  6624.  
  6625.  
  6626.  Clocks and Timers
  6627.  
  6628.    PCs and PS/2s have several clocks and timers that run at different rates
  6629.    and perform different functions. Some of them are intrinsic to the circuit
  6630.    design of these computers; their operation is independent of software
  6631.    control. Others are designed to support timing functions in software; the
  6632.    operation of these timers can be controlled by software through ROM BIOS
  6633.    services or by direct hardware programming.
  6634.  
  6635.  The CPU Clock
  6636.  
  6637.    Probably the most basic of the timed events in a PC or PS/2 is the
  6638.    step-by-step operation of the computer's CPU, whose speed is determined by
  6639.    the frequency of a special oscillator circuit that generates
  6640.    high-frequency pulses at regular intervals. This frequency is the CPU's
  6641.    clock speed, and it determines how quickly the CPU can carry out its
  6642.    functions.
  6643.  
  6644.    The CPU oscillator keeps time for the CPU in much the same way a metronome
  6645.    keeps time for a musician. At each tick of the CPU clock (that is, at each
  6646.    pulse in the CPU oscillator's signal), the CPU carries out part of one
  6647.    machine instruction. All instructions require two or more clock cycles to
  6648.    complete. For example, the register INC instruction requires two clock
  6649.    cycles to execute; more complicated instructions like CALL and MUL take a
  6650.    longer amount of time.
  6651.  
  6652.    In IBM PCs and PC/XTs, the CPU's clock speed is 4,772,727 cycles per
  6653.    second, or about 4.77 megahertz. (A megahertz, or MHz, is one million
  6654.    cycles per second.) One CPU clock cycle thus lasts about 1/4,772,727 of a
  6655.    second, or about 210 nanoseconds (billionths of a second). With this clock
  6656.    frequency, a 2-cycle INC instruction executes in roughly 420 nanoseconds
  6657.    (0.42 microseconds or millionths of a second).
  6658.  
  6659.    The odd clock speed of 4.77 MHz was actually a convenient frequency for
  6660.    the designers of the original PC to use. In fact, the CPU clock frequency
  6661.    is derived from a basic oscillator frequency of 14.31818 MHz, which is
  6662.    commonly used in television circuitry. Dividing the basic frequency by 3
  6663.    gives the CPU clock frequency. Dividing by 4 gives a clock rate of 3.57955
  6664.    MHz, which is the frequency of the color burst signal used in color
  6665.    televisions and in the PC's Color Graphics Adapter. Dividing the basic
  6666.    frequency by 12 gives 1.19318 MHz, which is the clock frequency used by
  6667.    the PC's system timers.
  6668.  
  6669.    In later, faster members of the PC and PS/2 family, the CPU clock speed is
  6670.    higher, so the overall computational speed of these computers is greater.
  6671.    The 80286 and 80386 processors also execute many machine instructions in
  6672.    fewer clock cycles than the 8088 used in the PC and PC/XT. For example,
  6673.    the register PUSH instruction in the 8088 executes in 15 clock cycles; in
  6674.    the 80286 the same instruction takes 3 cycles; and in the 80386 only 2
  6675.    cycles. The combination of a higher CPU clock rate and faster machine
  6676.    instructions means that the 80286- and 80386-based members of the PC
  6677.    family execute programs significantly faster than do the 8088- and
  6678.    8086-based machines. (See Figure 7-1.)
  6679.  
  6680.                                                     Approximate Speed
  6681.                                         CPU Clock   Relative to
  6682.    Model                    CPU         Frequency   4.77 MHz IBM PC
  6683.    ──────────────────────────────────────────────────────────────────────────
  6684.    PC                       8088        4.77 MHz    1.0
  6685.    PC/XT                    8088        4.77 MHz    1.0
  6686.    PC/AT                    80286       6 MHz       3.4
  6687.                                         8 MHz       4.8
  6688.    PS/2 models 25 and 30    8086        8 MHz       2.5
  6689.    PS/2 models 50 and 60    80286       10 MHz      6.1
  6690.    PS/2 Model 80            80386       16 MHz      12.5
  6691.                                         20 MHz      15.5
  6692.    ──────────────────────────────────────────────────────────────────────────
  6693.  
  6694.    Figure 7-1.  CPU clock frequencies and relative computation speeds for PCs
  6695.    and PS/2s.
  6696.  
  6697.  System Timers
  6698.  
  6699.    Apart from the operation of the CPU, other basic hardware and software
  6700.    functions occur at regular intervals based on a preset clock frequency.
  6701.    For example, the dynamic RAM chips that constitute the computer's main
  6702.    memory must be accessed at regular intervals to refresh the information
  6703.    represented in them. Also, ROM BIOS and operating system functions such as
  6704.    keeping track of the time of day require the computer to generate a
  6705.    "clock-tick" signal at a predetermined rate. All PCs and PS/2s have
  6706.    circuitry that generates the necessary timing signals.
  6707.  
  6708.    In the PC and PC/XT, an Intel 8253-5 programmable timer/counter chip
  6709.    produces the RAM refresh and timer-tick signals. In the PC/AT, an Intel
  6710.    8254-2 is used in the same way. The PS/2 models 25 and 30 use an 8253-5
  6711.    for the timer tick, but RAM refresh timing is a function of a custom
  6712.    integrated circuit. In the PS/2 models 50, 60, and 80, all timing
  6713.    functions are implemented in custom silicon. Despite these hardware
  6714.    variations, the timer programming interface is the same in all PCs and
  6715.    PS/2s.
  6716.  
  6717.    In the PC/XT/AT family, the timer chip has three output channels, each
  6718.    with a particular dedicated function:
  6719.  
  6720.    ■  Channel 0 is the system clock-tick timer. When the computer is cold
  6721.       booted, the ROM BIOS programs the timer to oscillate with a frequency
  6722.       of about 18.2 ticks per second. This signal is tied to the computer's
  6723.       interrupt controller in such a way that interrupt 08H is generated each
  6724.       time the clock ticks.
  6725.  
  6726.    ■  Channel 1 is always dedicated to producing the RAM refresh timing
  6727.       signal; it's not intended for use in software applications.
  6728.  
  6729.    ■  Channel 2 is used to control the computer's speaker: The frequency of
  6730.       the timer's channel 2 signal determines the frequency of the sound
  6731.       emitted by the loudspeaker. (We'll come back to this later.)
  6732.  
  6733.    PS/2 models 50, 60, and 80 also have a timer channel 3. The signal
  6734.    produced on channel 3 is tied to the computer's nonmaskable interrupt
  6735.    (interrupt 02H), and can be used by an operating system as a "watchdog" to
  6736.    ensure that some other critical function, such as servicing a clock-tick
  6737.    interrupt, does not crash the computer by taking too long to execute.
  6738.  
  6739.  Using the System Timer Tick
  6740.  
  6741.    In all PCs and PS/2s, the input oscillator to the system timer circuit has
  6742.    a frequency of 1.19318 MHz. On each cycle, the timer chip decrements the
  6743.    values in a set of internal 16-bit counters, one for each of the timer's
  6744.    output channels. When the value in a counter reaches 0, the chip generates
  6745.    a single output pulse on the corresponding channel, resets the count, and
  6746.    starts counting down again.
  6747.  
  6748.    When the ROM BIOS initializes the system timer, it stores a countdown
  6749.    value of 0 in the count register for channel 0. This means that the timer
  6750.    chip decrements the counter 2^16 times between output pulses on channel 0,
  6751.    so output pulses occur 1,193,180/65,536, or about 18.2 times per second.
  6752.    The output from timer channel 0 is used as the signal on interrupt request
  6753.    level 0 (IRQ0), so interrupt 08H occurs whenever channel 0 of the system
  6754.    timer counts down to 0──that is, 18.2 times per second.
  6755.  
  6756.    The ROM BIOS contains an interrupt handler for interrupt 08H that
  6757.    increments a running count of clock ticks at 0040:006CH in the BIOS data
  6758.    area. This same interrupt handler also decrements the byte at 0040:0040H;
  6759.    if the value in the byte reaches 0, the interrupt handler issues a command
  6760.    to the diskette drive controller to turn off the diskette drive motor if
  6761.    it's on.
  6762.  
  6763.    The ROM BIOS interrupt 08H handler also issues software interrupt 1CH,
  6764.    which is intended for use in programs that want to be notified when a
  6765.    system timer tick occurs. A program can detect when each timer tick occurs
  6766.    simply by pointing the interrupt 1CH vector at 0000:0070H to its own
  6767.    interrupt handler. If you use an interrupt 1CH handler in a program,
  6768.    however, be aware that the ROM BIOS interrupt 08H handler does not allow
  6769.    subsequent clock-tick interrupts on IRQ0 to occur until your interrupt 1CH
  6770.    handler returns. If you install an interrupt 1CH handler, be certain that
  6771.    it doesn't keep IRQ0 disabled for too long or the system may crash.
  6772.  
  6773.    The system timer tick and its interrupt are useful in programs that must
  6774.    perform a simple task at a regular interval regardless of what else is
  6775.    going on in the computer. The timer-tick interrupt has the highest
  6776.    priority of any of the hardware interrupts (except the nonmaskable
  6777.    interrupt), so the code in the corresponding interrupt 08H and 1CH
  6778.    handlers takes precedence over all other system software.
  6779.  
  6780.    For this reason, the timer tick is used primarily in operating system
  6781.    software and in memory-resident "pop-up" programs like SideKick or the
  6782.    Norton Guides. Such programs have their own timer-tick interrupt handlers
  6783.    that check whether it is time to pop up on the screen. These programs
  6784.    generally rely on the system timer tick to occur at the default frequency
  6785.    of 18.2 ticks per second.
  6786.  
  6787.    Because timer-tick function is so essential to the proper operation of the
  6788.    computer, you should change the output frequency of system timer channel 0
  6789.    only if you are careful to preserve the functionality of the ROM BIOS
  6790.    interrupt 08H handler. For example, BASIC uses the timer tick to measure
  6791.    the duration of tones created with the PLAY or SOUND command. However,
  6792.    because the standard rate of 18.2 ticks per second is not fast enough to
  6793.    provide the precision that some kinds of music demand, BASIC reprograms
  6794.    the timer to tick four times faster, which causes interrupt 08H to occur
  6795.    72.8 times per second instead of 18.2 times per second. When BASIC counts
  6796.    against the quadruple rate, it is able to more accurately reproduce the
  6797.    proper tempo of a piece of music.
  6798.  
  6799.    BASIC can do this because it has a special interrupt 08H handler that
  6800.    calls the default interrupt 08H handler on every fourth timer tick. This
  6801.    ensures that the usual interrupt 08H functions still occur 18.2 times per
  6802.    second. If you reprogram system timer channel 0 to a nonstandard rate,
  6803.    your program should use the same technique of preserving interrupt 08H
  6804.    functionality.
  6805.  
  6806.    Programming system timer channel 2, the sound frequency generator, is not
  6807.    as demanding, because no ROM BIOS or operating system functions rely on
  6808.    it. Before we cover the programming details, however, we'll describe some
  6809.    of the basic mechanics of creating sounds with a computer.
  6810.  
  6811.  
  6812.  The Physics of Sound
  6813.  
  6814.    Sounds are simply regular pulses or vibrations in air pressure. Sound is
  6815.    produced when air particles are set into motion by a vibrating source.
  6816.    When the vibrating source pushes out, it compresses the air particles
  6817.    around it. As it pulls in, the pressure release pulls the particles apart.
  6818.    A vibration composed of both the pressing and the pulling actions causes
  6819.    air particles to bump into each other. This motion begins a chain reaction
  6820.    that carries the vibration through the air away from the original source.
  6821.    Such a motion is called a sound wave.
  6822.  
  6823.    The speaker in the IBM PCs and PS/2s is made to vibrate by the electrical
  6824.    impulses sent to it by the computer. Because computers normally deal with
  6825.    binary numbers, the voltages they produce are either high or low. Every
  6826.    transition from one voltage state to another either pushes the speaker
  6827.    cone out or relaxes it. A sound is produced when the voltage to the
  6828.    speaker goes from low to high to low again, causing the speaker to move
  6829.    out and then in. This single vibration, consisting of a pulse out and a
  6830.    pulse in, is called a cycle. Through the speaker, a single cycle of sound
  6831.    is heard as a click. A continuous sound is produced when a continuous
  6832.    stream of pulses is sent to the speaker. As the pulse rate increases, so
  6833.    does the pitch of the tone. For example, if you pulse the speaker in and
  6834.    out 261.63 times a second (that is, at a rate of 261.63 hertz, or cycles
  6835.    per second), you hear the musical note known as middle C. Figure 7-2
  6836.    lists the frequencies required to generate other musical notes.
  6837.  
  6838. ╓┌─┌───────┌───────────────┌──────┌───────────────┌───────┌───────────────┌──
  6839.    Note    Frequency       Note   Frequency       Note    Frequency       Note
  6840.    ───────────────────────────────────────────────────────────────────────────
  6841.    C0      16.35           C2     65.41           C4      261.63          C6
  6842.    C#0     17.32           C#2    69.30           C#4     277.18          C#6
  6843.    D0      18.35           D2     73.42           D4      293.66          D6
  6844.    D#0     19.45           D#2    77.78           D#4     311.13          D#6
  6845.    E0      20.60           E2     82.41           E4      329.63          E6
  6846.    F0      21.83           F2     87.31           F4      349.23          F6
  6847.    F#0     23.12           F#2    92.50           F#4     369.99          F#6
  6848.    Note    Frequency       Note   Frequency       Note    Frequency       Note
  6849.    ───────────────────────────────────────────────────────────────────────────
  6850.   F#0     23.12           F#2    92.50           F#4     369.99          F#6
  6851.    G0      24.50           G2     98.00           G4      392.00          G6
  6852.    G#0     25.96           G#2    103.83          G#4     415.30          G#6
  6853.    A0      27.50           A2     110.00          A4      440.00          A6
  6854.    A#0     29.14           A#2    116.54          A#4     466.16          A#6
  6855.    B0      30.87           B2     123.47          B4      493.88          B6
  6856.    C1      32.70           C3     130.81          C5      523.25          C7
  6857.    C#1     34.65           C#3    138.59          C#5     554.37          C#7
  6858.    D1      36.71           D3     146.83          D5      587.33          D7
  6859.    D#1     38.89           D#3    155.56          D#5     622.25          D#7
  6860.    E1      41.20           E3     164.81          E5      659.26          E7
  6861.    F1      43.65           F3     174.61          F5      698.46          F7
  6862.    F#1     46.25           F#3    185.00          F#5     739.99          F#7
  6863.    G1      49.00           G3     196.00          G5      783.99          G7
  6864.    G#1     51.91           G#3    207.65          G#5     830.61          G#7
  6865.    A1      55.00           A3     220.00          A5      880.00          A7
  6866.    A#1     58.27           A#3    233.08          A#5     932.33          A#7
  6867.    B1      61.74           B3     246.94          B5      987.77          B7
  6868.                                                                           C8
  6869.    Note    Frequency       Note   Frequency       Note    Frequency       Note
  6870.    ───────────────────────────────────────────────────────────────────────────
  6871.                                                                          C8
  6872.    ───────────────────────────────────────────────────────────────────────────
  6873.  
  6874.  
  6875.    Note: Equal Tempered Chromatic Scale; A4 = 440
  6876.          American Standard pitch──adopted by the American Standards
  6877.          Association in 1936
  6878.  
  6879.    Figure 7-2.  Eight octaves of musical note frequencies.
  6880.  
  6881.    The average person can hear sounds ranging from roughly 20 to 20,000
  6882.    hertz. The IBM PC can generate sounds through its speaker at frequencies
  6883.    that could theoretically range from about 18 to more than a million hertz,
  6884.    far beyond the range of human hearing. To give this frequency range some
  6885.    perspective, compare it to an average human voice, which has a range of
  6886.    only 125 to 1000 hertz.
  6887.  
  6888.    The speaker that comes with the standard IBM personal computers has no
  6889.    volume control and is not really intended for accurate sound reproduction.
  6890.    As a result, different frequencies will produce different effects; some
  6891.    may sound louder than others and some may have a more accurate pitch. This
  6892.    variation is a by-product of the speaker design and is not something you
  6893.    can control.
  6894.  
  6895.  
  6896.  How the Computer Produces Sound
  6897.  
  6898.    You can generate sounds through the speaker in two ways, using one or both
  6899.    of two different sound sources. One method is to write a program that
  6900.    turns the speaker on and off by manipulating two speaker bits in the I/O
  6901.    port that provides access to the speaker-control circuitry. When you use
  6902.    this method, your program controls the timing of the pulse and the
  6903.    resulting sound frequency. The other method is to use channel 2 of the
  6904.    system timer chip to pulse the speaker at a precise frequency. Using the
  6905.    timer chip is a more popular method for two reasons: Because speaker
  6906.    pulses are controlled by the timer chip instead of a program, the CPU can
  6907.    devote its time to the other demands of the computer system; and the timer
  6908.    chip is not dependent on the working speed of the CPU, which varies
  6909.    according to which PC or PS/2 model you use. The program method and timer
  6910.    method can be used together or separately to create many simple and
  6911.    complex sounds.
  6912.  
  6913.  Timer-Chip Sound Control
  6914.  
  6915.    The programmable timer chip is the heart of the standard PC models'
  6916.    sound-making abilities. As we have seen, channel 2 of the timer chip is
  6917.    dedicated to sound generation. To create sounds, you must program channel
  6918.    2 properly and then use the pulses from channel 2 to drive the speaker.
  6919.  
  6920.    The timer can be programmed to produce pulses at whatever frequency you
  6921.    want, but because it does not keep track of how long the sound continues,
  6922.    the sound will continue forever unless it is turned off. Therefore, your
  6923.    programs must choose when to end a sound through some sort of timing
  6924.    instruction.
  6925.  
  6926.    Programming the timer chip
  6927.  
  6928.    To program timer channel 2, load the timer chip with an appropriate
  6929.    countdown value for the channel 2 counter. (The timer chip holds this
  6930.    value in an internal register so that it can reset the counter each time
  6931.    it reaches zero.) The countdown value takes effect immediately after you
  6932.    load it into the timer chip. The timer chip decrements the counter with
  6933.    each cycle of its 1.19318 MHz clock until the counter reaches zero, and
  6934.    then it sends an output pulse on channel 2 to the sound generator
  6935.    circuitry and starts counting down again.
  6936.  
  6937.    In effect, the timer "divides" the countdown value into the clock
  6938.    frequency to produce an output frequency. The result is that the timer
  6939.    sends out a series of pulses that produce a sound of a certain frequency
  6940.    when you turn on the speaker.
  6941.  
  6942.    The controlling count and the resulting frequency have a reciprocal
  6943.    relationship, as shown by these formulas:
  6944.  
  6945.      Count=1,193,180÷Frequency
  6946.      Frequency=1,193,180÷Count
  6947.  
  6948.    You can see that a low-frequency (low-pitched) sound is produced by a high
  6949.    count and that a high-frequency (high-pitched) sound is produced by a low
  6950.    count. A count of 100 would produce a high pitch of roughly 11,931 cycles
  6951.    per second, and a count of 10,000 would produce a low pitch of about 119
  6952.    cycles per second.
  6953.  
  6954.    You can produce just about any frequency, within the limitations of 16-bit
  6955.    arithmetic. The lowest frequency is 18.2 hertz with a divisor of 65,535
  6956.    (FFFFH), and the highest is 1.193 megahertz with a divisor of 1. BASIC
  6957.    holds this to a practical range of 37 through 32,767 hertz. The following
  6958.    program demonstrates that the actual frequency range of the internal
  6959.    speaker is even less than BASIC provides.
  6960.  
  6961.    Once you calculate the count that you need for the frequency you want, you
  6962.    send it to the timer channel 2 registers. This is done with three port
  6963.    outputs. The first port output notifies the timer that the count is coming
  6964.    by sending the value B6H (decimal 182) to port 43H (decimal 67). The next
  6965.    two outputs send the low- and high-order bytes of the count, a 16-bit
  6966.    unsigned word, to port 42H (decimal 66)──the low-order byte followed by
  6967.    the high-order byte. The BASIC program on the following page illustrates
  6968.    the process.
  6969.  
  6970.    10 COUNT = 1193280! / 3000      ' 3000 is the desired frequency
  6971.    20 LO.COUNT = COUNT MOD 256     ' calculate low-order byte value
  6972.    30 HI.COUNT = COUNT / 256       ' calculate high-order byte value
  6973.    40 OUT &H43, &HB6               ' get timer ready
  6974.    50 OUT &H42, LO.COUNT           ' load low-order byte
  6975.    60 OUT &H42, HI.COUNT           ' load high-order byte
  6976.  
  6977.    Activating the speaker
  6978.  
  6979.    After you have programmed the timer, you still need to activate the
  6980.    speaker circuitry in order to use the signal that the timer is generating.
  6981.    As with most other parts of the PC and PS/2, the speaker is manipulated by
  6982.    sending certain values to a specific port, a process illustrated in Figure
  6983.    7-3. The speaker is controlled by changing the values of bits 0 and 1 at
  6984.    I/O port 61H (decimal 97). Only 2 of the port's 8 bits are used by the
  6985.    speaker: the low-order bits numbered 0 and 1. The other 6 bits are used
  6986.    for other purposes, so it is important that you don't disturb them while
  6987.    working with the speaker.
  6988.  
  6989.            Get                               Send pulses
  6990.            timer        Port                 to
  6991.    ┌─────┐ ready        43H  ┌──────────────┐speaker┌───────────┐
  6992.    │     ├──────────────────│              ├──────│           │
  6993.    │     │ Load              │    8253-5    │       │           │
  6994.    │     │ frequency    Port │ Programmable │       │           │    ┌─────┐
  6995.    │     │ count        42H  │    timer     │       │           │  ┌─┘     │
  6996.    │ CPU ├──────────────────│              │       │ Amplifier ├─│Speaker│
  6997.    │     │                   └──────────────┘       │           │  └─┐     │
  6998.    │     │ Turn on                             Port │           │    └─────┘
  6999.    │     │ speaker                             61H  │           │
  7000.    │     ├─────────────────────────────────────────│           │
  7001.    └─────┘                                          └───────────┘
  7002.  
  7003.    Figure 7-3.  How sound frequencies are generated through the system timer
  7004.    and speaker.
  7005.  
  7006.    The lowest bit, bit 0, controls transmission of the timer chip's output
  7007.    signal to the speaker. The second bit, bit 1, controls the pulsing of the
  7008.    speaker. Both bits must be set to make the speaker respond to the timer
  7009.    chip's signal. You can turn them on without disturbing the nonspeaker bits
  7010.    with an operation like this:
  7011.  
  7012.    70 OLD.PORT = INP (&H61)          ' read the value at port 61H
  7013.    80 NEW.PORT = (OLD.PORT OR &H03)  ' set bits 0 and 1
  7014.    90 OUT &H61, NEW.PORT             ' turn speaker on
  7015.  
  7016.  Direct Speaker Control
  7017.  
  7018.    The timer controls the speaker by sending periodic signals that pulse the
  7019.    speaker in and out. You can do the same thing with a program that sends in
  7020.    or out signals directly to the speaker. Do this by setting bit 0 of port
  7021.    61H (decimal 97) to 0 to turn the speaker off and then alternately setting
  7022.    bit 1 on and off to pulse the speaker. When you use this method, the speed
  7023.    of the program determines the frequency of the sound; the faster the
  7024.    program executes, the higher the pitch. The following BASIC program is an
  7025.    example of this method:
  7026.  
  7027.    10 X = INP (&H61) AND &HFC   ' read port value, turn off bits 1 and 0
  7028.    20 OUT &H61, X               ' pull speaker in
  7029.    30 OUT &H61, X OR 2          ' push speaker out
  7030.    40 GOTO 20
  7031.  
  7032.    The actions in lines 20 and 30 pulse the speaker in and out. Each one is a
  7033.    half-cycle, and the two together produce one complete sound cycle.
  7034.  
  7035.    This example runs as fast as BASIC can process it, producing as high a
  7036.    note as possible. If you needed more range in your application, you could
  7037.    use a faster language and insert deliberate delays equal to half the
  7038.    frequency cycle time between each complete cycle (half the cycle time,
  7039.    because each ON or OFF operation is a half-cycle). No matter what language
  7040.    you use, you must include a duration count to end the sound. To produce
  7041.    different sounds at a particular frequency, such as clicking or buzzing
  7042.    sounds, just vary the delays between pulses.
  7043.  
  7044.    Despite all these wonderful possibilities, generating sounds through the
  7045.    speaker by direct program action is not a good way to make sounds. It has
  7046.    three big disadvantages compared to the use of the timer:
  7047.  
  7048.    ■  A program requires the constant attention of the CPU, so the computer
  7049.       has a hard time getting any other work done.
  7050.  
  7051.    ■  The frequency is at the mercy of the speed of the computer; that is,
  7052.       the same program would make a lower or higher sound on a slower or
  7053.       faster model.
  7054.  
  7055.    ■  The clock-tick interrupts interfere with the smoothness of the sound,
  7056.       making a warble. The only way to avoid this is to suspend the clock
  7057.       tick by disabling the interrupts──and that disrupts the computer's
  7058.       sense of time.
  7059.  
  7060.    As far as we know, there is only one advantage to making sounds using the
  7061.    direct method: With the proper control over the program delays, the direct
  7062.    method lets you make a low-fidelity polyphonic sound. Be forewarned,
  7063.    though, that this requires some very clever and tedious programming and,
  7064.    all in all, may not be worth the trouble.
  7065.  
  7066.  
  7067.  Speaker Volume and Sound Quality
  7068.  
  7069.    The computer's internal speaker has no volume control of any kind and,
  7070.    like all speakers, varies in how well it responds to different
  7071.    frequencies; some frequencies may sound louder than others. In the case of
  7072.    a crude speaker like that found in most PCs and PS/2s, the loudness of the
  7073.    sound varies widely with the frequency. You can use the following program
  7074.    to test this──it may help you choose the best sound pitch for your
  7075.    purpose:
  7076.  
  7077.    10 PLAY "MF"                            ' plays each sound separately
  7078.    20 FREQUENCY = 37
  7079.    30 WHILE FREQUENCY < 32000              ' use all frequencies to
  7080.                                              32000 Hz
  7081.    40   PRINT USING "##,###"; FREQUENCY    ' display frequency
  7082.    50   SOUND FREQUENCY, 5                 ' produce sound with
  7083.                                              duration of 5
  7084.    60   FREQUENCY = FREQUENCY * 1.1        ' increment frequency by 1/10
  7085.    70 WEND
  7086.  
  7087.    Be aware that the speakers in the various PC and PS/2 models may not sound
  7088.    alike, partly because the materials of each system housing resonate
  7089.    differently as speaker enclosures. Try the following samples on two
  7090.    different models and be prepared for these variations in sound:
  7091.  
  7092.    100 'sound samples
  7093.    110 '
  7094.    120 'warble (two rapidly alternating tones)
  7095.    130 FOR N% = 0 TO 5
  7096.    140  SOUND 440, .7
  7097.    150  SOUND 466.16, .5
  7098.    160 NEXT
  7099.    170 WHILE(INKEY$="") : WEND     ' wait for a keystroke
  7100.    180 '
  7101.    190 'two tones played quickly
  7102.    200 SOUND 900, .1
  7103.    210 SOUND 760, 1
  7104.    220 WHILE(INKEY$="") : WEND
  7105.    230 '
  7106.    240 'random noise
  7107.    250 X = INP(&H61) AND &HFC
  7108.    260 I=20                        ' changing I changes the noise
  7109.    270 FOR N% = 0 TO 500
  7110.    280  IF (RND * 100 < I) THEN OUT &H61,X OR 2 : OUT &H61,X
  7111.    290 NEXT
  7112.  
  7113.  
  7114.  The Real-Time Clock
  7115.  
  7116.    The PC/AT and the PS/2s all have a real-time clock that keeps track of
  7117.    the current date and time. In the PC/AT, the real-time clock is part of
  7118.    the Motorola MC146818 chip that supports the PC/AT's nonvolatile CMOS RAM.
  7119.    In the PS/2s, the real-time clock is in custom silicon. In all these
  7120.    machines, the real-time clock runs off a battery so that the time and date
  7121.    are maintained even while the computer is turned off.
  7122.  
  7123.  Using the Date and Time
  7124.  
  7125.    When you boot a PC/AT or PS/2, the ROM BIOS start-up routines read the
  7126.    time of day from the real-time clock and convert it into the corresponding
  7127.    number of timer ticks. This value is used to initialize the 4-byte count
  7128.    stored at 0040:006CH in the ROM BIOS data area. All versions of DOS use
  7129.    this count value to determine the current time of day. Starting in version
  7130.    3.0, DOS also obtains the current date from the real-time clock and
  7131.    initializes its own internal record of the date at boot-up time.
  7132.  
  7133.    To work with the current date and time in a program, we recommend that you
  7134.    use the DOS date and time services (Chapter 16) to get and set the
  7135.    current values. You could also use ROM BIOS services to access the
  7136.    real-time clock (Chapter 10). However, if you call the ROM BIOS to change
  7137.    the date or time, DOS may not be aware of the change and may assume an
  7138.    incorrect time or date.
  7139.  
  7140.  Setting the Alarm
  7141.  
  7142.    The real-time clock's alarm feature generates an interrupt at a specific
  7143.    time. To take advantage of this feature, you must create an interrupt
  7144.    handler that performs an action when the alarm interrupt occurs. You can
  7145.    even make this action independent of other programs by leaving the
  7146.    interrupt handler resident in memory with a DOS
  7147.    Terminate-and-Stay-Resident service. (See Chapters 16 and 17.)
  7148.  
  7149.    The ROM BIOS provides a set of services through interrupt 1AH that give
  7150.    you access to the real-time clock's alarm feature. See Chapter 12 for
  7151.    more details.
  7152.  
  7153.  
  7154.  
  7155.  ────────────────────────────────────────────────────────────────────────────
  7156.  Chapter 8  ROM BIOS Basics
  7157.  
  7158.    The ROM BIOS Philosophy
  7159.  
  7160.    The ROM BIOS Service Interrupts
  7161.  
  7162.    ROM BIOS Service Operating Characteristics
  7163.  
  7164.    Creating an Assembly-Language Interface
  7165.      The Basic Form of an Interface Routine
  7166.  
  7167.    Advanced BIOS Interface
  7168.  
  7169.    One secret of successful programming for the PC family lies in the
  7170.    effective use of the software that is built right into the machine: the
  7171.    ROM BIOS services. Conceptually, the ROM BIOS services are sandwiched
  7172.    between the hardware and the high-level languages (including the operating
  7173.    system). They work directly with the computer's hardware and peripheral
  7174.    devices, performing some of the system's most fundamental tasks, such as
  7175.    reading and writing individual bytes of data to the display screen or
  7176.    disk. DOS services and programming-language services are often built from
  7177.    these basic functions and enhanced to make a particular process more
  7178.    efficient. You can enhance your programs in the same way by plugging them
  7179.    directly into the ROM BIOS, thereby gaining access to an extremely
  7180.    powerful set of tools and using your computers in the way that IBM
  7181.    intended them to be used.
  7182.  
  7183.    That last point is worth emphasizing. IBM has gone to considerable lengths
  7184.    to create a clean and well-defined method for directing the operation of
  7185.    the computer through the ROM BIOS services. As each new PC model is
  7186.    designed, IBM (and any other computer maker who is faithfully extending
  7187.    the PC family) makes sure its ROM BIOS services are thoroughly compatible
  7188.    with those of the other members of the family. As long as you control your
  7189.    computers through the ROM BIOS, whether directly or indirectly, you are
  7190.    safe from any compatibility problems. If you bypass the ROM BIOS and
  7191.    program directly to the hardware, you are not only asking for trouble, but
  7192.    you are also severely limiting the range and viability of your programs.
  7193.  
  7194.    That's not to say that you should always use ROM BIOS services when
  7195.    they're available. The input/output functions provided in DOS and in
  7196.    high-level programming languages often provide the same services as the
  7197.    ROM BIOS, but in a form that is easier to use within your programs.
  7198.    However, when a program needs more direct access to the computer's
  7199.    input/output devices than DOS or your programming language can provide,
  7200.    the ROM BIOS services are usually the answer.
  7201.  
  7202.    The next five chapters discuss the ROM BIOS service routines. Fortunately,
  7203.    the routines fall naturally into groups derived from the hardware devices
  7204.    they support, so the video services, disk services, and keyboard services
  7205.    can all be reviewed separately. But before you take a closer look at the
  7206.    individual services, you need to find out how to incorporate them into
  7207.    your programs. This chapter sets the stage by explaining what goes into
  7208.    writing an interface routine, the bridge between programming languages and
  7209.    the ROM BIOS services. First, a word on how the ROM BIOS operates.
  7210.  
  7211.  
  7212.  The ROM BIOS Philosophy
  7213.  
  7214.    All ROM BIOS services are invoked by interrupts. Each interrupt
  7215.    instruction selects a particular entry in the interrupt vector table in
  7216.    low memory. The addresses of all ROM BIOS service routines are stored in
  7217.    this table. This design makes it possible for any program to request a
  7218.    service without knowing the specific memory location of the ROM BIOS
  7219.    service routine. It also allows the services to be moved around, expanded,
  7220.    or adapted without affecting the programs that use the services. Although
  7221.    IBM has tried to maintain the absolute memory location of some parts of
  7222.    the ROM BIOS, it would be foolish to use these addresses because they may
  7223.    change in the future. The standard, preferred, and most reliable way to
  7224.    invoke a ROM BIOS service is to use its interrupt rather than its absolute
  7225.    address.
  7226.  
  7227.    The ROM BIOS services could be supervised by one master interrupt, but
  7228.    instead they are divided into subject categories, each with its own
  7229.    controlling interrupt. This design lets each interrupt handler be easily
  7230.    replaced. For example, if a hardware manufacturer created a radically
  7231.    different video display that operated under a completely new ROM BIOS
  7232.    program, the manufacturer could provide the new ROM BIOS program along
  7233.    with the hardware. The new ROM BIOS program might be stored in RAM, and it
  7234.    would replace the one part of IBM's ROM BIOS that was used with the old
  7235.    hardware. By making the ROM BIOS modular, IBM has made it easier to
  7236.    improve and extend the capabilities of its computers.
  7237.  
  7238.  
  7239.  The ROM BIOS Service Interrupts
  7240.  
  7241.    The twelve ROM BIOS interrupts fall into five groups (Figure 8-1):
  7242.  
  7243.    ■  Six interrupts serve specific peripheral devices.
  7244.  
  7245.    ■  Two interrupts report on the computer's equipment.
  7246.  
  7247.    ■  One interrupt works with the time/date clock.
  7248.  
  7249.    ■  One interrupt performs the print-screen operation.
  7250.  
  7251.    ■  Two interrupts place the computer into another state altogether,
  7252.       activating ROM BASIC and the system start-up routine.
  7253.  
  7254.    As you'll see, most of the interrupts are tied to a group of subservices
  7255.    that actually do the work. For example, the video service interrupt 10H
  7256.    (decimal 16) has 25 subservices that do everything from setting the video
  7257.    mode to changing the size of the cursor. You call a subservice by invoking
  7258.    its governing interrupt and specifying the subservice number in register
  7259.    AH. This process is explained in the example at the end of this chapter.
  7260.  
  7261. ╓┌─┌──────────────────┌──────────────────────────────────────────────────────╖
  7262.    Interrupt
  7263.    Hex   Dec          Use
  7264.    ──────────────────────────────────────────────────────────────────────────
  7265.    Peripheral Devices Services
  7266.    10H   16           Video-display services (see Chapter 9)
  7267.    13H   19           Diskette services (see Chapter 10)
  7268.    Interrupt
  7269.    Hex   Dec          Use
  7270.    ──────────────────────────────────────────────────────────────────────────
  7271.   13H   19           Diskette services (see Chapter 10)
  7272.    14H   20           Communications services (see Chapter 12)
  7273.    15H   21           System services (see Chapter 12)
  7274.    16H   22           Standard keyboard services (see Chapter 11)
  7275.    17H   23           Printer services (see Chapter 12)
  7276.  
  7277.    Equipment Status Services
  7278.    11H   17           Equipment-list service (see Chapter 12)
  7279.    12H   18           Memory-size service (see Chapter 12)
  7280.  
  7281.    Time/Date Service
  7282.    1AH   26           Time and date services (see Chapter 12)
  7283.  
  7284.    Print-Screen Service
  7285.    5H   5             Print-screen service (see Chapter 12)
  7286.  
  7287.    Special Services
  7288.    18H   24           Activate ROM BASIC (see Chapter 12)
  7289.    Interrupt
  7290.    Hex   Dec          Use
  7291.    ──────────────────────────────────────────────────────────────────────────
  7292.   18H   24           Activate ROM BASIC (see Chapter 12)
  7293.    19H   25           Activate bootstrap start-up routine (see Chapter 12)
  7294.    ──────────────────────────────────────────────────────────────────────────
  7295.  
  7296.  
  7297.    Figure 8-1.  The 12 ROM BIOS services.
  7298.  
  7299.  
  7300.  ROM BIOS Service Operating Characteristics
  7301.  
  7302.    The ROM BIOS services use some common calling conventions that provide
  7303.    consistency in the use of registers, flags, the stack, and memory. We'll
  7304.    outline the characteristics of these operating conventions, beginning with
  7305.    the segment registers.
  7306.  
  7307.    The code segment register (CS) is automatically reserved, loaded, and
  7308.    restored as part of the interrupt process. Consequently, you don't have to
  7309.    worry about your program's CS. The DS and ES registers are preserved by
  7310.    the ROM BIOS service routines, except in the few cases where they are
  7311.    explicitly used. The stack segment register (SS) is left unchanged, and
  7312.    the ROM BIOS services depend on you to provide a working stack.
  7313.    (Everything depends on a working stack!)
  7314.  
  7315.    The stack requirements of the ROM BIOS services are not spelled out and
  7316.    can vary considerably, particularly because some services invoke other
  7317.    services. Generally, however, most programs ought to be working with a
  7318.    much larger stack than the ROM BIOS services need.
  7319.  
  7320.    The ROM BIOS varies in its usage of the other 8086 registers. The
  7321.    instruction pointer (IP) is preserved by the same mechanism that preserves
  7322.    the code segment. In effect, the stack pointer (SP) is preserved because
  7323.    all the ROM BIOS services leave the stack clean, popping off anything that
  7324.    was pushed on during the service-routine execution.
  7325.  
  7326.    As usual, the general-purpose registers, AX through DX, are considered
  7327.    fair game. The standard rule is not to expect any contents of these
  7328.    registers to be maintained when you pass control to another routine, and
  7329.    that applies to the ROM BIOS services as well. If you closely inspect the
  7330.    coding of the services in the IBM technical reference manuals, you will
  7331.    find that one or more registers are left undisturbed in one service or
  7332.    another, but you would be foolish to try to take advantage of this. As a
  7333.    general rule, when a simple result is returned from a subroutine, it is
  7334.    left in the AX register; this applies to both the ROM BIOS and to all
  7335.    programming languages. We'll see how often this really happens when we
  7336.    cover the ROM BIOS services in detail.
  7337.  
  7338.    The index registers (SI and DI) can be changed, exactly like the AX
  7339.    through DX registers. The stack frame register (BP) can also be changed by
  7340.    a few ROM BIOS service routines.
  7341.  
  7342.    The various flags in the flag register are routinely changed as a
  7343.    by-product of the instruction steps in the ROM BIOS routines. You should
  7344.    not expect any of them to be preserved. In a few instances, the carry flag
  7345.    (CF) or the zero flag (ZF) is used to signal the overall success or
  7346.    failure of a requested operation.
  7347.  
  7348.    These details are important but rather tedious, and there is little reason
  7349.    for you to pay much attention to them. If your programs follow the general
  7350.    interface rules given in the next section, and if they follow the specific
  7351.    requirements of your programming language (covered in Chapters 19 and
  7352.    20), you may not need to be concerned with them at all.
  7353.  
  7354.    ──────────────────────────────────────────────────────────────────────────
  7355.    NOTE:
  7356.      If you set out to use the ROM BIOS services in your programs, you'll
  7357.      naturally be concerned about the possible conflicts between the services
  7358.      and the operating conventions that your language follows. Put your mind
  7359.      at ease. You will find that you do not have to take any extraordinary
  7360.      precautions to protect your programming language from the ROM BIOS, or
  7361.      vice versa.
  7362.    ──────────────────────────────────────────────────────────────────────────
  7363.  
  7364.  
  7365.  Creating an Assembly-Language Interface
  7366.  
  7367.    In order to make direct use of the ROM BIOS services from your programs,
  7368.    you generally need to create an assembly-language interface routine to
  7369.    link the programming language to the ROM BIOS. When we say "interface
  7370.    routine," we are referring to the conventional program-development
  7371.    subroutines──subroutines that are assembled into object modules (.OBJ
  7372.    files) and then linked into working programs (.EXE or .COM files in DOS).
  7373.    For more on this subject, see Chapter 19.
  7374.  
  7375.    Working with assembly language can seem a fearsome task if you are not
  7376.    already comfortable with it. While there are plenty of good reasons to be
  7377.    intimidated by assembly language──after all, it is the most difficult and
  7378.    demanding kind of programming──it's really not that difficult to create an
  7379.    assembly-language interface routine.
  7380.  
  7381.    ──────────────────────────────────────────────────────────────────────────
  7382.    ROM BIOS Interrupt Conflicts
  7383.      In the hardware specification for the 8086 family of microprocessors,
  7384.      Intel reserved interrupt numbers 00H through 1FH for use by the
  7385.      microprocessor itself. (See Figure 8-2.) Unfortunately, IBM had
  7386.      appropriated several of these reserved interrupt numbers for its own use
  7387.      in the design of the IBM PC. This wasn't a problem with the PC and
  7388.      PC/XT, which used the Intel 8088, because the 8088 predefined only
  7389.      interrupts 00H through 04H.
  7390.  
  7391.      When the PC/AT appeared, however, IBM's use of Intel's reserved
  7392.      interrupt numbers led to a conflict. The reason: The AT's 80286 chip
  7393.      predefines some of the same interrupt numbers that IBM's ROM BIOS uses.
  7394.      The conflict appears when you use the 80286 BOUND instruction to
  7395.      validate an array index, because the 80286 signals an out-of-bounds
  7396.      array index by executing interrupt 05H──which IBM had previously
  7397.      assigned to the ROM BIOS print-screen function. If you aren't careful, a
  7398.      program that executes the BOUND instruction can unexpectedly print the
  7399.      screen.
  7400.  
  7401.      To resolve the conflict, you must install an interrupt 05H handler that
  7402.      inspects the code that caused the interrupt: This handler can determine
  7403.      whether the interrupt was executed in software or by the CPU. You can
  7404.      also avoid this problem by using a protected-mode operating system like
  7405.      OS/2, which bypasses the ROM BIOS. If you use DOS, however, be aware
  7406.      that a programming error can occasionally lead to unexpected execution
  7407.      of a ROM BIOS routine.
  7408.    ──────────────────────────────────────────────────────────────────────────
  7409.  
  7410.      Interrupt     CPU                          Function
  7411.      ────────────────────────────────────────────────────────────────────────
  7412.      00H           8088,8086,80286,80386        Divide error
  7413.      01H           8088,8086,80286,80386        Single-step
  7414.      02H           8088,8086,80286,80386        NMI (nonmaskable interrupt)
  7415.      03H           8088,8086,80286,80386        Breakpoint (INT 3)
  7416.      04H           8088,8086,80286,80386        Overflow (INTO)
  7417.      05H           80286,80386                  BOUND out of range
  7418.      06H           80286,80386                  Invalid opcode
  7419.      07H           80286,80386                  Coprocessor not available
  7420.      08H           80286,80386                  Double exception (double
  7421.                                                 fault)
  7422.      09H           80286,80386                  Coprocessor segment overrun
  7423.      0AH           80386                        Invalid task-state segment
  7424.      0BH           80386                        Segment not present
  7425.      0CH           80386                        Stack fault
  7426.      0DH           80286,80386                  General protection exception
  7427.      0EH           80386                        Page fault
  7428.      10H           80286,80386                  Coprocessor error
  7429.      ────────────────────────────────────────────────────────────────────────
  7430.  
  7431.      Figure 8-2.  Predefined hardware interrupts in Intel microprocessors.
  7432.  
  7433.    To create your own interfaces, you will need to have an assembler that is
  7434.    compatible with the DOS standards for object files. All the examples we
  7435.    give here are for the Microsoft Macro Assembler.
  7436.  
  7437.    ──────────────────────────────────────────────────────────────────────────
  7438.    NOTE:
  7439.      Interpreted BASIC can work with machine-language subroutines put
  7440.      directly into memory. Preparing the sort of assembler subroutine that
  7441.      will work with BASIC can be done as easily with DEBUG's A (assemble)
  7442.      command as it can with an ordinary assembler. See Chapter 20 for more
  7443.      on this subject.
  7444.    ──────────────────────────────────────────────────────────────────────────
  7445.  
  7446.  The Basic Form of an Interface Routine
  7447.  
  7448.    An interface routine's form varies with its intended use. An
  7449.    assembly-language interface is a handshaker between your programming
  7450.    language and a ROM BIOS service, so it has to be tailored to meet the
  7451.    needs of both ends. It matters which programming language is being used;
  7452.    it matters which ROM BIOS service is being invoked; and it matters whether
  7453.    any data is being passed in one direction or the other. However, the
  7454.    general outline of an assembly-language interface is basically the same,
  7455.    no matter what you are doing.
  7456.  
  7457.    One of the best ways to understand how an assembly-language interface is
  7458.    coded is to view it as five nested parts, which are outlined here:
  7459.  
  7460.      Level 1: General assembler overhead
  7461.        Level 2: Subroutine assembler overhead
  7462.          Level 3: Entry code
  7463.            Level 4: Get parameter data from caller
  7464.              Level 5: Invoke ROM BIOS service
  7465.            Level 4: Pass back results to caller
  7466.          Level 3: Exit code
  7467.        Level 2: Finish subroutine assembler overhead
  7468.      Level 1: Finish general assembler overhead
  7469.  
  7470.    In this outline, Levels 1 and 2 tell the assembler what's going on, but
  7471.    don't produce any working instructions. Levels 3 through 5 produce the
  7472.    actual machine-language instructions.
  7473.  
  7474.    We'll examine each of these levels to show you the rules and explain
  7475.    what's going on. Don't forget that the specific requirements of an
  7476.    interface routine change for different circumstances. We'll point out the
  7477.    few design elements that are universal to all routines.
  7478.  
  7479.    Here is a simple ROM BIOS interface routine. It's designed to be called
  7480.    from a C program, but the elements of the interface design are the same
  7481.    whether you use this routine as is or adapt it to another programming
  7482.    language.
  7483.  
  7484.    _TEXT               SEGMENT      byte public 'CODE'
  7485.                        ASSUME       cs:_TEXT
  7486.  
  7487.                        PUBLIC       _GetMemSize
  7488.    _GetMemSize         PROC         near
  7489.  
  7490.                        push         bp
  7491.                        mov          bp,sp
  7492.  
  7493.                        int          12H
  7494.                        pop          bp
  7495.                        ret
  7496.  
  7497.    _GetMemSize         ENDP
  7498.  
  7499.    _TEXT               ENDS
  7500.  
  7501.                        END
  7502.  
  7503.    In the next few pages we'll examine the construction of this routine.
  7504.  
  7505.    Level 1: General assembler overhead
  7506.  
  7507.    Here is an outline of a typical Level-1 section of an interface routine,
  7508.    with the lines numbered for reference:
  7509.  
  7510.    1-1  _TEXT        SEGMENT    byte public 'CODE'
  7511.    1-2               ASSUME     cs:_TEXT
  7512.  
  7513.    (Levels 2 through 5 appear here)
  7514.  
  7515.    1-3  _TEXT        ENDS
  7516.    1-4               END
  7517.  
  7518.    Line 1-1 is a SEGMENT directive that declares the name of a logical
  7519.    grouping of executable machine instructions and informs the assembler (and
  7520.    any person who reads the source code) that what follows consists of
  7521.    executable code. Line 1-2, the ASSUME directive, tells the assembler to
  7522.    associate the CS register with any address labels in the _TEXT segment.
  7523.    This makes sense because the CS register is used by the 8086 to address
  7524.    executable code.
  7525.  
  7526.    Line 1-3 ends the segment started in line 1-1, and line 1-4 marks the end
  7527.    of the source code for this routine.
  7528.  
  7529.    The names _TEXT and CODE conform to the conventions used by virtually all
  7530.    C language compilers for PCs and PS/2s, as do the BYTE and PUBLIC
  7531.    attributes. Alternative names and attributes are available to advanced
  7532.    programmers, but for now we'll stick with the simplest.
  7533.  
  7534.    Level 2: Subroutine assembler overhead
  7535.  
  7536.    Next, let's look at an outline of a typical Level 2, the assembler
  7537.    overhead for a subroutine (called a procedure in assembler parlance). The
  7538.    sample on the following page shows some typical Level-2 coding.
  7539.  
  7540.    2-1                  PUBLIC   _GetMemSize
  7541.    2-2  _GetMemSize     PROC     near
  7542.  
  7543.    (Levels 3 through 5 appear here)
  7544.  
  7545.    2-3  _GetMemSize     ENDP
  7546.  
  7547.    Line 2-1 instructs the assembler to make the name of the procedure,
  7548.    _GetMemSize, public information, which means that the link program can
  7549.    then connect it to other routines that refer to it by name.
  7550.  
  7551.    Lines 2-2 and 2-3 bracket the procedure, named _GetMemSize. PROC and ENDP
  7552.    are mandatory and surround any procedure, with PROC defining the beginning
  7553.    of the procedure and ENDP signaling the end of it. Again, the near
  7554.    attribute on the PROC statement follows the conventions established for
  7555.    linking assembly-language routines to C programs. In more advanced C
  7556.    programs and in routines linked with programs written in languages like
  7557.    FORTRAN and BASIC, you must sometimes use a different attribute, far.
  7558.    (More about this in Chapter 20.)
  7559.  
  7560.    Level 3: Entry and exit code
  7561.  
  7562.    Levels 3, 4, and 5 contain actual executable instructions. In Level 3, the
  7563.    assembly-language routine handles the housekeeping overhead required if a
  7564.    subroutine is to work cooperatively with the calling program. The key to
  7565.    this cooperation is the stack.
  7566.  
  7567.    When the calling program transfers control to the subroutine, it does so
  7568.    by means of a CALL instruction. (In this example, the instruction would be
  7569.    CALL _GetMemSize.) When this instruction executes, the 8086 pushes a
  7570.    return address──the address of the instruction following the CALL──onto
  7571.    the stack. Later, the assembly-language routine can return control to the
  7572.    calling program by executing a RET instruction, which pops the return
  7573.    address off the stack and transfers control to the instruction at that
  7574.    address.
  7575.  
  7576.    If any parameters are to be passed to the assembly-language routine, the
  7577.    calling program pushes them onto the stack before it executes the CALL
  7578.    instruction. Thus, when the routine gets control, the value on top of the
  7579.    stack is the return address, and any parameters are found on the stack
  7580.    below the return address. If you keep in mind that the stack grows from
  7581.    higher to lower addresses and that each value on the stack is 2 bytes in
  7582.    size, you end up with the situation depicted in Figure 8-3.
  7583.  
  7584.    To access the parameters on the stack, most compilers and
  7585.    assembly-language programmers copy the value in SP into register BP. In
  7586.    this way the values on the stack can be accessed even within a routine
  7587.    that changes SP by pushing parameters or calling a subroutine. The
  7588.    conventional way of doing this is shown by the code on the next page.
  7589.  
  7590.    3-1        push       bp         ; preserve the current contents of BP
  7591.    3-2        mov        bp,sp      ; copy SP to BP
  7592.  
  7593.    (Levels 4 and 5 appear here)
  7594.  
  7595.    3-3        pop        bp
  7596.    3-4        ret
  7597.  
  7598.    After lines 3-1 and 3-2 have executed, the stack is addressable as in
  7599.    Figure 8-4. (In a moment, we'll show how useful this is.) When it's time
  7600.    to return control to the calling program, the routine restores the
  7601.    caller's BP register value (line 3-3) and then executes a RET instruction
  7602.    (line 3-4).
  7603.  
  7604.                      Bottom of stack
  7605.                             
  7606.                     │       │        │
  7607.                     │       │        │
  7608.    Higher addresses ├────────────────┤
  7609.                     │   Parameter    │
  7610.                     ├────────────────┤──── SP + 4
  7611.                     │   Parameter    │
  7612.                     ├────────────────┤──── SP + 2
  7613.                     │ Return address │
  7614.     Lower addresses └────────────────┘──── SP
  7615.  
  7616.    Figure 8-3.  The stack at the time a subroutine is called.
  7617.  
  7618.     Bottom of stack
  7619.            
  7620.    │       │        │
  7621.    │       │        │
  7622.    ├────────────────┤
  7623.    │   Parameter    │
  7624.    ├────────────────┤──── BP + 6
  7625.    │   Parameter    │
  7626.    ├────────────────┤──── BP + 4
  7627.    │ Return address │
  7628.    ├────────────────┤──── BP + 2
  7629.    │  Caller's BP   │
  7630.    └────────────────┘──── BP
  7631.  
  7632.    Figure 8-4.  The stack after register BP is initialized.
  7633.  
  7634.    If you think about it, you'll realize that things could be more
  7635.    complicated. For example, a calling program might use either a near or a
  7636.    far CALL instruction to transfer control to a subroutine. If your program
  7637.    uses far subroutine calls by convention (instead of the near calls used by
  7638.    default in C), the PROC directive (Line 2-2) would require the far
  7639.    attribute instead of near. This would instruct the assembler to generate a
  7640.    far RET instruction instead of a near RET.
  7641.  
  7642.    Furthermore, with a far calling convention, the return address on the
  7643.    stack would be 4 bytes in size instead of 2 bytes, so the first parameter
  7644.    would be at address [BP + 6] instead of [BP + 4] as shown in Figure 8-4.
  7645.    In this book, however, we'll stick to the most straightforward case: near
  7646.    PROCs and 2-byte return addresses.
  7647.  
  7648.    Level 4: Get parameter data from caller
  7649.  
  7650.    Level 4 deals with the parameters by passing them from the caller to the
  7651.    ROM BIOS, and with the results by passing them from the ROM BIOS to
  7652.    the caller. (Note, however, that the sample program contains no parameters
  7653.    from the caller.) The caller's parameters are on the stack, either in the
  7654.    form of data or addresses. (See Chapter 20 for help with this.) The
  7655.    registers, mostly AX through DX, are used for ROM BIOS input and output.
  7656.    The trick here──and it can be tricky──is to use the correct stack offsets
  7657.    to find the parameters. We'll sneak up on this problem in stages.
  7658.  
  7659.    First, you get to the parameters on the stack by addressing relative to
  7660.    the address stored in BP in lines 3-1 and 3-2. (Refer to Figure 8-2 to
  7661.    determine how items on the stack relate to the value in BP.) When more
  7662.    than one parameter is present on the stack, you must decide which
  7663.    parameter is which. Most languages push their parameters onto the stack in
  7664.    the order they are written. This means that the last parameter is the one
  7665.    closest to the top of the stack, at [BP + 4]. However, C uses the reverse
  7666.    order, so that the parameter at [BP + 4] is the first one written in the
  7667.    calling program.
  7668.  
  7669.    Parameters normally take up 2 or 4 bytes on the stack, although 2 bytes is
  7670.    more common. If any of these parameters were 4 bytes in size, you would
  7671.    need to adjust the subsequent references accordingly.
  7672.  
  7673.    If data were placed on the stack, then you could get it immediately by
  7674.    addressing it like this: [BP + 4]. If an address were placed on the stack,
  7675.    two steps would be needed: First, you would get the address, and second,
  7676.    you would use the address to get the data. A Level-4 example showing both
  7677.    data ([BP + 4]) and address ([BP + 6]) retrieval follows on the next page.
  7678.  
  7679.    4-1        mov     ax,[bp+4]       ; value of parameter1
  7680.    4-2        mov     bx,[bp+6]       ; address of parameter2
  7681.    4-3        mov     dx,[bx]         ; value of parameter2
  7682.  
  7683.    (Level 5 appears here)
  7684.  
  7685.    4-4        mov    bx,[bp+6]        ; address of parameter2 (again)
  7686.    4-5        mov    [bx],dx          ; store new value at parameter2 address
  7687.  
  7688.    All of these MOV instructions move data from the second operand to the
  7689.    first operand. Line 4-1 grabs data right off the stack and slaps it into
  7690.    the AX register. Lines 4-2 and 4-3 get data by means of an address on the
  7691.    stack: Line 4-2 gets the address (parking it in BX), and then line 4-3
  7692.    uses that address to get to the actual data, which is moved into DX. Lines
  7693.    4-4 and 4-5 reverse this process: Line 4-4 gets the address again, and
  7694.    then line 4-5 moves the contents of DX into that memory location.
  7695.  
  7696.    ──────────────────────────────────────────────────────────────────────────
  7697.    NOTE:
  7698.      A crucial bit of assembler notation is demonstrated here: BX refers to
  7699.      what's in BX, and [BX] refers to a memory location whose address is in
  7700.      BX. A reference like [BP + 6] indicates a memory location 6 bytes past
  7701.      the address stored in register BP.
  7702.    ──────────────────────────────────────────────────────────────────────────
  7703.  
  7704.    While sorting out these references may not be a snap, if you think it
  7705.    through carefully, it works out right.
  7706.  
  7707.    Level 5: Invoke ROM BIOS service
  7708.  
  7709.    Level 5 is our final step: It simply invokes the ROM BIOS service.
  7710.  
  7711.    Once all registers contain appropriate values (usually passed from
  7712.    the calling program and copied into registers by means of the stack), the
  7713.    routine can transfer control to the ROM BIOS using an interrupt:
  7714.  
  7715.    5-1        int     12h
  7716.  
  7717.    In this example, this single INT instruction does all the work for you.
  7718.    The ROM BIOS returns the computer's memory size in register AX, where C
  7719.    expects the routine to leave it when the routine returns control to the
  7720.    calling program. In other cases, you might need to leave a result
  7721.    elsewhere, as in Lines 4-4 and 4-5, above.
  7722.  
  7723.    Most ROM BIOS interrupts, however, provide access to several different
  7724.    services. In such cases, you must specify a service number in register AH
  7725.    before you execute the interrupt. For example, to access the first video
  7726.    service, you would execute the commands on the following page.
  7727.  
  7728.    mov     ah,0            ; AH=service number 0
  7729.    int     10h             ; ROM BIOS video services interrupt
  7730.  
  7731.    This five-step process outlines the basic principles of nearly all aspects
  7732.    of an assembly-language interface. In the following chapters, you'll see
  7733.    how this design is used in specific examples.
  7734.  
  7735.  
  7736.  Advanced BIOS Interface
  7737.  
  7738.    To conclude this chapter we'd like to mention the alternative BIOS
  7739.    interface that IBM introduced in the PS/2 models 50, 60, and 80. This
  7740.    Advanced BIOS (ABIOS) interface addresses some of the major design
  7741.    shortcomings of the interrupt-based interface described in this chapter.
  7742.  
  7743.    The traditional, interrupt-based ROM BIOS interface is limited in two
  7744.    important ways:
  7745.  
  7746.    ■  It cannot be used in protected mode in a PS/2 Model 50, 60, or 80.
  7747.  
  7748.    ■  It provides poor support for multitasking, so an operating system that
  7749.       offers multitasking cannot rely on the traditional ROM BIOS interface.
  7750.  
  7751.    IBM's solution to these problems is the Advanced BIOS interface in the
  7752.    PS/2 models 50, 60, and 80. Through the Advanced BIOS interface, BIOS
  7753.    services are accessed through a set of address tables and common data
  7754.    areas designed for use in protected mode as well as with a multitasking
  7755.    operating system. However, the complexity of the Advanced BIOS interface
  7756.    makes it better suited to supporting an operating system than to
  7757.    supporting applications programs. Unless you're writing a protected-mode,
  7758.    multitasking operating system, we recommend that you keep using the
  7759.    traditional ROM BIOS interface that is common to all computers in the PC
  7760.    family.
  7761.  
  7762.  
  7763.  
  7764.  ────────────────────────────────────────────────────────────────────────────
  7765.  Chapter 9  ROM BIOS Video Services
  7766.  
  7767.    Accessing the ROM BIOS Video Services
  7768.      Service 00H (decimal 0): Set Video Mode
  7769.      Service 01H (decimal 1): Set Cursor Size
  7770.      Service 02H (decimal 2): Set Cursor Position
  7771.      Service 03H (decimal 3): Read Cursor Position
  7772.      Service 04H (decimal 4): Read Light-Pen Position
  7773.      Service 05H (decimal 5): Set Active Display Page
  7774.      Service 06H (decimal 6): Scroll Window Up
  7775.      Service 07H (decimal 7): Scroll Window Down
  7776.      Service 08H (decimal 8): Read Character and Attribute
  7777.      Service 09H (decimal 9): Write Character and Attribute
  7778.      Service 0AH (decimal 10): Write Character
  7779.      Service 0BH (decimal 11): Set 4-Color Palette
  7780.      Service 0CH (decimal 12): Write Pixel
  7781.      Service 0DH (decimal 13): Read Pixel
  7782.      Service 0EH (decimal 14): Write Character in Teletype Mode
  7783.      Service 0FH (decimal 15): Get Current Video Mode
  7784.      Service 10H (decimal 16): Color Palette Interface
  7785.      Service 11H (decimal 17): Character Generator Interface
  7786.      Service 12H (decimal 18): "Alternate Select"
  7787.      Service 13H (decimal 19): Write Character String
  7788.      Service 1AH (decimal 26): Read/Write Display Combination Code
  7789.      Service 1BH (decimal 27): Return Functionality/State Information
  7790.      Service 1CH (decimal 28): Save/Restore Video State
  7791.  
  7792.    Comments and Example
  7793.  
  7794.    In this chapter, we will discuss each of the video, or screen-control,
  7795.    services provided by the ROM BIOS. We have devoted most of the chapter to
  7796.    detailed descriptions of each video service. Beginning on page 194, we
  7797.    have included some programming hints and an assembly-language routine that
  7798.    makes use of some of the video services. For a more general discussion of
  7799.    video hardware in the PC family, see Chapter 4. For information on
  7800.    low-memory locations used by the ROM BIOS for video status information,
  7801.    turn to page 54.
  7802.  
  7803.  
  7804.  Accessing the ROM BIOS Video Services
  7805.  
  7806.    The ROM BIOS video services are all requested by generating interrupt 10H
  7807.    (decimal 16). There are 25 principal services available under this
  7808.    interrupt. (See Figure 9-1.) Like all other ROM BIOS services, the video
  7809.    services are numbered from 00H and are selected by placing the service
  7810.    number in the AH register. The services usually require you to specify
  7811.    additional parameters in register AL, BX, CX, or DX. We'll cover the
  7812.    purpose and placement of the parameters under each service description.
  7813.  
  7814. ╓┌─┌────────────────────────┌────────────────────────────────────────────────╖
  7815.     Service
  7816.    Hex   Dec                Description
  7817.    ──────────────────────────────────────────────────────────────────────────
  7818.    00H    0                 Set Video Mode.
  7819.    01H    1                 Set Cursor Size.
  7820.    02H    2                 Set Cursor Position.
  7821.    03H    3                 Read Cursor Position.
  7822.    04H    4                 Read Light-Pen Position.
  7823.    05H    5                 Set Active Display Page.
  7824.    06H    6                 Scroll Window Up.
  7825.    07H    7                 Scroll Window Down.
  7826.    08H    8                 Read Character and Attribute.
  7827.    09H    9                 Write Character and Attribute.
  7828.    0AH   10                 Write Character.
  7829.    0BH   11                 Set 4-Color Palette.
  7830.    0CH   12                 Write Pixel.
  7831.    0DH   13                 Read Pixel.
  7832.    0EH   14                 Write Character in Teletype Mode.
  7833.    0FH   15                 Get Current Video Mode.
  7834.    10H   16                 Color Palette Interface.
  7835.     Service
  7836.    Hex   Dec                Description
  7837.    ──────────────────────────────────────────────────────────────────────────
  7838.   10H   16                 Color Palette Interface.
  7839.    11H   17                 Character Generator Interface.
  7840.    12H   18                 "Alternate Select".
  7841.    13H   19                 Write Character String.
  7842.    14H   20                 (PC convertible only)
  7843.    15H   21                 (PC convertible only)
  7844.    1AH   26                 Read/Write Display Combination Code.
  7845.    1BH   27                 Return Functionality/State Information.
  7846.    1CH   28                 Save/Restore Video State.
  7847.    ──────────────────────────────────────────────────────────────────────────
  7848.  
  7849.  
  7850.    Figure 9-1.  The 25 video services.
  7851.  
  7852.  Service 00H (decimal 0): Set Video Mode
  7853.  
  7854.    Service 00H (decimal 0) is used to configure your video subsystem into one
  7855.    of the 20 video modes listed in Figure 9-2. For details of the video
  7856.    modes, see page 72.
  7857.  
  7858.    You may recall from our discussion in Chapter 4 that modes 00H through
  7859.    06H apply to the standard Color Graphics Adapter; mode 07H applies to the
  7860.    Monochrome Display Adapter; modes 0DH through 10H were added for the
  7861.    Enhanced Graphics Adapter; and modes 11H through 13H were introduced with
  7862.    the Multi-Color Graphics Array (PS/2 models 25 and 30) and Video Graphics
  7863.    Array (PS/2 models 50, 60, and 80).
  7864.  
  7865.    Mode        Type         Resolution  Colors      Video Subsystem
  7866.    ──────────────────────────────────────────────────────────────────────────
  7867.    00H, 01H    Text         40 x 25     16          CGA, EGA, MCGA, VGA
  7868.    02H, 03H    Text         80 x 25     16          CGA, EGA, MCGA, VGA
  7869.    04H, 05H    Graphics     320 x 200   4           CGA, EGA, MCGA, VGA
  7870.    06H         Graphics     640 x 200   2           CGA, EGA, MCGA, VGA
  7871.    07H         Text         80 x 25     Mono        MDA, EGA, VGA
  7872.    08H, 09H,
  7873.    0AH                                              (PCjr only)
  7874.    0BH,0CH                                          (used internally by EGA
  7875.                                                     BIOS)
  7876.    0DH         Graphics     320 x 200   16          EGA,VGA
  7877.    0EH         Graphics     640 x 200   16          EGA,VGA
  7878.    0FH         Graphics     640 x 350   Mono        EGA,VGA
  7879.    10H         Graphics     640 x 350   16          EGA,VGA
  7880.    11H         Graphics     640 x 480   2           MCGA,VGA
  7881.    12H         Graphics     640 x 480   16          VGA
  7882.    13H         Graphics     320 x 200   256         MCGA,VGA
  7883.    ──────────────────────────────────────────────────────────────────────────
  7884.  
  7885.    Figure 9-2.  Video modes available through ROM BIOS video service 00H.
  7886.  
  7887.    Normally, the ROM BIOS clears the screen memory buffer when the mode is
  7888.    set, even if it is set to the same mode again and again. In fact,
  7889.    resetting the same video mode can be an easy way to clear the screen. In
  7890.    some versions of DOS, in fact, the DOS command CLS clears the screen this
  7891.    way. Setting the video mode also sets the color palette to default color
  7892.    values, however, so don't rely on service 00H to clear the screen if
  7893.    you're working with colors; use video service 06H instead.
  7894.  
  7895.    On the EGA, MCGA, and VGA, you can also tell the ROM BIOS not to clear the
  7896.    screen when it sets up the video mode. Do this by adding 80H (decimal 128)
  7897.    to the video mode number you specify in AL. For example, to change to 640
  7898.    x 200, 2-color mode without clearing the screen, call service 00H with AL
  7899.    = 86H. Use this feature with caution, though. Displayable video data is
  7900.    formatted differently in different modes, so a screenful of useful data in
  7901.    one video mode may become unintelligible when you switch to another mode
  7902.    without clearing the screen.
  7903.  
  7904.    See Chapter 4, page 72 for more on video modes. See page 58, memory
  7905.    location 0040:0049H, for more on how a record of the mode is stored in
  7906.    memory. See service 0FH (decimal 15) to find out how to determine the
  7907.    current video mode.
  7908.  
  7909.  Service 01H (decimal 1): Set Cursor Size
  7910.  
  7911.    Service 01H (decimal 1) controls the form and size of the blinking cursor
  7912.    that appears in text modes. The default cursor appears as one or two
  7913.    blinking scan lines at the bottom of a character display position. You can
  7914.    change the default cursor size by redefining the number of lines that are
  7915.    displayed.
  7916.  
  7917.    The Color Graphics Adapter (CGA) can display a cursor that has 8 scan
  7918.    lines, numbered from 0 at the top to 7 at the bottom. The Monochrome
  7919.    Display Adapter (MDA) and the EGA can display a cursor that has 14 scan
  7920.    lines, also numbered from the top, from 0 through 13. Both the MCGA and
  7921.    the VGA have default text characters that are 16 scan lines high, so the
  7922.    maximum size of the text cursor in default PS/2 text modes is 16 scan
  7923.    lines. You set the cursor size by specifying the starting and ending scan
  7924.    lines. (These are the same as the start and stop parameters of BASIC's
  7925.    LOCATE statement.) The start line number is loaded into the CH register
  7926.    and the stop line number into the CL register. Default cursor settings are
  7927.    CH = 6, CL = 7 for the CGA, CH = 11, CL = 12 for the MDA and EGA, and CH =
  7928.    13, CH = 14 for the MCGA and VGA.
  7929.  
  7930.    You will notice that the valid scan line numbers occupy only four of the
  7931.    bits (bits 0 through 3) placed in these registers. If bit 5 of CH is set
  7932.    on by specifying a value of 20H (decimal 32), the cursor will disappear.
  7933.    This is one of two techniques that you can use to remove the cursor in the
  7934.    text modes. The other technique is to actually move it off the screen, say
  7935.    to row 26, column 1. When a graphics mode is set, bit 5 is automatically
  7936.    set to keep the cursor from being displayed. Because there is no true
  7937.    cursor in the graphics modes, you must simulate one with the solid-block
  7938.    character, DFH (decimal 223), or with a change of background attributes.
  7939.  
  7940.  Service 02H (decimal 2): Set Cursor Position
  7941.  
  7942.    Service 02H (decimal 2) sets the position of the cursor using row and
  7943.    column coordinates. In text modes, multiple display pages can exist, each
  7944.    one having an independently recorded cursor position. Even though the
  7945.    graphics modes have no visible cursor, they keep track of the logical
  7946.    cursor position in the same way as the text modes. This logical cursor
  7947.    position is used to control character I/O.
  7948.  
  7949.    The cursor position is specified by placing a row number in register DH, a
  7950.    column number in DL, and a display page number in BH. The numbering for
  7951.    the rows and columns begins with coordinates 0,0 in the top left corner.
  7952.    The graphics modes also use the character row and column coordinates to
  7953.    identify the cursor location, rather than pixel coordinates. The display
  7954.    page number must be set to 0 in CGA-compatible graphics modes, although
  7955.    the EGA and VGA both support multiple display pages in 16-color graphics
  7956.    modes as well as in text modes.
  7957.  
  7958.    See Figure 9-3 for a summary of register settings. See page 87 for more
  7959.    on display pages. See service 03H for the reverse operation: Read cursor
  7960.    position.
  7961.  
  7962.    Service Number           Parameters
  7963.    ──────────────────────────────────────────────────────────────────────────
  7964.    AH = 02H                 DH = row number
  7965.                             DL = column number
  7966.                             BH = page number
  7967.    ──────────────────────────────────────────────────────────────────────────
  7968.  
  7969.    Figure 9-3.  Registers values for setting the cursor position using
  7970.    service 02H.
  7971.  
  7972.  Service 03H (decimal 3): Read Cursor Position
  7973.  
  7974.    Service 03H (decimal 3) is the opposite of services 01H and 02H. When you
  7975.    specify the page number in BH, the ROM BIOS reports the cursor size by
  7976.    returning the starting scan line in CH and the ending scan line in CL. In
  7977.    addition, it reports the cursor position by returning the row in DH and
  7978.    the column in DL. (See Figure 9-4.)
  7979.  
  7980.    Service Number           Returns
  7981.    ──────────────────────────────────────────────────────────────────────────
  7982.    AH = 03H                 BH = page number (set to 0 in graphics modes)
  7983.                             DH = row number
  7984.                             DL = column number
  7985.                             CH = starting scan line of cursor
  7986.                             CL = ending scan line of cursor
  7987.    ──────────────────────────────────────────────────────────────────────────
  7988.  
  7989.    Figure 9-4.  Values reported by video service 03H.
  7990.  
  7991.  Service 04H (decimal 4): Read Light-Pen Position
  7992.  
  7993.    Service 04H (decimal 4) reports the light-pen status on a CGA or EGA,
  7994.    specifically whether or not the pen has been triggered, and where it is on
  7995.    the screen if it has been triggered.
  7996.  
  7997.    Register AH is set to indicate triggering: If AH = 01H, the light pen has
  7998.    been triggered; if AH = 00H, it has not been triggered. If the pen has
  7999.    been triggered, the ROM BIOS determines the light pen's character column
  8000.    and pixel row (y-coordinate) from the video hardware. From these, the ROM
  8001.    BIOS computes the character row and pixel column (x-coordinate). The
  8002.    results are returned in registers BX, CX, and DX as shown in Figure 9-5.
  8003.  
  8004.    Service Number           Returns
  8005.    ──────────────────────────────────────────────────────────────────────────
  8006.    AH = 04H                 DH = character row number
  8007.                             DL = character column number
  8008.                             CH = pixel line number (CGA and EGA video modes
  8009.                             04H, 05H, and 06H)
  8010.                             CX = pixel line number (all other EGA video
  8011.                             modes)
  8012.                             BX = pixel column number
  8013.    ──────────────────────────────────────────────────────────────────────────
  8014.  
  8015.    Figure 9-5.  Light-pen position values returned by service 04H.
  8016.  
  8017.  Service 05H (decimal 5): Set Active Display Page
  8018.  
  8019.    Service 05H (decimal 5) selects the active display page for text modes 0
  8020.    through 3 and also for 16-color EGA and VGA graphics modes. You specify
  8021.    the page number in register AL. (See Figure 9-6.) In text modes, page
  8022.    numbers range from 0 through 7. Don't forget, however, that the CGA
  8023.    hardware can display only four different 80-column pages, so CGA pages 4
  8024.    through 7 overlap pages 0 through 3 when you're in 80 x 25 text mode. On
  8025.    the EGA and in the PS/2 video subsystems, you can also select among
  8026.    multiple display pages in 16-color graphics modes.
  8027.  
  8028.    Service Number           Parameters
  8029.    ──────────────────────────────────────────────────────────────────────────
  8030.    AH = 05H                 AL = new display page number
  8031.    ──────────────────────────────────────────────────────────────────────────
  8032.  
  8033.    Figure 9-6.  The registers used to set the active display page using
  8034.    service 05H.
  8035.  
  8036.    In all video modes, page 0 is used by default. Page 0 is located at the
  8037.    beginning of display memory, with higher page numbers in higher memory
  8038.    locations. See page 87 for more on display pages.
  8039.  
  8040.  Service 06H (decimal 6): Scroll Window Up
  8041.  
  8042.    Service 06H (decimal 6) and companion service 07H are used to define a
  8043.    rectangular window of text on the screen and to scroll the window's
  8044.    contents up or down one or more lines. To accomplish the scrolling effect,
  8045.    blank lines are inserted at the bottom of the window area with service 06H
  8046.    (at the top with service 07H) and the top lines of the window (the bottom
  8047.    lines with service 07H) are scrolled off and disappear.
  8048.  
  8049.    The number of lines to be scrolled is specified in AL. If AL = 00H, the
  8050.    entire window is blanked. (The same thing would happen if you scrolled
  8051.    more lines than the window size allowed.) The location or size of the
  8052.    window is specified in the CX and DX registers: CH is the top row, and DH
  8053.    is the bottom row; CL is the left column, and DL is the right column. The
  8054.    display attribute for the new blank lines inserted by the two services is
  8055.    taken from BH. Figure 9-7 summarizes the register settings for both
  8056.    services 06H and 07H.
  8057.  
  8058.    When you fill a window with lines of text, you'll discover that window
  8059.    scrolling is normally a two-stage process: When a new line is ready to be
  8060.    written in the window, service 06H (or service 07H) scrolls the current
  8061.    window contents. Then the new line is filled with text using the cursor-
  8062.    positioning and character-writing services. The following example
  8063.    demonstrates this window action.
  8064.  
  8065.    DEBUG                   ; invoke DEBUG from DOS utilities
  8066.    A                       ; ask to assemble instructions
  8067.    INT 10                  ; create interrupt 10H instruction
  8068.    [Return]                ; finish assembling
  8069.    R AX                    ; ask to see and change contents of AX
  8070.    0603                    ; specify service 06H (scroll up), using
  8071.                            ; 3-line window
  8072.    R CX                    ; ask to see and change contents of CX
  8073.    050A                    ; specify top left corner: row 5, column 10
  8074.    R DX                    ; ask to see and change contents of DX
  8075.    1020                    ; specify bottom right corner: row 16, column 32
  8076.    D 0 L 180               ; fill screen with nonsense
  8077.    G =100 102              ; execute INT 10H, then stop
  8078.  
  8079.    Service Number           Parameters
  8080.    ──────────────────────────────────────────────────────────────────────────
  8081.    AH = 06H (scroll up)     AL = number of lines to scroll
  8082.    AH = 07H (scroll down)   CH = row number of upper-left corner
  8083.                             CL = column number of upper-left corner
  8084.                             DH = row number of lower-right corner
  8085.                             DL = column number of lower-right corner
  8086.                             BH = display attribute for blank lines
  8087.    ──────────────────────────────────────────────────────────────────────────
  8088.  
  8089.    Figure 9-7.  Register values for scrolling using services 06H and 07H.
  8090.  
  8091.    See Chapter 8 for more on assembly-language routines. See the IBM DOS
  8092.    Technical Reference Manual for more on DEBUG.
  8093.  
  8094.  Service 07H (decimal 7): Scroll Window Down
  8095.  
  8096.    Service 07H (decimal 7) is, as we've already mentioned, the mirror image
  8097.    of service 06H. The difference between the two services is the scrolling
  8098.    action. In service 07H, the new blank lines appear at the top of the
  8099.    window and the old lines disappear at the bottom. The opposite scrolling
  8100.    action takes place in service 06H. See Figure 9-7 under service 06H for
  8101.    the register parameter settings.
  8102.  
  8103.  Service 08H (decimal 8): Read Character and Attribute
  8104.  
  8105.    Service 08H (decimal 8) is used to read characters "off the screen," that
  8106.    is, directly out of the display memory. This service is unusually spiffy
  8107.    because it works in both text and graphics modes.
  8108.  
  8109.    In graphics modes, the same character-drawing tables used to write
  8110.    characters are also used to recognize them by a pattern-matching
  8111.    operation. Even if you create your own character set in graphics mode,
  8112.    this service will be able to recognize them. In text modes, of course, the
  8113.    ASCII character codes are directly available in the display memory.
  8114.  
  8115.    Service 08H returns the ASCII character code of the character in AL. (See
  8116.    Figure 9-8.) In graphics modes, if the character doesn't match any
  8117.    characters in the graphics character set, the ROM BIOS returns ASCII code
  8118.    0. In text modes, the service also returns the character's color
  8119.    attributes in AH. Remember to specify a display page number in BH when you
  8120.    call this service.
  8121.  
  8122.    Service Number Parameters                   Returns
  8123.    ──────────────────────────────────────────────────────────────────────────
  8124.    AH = 08H       BH = active display          AL = ASCII character read from
  8125.                   page number                  cursor location
  8126.                                                AH = attribute of text
  8127.                                                character (text modes only)
  8128.    ──────────────────────────────────────────────────────────────────────────
  8129.  
  8130.    Figure 9-8.  The registers used to read a character and attribute with
  8131.    service 08H.
  8132.  
  8133.    See page 82 for more on text characters and attribute bytes. See page
  8134.    84 for more on text- and graphics-mode characters. See Appendix C for
  8135.    more on ASCII characters.
  8136.  
  8137.  Service 09H (decimal 9): Write Character and Attribute
  8138.  
  8139.    Service 09H (decimal 9) writes one or more copies of a single character
  8140.    and its color attribute. The character is specified in AL, and the
  8141.    text-mode attribute or graphics-mode color is specified in BL. The number
  8142.    of times the character is to be written (one or more times) is placed in
  8143.    CX, and BH contains the display page number. (See Figure 9-9.)
  8144.  
  8145.    Service Number           Parameters
  8146.    ──────────────────────────────────────────────────────────────────────────
  8147.    AH = 09H                 AL = ASCII character to write to screen
  8148.                             BL = attribute value (text modes) or foreground
  8149.                             color (graphics modes)
  8150.                             BH = background color (video mode 13H only) or
  8151.                             display page number (all other modes)
  8152.                             CX = number of times to write character and
  8153.                             attribute
  8154.    ──────────────────────────────────────────────────────────────────────────
  8155.  
  8156.    Figure 9-9.  The registers used to write a text character and attribute
  8157.    using service 09H.
  8158.  
  8159.    The ROM BIOS writes the character and its color attributes as many times
  8160.    as requested, starting at the current cursor location. Although the cursor
  8161.    is not moved, duplicate characters are written at subsequent screen
  8162.    locations. In text mode, the duplicated characters will successfully wrap
  8163.    around from line to line, which increases the usefulness of this service.
  8164.    In graphics mode, the characters will not wrap around.
  8165.  
  8166.    Service 09H is quite useful both for writing individual characters and for
  8167.    replicating a character. The repeat operation is most often used to
  8168.    rapidly lay out blanks or other repeated characters, such as the
  8169.    horizontal lines that are part of box drawings. (See Appendix C.) When
  8170.    you want to make a single copy of the character, be sure to set the count
  8171.    in CX to 1. If it's set to 0, the number of repetitions will be a lot more
  8172.    than you want.
  8173.  
  8174.    Service 09H has an advantage over the similar service 0EH, in that you
  8175.    can control the color attributes. However, its one disadvantage is that
  8176.    the cursor is not automatically advanced.
  8177.  
  8178.    In graphics modes, the value specified in BL is the foreground color──the
  8179.    color of the pixels that make up the character drawing. Normally the ROM
  8180.    BIOS displays the character with the specified foreground color on a black
  8181.    background. If, however, you set bit 7 of the color value in BL to 1, then
  8182.    the ROM BIOS creates the character's new foreground color by using an
  8183.    exclusive OR operation (XOR) to combine each of the previous foreground
  8184.    pixels with the value in BL. The same feature also applies to the
  8185.    character and pixel writing services, services 0AH and 0CH.
  8186.  
  8187.    Here's an example of what can happen when the ROM BIOS uses the XOR
  8188.    operation to display a character. Imagine you're in 320 x 200, 4-color
  8189.    graphics mode and the screen is completely filled with white pixels. If
  8190.    you now write a white character in the usual way, with a color value of
  8191.    03H (white) in register BL, the ROM BIOS displays a white character on a
  8192.    black background. If, however, you write the same character with a color
  8193.    value of 83H (bit 7 set to 1), the ROM BIOS uses XOR to display a black
  8194.    character on a white background.
  8195.  
  8196.    See page 82 for more on display attributes in text modes. See page 84
  8197.    for more on color attributes in graphics modes.
  8198.  
  8199.  Service 0AH (decimal 10): Write Character
  8200.  
  8201.    Service 0AH (decimal 10) is the same as service 09H (write character and
  8202.    attribute to cursor location) with one exception: Service 09H lets you
  8203.    change the existing screen color attribute in text mode but service 0AH
  8204.    does not.
  8205.  
  8206.    However, in graphics mode you must still specify a color in BL (see
  8207.    Figure 9-10), which makes the description of this service as only a
  8208.    character-writing service partly incorrect. Service 0AH has the same
  8209.    graphics color rules as services 09H and 0CH: The color can be used
  8210.    directly or used with XOR and the existing color. (See service 09H for an
  8211.    explanation.)
  8212.  
  8213.    See page 82 for more on display attributes in text modes. See page 84
  8214.    for more on color attributes in graphics modes.
  8215.  
  8216.    Service Number           Parameters
  8217.    ──────────────────────────────────────────────────────────────────────────
  8218.    AH = 0AH                 AL = ASCII character to write to screen
  8219.                             BL = foreground color (graphics modes only)
  8220.                             BH = background color (video mode 13H only) or
  8221.                             display page number (all other modes)
  8222.                             CX = number of times to write character
  8223.    ──────────────────────────────────────────────────────────────────────────
  8224.  
  8225.    Figure 9-10.  The registers used to write a character using service 0AH.
  8226.  
  8227.  Service 0BH (decimal 11): Set 4-Color Palette
  8228.  
  8229.    Service 0BH (decimal 11) actually consists of two subservices. You select
  8230.    either subservice 00H or subservice 01H by storing the proper value in
  8231.    register BH. (See Figure 9-11.) Subservice 00H lets you set the border
  8232.    color in CGA alphanumeric modes or the background color in CGA 320 x 200,
  8233.    4-color graphics mode. You designate the border color in BL with a value
  8234.    between 00H and 0FH.
  8235.  
  8236.    Subservice 01H lets you select one of the two 4-color palettes used in 320
  8237.    x 200, 4-color mode. The value in BL specifies which of the two hardware
  8238.    palettes to use. A value of 0 designates the red-green-brown palette, and
  8239.    a value of 1 selects the cyan-magenta-white palette. (See page 77 for
  8240.    more on color palettes.)
  8241.  
  8242.    This service was designed primarily for use with the CGA. Use service
  8243.    10H to control colors in other video modes on the EGA, MCGA, and VGA.
  8244.  
  8245.    Service Number Subservice Number            Parameters
  8246.    ──────────────────────────────────────────────────────────────────────────
  8247.    AH = 0BH       BH = 00H                     BL = border or background
  8248.                                                color
  8249.                   BH = 01H                     BL = palette number (0 or 1)
  8250.    ──────────────────────────────────────────────────────────────────────────
  8251.  
  8252.    Figure 9-11.  Color control in CGA-compatible video modes using service
  8253.    0BH.
  8254.  
  8255.  Service 0CH (decimal 12): Write Pixel
  8256.  
  8257.    Service 0CH (decimal 12) writes an individual pixel. You specify the
  8258.    pixel's location on the screen by passing its column (x-coordinate) in
  8259.    register CX and its row (y-coordinate) in DX. Remember that pixel rows and
  8260.    columns are not the same as the character row and column you use in other
  8261.    services to locate the cursor or to display a character. Pixel coordinates
  8262.    correspond to individual dots, not to characters.
  8263.  
  8264.    If you're using a graphics mode that supports multiple display pages, be
  8265.    sure to specify the display page number in register BH. (See Figure
  8266.    9-12.) Also, when you specify the pixel's color in register AL, you have
  8267.    the option of setting bit 7 of the color value to 1. As in service 09H,
  8268.    this tells the BIOS to display the pixel with an XORed color value. (See
  8269.    service 09H for an explanation.)
  8270.  
  8271.    Service Number           Parameters
  8272.    ──────────────────────────────────────────────────────────────────────────
  8273.    AH = 0CH                 AL = pixel color
  8274.                             BH = display page number
  8275.                             DX = row number of pixel
  8276.                             CX = column number of pixel
  8277.    ──────────────────────────────────────────────────────────────────────────
  8278.  
  8279.    Figure 9-12.  The registers used to write a pixel using service 0CH.
  8280.  
  8281.    See page 91 for more on pixels in graphics modes.
  8282.  
  8283.  Service 0DH (decimal 13): Read Pixel
  8284.  
  8285.    Service 0DH (decimal 13) is the reverse of service 0CH: It reads a pixel's
  8286.    color value rather than writing it. A pixel has only a single color
  8287.    attribute, which is returned through service 0DH. (The read-character
  8288.    service 08H returns both a color and an ASCII character code.) The row is
  8289.    specified in DX, the column in CX, and the display page in BH. The pixel
  8290.    color value is returned in AL. (See Figure 9-13.) All high-order bits of
  8291.    the value returned in AL are set to 0, as you would expect.
  8292.  
  8293.    Service Number Parameters                   Returns
  8294.    ──────────────────────────────────────────────────────────────────────────
  8295.    AH = 0DH       BH = display page number     AL = pixel color value
  8296.                   DX = row number of pixel
  8297.                   CX = column number of pixel
  8298.    ──────────────────────────────────────────────────────────────────────────
  8299.  
  8300.    Figure 9-13.  The registers used to read a pixel using service 0DH.
  8301.  
  8302.  Service 0EH (decimal 14): Write Character in Teletype Mode
  8303.  
  8304.    Service 0EH (decimal 14) is the workhorse service of conventional
  8305.    character output. It writes individual characters to the screen in what is
  8306.    known as teletype (TTY) mode. This makes the screen act as the simplest
  8307.    and crudest form of printer──exactly what is needed for routine text
  8308.    output. As such, this service has no regard for such niceties as color,
  8309.    blinking characters, or control over the cursor location.
  8310.  
  8311.    With this service, the character is written at the current cursor location
  8312.    and the cursor is advanced one position, wrapping to new lines or
  8313.    scrolling the screen as needed. The character to be written is specified
  8314.    in register AL.
  8315.  
  8316.    In text modes, the character is displayed as in service 0AH; that is, with
  8317.    the color attributes already in use at the screen location where the
  8318.    character is written. In graphics modes, however, you must also specify
  8319.    the foreground color value to be used for the character. (See Figure
  8320.    9-14.)
  8321.  
  8322.    There are four characters that service 0EH reacts to according to their
  8323.    ASCII meaning: 07H (decimal 7)──beep, 08H (decimal 8)──backspace, 0AH
  8324.    (decimal 10)──line feed, and 0DH (decimal 13)──carriage return. All other
  8325.    characters are displayed normally.
  8326.  
  8327.    The primary advantage of this service over service 09H is that the cursor
  8328.    is automatically moved; the advantage of service 09H is that you can
  8329.    control the color attribute. Now, if you could only combine the two....
  8330.  
  8331.    Service Number           Parameters
  8332.    ──────────────────────────────────────────────────────────────────────────
  8333.    AH = 0EH                 AL = ASCII character to write
  8334.                             BL = foreground color (in graphics modes only)
  8335.                             BH = display page (IBM PC BIOS dated 10/19/81 or
  8336.                             earlier)
  8337.    ──────────────────────────────────────────────────────────────────────────
  8338.  
  8339.    Figure 9-14.  The registers used to write a character in teletype mode
  8340.    using service 0EH.
  8341.  
  8342.  Service 0FH (decimal 15): Get Current Video Mode
  8343.  
  8344.    Service 0FH (decimal 15) returns the current video mode and two other
  8345.    useful pieces of information: the screen width in characters (80 or 40)
  8346.    and the display page number.
  8347.  
  8348.    The video mode number, as explained under service 00H, is returned in AL.
  8349.    The screen width is returned in AH as a number of characters per line. The
  8350.    display page number will be returned in BH. (See Figure 9-15.)
  8351.  
  8352.    Service Number           Returns
  8353.    ──────────────────────────────────────────────────────────────────────────
  8354.    AH = 0FH                 AL = current display mode
  8355.                             AH = number of characters per line
  8356.                             BH = active display page
  8357.    ──────────────────────────────────────────────────────────────────────────
  8358.  
  8359.    Figure 9-15.  Information returned by service 0FH.
  8360.  
  8361.    See page 72 for more on video modes. See page 58, memory location
  8362.    0040:0049H, for more on how a record of the mode is kept.
  8363.  
  8364.  Service 10H (decimal 16): Color Palette Interface
  8365.  
  8366.    Service 10H (decimal 16) was introduced with the PCjr and carried forward
  8367.    in the EGA and PS/2 ROM BIOS. It consists of a set of subservices (Figure
  8368.    9-16) that let you control palette colors, blinking, and (on the MCGA and
  8369.    VGA) the video DAC. Be aware that different subservices are supported with
  8370.    different hardware. Before you use these subservices in a program, be sure
  8371.    your program "knows" which subsystem it's running on. (Video service 1AH
  8372.    can provide this information to a program.)
  8373.  
  8374.    Subservice Number        Description
  8375.    ──────────────────────────────────────────────────────────────────────────
  8376.    AL = 00H                 Update a specified palette register.
  8377.    AL = 01H                 Specify the border color.
  8378.    AL = 02H                 Update all 16 palette registers plus border.
  8379.    AL = 03H                 Select background intensity or blink attribute.
  8380.    AL = 07H                 Read a specified palette register.
  8381.    AL = 08H                 Read the border color register.
  8382.    AL = 09H                 Read all 16 palette registers plus border.
  8383.    AL = 10H                 Update a specified video DAC color register.
  8384.    AL = 12H                 Update a block of video DAC color registers.
  8385.    AL = 13H                 Set video DAC color paging.
  8386.    AL = 15H                 Read a specified video DAC color register.
  8387.    AL = 17H                 Read a block of video DAC color registers.
  8388.    AL = 1AH                 Get video DAC color paging status.
  8389.    AL = 1BH                 Gray-scale a block of video DAC color registers.
  8390.    ──────────────────────────────────────────────────────────────────────────
  8391.  
  8392.    Figure 9-16.  Subservices available through video BIOS service 10H.
  8393.  
  8394.    Subservice 00H (decimal 0) updates one of the 16 palette registers on an
  8395.    EGA or VGA. You specify the palette register number in BL and a new
  8396.    palette register value in BH when you call this subservice. The VGA BIOS
  8397.    also supports subservice 07H (decimal 7), which performs the complementary
  8398.    operation: When you call subservice 07H with a palette register number in
  8399.    BL, the ROM BIOS returns that palette register's current contents in BH.
  8400.    (Subservice 07H isn't available in the EGA BIOS because the EGA has
  8401.    write-only palette registers.)
  8402.  
  8403.    Subservice 01H (decimal 1) sets the border color on an EGA or VGA. You
  8404.    pass the color value to the BIOS in register BH when you call this
  8405.    subservice. The VGA BIOS supports subservice 08H, which returns the
  8406.    current border color value in BH, but again this complementary subservice
  8407.    isn't available on the EGA.
  8408.  
  8409.    Here are two tips about setting the border color on an EGA or VGA. First,
  8410.    in most EGA video modes the border area is very small, and selecting any
  8411.    border color other than black results in a narrow, smeared border. On the
  8412.    VGA, the border is better. Second, if compatibility with the CGA is
  8413.    important, remember that you can also use video service 0BH (page 180) to
  8414.    set the border color.
  8415.  
  8416.    Subservice 02H (decimal 2) updates all 16 palette registers, plus the
  8417.    border color, with a single ROM BIOS call. Before you call subservice 02H,
  8418.    you must store all 16 palette register values plus the border color value
  8419.    in a 17-byte table. You then pass the address (segment and offset) of this
  8420.    table to the BIOS in registers ES and DX when you call this subservice.
  8421.    The VGA also provides a subservice that lets you read the palette
  8422.    registers back into a table: When you call subservice 09H (decimal 9) with
  8423.    ES:DX pointing to a 17-byte table, the ROM BIOS fills the table with the
  8424.    16 current palette register values and the border color.
  8425.  
  8426.    Subservice 03H (decimal 3) lets you selectively enable or disable the
  8427.    blinking attribute. The ROM BIOS uses blinking by default, but if you
  8428.    prefer to have a full range of 16 background colors instead of only 8, you
  8429.    can use subservice 03H to disable blinking. The value you pass in register
  8430.    BL determines whether blinking is enabled (BL = 01H) or disabled (BL =
  8431.    00H).
  8432.  
  8433.    Subservices 10H (decimal 16) and 15H (decimal 21) are supported only by
  8434.    the MCGA and VGA BIOS. These two subservices give you direct access to one
  8435.    of the 256 color registers in the video digital to analog convertor (DAC).
  8436.    To update a video DAC color register, call subservice 10H with the color
  8437.    register number in BX and 6-bit red, green, and blue color values in
  8438.    registers DH, CH, and CL. To read a specified color register, place the
  8439.    color register number in BX and use subservice 15H, which returns the RGB
  8440.    values in DH, CH, and CL.
  8441.  
  8442.    The related subservices 12H (decimal 18) and 17H (decimal 23) operate on a
  8443.    block of video DAC color registers instead of only one. To use subservice
  8444.    12H, create a table of 3-byte red-green-blue values. Then place the
  8445.    segment-offset address of the table in ES and DX, the first color register
  8446.    number to update in BX, and the number of registers to update in CX. When
  8447.    you call subservice 12H, the ROM BIOS stores each red-green-blue value in
  8448.    turn into the block of color registers you specified in BX and CX.
  8449.  
  8450.    The complementary subservice 17H requires you to pass the address of a
  8451.    table in ES:DX, along with a starting register number in BX and a register
  8452.    count in CX. The ROM BIOS fills the table with the red-green-blue values
  8453.    it reads from the block of color registers you specified.
  8454.  
  8455.    On the VGA, which has both palette registers and video DAC color
  8456.    registers, you can use subservices 13H (decimal 19) and 1AH (decimal 26)
  8457.    to switch rapidly between different palettes. By default, the ROM BIOS
  8458.    configures the VGA hardware so that color decoding is the same as on the
  8459.    EGA: Each of the 16 palette registers contains a 6-bit value that
  8460.    specifies one of the first 64 video DAC registers, and these 64 color
  8461.    registers specify the 64 colors available in the EGA palette.
  8462.  
  8463.    Subservice 13H lets you use the other three color pages, or groups of 64
  8464.    video DAC color registers. (See Figure 9-17.) If you call subservice 13H
  8465.    with BH = 01H and BL = 01H, for example, the BIOS configures the VGA
  8466.    hardware to display colors from the second group of 64 color registers
  8467.    (color page 1). To use the first group (color page 0) again, you could
  8468.    call the same subservice with BH = 00H and BL = 01H. If, for example, you
  8469.    used the default, EGA-compatible colors in color page 0, and their
  8470.    gray-scale equivalents in color page 1, you could switch rapidly between
  8471.    the two with a single call to subservice 13H.
  8472.  
  8473.    If you need to switch rapidly between more than four palettes, you can use
  8474.    subservice 13H with BH = 01H and BL = 00H to configure the VGA color
  8475.    decoding hardware to use 4-bit palette register values instead of 6-bit
  8476.    values. In this case, each palette register value can specify one of only
  8477.    16 different video DAC registers. This makes 16 color pages available,
  8478.    each comprising 16 color registers. You can select any of the 16 color
  8479.    pages using subservice 13H with BL = 01H.
  8480.  
  8481.    Parameters                           Description
  8482.    ──────────────────────────────────────────────────────────────────────────
  8483.    BL = 00H           BH = 00H          Use four 64-register pages.
  8484.                       BH = 01H          Use sixteen 16-register pages.
  8485.    BL = 01H           BH = n            Color page number.
  8486.                                         (n = 00H─03H if using 64-register
  8487.                                         pages
  8488.                                         n = 00H─0FH if using 16-register
  8489.                                         pages)
  8490.    ──────────────────────────────────────────────────────────────────────────
  8491.  
  8492.    Figure 9-17.  Video DAC color paging with service 10H, subservice 13H.
  8493.  
  8494.    The VGA ROM BIOS supplements subservice 13H with a complementary function,
  8495.    subservice 1AH. This subservice returns the color page status in BL (16-
  8496.    or 64-register color pages) and BH (current color page number).
  8497.  
  8498.    With subservice 1BH (decimal 27) on the MCGA and VGA, you can convert the
  8499.    color values in a block of consecutive video DAC color registers to
  8500.    corresponding shades of gray. Call this subservice with BX containing the
  8501.    number of the first video DAC register to convert, and with CX containing
  8502.    the number of registers to update.
  8503.  
  8504.  Service 11H (decimal 17): Character Generator Interface
  8505.  
  8506.    Service 11H (decimal 17) first appeared in the EGA ROM BIOS. The many
  8507.    subservices available in service 11H were augmented and expanded in the
  8508.    PS/2 ROM BIOS to provide full support for the new video subsystems (MCGA
  8509.    and VGA) introduced with the PS/2s.
  8510.  
  8511.    To make sense of the many service 11H subservices, it helps to consider
  8512.    them in four groups (Figure 9-18):
  8513.  
  8514.    ■  Subservices in the first group (subservices 00H through 04H) change the
  8515.       character set used in text modes.
  8516.  
  8517.    ■  Subservices in the second group (subservices 10H through 14H) change
  8518.       the text-mode character set as well as the displayed height of
  8519.       text-mode characters.
  8520.  
  8521.    ■  Subservices in the third group (subservices 20H through 24H) update
  8522.       graphics-mode character sets.
  8523.  
  8524.    ■  The subservice in the fourth group (subservice 30H) returns information
  8525.       about the character sets currently displayed and about the character
  8526.       sets available to the ROM BIOS.
  8527.  
  8528.    Subservices 00H (decimal 0), 01H (decimal 1), 02H (decimal 2) and 04H
  8529.    (decimal 4) all change the character set used to display text-mode
  8530.    characters on the EGA, MCGA, or VGA. Subservices 01H, 02H, and 04H are the
  8531.    easiest to use. You need specify only which available tables in character
  8532.    generator RAM should contain the character set. Thus, for example, a call
  8533.    to service 11H with AL = 02H and BL = 00H instructs the ROM BIOS to use
  8534.    its 8 x 8 characters in the first (default) table in character generator
  8535.    RAM.
  8536.  
  8537.    If you want to define your own characters you need to use subservice 00H,
  8538.    as follows: Place a table of the bit patterns that define the characters
  8539.    in a buffer. Then call subservice 00H with the address of the table in
  8540.    ES:BP, the number of characters in CX, the ASCII code of the first
  8541.    character in the table in DX, and the number of bytes in each character's
  8542.    bit pattern in BH.
  8543.  
  8544.    Subservice 03H (decimal 3) lets you select among text-mode character sets
  8545.    once they are loaded into character generator RAM. The EGA and MCGA have
  8546.    four such tables; the VGA has eight. The value in BL specifies which one
  8547.    or two of the tables is to be used to display text-mode characters. On the
  8548.    EGA and MCGA, bits 0 and 1 of BL specify one table, and bits 2 and 3
  8549.    specify a second table. If the two bit fields specify the same table,
  8550.    that's the table that will be used for all text-mode characters.
  8551.  
  8552. ╓┌─┌─────────────────────────────┌───────────────────────────────────────────╖
  8553.    Subservice Number             Description
  8554.    ──────────────────────────────────────────────────────────────────────────
  8555.    Load a text-mode character set:
  8556.    AL = 00H                      Load a user-specified character set.
  8557.    AL = 01H                      Load the ROM BIOS 8 x 14 character set.
  8558.    AL = 02H                      Load the ROM BIOS 8 x 8 character set.
  8559.    AL = 03H                      Select displayed character set.
  8560.    AL = 04H                      Load the ROM BIOS 8 x 16 character set
  8561.                                  (MCGA, VGA only).
  8562.  
  8563.    Load a text-mode character set and adjust the displayed character height:
  8564.    AL = 10H                      Load a user-specified character set.
  8565.    AL = 11H                      Load the ROM BIOS 8 x 14 character set.
  8566.    AL = 12H                      Load the ROM BIOS 8 x 8 character set.
  8567.    AL = 14H                      Load the ROM BIOS 8 x 16 character set
  8568.                                  (MCGA, VGA only).
  8569.  
  8570.    Subservice Number             Description
  8571.    ──────────────────────────────────────────────────────────────────────────
  8572. 
  8573.    Load a graphics-mode character set:
  8574.    AL = 20H                      Load a CGA-compatible, user-specified
  8575.                                  character set.
  8576.    AL = 21H                      Load a user-specified character set.
  8577.    AL = 22H                      Load the ROM BIOS 8 x 14 character set.
  8578.    AL = 23H                      Load the ROM BIOS 8 x 8 character set.
  8579.    AL = 24H                      Load the ROM BIOS 8 x 16 character set
  8580.                                  (MCGA, VGA only).
  8581.  
  8582.    Get character generator information:
  8583.    AL = 30H                      Get character generator information.
  8584.    ──────────────────────────────────────────────────────────────────────────
  8585.  
  8586.  
  8587.    Figure 9-18.  Subservices available through video BIOS service 11H.
  8588.  
  8589.    Subservices 10H (decimal 16), 11H (decimal 17), 12H (decimal 18), and 14H
  8590.    (decimal 20) are similar to subservices 00H, 01H, 02H, and 04H. The
  8591.    difference is that with these higher-numbered subservices, the ROM BIOS
  8592.    not only loads a character set but also adjusts the displayed character
  8593.    height appropriately. This difference is obvious if you compare the effect
  8594.    of executing subservice 02H and subservice 12H to load the ROM BIOS 8 x 8
  8595.    character set. With subservice 02H, the 8 x 8 characters are used without
  8596.    adjusting the displayed character height, so if you're in a default ROM
  8597.    BIOS text mode, you'll see 25 rows of characters. With subservice 12H, the
  8598.    ROM BIOS adjusts the displayed character height so that in a default ROM
  8599.    BIOS text mode you see 43 rows of characters on an EGA or 50 rows of
  8600.    characters on a VGA.
  8601.  
  8602.    Subservices 20H through 24H (decimal 32 through decimal 36) are related to
  8603.    subservices 00H through 04H in that they also load character sets into
  8604.    memory. However, this third group of subservices is designed for use only
  8605.    in graphics modes. Subservice 20H loads a CGA-compatible set of 8 x 8
  8606.    characters into RAM. To use subservice 20H, place a table containing the
  8607.    bit patterns for ASCII characters 80H through FFH into memory, and pass
  8608.    the address of this table to the ROM BIOS in registers ES:BP. Subservices
  8609.    21H through 24H are similar to subservices 00H, 01H, 02H, and 04H. Call
  8610.    them with 00H in BL, the number of displayed character rows in DL, and
  8611.    (for subservice 21H) the number of bytes in each character's bit pattern
  8612.    in CX.
  8613.  
  8614.    Subservice 30H (decimal 48) returns several pieces of handy information
  8615.    regarding the ROM BIOS character generator. This subservice reports the
  8616.    height of the displayed character matrix in CX and the number of the
  8617.    bottom character row in DL. For example, if you call subservice 30H in the
  8618.    default EGA text mode (80 x 25), the BIOS returns 14 in CX and 24 in DL.
  8619.  
  8620.    Parameter          Returns
  8621.    ──────────────────────────────────────────────────────────────────────────
  8622.    BH = 00H           CGA-compatible 8 x 8 graphics-mode characters
  8623.                       (contents of interrupt 1FH vector)
  8624.    BH = 01H           Current graphics-mode characters (contents of
  8625.                       interrupt 43H vector)
  8626.    BH = 02H           ROM BIOS 8 x 14 characters
  8627.    BH = 03H           ROM BIOS 8 x 8 characters
  8628.    BH = 04H           Second half of ROM BIOS 8 x 8 character table
  8629.    BH = 05H           ROM BIOS 9 x 14 alternate characters
  8630.    BH = 06H           ROM BIOS 8 x 16 characters (MCGA and VGA only)
  8631.    BH = 07H           ROM BIOS 9 x 16 alternate characters (VGA only)
  8632.    ──────────────────────────────────────────────────────────────────────────
  8633.  
  8634.    Figure 9-19.  Character bit pattern table addresses returned in ES:BP by
  8635.    subservice 30H of video ROM BIOS service 11H.
  8636.  
  8637.    Subservice 30H also returns the address of any of several bit pattern
  8638.    tables for the default ROM BIOS character sets. The value you pass in BH
  8639.    when you call this subservice determines which address the ROM BIOS
  8640.    returns in ES:BP. (See Figure 9-19.)
  8641.  
  8642.  Service 12H (decimal 18): "Alternate Select"
  8643.  
  8644.    Service 12H (decimal 18) made its debut along with service 11H in the EGA
  8645.    BIOS. It, too, is supported in the ROM BIOS in all PC/2 video subsystems.
  8646.    IBM's name for this service derives from the purpose of one of the
  8647.    subservices of service 12H, namely, to select an alternate print-screen
  8648.    routine for the ROM BIOS Shift-PrtSc function. The name lingers on even
  8649.    though service 12H has been expanded by adding a number of unrelated
  8650.    subservices. (See Figure 9-20.)
  8651.  
  8652.    Subservice Number        Description
  8653.    ──────────────────────────────────────────────────────────────────────────
  8654.    BL = 10H                 Return video configuration information.
  8655.    BL = 20H                 Select alternate print-screen routine.
  8656.    BL = 30H                 Select scan lines for VGA text modes.
  8657.    BL = 31H                 Enable/disable default palette loading.
  8658.    BL = 32H                 Enable/disable CPU access to video RAM.
  8659.    BL = 33H                 Enable/disable gray-scale summing.
  8660.    BL = 34H                 Enable/disable ROM BIOS cursor emulation.
  8661.    BL = 35H                 PS/2 display switch interface.
  8662.    BL = 36H                 Enable/disable video refresh.
  8663.    ──────────────────────────────────────────────────────────────────────────
  8664.  
  8665.    Figure 9-20.  Subservices available through video BIOS service 12H.
  8666.  
  8667.    Subservice 10H (decimal 16) reports on the configuration of an EGA or VGA.
  8668.    The value returned in BH indicates whether the current video mode is color
  8669.    (BH = 00H) or monochrome (BH = 01H). BL contains a number between 0 and 3
  8670.    that represents the amount of RAM installed on an EGA (0 means 64 KB; 1
  8671.    means 128 KB; 2 means 192 KB; 3 means 256 KB). The value in CH reflects
  8672.    the status of input from the EGA feature connector, and CL contains the
  8673.    settings of the EGA configuration switches.
  8674.  
  8675.    Subservice 20H (decimal 32) is provided for the convenience of users of
  8676.    the EGA or a VGA adapter. It replaces the motherboard ROM BIOS
  8677.    print-screen routine with a more flexible routine in the adapter ROM BIOS.
  8678.    Unlike the motherboard ROM BIOS routine, the adapter BIOS routine can
  8679.    print a snapshot of a text-mode screen that has more than 25 rows of
  8680.    characters. In PS/2s, of course, the motherboard routine can already do
  8681.    this, eliminating the need for this subservice.
  8682.  
  8683.    Subservice 30H (decimal 48) lets you specify how many scan lines to
  8684.    display in VGA text modes. The default ROM BIOS text modes contain 400
  8685.    scan lines. When you call subservice 30H, the value you pass in register
  8686.    AL can instruct the ROM BIOS to use a different vertical resolution: If AL
  8687.    = 00H, ROM BIOS text modes will display 200 scan lines, as they do on a
  8688.    CGA. If AL = 01H, text modes will display an EGA-compatible 350 scan
  8689.    lines. Finally, when AL = 02H, the ROM BIOS uses its default resolution of
  8690.    400 scan lines.
  8691.  
  8692.    When you use subservice 30H, the vertical resolution does not change until
  8693.    the next time a program uses video ROM BIOS service 00H to select a text
  8694.    mode. Thus, changing the vertical resolution actually requires you to make
  8695.    two different ROM BIOS calls: one to specify the resolution and another to
  8696.    set up the text mode.
  8697.  
  8698.    Subservice 31H (decimal 49) lets you enable or disable palette loading
  8699.    when the ROM BIOS sets up a new MCGA or VGA video mode. Calling subservice
  8700.    31H with AL = 01H disables palette loading, so you can subsequently change
  8701.    video modes without changing the colors in a previously-loaded palette. A
  8702.    call with AL = 00H enables default palette loading.
  8703.  
  8704.    Subservices 32H (decimal 50) and 35H (decimal 53) are provided for
  8705.    programmers who want to use two different video subsystems in the same
  8706.    PS/2 computer. In particular, these routines support the use of a VGA
  8707.    alongside the built-in MCGA subsystem in a PS/2 Model 30.
  8708.  
  8709.    Subservice 32H enables or disables buffer and port addressing according to
  8710.    the value passed in AL (AL = 00H means enable; AL = 01H means disable).
  8711.    This feature is important if any addresses in the two video subsystems
  8712.    overlap: Before accessing one subsystem, you must disable addressing in
  8713.    the other one.
  8714.  
  8715.    Subservice 35H provides a complete switching interface that lets you
  8716.    selectively access both an MCGA and a VGA in the same computer. This
  8717.    subservice relies on the function provided through subservice 32H to
  8718.    independently enable and disable each video subsystem. See Chapter 13 and
  8719.    the IBM BIOS Interface Technical Reference manual for details.
  8720.  
  8721.    Subservice 33H (decimal 51) tells the ROM BIOS whether or not to average
  8722.    colors to gray scales when it establishes a new video mode on an MCGA or
  8723.    VGA. A call to this subservice with AL = 01H disables the gray-scaling; a
  8724.    call with AL = 00H enables gray-scaling. You can also use this subservice
  8725.    to force the ROM BIOS to use a gray-scale palette even if you're using a
  8726.    color monitor.
  8727.  
  8728.    Subservice 34H (decimal 52) enables or disables text-mode cursor emulation
  8729.    on the VGA. When you call this subservice with AL = 00H, the ROM BIOS
  8730.    emulates CGA text-mode cursor sizing whenever you change
  8731.  
  8732.    video modes or update the cursor size. When called with AL = 01H, this
  8733.    subservice disables text-mode cursor emulation.
  8734.  
  8735.    Subservice 36H (decimal 54) lets you enable or disable VGA video refresh.
  8736.    Calling this subservice with AL = 01H disables refresh, and a call with AL
  8737.    = 00H enables refresh. When you disable refresh, the screen goes blank,
  8738.    but reads and writes to the video buffer are somewhat faster than when
  8739.    refresh is enabled. If you are writing a program that needs to run as fast
  8740.    as possible, and if you don't mind having the screen go blank while you
  8741.    access the video buffer, then consider using subservice 36H to temporarily
  8742.    blank the screen while you update it.
  8743.  
  8744.  Service 13H (decimal 19): Write Character String
  8745.  
  8746.    Service 13H (decimal 19), allows you to write a string of characters to
  8747.    the display screen. Through the four subservices that make up this
  8748.    service, you can specify the character attributes individually or as a
  8749.    group. You can also move the cursor to the end of the string or leave it
  8750.    in place, depending on which subservice you choose.
  8751.  
  8752.    The subservice number is placed in AL, the pointer to the string in ES:BP,
  8753.    the length of the string in CX, the starting position where the string is
  8754.    to be written in DX, and the display page number in BH.
  8755.  
  8756.    Subservices 00H (decimal 0) and 01H (decimal 1) write a string of
  8757.    characters to the screen using the attribute specified in register BL.
  8758.    With subservice 00H, the cursor is not moved from the location specified
  8759.    in register DX; with subservice 01H, the cursor is moved to the location
  8760.    following the last character in the string.
  8761.  
  8762.    Subservices 02H (decimal 2) and 03H (decimal 3) write a string of
  8763.    characters and attributes to the screen, writing first the character and
  8764.    then the attribute. With subservice 02H, the cursor is not moved from the
  8765.    location specified in register DX; with subservice 03H, the cursor is
  8766.    moved to the location following the last character in the string.
  8767.  
  8768.    Service 13H is available only in the PC/AT, EGA, PS/2s, and later versions
  8769.    of the PC/XT ROM BIOS.
  8770.  
  8771.  Service 1AH (decimal 26): Read/Write Display Combination Code
  8772.  
  8773.    Service 1AH (decimal 26) was introduced in the ROM BIOS in the PS/2s, but
  8774.    it is also part of the ROM BIOS of the VGA. This service returns a 2-byte
  8775.    code that indicates which combination of video subsystems and video
  8776.    displays is found in your computer. The display combination codes
  8777.    recognized by this ROM BIOS service are listed in Figure 9-21. Service
  8778.    1AH lets you select either of two subservices using the value in register
  8779.    AL; subservice 00H or subservice 01H.
  8780.  
  8781.    Subservice 00H (decimal 0) returns a 2-byte display combination code in
  8782.    register BX. If your computer has two different video subsystems, the
  8783.    value in BL indicates which one is active; that is, which is currently
  8784.    being updated by the video ROM BIOS. The value in BH indicates the
  8785.    inactive subsystem. If your computer has only video subsystem, the value
  8786.    in BH is zero.
  8787.  
  8788.    Subservice 01H (decimal 1) performs the reverse function of subservice
  8789.    00H. It lets you change the current display combination code known to the
  8790.    ROM BIOS. Don't use this subservice, however, unless you know exactly what
  8791.    you're doing. It's a rare program indeed that requires you to change the
  8792.    ROM BIOS's idea of what the video hardware actually is.
  8793.  
  8794.    Code               Video Subsystem
  8795.    ──────────────────────────────────────────────────────────────────────────
  8796.    00H                (No display)
  8797.    01H                MDA
  8798.    02H                CGA
  8799.    03H                (Reserved)
  8800.    04H                EGA with color display
  8801.    05H                EGA with monochrome display
  8802.    06H                Professional Graphics Controller
  8803.    07H                VGA with monochrome display
  8804.    08H                VGA with color display
  8805.    09H,0AH            (Reserved)
  8806.    0BH                MCGA with monochrome display
  8807.    0CH                MCGA with color display
  8808.    0FFH               (Unknown)
  8809.    ──────────────────────────────────────────────────────────────────────────
  8810.  
  8811.    Figure 9-21.  Display combination codes returned by video BIOS service
  8812.    1AH.
  8813.  
  8814.  Service 1BH (decimal 27): Return Functionality/State Information
  8815.  
  8816.    Service 1BH (decimal 27) is available in all PS/2s as well as with the
  8817.    VGA. It returns a great deal of detailed information regarding the
  8818.    capabilities of the ROM BIOS as well as the current ROM BIOS and video
  8819.    hardware status.
  8820.  
  8821.    Service 1BH returns this information in a 64-byte buffer whose address is
  8822.    passed in registers ES:DI. In addition to this address, you must also
  8823.    specify an "implementation type" value of 0 in register BX. (Presumably
  8824.    future IBM video products will recognize implementation type values other
  8825.    than 0.)
  8826.  
  8827.    The BIOS fills the buffer with information about the current video mode
  8828.    (the mode number, character columns and rows, number of colors
  8829.  
  8830.    available) as well as about the video hardware configuration (total video
  8831.    memory available, display combination code, and so on). See the IBM BIOS
  8832.    Interface Technical Reference manual for details on the buffer format.
  8833.  
  8834.    In the first 4 bytes of the buffer, the ROM BIOS returns a pointer to a
  8835.    table of "static" functionality information. This table lists nearly all
  8836.    of the features the ROM BIOS and the video hardware can support: the video
  8837.    modes available, support for palette switching, RAM-loadable character
  8838.    sets, light-pen support, and many other details.
  8839.  
  8840.    When you write a program that runs on a PS/2 or in a system with a VGA
  8841.    adapter, service 1BH offers a simple and consistent way for your program
  8842.    to determine what the video subsystem's current and potential capabilities
  8843.    are. Unfortunately, you can't rely on this service if your program must be
  8844.    compatible with non-PS/2 computers. Neither the PC motherboard ROM BIOS
  8845.    nor the EGA BIOS supports this service. A program can determine whether
  8846.    service 1BH is supported by examining the value returned by this service
  8847.    in AL; this value is 1BH if the service is supported.
  8848.  
  8849.  Service 1CH (decimal 28): Save/Restore Video State
  8850.  
  8851.    Service 1CH (decimal 28) is provided by the ROM BIOS only in the PS/2
  8852.    models 50, 60, and 80, and with VGA adapters. (In other words, where you
  8853.    find a VGA you also find service 1CH.) This BIOS service lets you preserve
  8854.    all information that describes the state of the video BIOS and hardware.
  8855.    The ROM BIOS can preserve three types of information: the video DAC state,
  8856.    the BIOS data area in RAM, and the current values in all video control
  8857.    registers.
  8858.  
  8859.    You can select three different subservices with the value you pass in
  8860.    register AL: subservices 00H, 01H, and 02H.
  8861.  
  8862.    Subservice 00H (decimal 0) is designed to be called before subservices 01H
  8863.    or 02H. Subservice 00H requires you to specify which of the three types of
  8864.    information you want to preserve, by setting one or more of the three
  8865.    low-order bits of the value in CX. When this service returns, BX contains
  8866.    the size of the buffer you will need to store the information.
  8867.  
  8868.    Subservice 01H (decimal 1) saves the current video state information in
  8869.    the buffer whose address you pass in ES:BX. Then you can change video
  8870.    modes, reprogram the palette, or otherwise program the ROM BIOS or video
  8871.    hardware.
  8872.  
  8873.    Subservice 02H (decimal 2) lets you restore the previous video state.
  8874.  
  8875.  
  8876.  Comments and Example
  8877.  
  8878.    In cruising through the ROM BIOS video services, you've seen how they work
  8879.    individually. Once you have that information in mind, the next question
  8880.    usually is: Given a choice between using the ROM BIOS services directly or
  8881.    using higher-level services such as the DOS services or the services built
  8882.    into your programming language, which is best? The general advice that we
  8883.    always give is to use the highest-level services that will accomplish what
  8884.    you want to do. In this case, there is no specific reason for you to avoid
  8885.    using the ROM BIOS video services──you can't do any great harm by using
  8886.    them. But in the next chapter on the diskette services, we'll argue the
  8887.    case the other way, advising you to avoid using the ROM BIOS diskette
  8888.    services because more risk is associated with them.
  8889.  
  8890.    The video capabilities of the PC models are remarkable, and the ROM BIOS
  8891.    services give you full use of them. The DOS services, as you'll see in
  8892.    Chapters 14 through 18, are rather weak and provide only the simplest
  8893.    character services. Likewise, many programming languages (for example,
  8894.    Pascal and C) only provide a dressed-up version of the DOS services and
  8895.    nothing more. So, if you need to use the PC's fancy screen capabilities
  8896.    and if you aren't using a language such as BASIC that provides the
  8897.    services you need, you should be using the ROM BIOS services. Getting
  8898.    control of the display screen is one of the very best reasons for using
  8899.    the ROM BIOS services.
  8900.  
  8901.    Using the ROM BIOS services directly usually calls for an
  8902.    assembly-language interface, so we'll give you an example of how one can
  8903.    be set up. For the example, we'll set up a module in a format that would
  8904.    be called by C. We'll make the module switch to video mode 1 (40-column
  8905.    text in color) and set the border color to blue.
  8906.  
  8907.    Here is the assembly module (see Chapter 8, page 161, for general notes
  8908.    on the format):
  8909.  
  8910.    _TEXT           SEGMENT         byte public 'CODE'
  8911.                    ASSUME          cs:_TEXT
  8912.  
  8913.                    PUBLIC          _Blue40
  8914.    _Blue40         PROC            near
  8915.  
  8916.                    push            bp       ; save previous BP value
  8917.                    mov             bp,sp    ; use BP to access the stack
  8918.  
  8919.  
  8920.    ; set video mode
  8921.  
  8922.                    mov            ah,0      ; BIOS service number
  8923.                    mov            al,1      ; video mode number
  8924.                    int            10h       ; call BIOS to set 40x25 text mode
  8925.  
  8926.    ; set border color
  8927.  
  8928.                    mov            ah,0Bh    ; BIOS service number
  8929.                    mov            bh,0      ; subservice number
  8930.                    mov            bl,1      ; color value (blue)
  8931.                    int            10h       ; call BIOS to set border color
  8932.  
  8933.                    pop            bp        ; restore previous BP value
  8934.                    ret
  8935.  
  8936.    _Blue40         ENDP
  8937.  
  8938.    _TEXT           ENDS
  8939.  
  8940.  
  8941.  
  8942.  ────────────────────────────────────────────────────────────────────────────
  8943.  Chapter 10  ROM BIOS Disk Services
  8944.  
  8945.    The ROM BIOS Disk Services
  8946.      Service 00H (decimal 0): Reset Disk System
  8947.      Service 01H (decimal 1): Get Disk Status
  8948.      Service 02H (decimal 2): Read Disk Sectors
  8949.      Service 03H (decimal 3): Write Disk Sectors
  8950.      Service 04H (decimal 4): Verify Disk Sectors
  8951.      Service 05H (decimal 5): Format Disk Track
  8952.      Service 06H (decimal 6): Format PC/XT Fixed-Disk Track
  8953.      Service 07H (decimal 7): Format PC/XT Fixed Disk
  8954.      Service 08H (decimal 8): Get Disk-Drive Parameters
  8955.      Service 09H (decimal 9): Initialize Fixed-Disk Parameter Tables
  8956.      Service 0AH and 0BH (decimal 10 and 11): Read and Write Long
  8957.      Service 0CH (decimal 12): Seek to Cylinder
  8958.      Service 0DH (decimal 13): Alternate Fixed-Disk Reset
  8959.      Service 10H (decimal 16): Test for Drive Ready
  8960.      Service 11H (decimal 17): Recalibrate Drive
  8961.      Service 15H (decimal 21): Get Disk Type
  8962.      Service 16H (decimal 22): Diskette Change Status
  8963.      Service 17H (decimal 23): Set Diskette Type
  8964.      Service 18H (decimal 24): Set Media Type for Format
  8965.      Service 19H (decimal 25): Park Heads
  8966.      Service 1AH (decimal 26): Format ESDI Unit
  8967.  
  8968.    Disk-Base Tables
  8969.  
  8970.    Comments and Examples
  8971.  
  8972.    We're now going to cover the disk services provided by the ROM BIOS. To
  8973.    understand the logical structure of the contents of a disk, see Chapter
  8974.    5, particularly pages 106 through 121. For information about the
  8975.    higher-level disk services provided by DOS, see Chapters 15 through 18.
  8976.  
  8977.    Generally speaking, disk operations are best left to disk operating
  8978.    systems. If you decide to use any of the ROM BIOS disk services, we
  8979.    recommend that you read the section entitled "Comments and Examples" on
  8980.    page 212 of this chapter.
  8981.  
  8982.  
  8983.  The ROM BIOS Disk Services
  8984.  
  8985.    The original IBM PC ROM BIOS offered only six different disk services. As
  8986.    the diskette and fixed-disk subsystems of the PC and PS/2 family have
  8987.    become increasingly sophisticated, the number of ROM BIOS services that
  8988.    support disk I/O has increased. To keep the ROM BIOS software modular and
  8989.    flexible, IBM separated the support routines for fixed-disk subsystems
  8990.    from the diskette support routines. Nevertheless, the number of BIOS disk
  8991.    services has grown from six on the original IBM PC to 22 in the PS/2s.
  8992.    (See Figure 10-1.)
  8993.  
  8994.    All ROM BIOS disk services are invoked with interrupt 13H (decimal 19) and
  8995.    selected by loading the service number into the AH register. Disk drives
  8996.    are identified by a zero-based number passed in DL, with the high-order
  8997.    bit set to 1 to indicate a fixed disk. Thus the first diskette drive in
  8998.    the computer is identified by drive number 00H, and the first fixed disk
  8999.    is designated by drive number 80H.
  9000.  
  9001.    The ROM BIOS uses a set of descriptive parameter tables called disk-base
  9002.    tables to gain information about the capabilities of the disk controller
  9003.    hardware and the disk media. The ROM BIOS maintains the segmented
  9004.    addresses of the disk-base tables it uses in interrupt vectors: The
  9005.    address of the table for the current diskette drive is in the interrupt
  9006.    1EH vector (0000:0074H); addresses of tables for the first and second
  9007.    fixed drives are in interrupt vectors 41H (0000:0104H) and 46H
  9008.    (0000:0118H).
  9009.  
  9010.    For most programmers, the disk-base tables are an invisible part of the
  9011.    disk services. However, some disk-base parameters may occasionally need to
  9012.    be changed for special purposes. For this reason we include a brief
  9013.    description of the disk-base table toward the end of this chapter.
  9014.  
  9015.    The following sections describe each of the ROM BIOS services.
  9016.  
  9017. ╓┌─┌───────────┌────────────────────────────────────┌────────────┌───────────╖
  9018.    Service     Description                          Diskette     Fixed Disk
  9019.    ──────────────────────────────────────────────────────────────────────────
  9020.    00H         Reset Disk System.                  x            x
  9021.    01H         Get Disk Status.                    x            x
  9022.    02H         Read Disk Sectors.                  x            x
  9023.    03H         Write Disk Sectors.                 x            x
  9024.    04H         Verify Disk Sectors.                x            x
  9025.    05H         Format Disk Track.                  x            x
  9026.    06H         Format PC/XT Fixed-Disk Track.                   x
  9027.    07H         Format PC/XT Fixed Disk.                         x
  9028.    08H         Get Disk-Drive Parameters.          x            x
  9029.    09H         Initialize Fixed-Disk Parameter                   x
  9030.                Tables.
  9031.    0AH         Read Long.                                       x
  9032.    Service     Description                          Diskette     Fixed Disk
  9033.    ──────────────────────────────────────────────────────────────────────────
  9034.   0AH         Read Long.                                       x
  9035.    0BH         Write Long.                                      x
  9036.    0CH         Seek to Cylinder.                                x
  9037.    0DH         Alternate Fixed-Disk Reset.                      x
  9038.    10H         Test for Drive Ready.                            x
  9039.    11H         Recalibrate Drive.                               x
  9040.    15H         Get Disk Type.                      x            x
  9041.    16H         Get Diskette Change Status.         x
  9042.    17H         Set Diskette Type.                  x
  9043.    18H         Set Media Type for Format.          x
  9044.    19H         Park Heads.                                      x
  9045.    1AH         Format ESDI Unit.                                x
  9046.    ──────────────────────────────────────────────────────────────────────────
  9047.  
  9048.  
  9049.    Figure 10-1.  The ROM BIOS disk services.
  9050.  
  9051.  Service 00H (decimal 0): Reset Disk System
  9052.  
  9053.    Service 00H resets the disk controller and drive. This service does not
  9054.    affect the disk itself. Instead, a reset through service 00H forces the
  9055.    ROM BIOS disk-support routines to start from scratch for the next disk
  9056.    operation by recalibrating the disk drive's read/write head──an operation
  9057.    that positions the head on a certain track. This reset service is normally
  9058.    used after an error in any other drive operation.
  9059.  
  9060.    When you call service 00H for a fixed-disk drive, the ROM BIOS also resets
  9061.    the diskette-drive controller. If you want to reset the fixed-disk
  9062.    controller only, use service 0DH. (See page 207.)
  9063.  
  9064.  Service 01H (decimal 1): Get Disk Status
  9065.  
  9066.    Service 01H (decimal 1) reports the disk status in register 0AH. The
  9067.    status is preserved after each disk operation, including the read, write,
  9068.    verify, and format operations. By preserving the disk status, an
  9069.    error-handling or error-reporting routine can be completely independent of
  9070.    the routines that operate the disk. This can be very useful. Under the
  9071.    right circumstances, you can rely on DOS or your programming language to
  9072.    drive the disk (a wise choice; see "Comments and Examples" on page 212),
  9073.    and at the same time have your program find out and report the details of
  9074.    what went wrong. See Figure 10-2 for details of the status byte.
  9075.  
  9076. ╓┌─┌────────────────────────┌────────────────────────────────────────────────╖
  9077.    Value (hex)              Meaning
  9078.    ──────────────────────────────────────────────────────────────────────────
  9079.    00H                      No error
  9080.    01H                      Bad command
  9081.    02H                      Address mark not found
  9082.    03H                      Write attempted on
  9083.                             write-protected disk
  9084.    04H                      Sector not found
  9085.    05H                      Reset failed
  9086.    06H                      Diskette removed
  9087.    07H                      Bad parameter table
  9088.    08H                      DMA overrun
  9089.    09H                      DMA across 64 KB boundary
  9090.    0AH                      Bad sector flag
  9091.    0BH                      Bad cylinder
  9092.    0CH                      Bad media type
  9093.    0DH                      Invalid number of sectors on format
  9094.    0EH                      Control data address mark detected
  9095.    Value (hex)              Meaning
  9096.    ──────────────────────────────────────────────────────────────────────────
  9097.   0EH                      Control data address mark detected
  9098.    0FH                      DMA arbitration level out of range
  9099.    10H                      Bad CRC or ECC
  9100.    11H                      ECC corrected data error
  9101.    20H                      Controller failed
  9102.    40H                      Seek failed
  9103.    80H                      Time out
  9104.    AAH                      Drive not ready
  9105.    BBH                      Undefined error
  9106.    CCH                      Write fault
  9107.    EOH                      Status error
  9108.    FFH                      Sense operation failed
  9109.    ──────────────────────────────────────────────────────────────────────────
  9110.  
  9111.  
  9112.    Figure 10-2.  The value of the disk status byte returned in register AH by
  9113.    service 01H.
  9114.  
  9115.  Service 02H (decimal 2): Read Disk Sectors
  9116.  
  9117.    Service 02H (decimal 2) reads one or more disk sectors into memory. If you
  9118.    want to read more than one sector, every sector must be on the same track
  9119.    and read/write head. This is largely because the ROM BIOS doesn't know how
  9120.    many sectors might be on a track, so it can't know when to switch from one
  9121.    head or track to another. Usually, this service is used for reading either
  9122.    individual sectors or an entire trackful of sectors for bulk operations
  9123.    such as DISKCOPY in DOS. Various registers are used for control
  9124.    information in a read operation. They are summarized in Figure 10-3.
  9125.  
  9126.    Parameters                           Status Results
  9127.    ──────────────────────────────────────────────────────────────────────────
  9128.    DL = drive number                    If CF = 0, then no error and AH = 0
  9129.  
  9130.    DH = head number                     If CF = 1, then error and AH contains
  9131.                                         service 01H status bits
  9132.  
  9133.    CH = cylinder number
  9134.    low-order 8 bits of cylinder
  9135.    number
  9136.  
  9137.    CL = sector number
  9138.    high-order 2 bits of cylinder number
  9139.    plus 6-bit sector number
  9140.  
  9141.    AL = number of sectors to be read
  9142.    ES:BX = address of buffer
  9143.    ──────────────────────────────────────────────────────────────────────────
  9144.  
  9145.    Figure 10-3.  The registers used for control information by the read,
  9146.    write, verify, and format services.
  9147.  
  9148.    DL contains the drive number, and DH contains the diskette side or
  9149.    fixed-disk read/write head number.
  9150.  
  9151.    CH and CL identify, for diskettes, the cylinder and sector number to be
  9152.    read. CH contains the cylinder number, which should be less than the total
  9153.    number of cylinders on the formatted diskette. (See Chapter 5 for a table
  9154.    of standard IBM formats.) Of course, the cylinder number can be higher
  9155.    with non-IBM formats or with some copy-protection schemes. CL contains the
  9156.    sector number.
  9157.  
  9158.    For fixed disks, there may be more than 256 cylinders, so the ROM BIOS
  9159.    requires you to specify a 10-bit cylinder number in CH and CL: You must
  9160.    place the 8 low-order bits of the cylinder number in CH. The 2 high-order
  9161.    bits of CL contain the 2 high-order bits of the cylinder number. The 6
  9162.    low-order bits of CL designate the sector number to be read. Don't forget
  9163.    that sectors are numbered from 1, unlike drives, cylinders, or heads
  9164.    (sides).
  9165.  
  9166.    AL contains the number of sectors to be read. For diskettes, this is
  9167.    normally either 1, 8, 9, 15, or 18. We are warned by IBM not to request 0
  9168.    sectors.
  9169.  
  9170.    ES:BX contains the buffer location. The location of the memory area where
  9171.    the data will be placed is provided by a segmented address given in this
  9172.    register pair.
  9173.  
  9174.    The data area should be big enough to accommodate as much as is read; keep
  9175.    in mind that while normal DOS sectors are 512 bytes, sectors can be as
  9176.    large as 1024 bytes. (See the format service that follows.) When this
  9177.    service reads more than one sector, it lays the sectors out in memory one
  9178.    right after another.
  9179.  
  9180.    CF (the carry flag) contains the error status of the operation. The result
  9181.    of the operation is actually reported through a combination of the carry
  9182.    flag and the AH register. If CF = 0, no error occurred, AH will also be 0,
  9183.    and, for a diskette, the number of sectors read will be returned in AL. If
  9184.    CF = 1, an error did occur, and AH will contain the status value detailed
  9185.    under service 01H, the status service.
  9186.  
  9187.    When using service 02H with a diskette drive or any other active diskette
  9188.    service, remember that the diskette-drive motor takes some time to reach a
  9189.    working speed and that none of these services waits for this to happen.
  9190.    Although our own experience with the ROM BIOS diskette services suggests
  9191.    that this is rarely a problem, IBM recommends that any program using these
  9192.    services try three times before assuming that an error is real and that it
  9193.    use the reset service between tries. The logic of the suggested operation
  9194.    is as follows (partly expressed in BASIC):
  9195.  
  9196.    10 ERROR COUNT = 0
  9197.    20 WHILE ERROR.COUNT < 3
  9198.    30 ' do read/write/verify/format operation
  9199.    40 ' error checking here: if no error goto 90
  9200.    50   ERROR.COUNT = ERROR.COUNT + 1
  9201.    60 ' do reset operation
  9202.    70 WEND
  9203.    80 ' act on error
  9204.    90 ' carry on after success
  9205.  
  9206.    Be sure to see the section on page 209 for the effect of the disk-base
  9207.    table on the reset operation.
  9208.  
  9209.  Service 03H (decimal 3): Write Disk Sectors
  9210.  
  9211.    Service 03H (decimal 3) writes one or more sectors to a disk──the reverse
  9212.    of service 02H. All registers, details, and comments given for service
  9213.    02H also apply to service 03H. (Also see Figure 10-3.) The disk sectors
  9214.    must be formatted before they can be written to.
  9215.  
  9216.  Service 04H (decimal 4) : Verify Disk Sectors
  9217.  
  9218.    Service 04H (decimal 4) verifies the contents of one or more disk sectors.
  9219.    This operation is not what many people think it is: No comparison is made
  9220.    between the data on the disk and the data in memory. The verification
  9221.    performed by this service simply checks that the sectors can be found and
  9222.    read and that the cyclical redundancy check (CRC) is correct. The CRC acts
  9223.    as a sophisticated parity check for the data in each sector and will
  9224.    detect most errors, such as lost or scrambled bits, very reliably.
  9225.  
  9226.    Most programmers use the verify service to check the results of a write
  9227.    operation after using service 03H, but you can verify any part of a disk
  9228.    at any time. The DOS FORMAT program, for example, verifies each track
  9229.    after it is formatted. However, many people regard verification as an
  9230.    unnecessary operation because the disk drives are so reliable and because
  9231.    ordinary error reporting works so well. Even DOS doesn't verify a write
  9232.    operation unless you ask it to with the VERIFY ON command.
  9233.  
  9234.    ──────────────────────────────────────────────────────────────────────────
  9235.    NOTE:
  9236.      It's worth pausing here to note that there is nothing unusual or
  9237.      alarming about having "bad tracks" marked on a disk, particularly a
  9238.      fixed disk. In fact, it is quite common for a fixed disk to have a few
  9239.      bad patches on it. The DOS FORMAT program notices bad tracks and marks
  9240.      them as such in the disk's file-allocation table. Later, the bad-track
  9241.      marking tells DOS that these areas should be bypassed. Bad tracks are
  9242.      also common on diskettes; with a diskette, unlike a fixed disk, you have
  9243.      the option of throwing away the defective media and using only perfect
  9244.      disks.
  9245.    ──────────────────────────────────────────────────────────────────────────
  9246.  
  9247.    The verify service operates exactly as do the read and write services and
  9248.    uses the same registers. The only difference between them is that the
  9249.    verify operation does not use any memory area and therefore does not use
  9250.    the register pair ES:BX.
  9251.  
  9252.  Service 05H (decimal 5) : Format Disk Track
  9253.  
  9254.    Service 05H (decimal 5) formats one track. The format service operates as
  9255.    do the read and write services except that you need not specify a sector
  9256.    number in CL. All other parameters are as shown in Figure 10-3.
  9257.  
  9258.    Because formatting is done one full track at a time, you cannot format
  9259.    individual sectors. However, on a diskette you can specify individual
  9260.    characteristics for each sector on a track.
  9261.  
  9262.    Every sector on a diskette track has 4 descriptive bytes associated with
  9263.    it. You specify these 4 bytes for each sector to be formatted by creating
  9264.    a table of 4-byte groups and passing the table's address in the register
  9265.    pair ES:BX. When you format a disk track, the 4-byte groups are written to
  9266.    the diskette immediately in front of the individual sectors in the track.
  9267.    The 4 bytes of data associated with a sector on the disk are known as
  9268.    address marks and are used by the disk controller to identify individual
  9269.    sectors during the read, write, and verify operations. The 4 bytes are
  9270.    referred to as C for cylinder, H for head, R for record (or sector
  9271.    number), and N for number of bytes per sector (also called the size code).
  9272.  
  9273.    When a sector is being read or written, the diskette controller searches
  9274.    the diskette track for the sector's ID, the essential part of which is R,
  9275.    the record or sector number. The cylinder and head parameters are not
  9276.    actually needed in this address mark because the read/write head is
  9277.    positioned mechanically at the proper track and the side is selected
  9278.    electronically, but they are recorded and tested as a safety check.
  9279.  
  9280.    The size code (N) can take on any one of the four standard values shown in
  9281.    Figure 10-4. The normal setting is code 2 (512 bytes).
  9282.  
  9283.    Sectors are numbered on the diskette in the order specified by R. On
  9284.    diskettes, the sectors are normally numbered in numeric sequence (unless
  9285.    rearranged for copy protection), but on fixed disks the order of the
  9286.    sectors can be rearranged (interleaved), either for better performance or
  9287.    to create timing differences for copy-protection purposes. The actual
  9288.    interleave used on a fixed disk depends on the capabilities of the
  9289.    disk-controller hardware. For example, the PC/XT's fixed disk has its
  9290.    sectors interleaved so that logically consecutive sectors are physically
  9291.    located six sectors apart.
  9292.  
  9293.    N              Sector Size (bytes)          Sector Size (KB)
  9294.    ──────────────────────────────────────────────────────────────────────────
  9295.    0               128                         1/8
  9296.    1               256                         1/4
  9297.    2               512                         1/2
  9298.    3               1024                        1
  9299.    ──────────────────────────────────────────────────────────────────────────
  9300.  
  9301.    Figure 10-4.  The four standard sizes of the N size code.
  9302.  
  9303.    To format a diskette track using service 05H, perform the following steps:
  9304.  
  9305.    1.  Call service 17H to inform the ROM BIOS what kind of diskette is to
  9306.        be formatted. (See page 208 for more about service 17H.) This service
  9307.        needs to be called only once.
  9308.  
  9309.    2.  Call service 18H to describe the diskette media to the ROM BIOS. (See
  9310.        page 209.)
  9311.  
  9312.    3.  Create a table of address marks for the track. There must be a 4-byte
  9313.        entry in the table for each sector. For example, for track 0, side 1
  9314.        of a typical nine-sector DOS diskette, the table would contain nine
  9315.        entries:
  9316.  
  9317.        0 1 1 2  0 1 2 2  0 1 3 2  ... 0 1 9 2
  9318.  
  9319.    4.  Call service 05H to format the track.
  9320.  
  9321.    The method for formatting a fixed-disk track is somewhat different. You
  9322.    should omit the calls to services 17H and 18H (steps 1 and 2 above)
  9323.    because there is no need to describe the disk media to the ROM BIOS. Also,
  9324.    with a PC/AT or PS/2, the table whose address you pass in 3 step has a
  9325.    format that consists only of alternating flag bytes (00H = good sector,
  9326.    80H = bad sector) and sector number (R) bytes. With a PC/XT, you don't
  9327.    need a table at all. Instead, you call service 05H with an interleave
  9328.    value in AL, and the ROM BIOS does the rest.
  9329.  
  9330.    You may want to verify the formatting process by following each call to
  9331.    service 05H with a call to service 04H.
  9332.  
  9333.    When a diskette track is formatted, the diskette drive pays attention to
  9334.    the diskette's index hole and uses it as a starting marker to format the
  9335.    track. The index hole is ignored in all other operations (read, write, or
  9336.    verify), and tracks are simply searched for by their address marks.
  9337.  
  9338.    Nothing in this format service specifies the initial data value written
  9339.    into each formatted sector of a diskette. That is controlled by the
  9340.    disk-base table. (See page 209.)
  9341.  
  9342.    ──────────────────────────────────────────────────────────────────────────
  9343.    NOTE:
  9344.      Service 05H should not be used with ESDI drives in PS/2s. Use service
  9345.      1AH instead.
  9346.    ──────────────────────────────────────────────────────────────────────────
  9347.  
  9348.    Using Service 05H for Copy Protection
  9349.  
  9350.    Diskette tracks can be formatted in all sorts of ways, but DOS can only
  9351.    read certain formats. Consequently, some copy-protection schemes are based
  9352.    on an unconventional format that prevents the ROM BIOS or the operating
  9353.    system from successfully reading and copying data. You can choose from
  9354.    several different copy-protection methods:
  9355.  
  9356.    ■  You can rearrange the order of the sectors, which alters the access
  9357.       time in a way that the copy-protection scheme can detect.
  9358.  
  9359.    ■  You can squeeze more sectors onto a track (10 is about the outside
  9360.       limit for 512-byte sectors on a 360 KB diskette).
  9361.  
  9362.    ■  You can simply leave out a sector number.
  9363.  
  9364.    ■  You can add a sector with an oddball address mark (for example, you can
  9365.       make C = 45 or R = 22).
  9366.  
  9367.    ■  You can specify one or more sectors to be an unconventional size.
  9368.  
  9369.    Any of these techniques can be used either for copy protection or for
  9370.    changing the operating characteristics of the diskette. Depending on what
  9371.    options are used, a conventionally formatted diskette may have its
  9372.    copy-protection characteristics completely hidden from DOS.
  9373.  
  9374.  Service 06H (decimal 6): Format PC/XT Fixed-Disk Track
  9375.  
  9376.    This service is provided only in the PC/XT fixed-disk ROM BIOS. This
  9377.    service commands the XT's fixed-disk controller to format a track in which
  9378.    the disk media is defective. The disk controller records which sectors are
  9379.    defective in a table located in a reserved cylinder. The register
  9380.    parameters are the same as those shown in Figure 10-3, except that
  9381.    register AL contains a sector interleave value and no address need be
  9382.    specified in ES:BX.
  9383.  
  9384.  Service 07H (decimal 7): Format PC/XT Fixed Disk
  9385.  
  9386.    This service, like service 06H, is supported only in the PC/XT fixed-disk
  9387.    ROM BIOS. It formats the entire fixed-disk drive, starting at the cylinder
  9388.    number specified in CH and CL. Register parameters for service 07H are the
  9389.    same as for service 05H (Figure 10-3), except that register AL contains a
  9390.    sector interleave value and no head number need be specified in register
  9391.    DH.
  9392.  
  9393.  Service 08H (decimal 8): Get Disk-Drive Parameters
  9394.  
  9395.    In the PC/AT and PS/2 BIOS, service 08H (decimal 8) returns disk-drive
  9396.    parameters for the drive whose number you specify in DL. DL reports the
  9397.    number of disk drives attached to the disk controller, so diskette and
  9398.    fixed-disk drive counts are reported separately. DH reports the maximum
  9399.    head number, CH returns the maximum cylinder number, and CL returns the
  9400.    highest valid sector number plus the 2 high-order bits of the maximum
  9401.    cylinder number.
  9402.  
  9403.    For diskette drives, the PC/AT ROM BIOS (after 1/10/84) and the PS/2 ROM
  9404.    BIOS also report the drive type in BL: 01H = 360 KB, 5-1/4 inch; 02H = 1.2
  9405.    MB, 5-1/4 inch; 03H = 720 KB, 3-1/2 inch; 04H = 1.44 MB, 3-1/2 inch.
  9406.  
  9407.  Service 09H (decimal 9): Initialize Fixed-Disk Parameter Tables
  9408.  
  9409.    Service 09H (decimal 9) establishes the disk-base tables for two
  9410.    fixed-disk drives for the PC/AT or PS/2 ROM BIOS. Call this service with a
  9411.    valid fixed-disk drive number in DL and with the interrupt 41H and 46H
  9412.    vectors containing the addresses of disk-base tables for two different
  9413.    fixed-disk drives. Because fixed disks are nonremovable, this service
  9414.    should only be used to install a "foreign" disk drive not recognized by
  9415.    the ROM BIOS or the operating system. For more details, see the IBM BIOS
  9416.    Interface Technical Reference Manual.
  9417.  
  9418.    ──────────────────────────────────────────────────────────────────────────
  9419.    NOTE:
  9420.      Do not use service 09H for PS/2 ESDI drives.
  9421.    ──────────────────────────────────────────────────────────────────────────
  9422.  
  9423.  Service 0AH and 0BH (decimal 10 and 11): Read and Write Long
  9424.  
  9425.    Service 0AH (decimal 10) reads, and service 0BH (decimal 11) writes,
  9426.    "long" sectors on PC/AT or PS/2 fixed disks. A long sector consists of a
  9427.    sector of data plus a 4- or 6-byte error correction code (ECC) that the
  9428.    fixed-disk controller uses for error checking and error correction of the
  9429.    sector's data. These services use the same register parameters as parallel
  9430.    services 02H and 03H.
  9431.  
  9432.    ──────────────────────────────────────────────────────────────────────────
  9433.    NOTE:
  9434.      The IBM BIOS Interface Technical Reference Manual states that services
  9435.      0AH and 0BH are "reserved for diagnostics," so stay away from these
  9436.      services unless you have a very good reason for using them.
  9437.    ──────────────────────────────────────────────────────────────────────────
  9438.  
  9439.  Service 0CH (decimal 12): Seek to Cylinder
  9440.  
  9441.    Service 0CH (decimal 12) performs a seek operation that positions the disk
  9442.    read/write heads at a particular cylinder on a fixed disk. Register DL
  9443.    provides the drive ID, DH provides the head number, and CH and CL provide
  9444.    the 10-bit cylinder number.
  9445.  
  9446.  Service 0DH (decimal 13): Alternate Fixed-Disk Reset
  9447.  
  9448.    For fixed-disk drives, this service is the same as service 00H (reset disk
  9449.    system) except that the ROM BIOS does not automatically reset the
  9450.    diskette-drive controller. This service is available only in the PC/AT and
  9451.    PS/2 ROM BIOS; it should not be used with the PS/2 ESDI drives.
  9452.  
  9453.  Service 10H (decimal 16): Test for Drive Ready
  9454.  
  9455.    Service 10H (decimal 16) tests to see if a fixed-disk drive is ready. The
  9456.    drive is specified in register DL and the status is returned in register
  9457.    AH.
  9458.  
  9459.  Service 11H (decimal 17): Recalibrate Drive
  9460.  
  9461.    Service 11H (decimal 17) recalibrates a fixed-disk drive. The drive is
  9462.    specified in register DL and the status is returned in register AH.
  9463.  
  9464.  Service 15H (decimal 21): Get Disk Type
  9465.  
  9466.    Service 15H (decimal 21) returns information about the type of disk drive
  9467.    installed in a PC/AT or PS/2. Given the drive ID in register DL, it
  9468.    returns in register AH one of four disk-type indicators. If AH = 00H, no
  9469.    drive is present for the specified drive ID; if AH = 01H, a diskette drive
  9470.    that cannot sense when the disk has been changed (typical of many PC and
  9471.    PC/XT disk drives) is installed; if AH = 02H, a diskette drive that can
  9472.    sense a change of disks (drives like the AT's high-capacity diskette
  9473.    drives) is installed; finally, if AH = 03H, a fixed-disk drive is
  9474.    installed. When the drive type is 3, the register pair CX:DX contains a
  9475.    4-byte integer that gives the total number of disk sectors on the drive.
  9476.  
  9477.  Service 16H (decimal 22): Diskette Change Status
  9478.  
  9479.    In the PC/AT and PS/2 ROM BIOS, service 16H (decimal 22) reports whether
  9480.    the diskette in the drive specified in DL was changed. The status is
  9481.    reported in AH (Figure 10-5).
  9482.  
  9483.    Remember several important points about service 16H. First, before you use
  9484.    this ROM BIOS service, call service 15H to ensure that the diskette-drive
  9485.    hardware can sense when a diskette is changed. Also, you should follow a
  9486.    call to service 16H with a call to service 17H (Set Diskette Type)
  9487.    whenever you detect a diskette change.
  9488.  
  9489.    Keep in mind that the hardware can only detect whether the diskette-drive
  9490.    door was opened; it cannot tell whether a different physical diskette was
  9491.    placed in the drive. You must still read data from the diskette to
  9492.    determine whether a different diskette is actually in the drive. Data such
  9493.    as a volume label, the root directory, or a file allocation table can help
  9494.    to uniquely identify a diskette.
  9495.  
  9496.    Value                    Meaning
  9497.    ──────────────────────────────────────────────────────────────────────────
  9498.    AH = 00H                 No diskette change.
  9499.    AH = 01H                 Service called with invalid parameter.
  9500.    AH = 06H                 Diskette has been changed.
  9501.    AH = 80H                 Diskette drive not ready.
  9502.    ──────────────────────────────────────────────────────────────────────────
  9503.  
  9504.    Figure 10-5.  Status values returned in AH by diskette service 16H.
  9505.  
  9506.  Service 17H (decimal 23): Set Diskette Type
  9507.  
  9508.    In the PC/AT and PS/2 ROM BIOS, service 17H (decimal 23) describes the
  9509.    type of diskette in use in a specified drive. Call this service with a
  9510.    drive ID in register DL and a diskette-type ID in AL. (See Figure 10-6.)
  9511.    The ROM BIOS resets the diskette change status if it was previously set.
  9512.    It then records the diskette type in an internal status variable that can
  9513.    be referenced by other ROM BIOS services.
  9514.  
  9515.    Value                    Meaning
  9516.    ──────────────────────────────────────────────────────────────────────────
  9517.    AL = 01H                 320/360 KB diskette in 360 KB drive
  9518.    AL = 02H                 360 KB diskette in 1.2 MB drive
  9519.    AL = 03H                 1.2 MB diskette in 1.2 MB drive
  9520.    AL = 04H                 720 KB diskette in 720 KB drive (PC/AT or PS/2)
  9521.                             or 720 KB or 1.44 MB diskette in 1.44 MB drive
  9522.                             (PS/2)
  9523.    ──────────────────────────────────────────────────────────────────────────
  9524.  
  9525.    Figure 10-6.  Diskette-type ID values for diskette service 17H.
  9526.  
  9527.  Service 18H (decimal 24): Set Media Type for Format
  9528.  
  9529.    Service 18H (decimal 24) describes the number of tracks and sectors per
  9530.    track to the ROM BIOS before it formats a diskette in a specified drive.
  9531.    These values are placed in registers CH, CL, and DL when you call this
  9532.    service (see Figure 10-3). This service is available only in the PC/AT
  9533.    and PS/2 ROM BIOS.
  9534.  
  9535.  Service 19H (decimal 25): Park Heads
  9536.  
  9537.    Service 19H (decimal 25) parks the drive heads for the PS/2 fixed disk
  9538.    whose drive ID you specify in register DL. Calling this function causes
  9539.    the disk controller to move the drive heads away from the portion of the
  9540.    disk media where data is stored. This is a good idea if you plan to move
  9541.    the computer because it may prevent mechanical damage to the heads or to
  9542.    the surfaces of the disk media. On the Reference Diskette that accompanies
  9543.    every PS/2, IBM supplies a utility program that uses this ROM BIOS service
  9544.    to park the heads.
  9545.  
  9546.  Service 1AH (decimal 26): Format ESDI Unit
  9547.  
  9548.    This service is provided only in the ROM BIOS of the ESDI (Enhanced Small
  9549.    Device Interface) adapter for high-capacity PS/2 fixed disks. It formats a
  9550.    fixed disk attached to this adapter. See the IBM BIOS Interface Technical
  9551.    Reference Manual for more details.
  9552.  
  9553.  
  9554.  Disk-Base Tables
  9555.  
  9556.    As we mentioned near the beginning of this chapter, the ROM BIOS maintains
  9557.    a set of disk-base tables that describe the capabilities of each diskette
  9558.    drive and fixed-disk drive in the computer. During system startup, the ROM
  9559.    BIOS associates an appropriate disk-base table with each fixed-disk drive.
  9560.    (In the PC/AT and PS/2s, a data byte in the nonvolatile CMOS RAM
  9561.    designates which of several ROM tables to use.) There is no reason to
  9562.    change the parameters in the fixed-disk tables once they have been set up
  9563.    by the ROM BIOS. Doing so may lead to garbled data on the disk.
  9564.  
  9565.    The situation is different in the case of diskette drives. The parameters
  9566.    in the disk-base table associated with a diskette drive may need to be
  9567.    updated to accommodate different diskette formats. We'll spend the next
  9568.    few pages describing the structure of a disk-base table for a diskette
  9569.    drive and showing how a modified table can be useful.
  9570.  
  9571.    The disk-base table comprises the 11 bytes shown in Figure 10-7.
  9572.  
  9573.    Bytes 0 and 1 are referred to as the specify bytes. They are part of the
  9574.    command strings sent to the diskette-drive controller, which in IBM's
  9575.    technical reference manuals is also called the NEC (Nippon Electric
  9576.    Company) controller. The 4 high-order bits of byte 0 specify the step-rate
  9577.    time (SRT), which is the time the drive controller allows for the drive
  9578.    heads to move from track to track. The default ROM BIOS SRT value for
  9579.    diskette drives is conservative; for some drives, DOS reduces this value
  9580.    to speed up drive performance.
  9581.  
  9582.    Byte 2 specifies how long the diskette motor is to be left running after
  9583.    each operation. The motor is left on in case the diskette is needed again.
  9584.    The value is in units of clock ticks (roughly 18.2 ticks per second). All
  9585.    versions of the table have this set to 37 (25H)──meaning that the motor
  9586.    stays on for about 2 seconds.
  9587.  
  9588.    Offset         Use
  9589.    ──────────────────────────────────────────────────────────────────────────
  9590.    00H            Specify byte 1: step-rate time, head-unload time
  9591.    01H            Specify byte 2: head-load time, DMA mode
  9592.    02H            Wait time until diskette motor turned off
  9593.    03H            Bytes per sector: 0 = 128; 1 = 256; 2 = 512; 3 = 1024
  9594.    04H            Last sector number
  9595.    05H            Gap length between sectors for read/write operations
  9596.    06H            Data length when sector length not specified
  9597.    07H            Gap length between sectors for formatting operations
  9598.    08H            Data value stored in formatted sectors
  9599.    09H            Head-settle time
  9600.    0AH            Motor start-up time
  9601.    ──────────────────────────────────────────────────────────────────────────
  9602.  
  9603.    Figure 10-7.  The use of the 11 bytes in the disk-base table for a
  9604.    diskette drive.
  9605.  
  9606.    Byte 3 gives the sector length code──the same N code used in the format
  9607.    operation. (See page 203 under service 05H.) This is normally set to 2,
  9608.    representing the customary sector length of 512 bytes. In any read, write,
  9609.    or verify operation, the length code in the disk base must be set to the
  9610.    proper value, especially when working with sectors of unconventional
  9611.    length.
  9612.  
  9613.    Byte 4 gives the sector number of the last sector on the track.
  9614.  
  9615.    Byte 5 specifies the gap size between sectors, which is used when reading
  9616.    or writing data. In effect, it tells the diskette-drive controller how
  9617.    long to wait before looking for the next sector's address marking so that
  9618.    it can avoid looking at nonsense on the diskette. This length of time is
  9619.    known as the search gap.
  9620.  
  9621.    Byte 6 is called the data transfer length (DTL) and is set to FFH (decimal
  9622.    255). This byte sets the maximum data length when the sector length is not
  9623.    specified.
  9624.  
  9625.    Byte 7 sets the gap size between sectors when a track is formatted.
  9626.    Naturally, it is bigger than the search gap at offset 5. The normal format
  9627.    gap-size value varies with the diskette drive. For example, the value is
  9628.    54H for the PC/AT's 1.2 MB drive and 6CH for 3-1/2-inch PS/2 diskette
  9629.    drives.
  9630.  
  9631.    Byte 8 provides the data value stored in each byte of the sectors when a
  9632.    diskette track is formatted. The default value is F6H, the division
  9633.    symbol. You can change it to anything you want, if you can think of a good
  9634.    reason to do so.
  9635.  
  9636.    Byte 9 sets the head-settle time, which is how long the system waits for
  9637.    vibration to end after seeking to a new track. This value also depends on
  9638.    the drive hardware. On the original PC, the value was 19H (25
  9639.    milliseconds), but the ROM BIOS default for the PC/AT 1.2 MB drive and the
  9640.    PS/2 diskette drives is only 0FH (15 milliseconds).
  9641.  
  9642.    Byte 0AH (decimal 10), the final byte of the disk-base table, sets the
  9643.    amount of time allowed for the diskette-drive motor to get up to speed and
  9644.    is measured in 1/8 seconds.
  9645.  
  9646.    It's fun to tinker with the disk-base values; there are enough of them to
  9647.    give you an opportunity for all sorts of excitement and mischief. To do
  9648.    this, you need to write a program that builds your customized disk-base
  9649.    table in a buffer in memory. Then tell the ROM BIOS to use your table by
  9650.    carrying out the following steps:
  9651.  
  9652.    1.  Save the segmented address of the current disk base table. (This is
  9653.        the value in the interrupt 1EH vector, 0000:0078H.)
  9654.  
  9655.    2.  Store the segmented address of your modified table in the interrupt
  9656.        1EH vector.
  9657.  
  9658.    3.  Call ROM BIOS disk service 00H to reset the disk system. The ROM BIOS
  9659.        will reinitialize the diskette-drive controller with parameters from
  9660.        your table.
  9661.  
  9662.    When you're finished, be sure to restore the address of the previous
  9663.    disk-base table and reset the disk system again.
  9664.  
  9665.  
  9666.  Comments and Examples
  9667.  
  9668.    In the last chapter, where we covered the ROM BIOS video services, we
  9669.    were able to recommend that you make direct use of the ROM BIOS services
  9670.    when DOS or your programming language does not provide the support you
  9671.    need. But in the case of the ROM BIOS disk services, things are different.
  9672.  
  9673.    For the disk operations that a program would normally want performed, the
  9674.    manipulation and supervision of disk input/output should be left to DOS
  9675.    and performed either through the conventional file services of a
  9676.    programming language or through the DOS services. (See Chapters 14
  9677.    through 18.) There are several reasons for this. The main reason is that
  9678.    it is far easier to let DOS do the work. The DOS facilities take care of
  9679.    all fundamental disk operations, including formatting and labeling disks,
  9680.    cataloging files, and basic read and write operations. Most of the time it
  9681.    isn't necessary to go any deeper into the system software. However, there
  9682.    are times when you may want to work with disk data in an absolute and
  9683.    precise way, usually for copy protection. This is when you should use the
  9684.    ROM BIOS services.
  9685.  
  9686.    For our example, we'll use C to call a couple of subroutines that use ROM
  9687.    BIOS functions 02H and 03H to read and write absolute disk sectors. We
  9688.    start by defining how we want the interface to look from the C side, which
  9689.    the following program illustrates. If you are not familiar with C and
  9690.    don't want to decipher this routine, you can pass it by and still get the
  9691.    full benefit by studying the assembly-language interface example that
  9692.    follows it.
  9693.  
  9694.    main()
  9695.    {
  9696.            unsigned char Buffer[512];      /* a 512-byte buffer for reading */
  9697.                                            /*  or writing one sector */
  9698.  
  9699.            int     Drive;
  9700.            int     C,H,R;                  /* address mark parameters */
  9701.            int     StatusCode;             /* status value returned by BIOS */
  9702.  
  9703.            StatusCode = ReadSector( Drive, C, H, R, (char far *)Buffer );
  9704.            StatusCode = WriteSector( Drive, C, H, R, (char far *)Buffer );
  9705.    }
  9706.  
  9707.    This C fragment shows how you would call the ROM BIOS read and write
  9708.    services from a high-level language. The functions ReadSector() and
  9709.    WriteSector() are two assembly-language routines that use interrupt 13H to
  9710.    interface with the ROM BIOS disk services. The parameters are familiar: C,
  9711.    H, and R are the cylinder, head, and sector numbers we described earlier.
  9712.    The C compiler passes the buffer address as a segment and offset because
  9713.    of the explicit type cast (char far *).
  9714.  
  9715.    The form of the assembly-language interface should be familiar if you read
  9716.    the general remarks in Chapter 8 on page 161 or studied the example in
  9717.    Chapter 9 on page 194. The assembly-language routines themselves copy the
  9718.    parameters from the stack into the registers. The trick is in how the
  9719.    cylinder number is processed: The 2 high-order bits of the 10-bit cylinder
  9720.    number are combined with the 6-bit sector number in CL.
  9721.  
  9722.    _TEXT           SEGMENT byte public 'CODE'
  9723.                    ASSUME  cs:_TEXT
  9724.  
  9725.                    PUBLIC  _ReadSector
  9726.    _ReadSector     PROC    near            ; routine to read one sector
  9727.  
  9728.                    push    bp
  9729.                    mov     bp,sp           ; address the stack through BP
  9730.  
  9731.                    mov     ah,2            ; AH = ROM BIOS service number 02h
  9732.                    call    DiskService
  9733.  
  9734.                    pop     bp              ; restore previous BP
  9735.                    ret
  9736.  
  9737.    _ReadSector     ENDP
  9738.  
  9739.                    PUBLIC  _WriteSector
  9740.    _WriteSector    PROC    near            ; routine to write one sector
  9741.  
  9742.                    push    bp
  9743.                    mov     bp,sp
  9744.  
  9745.                    mov     ah,3            ; AH = ROM BIOS service number 03h
  9746.                    call    DiskService
  9747.  
  9748.                    pop     bp
  9749.                    ret
  9750.  
  9751.    _WriteSector    ENDP
  9752.  
  9753.  
  9754.    DiskService     PROC    near            ; Call with AH = ROM BIOS service n
  9755.  
  9756.                    push    ax              ; save service number on stack
  9757.                    mov     dl,[bp+4]       ; DL = drive ID
  9758.                    mov     ax,[bp+6]       ; AX = cylinder number
  9759.                    mov     dh,[bp+8]       ; DH = head number
  9760.                    mov     cl,[bp+10]      ; CL = sector number
  9761.                    and     cl,00111111b    ; limit sector number to 6 bits
  9762.                    les     bx,[bp+12]      ; ES:BX -> buffer
  9763.  
  9764.                    ror     ah,1            ; move bits 8 and 9
  9765.                    ror     ah,1            ;  of cylinder number
  9766.                                            ;  to bits 6 and 7 of AH
  9767.                    and     ah,11000000b
  9768.                    mov     ch,al           ; CH = bits 0-7 of cylinder number
  9769.                    or      cl,ah           ; copy bits 8 and 9
  9770.                                            ;  of cylinder number
  9771.                                            ;  to bits 6 and 7 of CL
  9772.  
  9773.                    pop     ax              ; AH = ROM BIOS service number
  9774.                    mov     al,1            ; AL = 1 (# of sectors to read/writ
  9775.                    int     13h             ; call ROM BIOS service
  9776.  
  9777.                    mov     al,ah           ; leave return status
  9778.                    xor     ah,ah           ; # in AX
  9779.  
  9780.                    ret
  9781.  
  9782.    DiskService     ENDP
  9783.  
  9784.    _TEXT           ENDS
  9785.  
  9786.    Note how the code that copies the parameters from the stack to the
  9787.    registers is consolidated in a subroutine, DiskService. When you work with
  9788.    the ROM BIOS disk services, you'll find that you can often use subroutines
  9789.    similar to DiskService because most of the ROM BIOS disk services use
  9790.    similar parameter register assignments.
  9791.  
  9792.  
  9793.  
  9794.  ────────────────────────────────────────────────────────────────────────────
  9795.  Chapter 11  ROM BIOS Keyboard Services
  9796.  
  9797.    Accessing the Keyboard Services
  9798.      Service 00H (decimal 0): Read Next Keyboard Character
  9799.      Service 01H (decimal 1): Report Whether Character Ready
  9800.      Service 02H (decimal 2): Get Shift Status
  9801.      Service 03H (decimal 3): Set Typematic Rate and Delay
  9802.      Service 05H (decimal 5): Keyboard Write
  9803.      Service 10H (decimal 16): Extended Keyboard Read
  9804.      Service 11H (decimal 17): Get Extended Keystroke Status
  9805.      Service 12H (decimal 18): Get Extended Shift Status
  9806.  
  9807.    Comments and Example
  9808.  
  9809.    Although the ROM BIOS services for the keyboard are not as numerous or as
  9810.    complicated as those for the display screen (Chapter 9) and for diskette
  9811.    drives (Chapter 10), the ROM BIOS keyboard services are important enough
  9812.    to warrant their own chapter. All other ROM BIOS services are gathered
  9813.    together in Chapter 12.
  9814.  
  9815.  
  9816.  Accessing the Keyboard Services
  9817.  
  9818.    The keyboard services are invoked with interrupt 16H (decimal 22). As with
  9819.    all other ROM BIOS services, the keyboard services are selected according
  9820.    to the value in register AH. Figure 11-1 lists the ROM BIOS keyboard
  9821.    services.
  9822.  
  9823.    Service                  Description
  9824.    ──────────────────────────────────────────────────────────────────────────
  9825.    00H                      Read Next Keyboard Character.
  9826.    01H                      Report Whether Character Ready.
  9827.    02H                      Get Shift Status.
  9828.    03H                      Set Typematic Rate and Delay.
  9829.    05H                      Keyboard Write.
  9830.    10H                      Extended Keyboard Read.
  9831.    11H                      Get Extended Keystroke Status.
  9832.    12H                      Get Extended Shift Status.
  9833.    ──────────────────────────────────────────────────────────────────────────
  9834.  
  9835.    Figure 11-1.  The ROM BIOS keyboard services.
  9836.  
  9837.  Service 00H (decimal 0): Read Next Keyboard Character
  9838.  
  9839.    Service 00H (decimal 0) reports the next keyboard input character. If a
  9840.    character is ready in the ROM BIOS keyboard buffer, it is reported
  9841.    immediately. If not, the service waits until one is ready. As described on
  9842.    page 134, each keyboard character is reported as a pair of bytes, which
  9843.    we call the main and auxiliary bytes. The main byte, returned in AL, is
  9844.    either 0 for special characters (such as the function keys) or else an
  9845.    ASCII code for ordinary ASCII characters. The auxiliary byte, returned in
  9846.    AH, is either the character ID for special characters or the standard
  9847.    PC-keyboard scan code that identifies which key was pressed.
  9848.  
  9849.    If no character is waiting in the keyboard buffer when service 00H is
  9850.    called, the service waits──essentially freezing the program that called
  9851.    it──until a character does appear. The service we'll discuss next allows a
  9852.    program to test for keyboard input without the risk of suspending program
  9853.    execution.
  9854.  
  9855.    Contrary to what some versions of the IBM PC Technical Reference Manual
  9856.    suggest, services 00H and 01H apply to both ordinary ASCII characters and
  9857.    special characters, such as function keys.
  9858.  
  9859.  Service 01H (decimal 1): Report Whether Character Ready
  9860.  
  9861.    Service 01H (decimal 1) reports whether a keyboard input character is
  9862.    ready. This is a sneak-preview or look-ahead operation: Even though the
  9863.    character is reported, it remains in the keyboard input buffer of the ROM
  9864.    BIOS until it is removed by service 00H. The zero flag (ZF) is used as the
  9865.    signal: 1 indicates no input is ready; 0 indicates a character is ready.
  9866.    Take care not to be confused by the apparent reversal of the flag values──
  9867.    1 means no and 0 means yes, in this instance. When a character is ready
  9868.    (ZF = 0), it is reported in AL and AH, just as it is with service 00H.
  9869.  
  9870.    This service is particularly useful for two commonly performed program
  9871.    operations. One is test-and-go, where a program checks for keyboard action
  9872.    but needs to continue running if there is none. Usually, this is done to
  9873.    allow an ongoing process to be interrupted by a keystroke. The other
  9874.    common operation is clearing the keyboard buffer. Programs can generally
  9875.    allow users to type ahead, entering commands in advance; however, in some
  9876.    operations (for example, at safety-check points, such as "OK to end?")
  9877.    this practice can be unwise. In these circumstances, programs need to be
  9878.    able to flush the keyboard buffer, clearing it of any input. The keyboard
  9879.    buffer is flushed by using services 00H and 01H, as this program outline
  9880.    demonstrates:
  9881.  
  9882.    call service 01H to test whether a character is available in the
  9883.    keyboard buffer
  9884.    WHILE (ZF = 0)
  9885.            BEGIN
  9886.            call service 00H to remove character from keyboard buffer
  9887.            call service 01H to test for another character
  9888.            END
  9889.  
  9890.    Contrary to what some technical reference manuals suggest, services 00H
  9891.    and 01H apply to both ordinary ASCII characters and special characters,
  9892.    such as function keys.
  9893.  
  9894.  Service 02H (decimal 2): Get Shift Status
  9895.  
  9896.    Service 02H (decimal 2) reports the shift status in register AL. The shift
  9897.    status is taken bit by bit from the first keyboard status byte, which is
  9898.    kept at memory location 0040:0017H. Figure 11-2 describes the settings of
  9899.    each bit. (See page 137 for information about the other keyboard status
  9900.    byte at 0040:0018H.)
  9901.  
  9902.          Bit
  9903.    7 6 5 4 3 2 1 0          Meaning
  9904.    ──────────────────────────────────────────────────────────────────────────
  9905.    X . . . . . . .          Insert state: 1 = active
  9906.    . X . . . . . .          CapsLock: 1 = active
  9907.    . . X . . . . .          NumLock: 1 = active
  9908.    . . . X . . . .          ScrollLock: 1 = active
  9909.    . . . . X . . .          1 = Alt pressed
  9910.    . . . . . X . .          1 = Ctrl pressed
  9911.    . . . . . . X .          1 = Left Shift pressed
  9912.    . . . . . . . X          1 = Right Shift pressed
  9913.    ──────────────────────────────────────────────────────────────────────────
  9914.  
  9915.    Figure 11-2.  The keyboard status bits returned to register AL using
  9916.    keyboard service 02H.
  9917.  
  9918.    Generally, service 02H and the status bit information are not particularly
  9919.    useful. If you plan to do some fancy keyboard programming, however, they
  9920.    can come in handy. You'll frequently see them used in programs that do
  9921.    unconventional things, such as differentiating between the left and right
  9922.    Shift keys.
  9923.  
  9924.  Service 03H (decimal 3): Set Typematic Rate and Delay
  9925.  
  9926.    Service 03H (decimal 3) was introduced with the PCjr, but has been
  9927.    supported in both the PC/AT (in ROM BIOS versions dated 11/15/85 and
  9928.    later) and in all PS/2s. It lets you adjust the rate at which the
  9929.    keyboard's typematic function operates; that is, the rate at which a
  9930.    keystroke repeats automatically while you hold down a key. This service
  9931.    also lets you to adjust the typematic delay (the amount of time you can
  9932.    hold down a key before the typematic repeat function takes effect).
  9933.  
  9934.    To use this service, call interrupt 16H with AH = 03H, and AL = 05H. BL
  9935.    must contain a value between 00H and 1FH (decimal 31) that indicates the
  9936.    desired typematic rate (Figure 11-3). The value in BH specifies the
  9937.    typematic delay (Figure 11-4). The default typematic rate for the PC/AT
  9938.    is 10 characters per second; for PS/2s it is 10.9 characters per second.
  9939.    The default delay for both the PC/AT and PS/2s is 500 ms.
  9940.  
  9941.    ──────────────────────────────────────────────────────────────────────────
  9942.    00H = 30.0               0BH = 10.9              16H = 4.3
  9943.    01H = 26.7               0CH = 10.0              17H = 4.0
  9944.    02H = 24.0               0DH = 9.2               18H = 3.7
  9945.    03H = 21.8               0EH = 8.6               19H = 3.3
  9946.    04H = 20.0               0FH = 8.0               1AH = 3.0
  9947.    05H = 18.5               10H = 7.5               1BH = 2.7
  9948.    06H = 17.1               11H = 6.7               1CH = 2.5
  9949.    07H = 16.0               12H = 6.0               1DH = 2.3
  9950.    08H = 15.0               13H = 5.5               1EH = 2.1
  9951.    09H = 13.3               14H = 5.0               1FH = 2.0
  9952.    0AH = 12.0               15H = 4.6               20H through FFH -
  9953.                                                     Reserved
  9954.    ──────────────────────────────────────────────────────────────────────────
  9955.  
  9956.    Figure 11-3.  Values for register BL in keyboard service 03H. The rates
  9957.    shown are in characters per second.
  9958.  
  9959.    ──────────────────────────────────────────────────────────────────────────
  9960.    00H = 250
  9961.    01H = 500
  9962.    02H = 750
  9963.    03H = 1000
  9964.    04H through FFH - Reserved
  9965.    ──────────────────────────────────────────────────────────────────────────
  9966.  
  9967.    Figure 11-4.  Values for register BH in keyboard service 03H. The delay
  9968.    values shown are in milliseconds.
  9969.  
  9970.  Service 05H (decimal 5): Keyboard Write
  9971.  
  9972.    Service 05H (decimal 5) is handy because it lets you store keystroke data
  9973.    in the keyboard buffer as if a key were pressed. You must supply an ASCII
  9974.    code in register CL and a keyboard scan code in CH. The ROM BIOS places
  9975.    these codes into the keyboard buffer following any keystroke data that may
  9976.    already be present there.
  9977.  
  9978.    Service 05H lets a program process input as if it were typed at the
  9979.    keyboard. For example, if you call service 05H with the following data,
  9980.    the result is the same as if the keys R-U-N-Enter were pressed:
  9981.  
  9982.    CH = 13H, CL = 52H, call service 05H (the R key)
  9983.    CH = 16H, CL = 55H, call service 05H (the U key)
  9984.    CH = 31H, CL = 4EH, call service 05H (the N key)
  9985.    CH = 1CH, CL = 0DH, call service 05H (the Enter key)
  9986.  
  9987.    If your program did this when it detected that the F2 function key was
  9988.    pressed, the result would be the same as if the word RUN followed by the
  9989.    Enter key had been typed. (If you use BASIC, this should sound familiar.)
  9990.  
  9991.    Beware: The keyboard buffer can hold only 15 character codes, so you can
  9992.    call service 05H a maximum of 15 consecutive times before the buffer
  9993.    overflows and the function fails.
  9994.  
  9995.  Service 10H (decimal 16): Extended Keyboard Read
  9996.  
  9997.    Service 10H (decimal 16) performs the same function as service 00H, but
  9998.    lets you take full advantage of the 101/102-key keyboard: It returns ASCII
  9999.    character codes and keyboard scan codes for keys that don't exist on the
  10000.    older 84-key keyboard. For example, the extra F11 and F12 keys found on
  10001.    the 101/102-key keyboard are ignored by service 00H but can be read using
  10002.    service 10H.
  10003.  
  10004.    Another example: On the 101/102-key keyboard, an extra Enter key appears
  10005.    to the right of the numeric keypad. When this key is pressed, service 00H
  10006.    returns the same character code (0DH) and scan code (1CH) as it does for
  10007.    the standard Enter key. Service 10H lets you differentiate between the two
  10008.    Enter keys because it returns a different scan code (E0H) for the keypad
  10009.    Enter key.
  10010.  
  10011.  Service 11H (decimal 17): Get Extended Keystroke Status
  10012.  
  10013.    Service 11H (decimal 17) is analogous to service 01H, but it, too, lets
  10014.    you use the 101/102-key keyboard to full advantage. The scan codes
  10015.    returned in register AH by this service distinguish between different keys
  10016.    on the 101/102-key keyboard.
  10017.  
  10018.  Service 12H (decimal 18): Get Extended Shift Status
  10019.  
  10020.    Like services 10H and 11H, service 12H (decimal 18) provides additional
  10021.    support for the 101/102-key keyboard. Service 12H expands the function of
  10022.    service 02H to provide information on the extra shift keys provided on the
  10023.    101/102-key keyboard. This service returns the same value in register AL
  10024.    as service 02H (Figure 11-2), but it also returns an additional byte of
  10025.    flags in register AH (Figure 11-5).
  10026.  
  10027.    This extra byte indicates the status of each individual Ctrl and Alt key.
  10028.    It also indicates whether the Sys Req, Caps Lock, Num Lock, or Scroll Lock
  10029.    keys are currently pressed. This information lets you detect when a user
  10030.    presses any combination of these keys at the same time.
  10031.  
  10032.          Bit                Meaning
  10033.    7 6 5 4 3 2 1 0
  10034.    ──────────────────────────────────────────────────────────────────────────
  10035.    X . . . . . . .          Sys Req pressed
  10036.    . X . . . . . .          Caps Lock pressed
  10037.    . . X . . . . .          Num Lock pressed
  10038.    . . . X . . . .          Scroll Lock pressed
  10039.    . . . . X . . .          Right Alt pressed
  10040.    . . . . . X . .          Right Ctrl pressed
  10041.    . . . . . . X .          Left Alt pressed
  10042.    . . . . . . . X          Left Ctrl pressed
  10043.    ──────────────────────────────────────────────────────────────────────────
  10044.  
  10045.    Figure 11-5.  Extended keyboard status bits returned in register AH by
  10046.    keyboard service 12H.
  10047.  
  10048.  
  10049.  Comments and Example
  10050.  
  10051.    If you are in a position to choose between the keyboard services of your
  10052.    programming language or the ROM BIOS keyboard services, you could safely
  10053.    and wisely use either one. Although in some cases there are arguments
  10054.    against using the ROM BIOS services directly, as with the diskette
  10055.    services, those arguments do not apply as strongly to the keyboard
  10056.    services. However, as always, you should fully examine the potential of
  10057.    the DOS services before resorting to the ROM BIOS services; you may find
  10058.    all you need there, and the DOS services are more long-lived in the
  10059.    ever-changing environments of personal computers.
  10060.  
  10061.    Most programming languages depend on the DOS services for their keyboard
  10062.    operations, a factor that has some distinct advantages. One advantage is
  10063.    that the DOS services allow the use of the standard DOS editing operations
  10064.    on string input (input that is not acted on until the Enter key is
  10065.    pressed). Provided that you do not need input control of your own, it can
  10066.    save you a great deal of programming effort (and user education) to let
  10067.    DOS handle the string input, either directly through the DOS services or
  10068.    indirectly through your language's services. But if you need full control
  10069.    of keyboard input, you'll probably end up using the ROM BIOS routines in
  10070.    the long run. Either way, the choice is yours.
  10071.  
  10072.    Another advantage to using the DOS keyboard services is that the DOS
  10073.    services can redirect keyboard input so that characters are read from a
  10074.    file instead of the keyboard. If you rely on the ROM BIOS keyboard
  10075.    services, you can't redirect keyboard input. (Chapters 16 and 17 contain
  10076.    information on input/output redirection.)
  10077.  
  10078.    For our assembly-language example of the use of keyboard services, we'll
  10079.    get a little fancier than we have in previous examples and show you a
  10080.    complete buffer flusher. This routine will perform the action outlined
  10081.    under keyboard service 01H, the report-whether-character-ready service.
  10082.  
  10083.    _TEXT           SEGMENT byte public 'CODE'
  10084.                    ASSUME  cs:_TEXT
  10085.  
  10086.                    PUBLIC  _kbclear
  10087.    _kbclear        PROC    near
  10088.  
  10089.                    push    bp
  10090.                    mov     bp,sp
  10091.  
  10092.    L01:            mov     ah,1            ; test whether buffer is empty
  10093.                    int     16h
  10094.                    jz      L02             ; if so, exit
  10095.  
  10096.                    mov     ah,0
  10097.                    int     16h             ; otherwise, discard data
  10098.                    jmp     L01             ; .. and loop
  10099.  
  10100.    L02:            pop     bp
  10101.                    ret
  10102.  
  10103.    _kbclear        ENDP
  10104.  
  10105.    _TEXT           ENDS
  10106.  
  10107.    The routine works by using interrupt 16H, service 01H to check whether the
  10108.    keyboard buffer is empty. If no characters exist in the buffer, service
  10109.    01H sets the zero flag, and executing the instruction JZ L02 causes the
  10110.    routine to exit by branching to the instruction labeled L02. If the buffer
  10111.    still contains characters, however, service 01H clears the zero flag, and
  10112.    the JZ L02 instruction doesn't jump. In this case the routine continues to
  10113.    the instructions that call service 00H to read a character from the
  10114.    buffer. Then the process repeats because the instruction JMP L01 transfers
  10115.    control back to label L01. Sooner or later, of course, the repeated calls
  10116.    to service 00H empty the buffer, service 01H sets the zero flag, and the
  10117.    routine terminates.
  10118.  
  10119.    Among the new things this buffer-flusher routine illustrates is the use of
  10120.    labels and branching. When we discussed the generalities of
  10121.    assembly-language interface routines in Chapter 8, we mentioned that an
  10122.    ASSUME CS statement is necessary in some circumstances, and you see one in
  10123.    action here.
  10124.  
  10125.    The ASSUME directive in this example tells the assembler that the labels
  10126.    in the code segment (that is, labels that would normally be addressed
  10127.    using the CS register) do indeed lie in the segment whose name is _TEXT.
  10128.    This may seem obvious, since no other segments appear in this routine.
  10129.  
  10130.    Nevertheless, it is possible to write assembly-language routines in which
  10131.    labels in one segment are addressed relative to some other segment; in
  10132.    such a case, the ASSUME directive would not necessarily reference the
  10133.    segment within which the labels appear. In later chapters you'll see
  10134.    examples of this technique, but here the only segment to worry about is
  10135.    the _TEXT segment, and the ASSUME directive makes this fact explicit.
  10136.  
  10137.  
  10138.  
  10139.  ────────────────────────────────────────────────────────────────────────────
  10140.  Chapter 12  Miscellaneous Services
  10141.  
  10142.    RS-232 Serial Communications Services
  10143.      Service 00H (decimal 0): Initialize Serial Port
  10144.      Service 01H (decimal 1): Send Out One Character
  10145.      Service 02H (decimal 2): Receive One Character
  10146.      Service 03H (decimal 3): Get Serial Port Status
  10147.      Service 04H (decimal 4): Initialize Extended Serial Port
  10148.      Service 05H (decimal 5): Control Extended Communications Port
  10149.  
  10150.    Miscellaneous System Services
  10151.      Service 00H (decimal 0): Turn On Cassette Motor
  10152.      Service 01H (decimal 1): Turn Off Cassette Motor
  10153.      Service 02H (decimal 2): Read Cassette Data Blocks
  10154.      Service 03H (decimal 3): Write Cassette Data Blocks
  10155.      Service 21H (decimal 33): Read or Write PS/2 POST Error Log
  10156.      Service 83H (decimal 131): Start or Cancel Interval Timer
  10157.      Service 84H (decimal 132): Read Joystick Input
  10158.      Service 86H (decimal 134): Wait During a Specified Interval
  10159.      Service 87H (decimal 135): Protected-Mode Data Move
  10160.      Service 88H (decimal 136): Get Extended Memory Size
  10161.      Service 89H (decimal 137): Switch to Protected Mode
  10162.      Service C0H (decimal 192): Get System Configuration Parameters
  10163.      Service C1H (decimal 193): Get ROM BIOS Extended Data Segment
  10164.      Service C2H (decimal 194): Pointing-Device Interface
  10165.      Service C3H (decimal 195): Enable/Disable Watchdog Timer
  10166.      Service C4H (decimal 196): Programmable Option Select
  10167.  
  10168.    ROM BIOS Hooks
  10169.      Service 4FH (decimal 79): Keyboard Intercept
  10170.      Service 80H (decimal 128): Device Open
  10171.      Service 81H (decimal 129): Device Close
  10172.      Service 82H (decimal 130): Program Termination
  10173.      Service 85H (decimal 133): Sys Req Keystroke
  10174.      Service 90H (decimal 144): Device Busy
  10175.      Service 91H (decimal 145): Interrupt Complete
  10176.  
  10177.    Printer Services
  10178.      Service 00H (decimal 0): Send 1 Byte to Printer
  10179.      Service 01H (decimal 1): Initialize Printer
  10180.      Service 02H (decimal 2): Get Printer Status
  10181.  
  10182.    Other Services
  10183.      Interrupt 05H (decimal 5): Print-Screen Service
  10184.      Interrupt 11H (decimal 17): Equipment-List Service
  10185.      Interrupt 12H (decimal 18): Memory-Size Service
  10186.      Interrupt 18H (decimal 24): ROM BASIC Loader Service
  10187.      Interrupt 19H (decimal 25): Bootstrap Loader Service
  10188.      Interrupt 1AH (decimal 26): Time-of-Day Services
  10189.  
  10190.    In this chapter, we'll be covering all ROM BIOS services that are either
  10191.    not important enough or not complex enough to warrant their own chapters:
  10192.    RS-232 serial communications services, system services, ROM BIOS hooks,
  10193.    and printer services. We'll also cover some services that are odd enough
  10194.    to be considered miscellaneous, even in a chapter of miscellany.
  10195.  
  10196.  
  10197.  RS-232 Serial Communications Services
  10198.  
  10199.    This section discusses the RS-232 asynchronous serial communications port
  10200.    services in the ROM BIOS. Before we begin describing the ROM BIOS services
  10201.    in detail, you need to know a few important things about the serial
  10202.    communications port, particularly the terminology. We assume you have a
  10203.    basic understanding of data communications, but if you discover that you
  10204.    don't understand the following information, turn to one of the many
  10205.    specialty books on communications for some background information.
  10206.  
  10207.    Many words are used to describe the RS-232 data path in and out of the
  10208.    computer. One of the most common is port. However, this use of the word
  10209.    port is completely different from our previous use of the word. Throughout
  10210.    most of this book, we have used port to refer to the addressable paths
  10211.    used by the 8088 microprocessor to talk to other parts of the computer
  10212.    within the confines of the computer's circuitry. All references to port
  10213.    numbers, the BASIC statements INP and OUT, and the assembly-language
  10214.    operations IN and OUT refer to these addressable ports. The RS-232
  10215.    asynchronous serial communications port differs because it is a
  10216.    general-purpose I/O path, which can be used to interconnect many kinds of
  10217.    information-processing equipment outside the computer. Typically, the
  10218.    serial ports are used for telecommunications (meaning a telephone
  10219.    connection through a modem) or to send data to a serial-type printer.
  10220.  
  10221.    Four serial communications services are common to all IBM models. These
  10222.    services are invoked with interrupt 14H (decimal 20), selected through
  10223.    register AH, and numbered 00H through 03H. (See Figure 12-1.) The PS/2
  10224.    ROM BIOS contains two additional services that provide extended support
  10225.    for the more capable PS/2 serial port.
  10226.  
  10227.    The original design of the IBM personal computers allowed up to seven
  10228.    serial ports to be added, although a computer rarely uses more than one or
  10229.    two. The PS/2 ROM BIOS explicitly supports only four serial ports. No
  10230.    matter how many serial ports exist, the serial port number is specified in
  10231.    the DX register for all ROM BIOS serial communications services. The first
  10232.    serial port is indicated by 00H in DX.
  10233.  
  10234.    Service            Description
  10235.    ──────────────────────────────────────────────────────────────────────────
  10236.    00H                Initialize Serial Port.
  10237.    01H                Send Out One Character.
  10238.    02H                Receive One Character.
  10239.    03H                Get Serial Port Status.
  10240.    04H                Initialize Extended Serial Port.
  10241.    05H                Control Extended Communication Port.
  10242.    ──────────────────────────────────────────────────────────────────────────
  10243.  
  10244.    Figure 12-1.  The RS-232 serial port services available through interrupt
  10245.    14H (decimal 20).
  10246.  
  10247.  Service 00H (decimal 0): Initialize Serial Port
  10248.  
  10249.    Service 00H (decimal 0) sets the various RS-232 parameters and initializes
  10250.    the serial port. It sets four parameters: the baud rate, the parity, the
  10251.    number of stop bits, and the character size (also called the word length).
  10252.    The parameters are combined into one 8-bit code, which is placed in the AL
  10253.    register with the format shown in Figure 12-2. The bit settings for each
  10254.    code are shown in Figure 12-3. When the service is finished, the
  10255.    communication port status is reported in AX, just as it is for service
  10256.    03H. (See service 03H for the details.)
  10257.  
  10258.          Bit
  10259.    7 6 5 4 3 2 1 0          Use
  10260.    ──────────────────────────────────────────────────────────────────────────
  10261.    X X X . . . . .          Baud-rate code
  10262.    . . . X X . . .          Parity code
  10263.    . . . . . X . .          Stop-bit code
  10264.    . . . . . . X X          Character-size code
  10265.    ──────────────────────────────────────────────────────────────────────────
  10266.  
  10267.    Figure 12-2.  The bit order of the serial port parameters passed in
  10268.    register AL to service 00H.
  10269.  
  10270.    ──────────────────────────────────────────────────────────────────────────
  10271.    NOTE:
  10272.      Although it is painfully slow, 300 baud used to be the most commonly
  10273.      used baud rate for personal computers using modems. A rate of 1200 baud
  10274.      is now the most common, particularly for serious applications that
  10275.      require faster transmission, but widespread use of at least 2400 baud
  10276.      communications is inevitable.
  10277.    ──────────────────────────────────────────────────────────────────────────
  10278.  
  10279.                             BAUD RATE
  10280.     Bit
  10281.    7 6 5                    Value                   Bits per Second
  10282.    ──────────────────────────────────────────────────────────────────────────
  10283.    0 0 0                    0                        110
  10284.    0 0 1                    1                        150
  10285.    0 1 0                    2                        300
  10286.    0 1 1                    3                        600
  10287.    1 0 0                    4                       1200
  10288.    1 0 1                    5                       2400
  10289.    1 1 0                    6                       4800
  10290.    1 1 1                    7                       9600
  10291.    ──────────────────────────────────────────────────────────────────────────
  10292.  
  10293.                             STOP BITS
  10294.    Bit                      Value                   Meaning
  10295.    2
  10296.    ──────────────────────────────────────────────────────────────────────────
  10297.    0                        0                       One
  10298.    1                        1                       Two
  10299.    ──────────────────────────────────────────────────────────────────────────
  10300.  
  10301.                             PARITY
  10302.    Bit                      Value                   Meaning
  10303.    4 3
  10304.    ──────────────────────────────────────────────────────────────────────────
  10305.    0 0                      0                       None
  10306.    0 1                      1                       Odd parity
  10307.    1 0                      2                       None
  10308.    1 1                      3                       Even parity
  10309.    ──────────────────────────────────────────────────────────────────────────
  10310.  
  10311.                             CHARACTER SIZE
  10312.    Bit                      Value                   Meaning
  10313.    1 0
  10314.    ──────────────────────────────────────────────────────────────────────────
  10315.    0 0                      0                       Not used
  10316.    0 1                      1                       Not used
  10317.    1 0                      2                       7-bit
  10318.    1 1                      3                       8-bit
  10319.    ──────────────────────────────────────────────────────────────────────────
  10320.  
  10321.    Figure 12-3.  The bit settings for the four serial port parameters for
  10322.    service 00H.
  10323.  
  10324.  Service 01H (decimal 1): Send Out One Character
  10325.  
  10326.    Service 01H (decimal 1) transmits one character out the serial port
  10327.    specified in DX. When you call service 01H, you place the character to be
  10328.    transmitted in AL. When service 01H returns, it reports the status of the
  10329.    communications port. If AH = 00H, then the service was successful.
  10330.    Otherwise bit 7 of AH indicates that an error occurred, and the other bits
  10331.    of AH report the type of error. These bits are outlined in the discussion
  10332.    of service 03H, the status service.
  10333.  
  10334.    The error report supplied through this service has one anomaly: Because
  10335.    bit 7 reports that an error has occurred, it is not available to indicate
  10336.    a time-out error (as the details in service 03H would suggest).
  10337.    Consequently, when this service or service 02H reports an error, the
  10338.    simplest and most reliable way to check the nature of the error is to use
  10339.    the complete status report given by service 03H, rather than the
  10340.    less-complete status code returned with the error through services 01H and
  10341.    02H.
  10342.  
  10343.  Service 02H (decimal 2): Receive One Character
  10344.  
  10345.    Service 02H (decimal 2) receives one character from the communications
  10346.    line specified in DX and returns it in the AL register. The service waits
  10347.    for a character or any signal that indicates the completion of the
  10348.    service, such as a time-out. AH reports the success or failure of the
  10349.    service in bit 7, as explained in the discussion of service 01H. Again,
  10350.    consider the advice under service 01H for error handling and see service
  10351.    03H for the error codes.
  10352.  
  10353.  Service 03H (decimal 3): Get Serial Port Status
  10354.  
  10355.    Service 03H (decimal 3) returns the complete serial port status in the AX
  10356.    register. The 16 status bits in AX are divided into two groups: AH reports
  10357.    the line status (which is also reported when errors occur with services
  10358.    01H and 02H), and AL reports the modem status, when applicable. Figure
  10359.    12-4 contains the bit codings of the status bits. Some codes report
  10360.    errors, and others simply report a condition.
  10361.  
  10362.    ──────────────────────────────────────────────────────────────────────────
  10363.    NOTE:
  10364.      One special bit of information about the time-out error (AH, bit 7) is
  10365.      worth noting: The earliest version of the ROM BIOS for the original PC
  10366.      had a programming error that caused a serial-port time-out to be
  10367.      reported as a transfer-shift-register-empty/break-detect-error
  10368.      combination (bits 01010000 rather than 10000000). This has been
  10369.      corrected on all subsequent versions of the ROM BIOS, but it has caused
  10370.      many communications programs to treat these error codes skeptically. You
  10371.      may want to keep this in mind. See page 63 for details on identifying
  10372.      the ROM BIOS version dates and machine ID codes.
  10373.    ──────────────────────────────────────────────────────────────────────────
  10374.  
  10375.          Bit
  10376.    7 6 5 4 3 2 1 0          Meaning (when set to 1)
  10377.    ──────────────────────────────────────────────────────────────────────────
  10378.    AH Register (line status)
  10379.    1 . . . . . . .          Time-out error
  10380.    . 1 . . . . . .          Transfer shift register empty
  10381.    . . 1 . . . . .          Transfer holding register empty
  10382.    . . . 1 . . . .          Break-detect error
  10383.    . . . . 1 . . .          Framing error
  10384.    . . . . . 1 . .          Parity error
  10385.    . . . . . . 1 .          Overrun error
  10386.    . . . . . . . 1          Data ready
  10387.  
  10388.    AL Register (modem status)
  10389.    1 . . . . . . .          Received line signal detect
  10390.    . 1 . . . . . .          Ring indicator
  10391.    . . 1 . . . . .          Data-set-ready
  10392.    . . . 1 . . . .          Clear-to-send
  10393.    . . . . 1 . . .          Delta receive line signal detect
  10394.    . . . . . 1 . .          Trailing-edge ring detector
  10395.    . . . . . . 1 .          Delta data-set-ready
  10396.    . . . . . . . 1          Delta clear-to-send
  10397.    ──────────────────────────────────────────────────────────────────────────
  10398.  
  10399.    Figure 12-4.  The bit coding for the status bytes returned in register AX
  10400.    by service 03H.
  10401.  
  10402.  Service 04H (decimal 4): Initialize Extended Serial Port
  10403.  
  10404.    Service 04H (decimal 4) is available only in the PS/2 ROM BIOS. It expands
  10405.    the capabilities of service 00H to provide support for the PS/2's improved
  10406.    serial ports. If you compare service 04H with service 00H, you'll find
  10407.    that the four serial port initialization parameters passed in AL in
  10408.    service 00H are separated into four registers in service 04H (Figure
  10409.    12-5). Also, service 04H returns both modem and line status in register
  10410.    AX, exactly as service 03H does. Because service 04H has these expanded
  10411.    capabilities, you should generally use it instead of service 00H for PS/2
  10412.    serial port initialization.
  10413.  
  10414.                             BREAK (register AL)
  10415.    Value                    Meaning
  10416.    ──────────────────────────────────────────────────────────────────────────
  10417.    00H                      No break
  10418.    01H                      Break
  10419.    ──────────────────────────────────────────────────────────────────────────
  10420.  
  10421.                             PARITY (register BH)
  10422.    Value                    Meaning
  10423.    ──────────────────────────────────────────────────────────────────────────
  10424.    00H                      None
  10425.    01H                      Odd
  10426.    02H                      Even
  10427.    03H                      Stick parity odd
  10428.    04H                      Stick parity even
  10429.    ──────────────────────────────────────────────────────────────────────────
  10430.  
  10431.                             BAUD RATE (register CL)
  10432.    Value                    Meaning
  10433.    ──────────────────────────────────────────────────────────────────────────
  10434.    00H                      110 baud
  10435.    01H                      150 baud
  10436.    02H                      300 baud
  10437.    03H                      600 baud
  10438.    04H                      1200 baud
  10439.    05H                      2400 baud
  10440.    06H                      4800 baud
  10441.    07H                      9600 baud
  10442.    08H                      19,200 baud
  10443.    ──────────────────────────────────────────────────────────────────────────
  10444.  
  10445.                             STOP BITS (register BL)
  10446.    Value                    Meaning
  10447.    ──────────────────────────────────────────────────────────────────────────
  10448.    00H                      One
  10449.    01H                      Two (for word length = 6, 7, or 8)
  10450.                             11/2 (for word length = 5)
  10451.    ──────────────────────────────────────────────────────────────────────────
  10452.  
  10453.                             WORD LENGTH (register CH)
  10454.    Value                    Meaning
  10455.    ──────────────────────────────────────────────────────────────────────────
  10456.    00H                      5 bits
  10457.    01H                      6 bits
  10458.    02H                      7 bits
  10459.    03H                      8 bits
  10460.    ──────────────────────────────────────────────────────────────────────────
  10461.  
  10462.    Figure 12-5.  Register values for serial port initialization with
  10463.    interrupt 14H, service 04H. (Register DX contains a serial port number
  10464.    between 0 and 3.)
  10465.  
  10466.  Service 05H (decimal 5): Control Extended Communications Port
  10467.  
  10468.    This service, provided only by the PS/2 ROM BIOS, lets you read from or
  10469.    write to the modem control register of a specified serial communications
  10470.    port. When you call service 05H with AL = 00H and a serial port number in
  10471.    DX, service 05H returns with register BL containing the value in the modem
  10472.    control register of the specified serial port. When you call service 05H
  10473.    with AL = 01H, the ROM BIOS copies the value you pass in register BL into
  10474.    the modem control register for the specified port. In both cases, service
  10475.    05H returns the modem status and line status in registers AL and AH, as
  10476.    does service 03H.
  10477.  
  10478.  
  10479.  Miscellaneous System Services
  10480.  
  10481.    The miscellaneous system services provided through interrupt 15H are
  10482.    indeed miscellaneous. (See Figure 12-6.) Many are intended primarily for
  10483.    writers of operating-system software. Most application programmers will
  10484.    find little use for these services in their programs, because the
  10485.    functions provided are better carried out by calls to the operating system
  10486.    than they are through the ROM BIOS. Some of these services, such as the
  10487.    pointing-device interface (subservice C2H), provide functionality not
  10488.    otherwise available in the ROM BIOS or in DOS; others are obsolete and
  10489.    virtually unusable.
  10490.  
  10491. ╓┌─┌──────────────────┌──────────────────────────────────────────────────────╖
  10492.    Service            Description
  10493.    ──────────────────────────────────────────────────────────────────────────
  10494.    00H                Turn On Cassette Motor.
  10495.    01H                Turn Off Cassette Motor.
  10496.    02H                Read Cassette Data Blocks.
  10497.    03H                Write Cassette Data Blocks.
  10498.    21H                Read or Write PS/2 Power-On Self-Test Error Log.
  10499.    4FH                Keyboard Intercept.
  10500.    80H                Device Open.
  10501.    81H                Device Close.
  10502.    Service            Description
  10503.    ──────────────────────────────────────────────────────────────────────────
  10504.   81H                Device Close.
  10505.    82H                Program Termination.
  10506.    83H                Start or Cancel Interval Timer.
  10507.    84H                Read Joystick Input.
  10508.    85H                Sys Req Keystroke.
  10509.    86H                Wait During a Specified Interval.
  10510.    87H                Protected-Mode Data Move.
  10511.    88H                Get Extended Memory Size.
  10512.    89H                Switch to Protected Mode.
  10513.    90H                Device Busy.
  10514.    91H                Interrupt Complete.
  10515.    C0H                Get System Configuration Parameters.
  10516.    C1H                Get Extended BIOS Data Segment.
  10517.    C2H                Pointing-Device Interface.
  10518.    C3H                Enable/Disable Watchdog Timer.
  10519.    C4H                Programmable Option Select.
  10520.    ──────────────────────────────────────────────────────────────────────────
  10521.  
  10522.  
  10523.    Figure 12-6.  Miscellaneous system services available through interrupt
  10524.    15H.
  10525.  
  10526.    The four cassette tape services are used when working with the cassette
  10527.    tape connection, which is a part of only two PC models: the original PC
  10528.    and the now-defunct PCjr. The cassette port was created with the original
  10529.    PC on the assumption that a demand might exist for it. None did, and it
  10530.    has remained almost totally unused. Nevertheless, IBM does support the use
  10531.    of the cassette port, both through the ROM BIOS services discussed here
  10532.    and through BASIC, which lets you read and write either data or BASIC
  10533.    programs on standard audio cassette tape.
  10534.  
  10535.    The cassette port never proved worthwhile, however. Nobody sells PC
  10536.    programs on tape, and nobody has found much use for the cassette port,
  10537.    given the convenience of diskettes and hard disks.
  10538.  
  10539.  Service 00H (decimal 0): Turn On Cassette Motor
  10540.  
  10541.    Service 00H (decimal 0) turns on the cassette motor, which is not an
  10542.    automatic operation of the ROM BIOS services as it is with the diskette
  10543.    services. Any program that is using this service can expect a slight delay
  10544.    while the motor starts.
  10545.  
  10546.  Service 01H (decimal 1): Turn Off Cassette Motor
  10547.  
  10548.    Service 01H (decimal 1) turns off the cassette motor. This is not an
  10549.    automatic operation of the ROM BIOS services as it is with the diskette
  10550.    services.
  10551.  
  10552.  Service 02H (decimal 2): Read Cassette Data Blocks
  10553.  
  10554.    Service 02H (decimal 2) reads one or more cassette data blocks. Cassette
  10555.    data is transferred in standard-size 256-byte blocks, just as diskette
  10556.    data normally uses a standard 512-byte sector. The number of bytes to be
  10557.    read is placed in the CX register. Although data is placed on tape in
  10558.    256-byte blocks, any number of bytes can be read or written. Consequently,
  10559.    the number of bytes placed in the CX register need not be a multiple of
  10560.    256. The register pair ES:BX is used as a pointer to the memory area where
  10561.    the data is to be placed.
  10562.  
  10563.    After the service is completed, DX contains the actual number of bytes
  10564.    read, ES:BX points to the byte immediately after the last byte
  10565.    transferred, and the carry flag (CF) is set or cleared to report the
  10566.    success or failure of the operation. On failure, AH returns an error code.
  10567.    (See Figure 12-7.)
  10568.  
  10569.    Code               Meaning
  10570.    ──────────────────────────────────────────────────────────────────────────
  10571.    01H                Cyclical redundancy check (CRC) error
  10572.    02H                Lost data transitions: bit signals scrambled
  10573.    04H                No data found on tape
  10574.    ──────────────────────────────────────────────────────────────────────────
  10575.  
  10576.    Figure 12-7.  The error code returned by service 02H in register AH if the
  10577.    CF indicates a failure to read the data blocks.
  10578.  
  10579.  Service 03H (decimal 3): Write Cassette Data Blocks
  10580.  
  10581.    Service 03H (decimal 3) writes one or more cassette data blocks of 256
  10582.    bytes each. (See service 02H.) As with service 02H, the CX register gives
  10583.    the count of bytes requested, and ES:BX points to the data area in memory.
  10584.    If the amount of data being written is not a multiple of 256 bytes, the
  10585.    last data block is padded out to full size.
  10586.  
  10587.    After the service is completed, CX should contain 00H, and ES:BX should
  10588.    point just past the last memory byte that was written.
  10589.  
  10590.    Curiously, no error signals are provided for this service, essentially
  10591.    because a cassette tape recorder can't inform the computer of any
  10592.    difficulties. This forces the ROM BIOS to write data in blind faith that
  10593.    all is well. Needless to say, it would be a good idea to read back any
  10594.    data written, just to check it.
  10595.  
  10596.  Service 21H (decimal 33): Read or Write PS/2 POST Error Log
  10597.  
  10598.    Service 21H (decimal 33) is used internally by the ROM BIOS power-on
  10599.    self-test (POST) routines in PS/2s with the Micro Channel bus to keep
  10600.    track of hardware initialization errors. You will rarely, if ever, find
  10601.    use for this service in your own applications.
  10602.  
  10603.  Service 83H (decimal 131): Start or Cancel Interval Timer
  10604.  
  10605.    This service lets a program set a specified time interval and lets the
  10606.    program check a flag to show when the interval expires. The program should
  10607.    call this service with AL = 00H, with the address of a flag byte in
  10608.    registers ES and BX, and with the time interval in microseconds in
  10609.    registers CX and DX. The high-order 16 bits of the interval should be in
  10610.    CX; the low-order 16 bits in DX.
  10611.  
  10612.    Initially, the flag byte should be 00H. When the time interval elapses,
  10613.    the ROM BIOS sets this byte to 80H. The program can thus inspect the flag
  10614.    byte at its own convenience to determine when the time interval has
  10615.    elapsed:
  10616.  
  10617.    Clear the flag byte
  10618.    Call service 83H to start the interval timer
  10619.    WHILE   (flag byte = 00H)
  10620.            BEGIN
  10621.            (do something useful)
  10622.            END
  10623.  
  10624.    The ROM BIOS interval timer uses the system time-of-day clock, which ticks
  10625.    about 1024 times per second, so the timer's resolution is approximately
  10626.    976 microseconds.
  10627.  
  10628.  Service 84H (decimal 132): Read Joystick Input
  10629.  
  10630.    Service 84H (decimal 132) provides a consistent interface for programs
  10631.    that use a joystick or a related input device connected to IBM's Game
  10632.    Control Adapter. When you call this service with DX = 00H, the ROM BIOS
  10633.    reports the adapter's four digital switch input values in bits 4 through 7
  10634.    of register AL. Calling service 84H with DX = 01H instructs the BIOS to
  10635.    return the adapter's four resistive input values in registers AX, BX, CX,
  10636.    and DX.
  10637.  
  10638.    Service 84H is not supported on the IBM PC or in the original PC/XT BIOS
  10639.    (dated 11/08/82). Be sure to check the computer's model identification and
  10640.    ROM BIOS revision date before you rely on this BIOS service in a program.
  10641.  
  10642.  Service 86H (decimal 134): Wait During a Specified Interval
  10643.  
  10644.    Like service 83H, service 86H (decimal 134) lets a program set a specified
  10645.    time interval to wait. Unlike service 83H, however, service 86H suspends
  10646.    operation of the program that calls it until the specified time interval
  10647.    has elapsed. Control returns to the program only when the wait has
  10648.    completed or if the hardware timer is unavailable.
  10649.  
  10650.  Service 87H (decimal 135): Protected-Mode Data Move
  10651.  
  10652.    A program running in real mode can use service 87H to transfer data to or
  10653.    from extended (protected-mode) memory on a PC/AT or PS/2 Model 50, 60, or
  10654.    80. This service is designed to be used by a protected-mode operating
  10655.    system. The IBM-supplied VDISK utility also uses this function to copy
  10656.    data to and from a virtual disk in extended memory. See the IBM BIOS
  10657.    Interface Technical Reference Manual for details.
  10658.  
  10659.  Service 88H (decimal 136): Get Extended Memory Size
  10660.  
  10661.    Service 88H (decimal 136) returns the amount of extended (protected-mode)
  10662.    memory installed in a PC/AT or PS/2 Model 50, 60, or 80. The value, in
  10663.    kilobytes, is returned in register AX.
  10664.  
  10665.    The amount of extended memory is established by the ROM BIOS POST
  10666.    routines. It includes extended memory installed beyond the first megabyte;
  10667.    that is, memory starting at 10000:0000H. Lotus/Intel/Microsoft "expanded"
  10668.    memory is not included in the value returned by service 88H.
  10669.  
  10670.  Service 89H (decimal 137): Switch to Protected Mode
  10671.  
  10672.    Service 89H (decimal 137) is provided by the ROM BIOS as an aid to
  10673.    configuring an 80286-based computer (PC/AT, PS/2 Model 50 or 60) or an
  10674.    80386-based computer (PS/2 Model 80) for protected-mode operation. This
  10675.    ROM BIOS service is intended for operating systems that run in protected
  10676.    mode. To use this service, you must be thoroughly acquainted with
  10677.    protected-mode programming techniques. See the IBM BIOS Interface
  10678.    Technical Reference Manual for details.
  10679.  
  10680.  Service C0H (decimal 192): Get System Configuration Parameters
  10681.  
  10682.    Service C0H (decimal 192) returns the address of a table of descriptive
  10683.    information pertaining to the hardware and BIOS configuration of a PC/AT
  10684.    (in ROM BIOS versions dated 6/10/85 and later) or PS/2. Figure 12-8 shows
  10685.    the structure of the table. You can find the meaning of the model and
  10686.    submodel bytes in Chapter 3, page 64.
  10687.  
  10688.    Offset         Size           Contents
  10689.    ──────────────────────────────────────────────────────────────────────────
  10690.    0              2 bytes        Size of configuration information table
  10691.    2              1 byte         Model byte
  10692.    3              1 byte         Submodel byte
  10693.    4              1 byte         ROM BIOS revision level
  10694.    5              1 byte         Feature information byte:
  10695.                                  Bit 7:  Fixed-disk BIOS uses DMA Channel 3
  10696.                                  Bit 6:  Cascaded interrupt level 2 (IRQ2)
  10697.                                  Bit 5:  Real-time clock present
  10698.                                  Bit 4:  BIOS keyboard intercept implemented
  10699.                                  Bit 3:  Wait for external event supported
  10700.                                  Bit 2:  Extended BIOS data area allocated
  10701.                                  Bit 1:  Micro Channel bus present
  10702.                                  Bit 0:  (Reserved)
  10703.    ──────────────────────────────────────────────────────────────────────────
  10704.  
  10705.    Figure 12-8.  System configuration information returned by service C0H.
  10706.  
  10707.  Service C1H (decimal 193): Get ROM BIOS Extended Data Segment
  10708.  
  10709.    Service C1H (decimal 193) returns the segment address of the ROM BIOS
  10710.    extended data area. The ROM BIOS clears the carry flag and returns the
  10711.    segment value in register ES if an extended BIOS data segment is in use.
  10712.    Otherwise, service C1H returns with the carry flag set.
  10713.  
  10714.    The ROM BIOS uses the extended data area for transient storage of data.
  10715.    For example, when you pass the address of a pointing-device interface
  10716.    subroutine to the BIOS, the BIOS stores this address in its extended data
  10717.    area.
  10718.  
  10719.  Service C2H (decimal 194): Pointing-Device Interface
  10720.  
  10721.    Service C2H (decimal 194) is the ROM BIOS interface to the built-in PS/2
  10722.    pointing-device controller. This interface makes it easy to use an IBM
  10723.    PS/2 mouse.
  10724.  
  10725.    To use the interface, you must write a short subroutine to which the ROM
  10726.    BIOS can pass packets of status information about the pointing device.
  10727.    Your subroutine should examine the data in each packet and respond
  10728.    appropriately, for example by moving a cursor on the screen. The
  10729.    subroutine must exit with a far return without changing the contents of
  10730.    the stack.
  10731.  
  10732.    To use the ROM BIOS pointing-device interface, carry out the following
  10733.    sequence of steps:
  10734.  
  10735.    1.  Pass the address of your subroutine to the BIOS (subservice 07H).
  10736.  
  10737.    2.  Initialize the interface (subservice 05H).
  10738.  
  10739.    3.  Enable the pointing device (subservice 00H).
  10740.  
  10741.    At this point, the BIOS begins sending packets of status information to
  10742.    your subroutine. The BIOS places each packet on the stack and calls your
  10743.    subroutine with a far CALL so that the stack is formatted when the
  10744.    subroutine gets control as in Figure 12-9. The low-order byte of the X
  10745.    and Y data words contains the number of units the pointing device has
  10746.    moved since the previous packet of data was sent. (The Z data byte is
  10747.    always 0.) The status byte contains sign, overflow, and button
  10748.    information. (See Figure 12-10.)
  10749.  
  10750.    ┌────────────────┐
  10751.    │    Status      │
  10752.    ├────────────────┤──── SP + 10
  10753.    │    X data      │
  10754.    ├────────────────┤──── SP + 8
  10755.    │    Y data      │
  10756.    ├────────────────┤──── SP + 6
  10757.    │    Z data      │
  10758.    ├────────────────┤──── SP + 4
  10759.    │                │
  10760.    │ Return address │
  10761.    │                │
  10762.    └────────────────┘──── SP
  10763.  
  10764.    Figure 12-9.  Pointing-device data packet.
  10765.  
  10766.    Bit                      Meaning
  10767.    ──────────────────────────────────────────────────────────────────────────
  10768.    0                        Set if left button pressed
  10769.    1                        Set if right button pressed
  10770.    2─3                      (Reserved)
  10771.    4                        Set if X data is negative
  10772.    5                        Set if Y data is negative
  10773.    6                        Set if X data overflows
  10774.    7                        Set if Y data overflows
  10775.    ──────────────────────────────────────────────────────────────────────────
  10776.  
  10777.    Figure 12-10.  Status byte in pointing-device data packet.
  10778.  
  10779.    When you use service C2H, the value you pass in register AL selects one of
  10780.    eight available subservices. (See Figure 12-11.) The actual register
  10781.    contents for each subservice are in Chapter 13, page 284.
  10782.  
  10783.    Subservice               Description
  10784.    ──────────────────────────────────────────────────────────────────────────
  10785.    00H                      Enable/disable pointing device.
  10786.    01H                      Reset pointing device.
  10787.    02H                      Set sample rate.
  10788.    03H                      Set resolution.
  10789.    04H                      Get pointing-device type.
  10790.    05H                      Initialize pointing device.
  10791.    06H                      Extended commands.
  10792.    07H                      Pass device-driver address to ROM BIOS.
  10793.    ──────────────────────────────────────────────────────────────────────────
  10794.  
  10795.    Figure 12-11.  Subservices available in the BIOS pointing-device interface
  10796.    (interrupt 15H, service C2H).
  10797.  
  10798.  Service C3H (decimal 195): Enable/Disable Watchdog Timer
  10799.  
  10800.    Service C3H (decimal 195) provides a consistent interface to the watchdog
  10801.    timer in the PS/2 models 50, 60, and 80. It lets an operating system
  10802.    enable the watchdog timer with a specified timeout interval or disable the
  10803.    timer. Because the watchdog timer is intended specifically for use in
  10804.    operating-system software, this ROM BIOS service will rarely be useful in
  10805.    your applications.
  10806.  
  10807.  Service C4H (decimal 196): Programmable Option Select
  10808.  
  10809.    Like many other interrupt 15H services, service C4H (decimal 196) is
  10810.    intended for use by operating system software. This service provides a
  10811.    consistent interface to the Programmable Option Select feature of the
  10812.    Micro Channel architecture in the PS/2 models 50, 60, and 80.
  10813.  
  10814.  
  10815.  ROM BIOS Hooks
  10816.  
  10817.    The ROM BIOS in the PC/AT and in the PS/2s provides a number of hooks.
  10818.    These hooks are implemented as interrupt 15H "services," but to use them
  10819.    you must write an interrupt 15H handler that processes only these services
  10820.    and passes all other interrupt 15H service requests to the ROM BIOS. (See
  10821.    Figure 12-12.) This arrangement lets different components of the BIOS
  10822.    communicate with each other and with operating-system or user-written
  10823.    programs in a consistent manner.
  10824.  
  10825.    The ROM BIOS hooks are intended primarily for use in operating systems and
  10826.    in programs written to augment operating-system or BIOS functions.
  10827.    However, neither DOS nor OS/2 uses these BIOS hooks, and few program
  10828.    applications have reason to. Still, you might find it worthwhile to
  10829.    examine what the ROM BIOS hooks do, if only to get an idea of how the ROM
  10830.    BIOS is put together and how an operating system can interact with it.
  10831.  
  10832.                 .                         ─┐
  10833.                 .                          │
  10834.                 .                          │
  10835.                 mov     ah,ServiceNumber   │
  10836.                 int     15h                ├─ Executed within ROM BIOS
  10837.                 .                          │
  10838.                 .                          │
  10839.                 .                          │
  10840.                                           ─┘          ─┐
  10841.    Userhandler  PROC  far  ; interrupt 15H vector      │
  10842.                            ; points here               │
  10843.                                                        │
  10844.                 .                                      │
  10845.                 .                                      │
  10846.                 .                                      │
  10847.                 cmp     ah,ServiceNumber               │
  10848.                 je      Service                        ├─ User-written
  10849.                 jmp     (to previous INT 15H handler)  │  interupt 15H
  10850.                                                        │  handler
  10851.    Service                                             │
  10852.                 .                                      │
  10853.                 .       (do something useful)          │
  10854.                 .                                      │
  10855.                 iret                                   │
  10856.    Userhandler  ENDP                                  ─┘
  10857.  
  10858.    Figure 12-12.  How the ROM BIOS hooks can be used.
  10859.  
  10860.  Service 4FH (decimal 79): Keyboard Intercept
  10861.  
  10862.    In the PC/AT ROM BIOS (dated 06/10/85 and later) and in the PS/2 ROM BIOS,
  10863.    the keyboard interrupt handler (that is, the handler for hardware
  10864.    interrupt 09H) executes interrupt 15H with AH = 4FH and with AL equal to
  10865.    the keyboard scan code. This action has little effect: The ROM BIOS
  10866.    interrupt 15H, service 4FH (decimal 79) handler returns with the carry
  10867.    flag set, and the interrupt 09H handler continues processing the
  10868.    keystroke.
  10869.  
  10870.    If you write an interrupt handler for interrupt 15H, however, you can hook
  10871.    service 4FH and process keystrokes yourself. Install your handler by
  10872.    storing its segmented address in the interrupt 15H vector. (Be sure to
  10873.    save the previous contents of the interrupt 15H vector.) Your interrupt
  10874.    15H handler would do the following:
  10875.  
  10876.    IF (AH<>4FH)
  10877.            jump to default interrupt 15H handler
  10878.    ELSE
  10879.            process keyboard scan code in AL
  10880.            set or reset carry flag
  10881.            exit from interrupt handler
  10882.  
  10883.    If your handler processes the scan code in AL, it must either set or reset
  10884.    the carry flag before it returns control to the ROM BIOS interrupt 09H
  10885.    handler. Setting the carry flag indicates that the BIOS interrupt 09H
  10886.    handler should continue processing the scan code in AL: Clearing the carry
  10887.    flag causes the BIOS handler to exit without processing the scan code.
  10888.  
  10889.    The problem with using the ROM BIOS keyboard intercept is that other
  10890.    programs, including DOS itself, can and do process keystrokes before the
  10891.    ROM BIOS interrupt 09H handler ever has a chance to issue interrupt 15H.
  10892.    (These programs do this by pointing the interrupt 09H vector to their own
  10893.    handlers instead of to the default ROM BIOS handler.) Because your program
  10894.    can't determine if this is happening, you cannot rely on the ROM BIOS
  10895.    keyboard intercept to be called for every keystroke.
  10896.  
  10897.  Service 80H (decimal 128): Device Open
  10898.  
  10899.    This hook lets programs determine when a particular hardware device is
  10900.    available for input or output. An installable device driver can issue
  10901.    interrupt 15H with AH = 80H to inform an operating system that the device
  10902.    was opened. The operating system's interrupt 15H handler can inspect BX
  10903.    for an identifying value for the device and CX for an ID value of the
  10904.    program that opened the device.
  10905.  
  10906.  Service 81H (decimal 129): Device Close
  10907.  
  10908.    Like service 80H, this service is provided for programs that establish
  10909.    input/output connections to hardware devices to communicate with an
  10910.    operating system. Service 81H (decimal 129) is called by such a program
  10911.    with a device ID value in register BX and a program ID value in CX. An
  10912.    operating system's interrupt 15H handler can inspect these values to
  10913.    determine that a particular device was closed for input/output by a
  10914.    particular program.
  10915.  
  10916.  Service 82H (decimal 130): Program Termination
  10917.  
  10918.    Service 82H (decimal 130) is provided by the ROM BIOS so that a program
  10919.    can signal its own termination to an operating system. When a program
  10920.    executes interrupt 15H with AH = 82H and an ID value in BX, the operating
  10921.    system can handle the interrupt and thus be informed that the program
  10922.    terminated.
  10923.  
  10924.  Service 85H (decimal 133): Sys Req Keystroke
  10925.  
  10926.    When you press the Sys Req key on an 84-key keyboard or Alt-Sys Req on a
  10927.    101/102-key keyboard, the ROM BIOS keyboard interrupt handler executes
  10928.    interrupt 15H with AH = 85H. You can detect when this key is pressed by
  10929.    hooking interrupt 15H and inspecting the value in AH.
  10930.  
  10931.    When the Sys Req key is first pressed, the ROM BIOS issues interrupt 15H
  10932.    with AH = 85H and AL = 00H. When the key is released, the BIOS executes
  10933.    interrupt 15H with AH = 85H and AL = 01H. Thus the structure of an
  10934.    interrupt 15H handler that detects Sys Req keystrokes would be as follows:
  10935.  
  10936.    IF (AH<>85H)
  10937.                    jump to previous interrupt 15H handler
  10938.    ELSE IF (AL = 00H)
  10939.                    process Sys Req keystroke
  10940.         ELSE
  10941.                    process Sys Req key release
  10942.         exit from interrupt handler
  10943.  
  10944.  Service 90H (decimal 144): Device Busy
  10945.  
  10946.    This service lets a device driver alert an operating system to the
  10947.    beginning of an input or output operation. An operating system's interrupt
  10948.    15H handler processes this information (for example) by preventing
  10949.    subsequent input/output to the device until the device signals, with
  10950.    service 91H, that it is no longer busy.
  10951.  
  10952.    The ROM BIOS device drivers for disks, the keyboard, and the printer all
  10953.    issue appropriate service 90H (decimal 144) interrupts. Each device is
  10954.    identified by a value in register AL. (See Figure 12-13.) These ID values
  10955.    are selected according to the following guidelines:
  10956.  
  10957.    ■  00H─7FH: Non-reentrant devices that can process only one I/O request at
  10958.       a time sequentially.
  10959.  
  10960.    ■  80H─BFH: Reentrant devices that can handle multiple I/O requests at
  10961.       once.
  10962.  
  10963.    ■  C0H─FFH: Devices that expect the operating system to wait for a
  10964.       predetermined period of time before returning control to the device.
  10965.       The operating system's interrupt 15H handler must set the carry flag to
  10966.       indicate that the wait has been carried out.
  10967.  
  10968.    Value                    Meaning
  10969.    ──────────────────────────────────────────────────────────────────────────
  10970.    00H                      Fixed disk
  10971.    01H                      Diskette
  10972.    02H                      Keyboard
  10973.    03H                      Pointing device
  10974.    80H                      Network
  10975.    FCH                      PS/2 fixed-disk reset
  10976.    FDH                      Diskette-drive motor start
  10977.    FEH                      Printer
  10978.    ──────────────────────────────────────────────────────────────────────────
  10979.  
  10980.    Figure 12-13.  Device identification values for interrupt 15H, services
  10981.    90H and 91H.
  10982.  
  10983.  Service 91H (decimal 145): Interrupt Complete
  10984.  
  10985.    Devices that use service 90H to notify an operating system that they are
  10986.    busy can subsequently use service 91H (decimal 145) to signal that an
  10987.    input/output operation has been completed. The identification value passed
  10988.    in AL should be the same as the value passed in service 90H.
  10989.  
  10990.  
  10991.  Printer Services
  10992.  
  10993.    The ROM BIOS printer services support printer output through the parallel
  10994.    printer adapter. The three ROM BIOS printer services are invoked with
  10995.    interrupt 17H (decimal 23), requested through the AH register, and
  10996.    numbered 00H through 02H. (See Figure 12-14.) The general PC-family
  10997.    design allows more than one printer to be installed, so a printer number
  10998.    must be specified in register DX for all these services.
  10999.  
  11000.    Service                  Description
  11001.    ──────────────────────────────────────────────────────────────────────────
  11002.    00H                      Send One Byte to Printer.
  11003.    01H                      Initialize Printer.
  11004.    02H                      Get Printer Status.
  11005.    ──────────────────────────────────────────────────────────────────────────
  11006.  
  11007.    Figure 12-14.  The three ROM BIOS printer services invoked through
  11008.    interrupt 17H (decimal 23).
  11009.  
  11010.  Service 00H (decimal 0): Send 1 Byte to Printer
  11011.  
  11012.    Service 00H (decimal 0) sends the byte you specify to the printer. When
  11013.    the service is completed, AH is then set to report the printer status (see
  11014.    service 02H), which can be used to determine the success or failure of
  11015.    the operation. See the special notes on printer time-out under service
  11016.    02H.
  11017.  
  11018.  Service 01H (decimal 1): Initialize Printer
  11019.  
  11020.    Service 01H (decimal 1) initializes the printer. To do this, the service
  11021.    simply sends two control codes (08H and 0CH) to the printer control port.
  11022.    As with the other two services, the printer status is reported in AH.
  11023.  
  11024.  Service 02H (decimal 2): Get Printer Status
  11025.  
  11026.    Service 02H (decimal 2) reports the printer status in the AH register. The
  11027.    individual bit codes are shown in Figure 12-15.
  11028.  
  11029.    The printer time-out has caused some difficulty in the IBM personal
  11030.    computers. Any I/O driver needs to set a time limit for a response from
  11031.    the device being controlled. Ideally, this time limit should be short
  11032.    enough to ensure that an unresponsive device can be reported in a timely
  11033.    manner. Unfortunately, one normal printer operation can take a
  11034.    surprisingly long time: a page eject ("skip to the top of the next page").
  11035.    The time allowed varies from version to version of the ROM BIOS. Treat a
  11036.    time-out signal with care.
  11037.  
  11038.          Bit
  11039.    7 6 5 4 3 2 1 0          Meaning (when set to 1)
  11040.    ──────────────────────────────────────────────────────────────────────────
  11041.    1 . . . . . . .          Printer not busy (0 = busy)
  11042.    . 1 . . . . . .          Acknowledgment from printer
  11043.    . . 1 . . . . .          Out-of-paper signal
  11044.    . . . 1 . . . .          Printer selected
  11045.    . . . . 1 . . .          I/O error
  11046.    . . . . . 1 . .          Not used
  11047.    . . . . . . 1 .          Not used
  11048.    . . . . . . . 1          Time-out
  11049.    ──────────────────────────────────────────────────────────────────────────
  11050.  
  11051.    Figure 12-15.  The printer status bits reported in the AH register by
  11052.    services 00H, 01H, and 02H.
  11053.  
  11054.  
  11055.  Other Services
  11056.  
  11057.    We now come to the grab bag of all other ROM BIOS services. (See Figure
  11058.    12-16.) Some of these services are intended for use in program
  11059.    applications; others are more likely to be used in operating-system
  11060.    software. The following sections describe these six service interrupts.
  11061.  
  11062.    Interrupt                Description
  11063.    Hex   Dec
  11064.    ──────────────────────────────────────────────────────────────────────────
  11065.    05H    5                 Print-Screen Service
  11066.    11H   17                 Equipment-List Service
  11067.    12H   18                 Memory-Size Service
  11068.    18H   24                 ROM BASIC Loader Service
  11069.    19H   25                 Bootstrap Loader Service
  11070.    1AH   26                 Time-of-Day Services
  11071.    ──────────────────────────────────────────────────────────────────────────
  11072.  
  11073.    Figure 12-16.  Six miscellaneous ROM BIOS services supported by IBM, and
  11074.    their associated interrupts.
  11075.  
  11076.  Interrupt 05H (decimal 5): Print-Screen Service
  11077.  
  11078.    Interrupt 05H (decimal 5) activates the print-screen service: The keyboard
  11079.    support routines generate interrupt 05H in response to the Shift-PrtSc
  11080.    combination; any other programs that want to perform a print-screen
  11081.    operation can safely and conveniently do so by generating interrupt 05H.
  11082.  
  11083.    The print-screen service will maintain the current cursor position on the
  11084.    screen and successfully print any printable characters from the screen in
  11085.    either text or graphics mode. It uses both the standard video services
  11086.    (those that waltz the cursor around the screen and read characters from
  11087.    the screen buffer) and the standard printer services.
  11088.  
  11089.    This service directs all its output to printer number 0, the default
  11090.    printer. There are no input or output registers for this service. However,
  11091.    a status code is available at low-memory location 0050:0000H. (See page
  11092.    61.) If the byte at that location has a value of FFH (decimal 255), then
  11093.    a previous print-screen operation was not completed successfully. A value
  11094.    of 00H indicates that no error occurred, and that the print-screen
  11095.    operation is ready to go. A value of 01H indicates that a print-screen
  11096.    operation is currently in progress; any request for a second one will be
  11097.    ignored.
  11098.  
  11099.    The ROM BIOS print-screen routine cannot print images drawn on the screen
  11100.    in graphics modes. If you want to produce a printed screen snapshot in
  11101.    CGA-compatible graphics modes, use the DOS utility program GRAPHICS. This
  11102.    program installs a memory-resident, graphics-mode print-screen routine
  11103.    that hooks interrupt 05H. Once you execute GRAPHICS, pressing Shift-PrtSc
  11104.    or executing interrupt 05H while in a graphics mode will cause the
  11105.    graphics-mode print-screen routine to run.
  11106.  
  11107.  Interrupt 11H (decimal 17): Equipment-List Service
  11108.  
  11109.    Interrupt 11H (decimal 17) reports what equipment is installed in the
  11110.    computer. This report contains the same information stored at low-memory
  11111.    location 0040:0010H. (See Chapter 3, page 55.) The report is coded as
  11112.    shown in Figure 12-17, in the bits of a 16-bit word, which is placed in
  11113.    register AX. See interrupt 12H for a related service.
  11114.  
  11115.    The equipment information is gathered on an as-accurate-as-possible basis
  11116.    and may not be exactly correct. Different methods are used for acquiring
  11117.    the information in the various models.
  11118.  
  11119.    The equipment list is determined only once at power-up time and is then
  11120.    left in memory. This means that you can change the equipment list under
  11121.    software control. For example, you could take some equipment off line so
  11122.    that it is not used. However, modifying the equipment list is risky
  11123.    business──don't bet on its success. See interrupt 19H for comments on how
  11124.    to modify the equipment list and get reliable results.
  11125.  
  11126. ╓┌─┌───────────────────────────────────────────────────────┌─────────────────
  11127.                             Bit
  11128.    15 14 13 12 11 10  9  8   7  6  5  4  3  2  1  0        Meaning
  11129.    ───────────────────────────────────────────────────────────────────────────
  11130.     X  X  .  .  .  .  .  .   .  .  .  .  .  .  .  .        Number of printers
  11131.     .  .  X  .  .  .  .  .   .  .  .  .  .  .  .  .        (Reserved)
  11132.                             Bit
  11133.    15 14 13 12 11 10  9  8   7  6  5  4  3  2  1  0        Meaning
  11134.    ───────────────────────────────────────────────────────────────────────────
  11135.    .  .  X  .  .  .  .  .   .  .  .  .  .  .  .  .        (Reserved)
  11136.     .  .  .  X  .  .  .  .   .  .  .  .  .  .  .  .        Game adapter: 1 = i
  11137.     .  .  .  .  X  X  X  .   .  .  .  .  .  .  .  .        Number of RSS-232 s
  11138.     .  .  .  .  .  .  .  X   .  .  .  .  .  .  .  .        (Not used)
  11139.     .  .  .  .  .  .  .  .   X  X  .  .  .  .  .  .        Number of diskette
  11140.     .  .  .  .  .  .  .  .   .  .  X  X  .  .  .  .        Initial video mode:
  11141.                                                            10 = 80-column colo
  11142.                                                            01 = 40-column colo
  11143.     .  .  .  .  .  .  .  .   .  .  .  .  X  X  .  .        PC with 64 KB mothe
  11144.                                                            system board RAM (1
  11145.                                                            10 = 48 KB; 01 = 32
  11146.                                                            PC/AT: (Not used)
  11147.                                                            PS/2s: Bit 3 = (unu
  11148.                                                            pointing device ins
  11149.     .  .  .  .  .  .  .  .   .  .  .  .  .  .  X  .        1 if math co-proces
  11150.     .  .  .  .  .  .  .  .   .  .  .  .  .  .  .  X        1 if any diskette d
  11151.                                                            see bits 7 and 6)
  11152.    ───────────────────────────────────────────────────────────────────────────
  11153.                             Bit
  11154.    15 14 13 12 11 10  9  8   7  6  5  4  3  2  1  0        Meaning
  11155.    ───────────────────────────────────────────────────────────────────────────
  11156.   ───────────────────────────────────────────────────────────────────────────
  11157.  
  11158.  
  11159.    Figure 12-17.  The bit coding for the equipment list reported in register
  11160.    AX and invoked by interrupt 11H (decimal 17).
  11161.  
  11162.    The format of the equipment list was defined for the original IBM PC. As a
  11163.    result, some parts of the list vary, depending on the PC model. For
  11164.    example, bits 2 and 3 originally indicated the amount of RAM installed on
  11165.    the motherboard. (Yes, in those days you could indeed have purchased a PC
  11166.    with as little as 16 KB of RAM.) In PS/2s, these bits have a different
  11167.    significance. (See Figure 12-17.)
  11168.  
  11169.  Interrupt 12H (decimal 18): Memory-Size Service
  11170.  
  11171.    Interrupt 12H (decimal 18) invokes the service that reports the available
  11172.    memory size in kilobytes──the same information stored at low-memory
  11173.    location 0040:0013H. (See page 55.) The value is reported in AX. The
  11174.    memory-size value reflects only the amount of base memory available. In a
  11175.    PC/AT or PS/2 with extended (protected-mode) memory, you must use
  11176.    interrupt 15H, service 88H (Get Extended Memory Size), to determine the
  11177.    amount of extended memory installed.
  11178.  
  11179.    In the standard models of the PC, this value is taken from the setting of
  11180.    the physical switches inside the system unit. These switches are supposed
  11181.    to reflect the actual memory installed, although under some circumstances
  11182.    they are set to less memory than is actually present. In the PC/AT and
  11183.    PS/2s, the ROM BIOS POST determines the amount of memory in the system by
  11184.    exploring available RAM to see what is installed. If the BIOS is using an
  11185.    extended data area, this data area is allocated at the highest memory
  11186.    address available, so the value returned by this service excludes the
  11187.    amount of RAM reserved for the extended data area.
  11188.  
  11189.  Interrupt 18H (decimal 24): ROM BASIC Loader Service
  11190.  
  11191.    Interrupt 18H (decimal 24) is normally used to activate ROM BASIC. Any
  11192.    program can activate BASIC (or whatever has replaced it) by generating
  11193.    interrupt 18H. This can be done to intentionally bring up ROM BASIC or
  11194.    also to abruptly shut down, or dead-end a program. However, see the next
  11195.    interrupt, number 19H, for a better way to dead-end a program.
  11196.  
  11197.  Interrupt 19H (decimal 25): Bootstrap Loader Service
  11198.  
  11199.    Interrupt 19H (decimal 25) activates the standard bootstrap routine for
  11200.    the computer (which produces a similar result to powering on and nearly
  11201.    the same net result as the Ctrl-Alt-Del key combination). However, this
  11202.    bootstrap interrupt bypasses the lengthy memory check of the power-on
  11203.    routines as well as the reset operations of Ctrl-Alt-Del.
  11204.  
  11205.    The bootstrap loader works by reading the first sector of the first track
  11206.    (the boot sector) from the diskette in drive A into memory at 0000:7C00H.
  11207.    If the ROM BIOS cannot read from the diskette, it reads the boot sector
  11208.    from the hard disk in drive C instead. If both attempts fail, the BIOS
  11209.    executes interrupt 18H to bring up ROM BASIC. If the BIOS reads a sector
  11210.    from the disk but the sector doesn't contain an operating-system boot
  11211.    record, the BIOS issues an error message and waits for you to reboot or
  11212.    replace the offending diskette.
  11213.  
  11214.    We know of two uses for this interrupt service. One is to immediately shut
  11215.    down, or dead-end, the operation of the computer. This can be done by a
  11216.    program when it encounters an "illegal" situation, for example, by a
  11217.    copy-protected program that detects an apparent violation of copy
  11218.    protection.
  11219.  
  11220.    The other use for this service is to reboot the computer without going
  11221.    through the reset and restart operations, which would, for example,
  11222.    recalculate the memory size and equipment list reported by interrupts 11H
  11223.    and 12H. This interrupt is particularly useful for any program that
  11224.    modifies either of these two items. The reasoning is simple: If you want
  11225.    to change the equipment list or the memory size (for example, to set aside
  11226.    some memory for a RAM disk), you cannot reliably count on all programs──
  11227.    including DOS──to check the actual memory or equipment specifications each
  11228.    time they are used. But a program could set aside some memory, change the
  11229.    memory specification, and then use this interrupt to reboot the system.
  11230.    When that is done and DOS is activated, DOS would take its own record of
  11231.    the available memory from the value set by your program. Neither DOS nor
  11232.    any civilized DOS program would be aware of, or interfere with, the memory
  11233.    area that was set aside.
  11234.  
  11235.    To give you a brief example, here's a fragment of assembler code that will
  11236.    change the ROM BIOS's record of the memory size and then use interrupt 19H
  11237.    to reboot the computer:
  11238.  
  11239.    mov     ax,40H                   ; get BIOS data segment of hex 40...
  11240.    mov     es,ax                    ; ...into ES segment register
  11241.    mov     word ptr es:[13h],256    ; set memory to 256 KB
  11242.    int     19h                      ; reboot system
  11243.  
  11244.  Interrupt 1AH (decimal 26): Time-of-Day Services
  11245.  
  11246.    Interrupt 1AH (decimal 26) provides the time-of-day services. Unlike other
  11247.    interrupts covered in this section but like all other ROM BIOS services,
  11248.    several services can be activated by this interrupt. When you execute
  11249.    interrupt 1AH, you specify the service number, as usual, in register AH.
  11250.    (See Figure 12-18.)
  11251.  
  11252.    Service            Description
  11253.    ──────────────────────────────────────────────────────────────────────────
  11254.    00H                Get Current Clock Count.
  11255.    01H                Set Current Clock Count.
  11256.    02H                Get Real-Time Clock Time.
  11257.    03H                Set Real-Time Clock Time.
  11258.    04H                Get Real-Time Clock Date.
  11259.    05H                Set Real-Time Clock Date.
  11260.    06H                Set Real-Time Clock Alarm.
  11261.    07H                Reset Real-Time Clock Alarm.
  11262.    09H                Get Real-Time Clock Alarm Time and Status.
  11263.    ──────────────────────────────────────────────────────────────────────────
  11264.  
  11265.    Figure 12-18.  The ROM-BIOS time-of-day services invoked by interrupt 1AH.
  11266.  
  11267.    The ROM BIOS maintains a time-of-day clock based on a count of
  11268.    system-clock ticks since midnight. The system clock "ticks" by generating
  11269.    interrupt 8 at specific intervals. On each clock tick, the ROM BIOS
  11270.    interrupt 08H service routine increments the clock count by 1. When the
  11271.    clock count passes 24 hours' worth of ticks, the count is reset to 0 and a
  11272.    record is made of the fact that midnight has been passed. This record is
  11273.    not in the form of a count, so you can't detect if two midnights have
  11274.    passed.
  11275.  
  11276.    The clock ticks at a rate that is almost exactly 1,193,180 ÷ 64 KB, or
  11277.    roughly 18.2 times a second. The count is kept as a 4-byte integer at
  11278.    low-memory location 0040:006CH. The midnight count value, used to compare
  11279.    against the rising clock count, is 1800B0H, or 1,573,040; when the clock
  11280.    hits the midnight count value, the byte at location 0040:0070H is set to
  11281.    01H and the count is reset. When DOS needs to know the time, it reads the
  11282.    clock count through the time-of-day service and calculates the time from
  11283.    this raw count. If it sees that midnight has passed, it also increments
  11284.    the date.
  11285.  
  11286.    You can use the following BASIC formulas to calculate the current time of
  11287.    day from the clock count:
  11288.  
  11289.    HOURS = INT(CLOCK / 65543)
  11290.    CLOCK = CLOCK - (HOURS * 65543)
  11291.    MINUTES = INT(CLOCK / 1092)
  11292.    CLOCK = CLOCK - (MINUTES * 1092)
  11293.    SECONDS = CLOCK / 18.2
  11294.  
  11295.    In reverse, we use the following formula to calculate a nearly correct
  11296.    clock count from the time:
  11297.  
  11298.    COUNT = (HOURS * 65543) + (MINUTES * 1092) + (SECONDS * 18.2)
  11299.  
  11300.    The ROM BIOS services in the PC/AT and PS/2s include time-of-day and date
  11301.    services that perform some of these tasks automatically.
  11302.  
  11303.    Service 00H (decimal 0): Get Current Clock Count
  11304.  
  11305.    Service 00H (decimal 0) returns the current clock count in two registers:
  11306.    the high-order portion in CX and the low-order portion in DX. AL = 00H if
  11307.    midnight has not passed since the last clock value was read or set; and AL
  11308.    = 01H if midnight has passed. The midnight signal is always reset when the
  11309.    clock is read. Any program using this service must use the midnight signal
  11310.    to keep track of date changes. DOS programs normally should not use this
  11311.    service directly. If they do, they must calculate and set a new date.
  11312.  
  11313.    ──────────────────────────────────────────────────────────────────────────
  11314.    NOTE:
  11315.      It's curious that version 2.0 of DOS did not consistently update the
  11316.      date on the midnight signal. The next version of DOS (2.1) and all other
  11317.      versions of DOS do.
  11318.    ──────────────────────────────────────────────────────────────────────────
  11319.  
  11320.    Service 01H (decimal 1): Set Current Clock Count
  11321.  
  11322.    Service 01H (decimal 1) sets the clock count in location 0040:006CH using
  11323.    the values you pass in registers CX and DX. This service automatically
  11324.    clears the midnight flag at 0040:0070H.
  11325.  
  11326.    Service 02H (decimal 2): Get Real-Time Clock Time
  11327.  
  11328.    The PC/AT and the PS/2s have a real-time clock that maintains the current
  11329.    date and time in nonvolatile memory. This clock runs in parallel to the
  11330.    system timer referenced by services 00H and 01H. When you boot a PC/AT or
  11331.    PS/2, the ROM BIOS initializes the system timer count with the time
  11332.    indicated by the real-time clock.
  11333.  
  11334.    You can access the real-time clock directly using service 02H (decimal 2).
  11335.    This service returns the time in binary-coded decimal format (BCD) in
  11336.    registers CH (hours), CL (minutes), and DH (seconds). If the real-time
  11337.    clock is defective, the ROM BIOS sets the carry flag.
  11338.  
  11339.    Service 03H (decimal 3): Set Real-Time Clock Time
  11340.  
  11341.    This service complements service 02H. It lets you set the real-time clock
  11342.    on a PC/AT or PS/2, using the same register assignments as service 02H.
  11343.    Again, the hours, minutes, and seconds values are in BCD format.
  11344.  
  11345.    Service 04H (decimal 4): Get Real-Time Clock Date
  11346.  
  11347.    Service 04H (decimal 4) returns the current date as maintained by the
  11348.    real-time clock in a PC/AT or PS/2. The ROM BIOS returns century (19 or
  11349.    20) in register CH, the year in CL, the month in DH, and the day in DL.
  11350.    Again, the values are returned in BCD format. As in service 02H, the ROM
  11351.    BIOS sets the carry flag if the real-time clock is not operating.
  11352.  
  11353.    Service 05H (decimal 5): Set Real-Time Clock Date
  11354.  
  11355.    Service 05H (decimal 5) complements service 04H. This service sets the
  11356.    real-time clock date, using the same registers as service 04H.
  11357.  
  11358.    Service 06H (decimal 6): Set Real-Time Clock Alarm
  11359.  
  11360.    Service 06H (decimal 6) lets you create an "alarm" program that executes
  11361.    at a specific time. This alarm program must be memory-resident at the time
  11362.    the alarm occurs. To use this service, make your alarm program
  11363.    memory-resident using the DOS Terminate-and-Stay-Resident service (see
  11364.    page 302), and be sure that interrupt vector 4AH (0000:0128H) points to
  11365.    the start of your program. Then call service 06H to set the time for the
  11366.    alarm to occur.
  11367.  
  11368.    Service 06H uses the same register values as service 03H: CH contains
  11369.    hours in BCD format, CL contains minutes, and DH contains seconds. The ROM
  11370.    BIOS sets the carry flag when it returns from this service if the
  11371.    real-time clock is not operating or if the alarm is already in use.
  11372.  
  11373.    When the real-time clock time matches the alarm time, the BIOS executes
  11374.    interrupt 4AH, which transfers control to your alarm program. Your program
  11375.    can then take appropriate action (display a message, for example). Because
  11376.    the ROM BIOS activates your alarm program by executing an
  11377.    INT 4AH instruction, the program must exit with an IRET instruction.
  11378.  
  11379.    Service 07H (decimal 7): Reset Real-Time Clock Alarm
  11380.  
  11381.    Use service 07H (decimal 7) to disable the real-time clock alarm if it has
  11382.    been set by a previous call to service 06H.
  11383.  
  11384.    Service 09H (decimal 9): Get Real-Time Clock Alarm Time and Status
  11385.  
  11386.    On PS/2 models 25 and 30, you can determine the current status of the
  11387.    real-time alarm by executing interrupt 1AH, service 09H. This service
  11388.    reports the alarm status in register DL. If DL = 01H, the alarm is active,
  11389.    and the alarm time is returned in CH, CL, and DH. If DL = 00H, the alarm
  11390.    isn't enabled.
  11391.  
  11392.  
  11393.  Chapter 13  ROM BIOS Services Summary
  11394.  ────────────────────────────────────────────────────────────────────────────
  11395.  
  11396.    Short Summary
  11397.  
  11398.    Long Summary
  11399.  
  11400.    This chapter summarizes the ROM BIOS service routines discussed in
  11401.    Chapters 8 through 12 in order to provide you with a quick reference
  11402.    guide.
  11403.  
  11404.    You can use this chapter to locate the ROM BIOS functions you need and to
  11405.    determine which registers they use. Where a particular service is very
  11406.    detailed or tricky to use, we'll refer you to the discussions in the
  11407.    chapters and to the IBM technical reference manuals.
  11408.  
  11409.  
  11410.  
  11411.  Short Summary
  11412.  
  11413.  
  11414.    In this section, we briefly list all the ROM BIOS services so that they
  11415.    can be seen together, at a glance.
  11416.  
  11417. ╓┌─┌────────────┌───┌───┌───────┌───────────────────────────┌────────────────╖
  11418.                Interrupt
  11419.    Subject      Hex Dec Service Description                 Notes
  11420.    ──────────────────────────────────────────────────────────────────────────
  11421.    Print screen 05H 5   N/A     Send screen contents to
  11422.                                 printer.
  11423.    Video        10H 16  00H     Set video mode.
  11424.    Video        10H 16  01H     Set cursor size.
  11425.    Video        10H 16  02H     Set cursor position.
  11426.                Interrupt
  11427.    Subject      Hex Dec Service Description                 Notes
  11428.    ──────────────────────────────────────────────────────────────────────────
  11429.   Video        10H 16  02H     Set cursor position.
  11430.    Video        10H 16  03H     Read cursor position.
  11431.    Video        10H 16  04H     Read light-pen position.
  11432.    Video        10H 16  05H     Set active display page.
  11433.    Video        10H 16  06H     Scroll window up.
  11434.    Video        10H 16  07H     Scroll window down.
  11435.    Video        10H 16  08H     Read character and
  11436.                                 attribute.
  11437.    Video        10H 16  09H     Write character and
  11438.                                 attribute.
  11439.    Video        10H 16  0AH     Write character.
  11440.    Video        10H 16  0BH     Set 4-color palette.
  11441.    Video        10H 16  0CH     Write pixel.
  11442.    Video        10H 16  0DH     Read pixel.
  11443.    Video        10H 16  0EH     Write character in teletype
  11444.                                 mode.
  11445.    Video        10H 16  0FH     Get current video mode.
  11446.    Video        10H 16  10H     EGA/VGA color palette
  11447.                Interrupt
  11448.    Subject      Hex Dec Service Description                 Notes
  11449.    ──────────────────────────────────────────────────────────────────────────
  11450.   Video        10H 16  10H     EGA/VGA color palette
  11451.                                 interface.
  11452.    Video        10H 16  11H     EGA/VGA character generator
  11453.                                 interface.
  11454.    Video        10H 16  12H     EGA/VGA "alternate
  11455.                                 select."
  11456.    Video        10H 16  13H     Write character string.    PC/AT, PS/2, EGA,
  11457.                                                             VGA only
  11458.    Video        10H 16  1AH     Get/Set display combination PS/2 only
  11459.                                 code.
  11460.    Video        10H 16  1BH     Functionality/State         PS/2 only
  11461.                                 information.
  11462.    Video        10H 16  1CH     Save/Restore video state.  VGA only
  11463.    Equipment    11H 17  N/A     Get list of peripheral
  11464.                                 equipment.
  11465.    Memory       12H 18  N/A     Get base memory size (in
  11466.                                 KB).
  11467.    Disk         13H 19  00H     Reset disk system.
  11468.                Interrupt
  11469.    Subject      Hex Dec Service Description                 Notes
  11470.    ──────────────────────────────────────────────────────────────────────────
  11471.   Disk         13H 19  00H     Reset disk system.
  11472.    Disk         13H 19  01H     Get disk status.
  11473.    Disk         13H 19  02H     Read disk sectors.
  11474.    Disk         13H 19  03H     Write disk sectors.
  11475.    Disk         13H 19  04H     Verify disk sectors.
  11476.    Disk         13H 19  05H     Format disk track.
  11477.    Disk         13H 19  06H     Format disk track and set   PC/XT fixed disk
  11478.                                 bad sector flags.          only
  11479.    Disk         13H 19  07H     Format drive starting at    PC/XT fixed disk
  11480.                                 specified cylinder.        only
  11481.    Disk         13H 19  08H     Get current drive
  11482.                                 parameters.
  11483.    Disk         13H 19  09H     Initialize fixed-disk
  11484.                                 parameter tables.
  11485.    Disk         13H 19  0AH     Read long.
  11486.    Disk         13H 19  0BH     Write long.
  11487.    Disk         13H 19  0CH     Seek to cylinder.
  11488.    Disk         13H 19  0DH     Alternate disk reset.
  11489.                Interrupt
  11490.    Subject      Hex Dec Service Description                 Notes
  11491.    ──────────────────────────────────────────────────────────────────────────
  11492.   Disk         13H 19  0DH     Alternate disk reset.
  11493.    Disk         13H 19  10H     Test for drive ready.
  11494.    Disk         13H 19  11H     Recalibrate drive.
  11495.    Disk         13H 19  14H     Controller diagnostics.
  11496.    Disk         13H 19  15H     Get disk type.
  11497.    Disk         13H 19  16H     Change of diskette status.
  11498.    Disk         13H 19  17H     Set diskette type for
  11499.                                 format.
  11500.    Disk         13H 19  18H     Set media type for diskette
  11501.                                 format.
  11502.    Disk         13H 19  19H     Park heads.                PS/2s only
  11503.    Disk         13H 19  1AH     Format ESDI unit.          PS/2 models 50,
  11504.                                                             60, 80 only
  11505.    Serial port  14H 20  00H     Initialize serial port.
  11506.    Serial port  14H 20  01H     Send out one character.
  11507.    Serial port  14H 20  02H     Receive one character.
  11508.    Serial port  14H 20  03H     Get serial port status.
  11509.    Serial port  14H 20  04H     Extended serial port        PS/2s only
  11510.                Interrupt
  11511.    Subject      Hex Dec Service Description                 Notes
  11512.    ──────────────────────────────────────────────────────────────────────────
  11513.   Serial port  14H 20  04H     Extended serial port        PS/2s only
  11514.                                 initialize.                Serial port
  11515.                                                             14H
  11516.                                                             20
  11517.                                                             05H
  11518.                                                             Extended serial
  11519.                                                             port control.
  11520.                                                             PS/2s only
  11521.    System       15H 21  00H     Turn on cassette motor.
  11522.    System       15H 21  01H     Turn off cassette motor.
  11523.    System       15H 21  02H     Read data blocks.
  11524.    System       15H 21  03H     Write data blocks.
  11525.    System       15H 21  21H     Read/write POST error log. PS/2 models 50,
  11526.                                                             60, 80 only
  11527.    System       15H 21  4FH     Keyboard intercept.        PC/AT, PS/2s only
  11528.    System       15H 21  80H     Device open.               PC/AT, PS/2s only
  11529.    System       15H 21  81H     Device close.              PC/AT, PS/2s only
  11530.    System       15H 21  82H     Program termination.       PC/AT, PS/2s only
  11531.                Interrupt
  11532.    Subject      Hex Dec Service Description                 Notes
  11533.    ──────────────────────────────────────────────────────────────────────────
  11534.   System       15H 21  82H     Program termination.       PC/AT, PS/2s only
  11535.    System       15H 21  83H     Start/stop interval timer. PC/AT, PS/2s only
  11536.    System       15H 21  84H     Joystick support.          PC/AT, PS/2s only
  11537.    System       15H 21  85H     Sys Req keystroke.         PC/AT, PS/2s only
  11538.    System       15H 21  86H     Wait.                      PC/AT, PS/2s only
  11539.    System       15H 21  87H     Protected-mode data move.  PC/AT, PS/2
  11540.                                                             models 50, 60, 80
  11541.    System       15H 21  88H     Get extended memory size.  PC/AT, PS/2
  11542.                                                             models 50, 60, 80
  11543.    System       15H 21  89H     Switch to protected mode.  PC/AT, PS/2
  11544.                                                             models 50, 60, 80
  11545.    System       15H 21  90H     Device busy.               PC/AT, PS/2s only
  11546.    System       15H 21  91H     Interrupt complete.        PC/AT, PS/2s only
  11547.    System       15H 21  C0H     Get system configuration
  11548.                                 parameters.
  11549.    System       15H 21  C1H     Get extended BIOS data      PS/2s only
  11550.                                 segment.
  11551.    System       15H 21  C2H     Pointing-device interface. PS/2s only
  11552.                Interrupt
  11553.    Subject      Hex Dec Service Description                 Notes
  11554.    ──────────────────────────────────────────────────────────────────────────
  11555.   System       15H 21  C2H     Pointing-device interface. PS/2s only
  11556.    System       15H 21  C3H     Enable/disable watchdog     PS/2 models 50,
  11557.                                 timer.                     60, 80
  11558.    System       15H 21  C4H     Programmable Option Select  PS/2 models 50,
  11559.                                 interface.                 60, 80
  11560.    Keyboard     16H 22  00H     Read next keystroke.
  11561.    Keyboard     16H 22  01H     Report whether keystroke
  11562.                                 ready.
  11563.    Keyboard     16H 22  02H     Get shift status.
  11564.    Keyboard     16H 22  03H     Set typematic rate and      PC/AT, PS/2s only
  11565.                                 delay.
  11566.    Keyboard     16H 22  05H     Write to keyboard buffer.  PC/AT, PS/2s only
  11567.    Keyboard     16H 22  10H     Extended keyboard read.    PC/AT, PS/2s only
  11568.    Keyboard     16H 22  11H     Extended keyboard status.  PC/AT, PS/2s only
  11569.    Keyboard     16H 22  12H     Extended shift status.     PC/AT, PS/2s only
  11570.    Printer      17H 23  00H     Send 1 byte to printer.
  11571.    Printer      17H 23  01H     Initialize printer.
  11572.    Printer      17H 23  02H     Get printer status.
  11573.                Interrupt
  11574.    Subject      Hex Dec Service Description                 Notes
  11575.    ──────────────────────────────────────────────────────────────────────────
  11576.   Printer      17H 23  02H     Get printer status.
  11577.    BASIC        18H 24  N/A     Switch control to ROM
  11578.                                 BASIC.
  11579.    Bootstrap    19H 25  N/A     Reboot computer.
  11580.    Time         1AH 26  00H     Read current clock count.
  11581.    Time         1AH 26  01H     Set current clock count.
  11582.    Time         1AH 26  02H     Read real-time clock.      PC/AT, PS/2s only
  11583.    Time         1AH 26  03H     Set real-time clock.       PC/AT, PS/2s only
  11584.    Time         1AH 26  04H     Read date from real-time    PC/AT, PS/2s only
  11585.                                 clock.
  11586.    Time         1AH 26  05H     Set date in real-time       PC/AT, PS/2s only
  11587.                                 clock.
  11588.    Time         1AH 26  06H     Set alarm.                 PC/AT, PS/2s only
  11589.    Time         1AH 26  07H     Reset alarm.               PC/AT, PS/2s only
  11590.    Time         1AH 26  09H     Get alarm time and status. PS/2 Model 30
  11591.                                                             only
  11592.    ──────────────────────────────────────────────────────────────────────────
  11593.  
  11594.  
  11595.  
  11596.  Long Summary
  11597.  
  11598.  
  11599.    In this section, we expand the previous summary table to show the register
  11600.    usage for input and output parameters. The preceding section is best used
  11601.    to quickly find which service you need; this section is best used to
  11602.    quickly find how to use each service.
  11603.  
  11604. ╓┌─┌────────────────┌───┌────────────────┌────────────────┌──────────────────╖
  11605.    Print Services              Register
  11606.                     Int Input            Output           Notes
  11607.    ──────────────────────────────────────────────────────────────────────────
  11608.    Print screen.    05H N/A              N/A              Send screen
  11609.                                                           contents to
  11610.                                                           printer. Status and
  11611.                                                           result byte at
  11612.                                                           0050:0000H.
  11613.  
  11614. ╓┌─┌────────────────┌───┌────────────────┌────────────────┌──────────────────╖
  11615.    Video Services              Register
  11616.                     Int Input            Output           Notes
  11617.    ──────────────────────────────────────────────────────────────────────────
  11618.    Set video mode.  10H AH = 00H         None             Video modes in AL:
  11619.                         AL = video mode                   00H: 40 x 25
  11620.                                                           16-color text
  11621.                                                           (gray-scaled on
  11622.                                                           composite
  11623.                                                           monitors).
  11624.                                                           01H: 40 x 25
  11625.                                                           16-color text.
  11626.                                                           02H: 80 x 25
  11627.                                                           16-color text
  11628.                                                           (gray-scaled on
  11629.                                                           composite
  11630.                                                           monitors).
  11631.                                                           03H: 80 x 25
  11632.                                                           16-color text.
  11633.                                                           04H: 320 x 200
  11634.                                                           4-color graphics.
  11635.                                                           05H: 320 x 200
  11636.    Video Services              Register
  11637.                     Int Input            Output           Notes
  11638.    ──────────────────────────────────────────────────────────────────────────
  11639.                                                          05H: 320 x 200
  11640.                                                           4-color graphics
  11641.                                                           (gray-scaled on
  11642.                                                           composite
  11643.                                                           monitors).
  11644.                                                           06H: 640 x 200
  11645.                                                           2-color graphics.
  11646.                                                           07H: 80 x 25
  11647.                                                           monochrome text
  11648.                                                           (MDA, EGA, VGA).
  11649.                                                           0DH: 320 x 200
  11650.                                                           16-color graphics
  11651.                                                           (EGA, VGA).
  11652.                                                           0EH: 640 x 200
  11653.                                                           16-color graphics
  11654.                                                           (EGA, VGA).
  11655.                                                           0FH: 640 x 350
  11656.                                                           monochrome graphics
  11657.    Video Services              Register
  11658.                     Int Input            Output           Notes
  11659.    ──────────────────────────────────────────────────────────────────────────
  11660.                                                          monochrome graphics
  11661.                                                           (EGA, VGA).
  11662.                                                           10H: 640 x 350
  11663.                                                           16-color graphics
  11664.                                                           (EGA, VGA).
  11665.                                                           11H: 640 x 480
  11666.                                                           2-color graphics
  11667.                                                           (MCGA, VGA).
  11668.                                                           12H: 640 x 480
  11669.                                                           16-color graphics
  11670.                                                           (VGA).
  11671.                                                           13H: 320 x 200
  11672.                                                           256-color graphics
  11673.                                                           (MCGA, VGA).
  11674.    ──────────────────────────────────────────────────────────────────────────
  11675.    Set cursor size. 10H AH = 01H         None             Useful values for
  11676.                         CH = starting                     CH and CL depend on
  11677.                         scan line                         video mode.
  11678.    Video Services              Register
  11679.                     Int Input            Output           Notes
  11680.    ──────────────────────────────────────────────────────────────────────────
  11681.                        scan line                         video mode.
  11682.                         CL = ending
  11683.                         scan line
  11684.    ──────────────────────────────────────────────────────────────────────────
  11685.    Set cursor       10H AH = 02H         None
  11686.    position.            BH = display
  11687.                         page
  11688.                         DH = row
  11689.                         DL = column
  11690.    ──────────────────────────────────────────────────────────────────────────
  11691.    Read cursor      10H AH = 03H         CH = starting
  11692.    position.            BH = display     scan line
  11693.                         page             CL = ending scan
  11694.                                          line
  11695.                                          DH = row
  11696.                                          DL = column
  11697.    ──────────────────────────────────────────────────────────────────────────
  11698.    Read light-pen   10H AH = 04H         AH = pen trigger
  11699.    Video Services              Register
  11700.                     Int Input            Output           Notes
  11701.    ──────────────────────────────────────────────────────────────────────────
  11702.   Read light-pen   10H AH = 04H         AH = pen trigger
  11703.    position.                             signal
  11704.                                          BX = pixel
  11705.                                          column
  11706.                                          CH = pixel row
  11707.                                          (CGA and EGA
  11708.                                          video modes 4,
  11709.                                          5, and 6)
  11710.                                          CX = pixel row
  11711.                                          (EGA except
  11712.                                          modes 4, 5, and
  11713.                                          6)
  11714.                                          DH = character
  11715.                                          row
  11716.                                          DL = character
  11717.                                          column
  11718.    ──────────────────────────────────────────────────────────────────────────
  11719.    Set active       10H AH = 05H         None
  11720.    Video Services              Register
  11721.                     Int Input            Output           Notes
  11722.    ──────────────────────────────────────────────────────────────────────────
  11723.   Set active       10H AH = 05H         None
  11724.    display page.        AL = page number
  11725.    ──────────────────────────────────────────────────────────────────────────
  11726.    Scroll           10H AH = 06H         None
  11727.    window up.           AL = lines to
  11728.                         scroll up
  11729.                         BH = fill
  11730.                         attribute
  11731.                         CH = upper row
  11732.                         CL = left column
  11733.                         DH = lower row
  11734.                         DL = right
  11735.                         column
  11736.    ──────────────────────────────────────────────────────────────────────────
  11737.    Scroll window    10H AH = 07H         None
  11738.    down.                AL = lines to
  11739.                         scroll down
  11740.                         BH = fill
  11741.    Video Services              Register
  11742.                     Int Input            Output           Notes
  11743.    ──────────────────────────────────────────────────────────────────────────
  11744.                        BH = fill
  11745.                         attribute
  11746.                         CH = upper row
  11747.                         CL = left column
  11748.                         DH = lower row
  11749.                         DL = right
  11750.                         column
  11751.    ──────────────────────────────────────────────────────────────────────────
  11752.    Read character   10H AH = 08H         AH = attribute
  11753.    and attribute.       BH = display     AL = character
  11754.                         page
  11755.    ──────────────────────────────────────────────────────────────────────────
  11756.    Write character  10H AH = 09H         None
  11757.    and attribute.       AL = character
  11758.                         BH = display
  11759.                         page
  11760.                         BL = attribute
  11761.                         CX = number of
  11762.    Video Services              Register
  11763.                     Int Input            Output           Notes
  11764.    ──────────────────────────────────────────────────────────────────────────
  11765.                        CX = number of
  11766.                         characters to
  11767.                         repeat
  11768.    ──────────────────────────────────────────────────────────────────────────
  11769.    Write character. 10H AH = 0AH         None
  11770.                         AL = character
  11771.                         BH = page number
  11772.                         BL = color in
  11773.                         graphics mode
  11774.                         CX = number of
  11775.                         characters to
  11776.                         repeat
  11777.    ──────────────────────────────────────────────────────────────────────────
  11778.    Set color        10H AH = 0BH         None
  11779.    palette.             BH = palette
  11780.                         color ID
  11781.                         BL = color to be
  11782.                         used with
  11783.    Video Services              Register
  11784.                     Int Input            Output           Notes
  11785.    ──────────────────────────────────────────────────────────────────────────
  11786.                        used with
  11787.                         palette ID
  11788.    ──────────────────────────────────────────────────────────────────────────
  11789.    Write pixel.     10H AH = 0CH         None
  11790.                         AL = color
  11791.                         BH = display
  11792.                         page
  11793.                         CX = pixel
  11794.                         column
  11795.                         DX = pixel row
  11796.    ──────────────────────────────────────────────────────────────────────────
  11797.    Read pixel.      10H AH = 0DH         AL = pixel value
  11798.                         BH = display
  11799.                         page
  11800.                         CX = pixel
  11801.                         column
  11802.                         DX = pixel row
  11803.    ──────────────────────────────────────────────────────────────────────────
  11804.    Video Services              Register
  11805.                     Int Input            Output           Notes
  11806.    ──────────────────────────────────────────────────────────────────────────
  11807.   ──────────────────────────────────────────────────────────────────────────
  11808.    Write character  10H AH = 0EH         None             Display page number
  11809.    in teletype          AL = character                    required only for
  11810.    mode.                BH = display                      IBM PC ROM BIOS
  11811.                         page                              dated 10/19/81 and
  11812.                         BL = color for                    earlier.
  11813.                         graphics mode
  11814.    ──────────────────────────────────────────────────────────────────────────
  11815.    Get current      10H AH = 0FH         AH = width in
  11816.    video mode.                           characters
  11817.                                          AL = video mode
  11818.                                          BH = display
  11819.                                          page
  11820.    ──────────────────────────────────────────────────────────────────────────
  11821.    Set one palette  10H AH = 10H         None             EGA, VGA.
  11822.    register.            AL = 00H
  11823.                         BH = palette
  11824.                         register value
  11825.    Video Services              Register
  11826.                     Int Input            Output           Notes
  11827.    ──────────────────────────────────────────────────────────────────────────
  11828.                        register value
  11829.                         BL = palette
  11830.                         register number
  11831.    ──────────────────────────────────────────────────────────────────────────
  11832.    Set border       10H AH = 10H         None             EGA, VGA.
  11833.    register.            AL = 01H
  11834.                         BH = border
  11835.                         color
  11836.    ──────────────────────────────────────────────────────────────────────────
  11837.    Set all palette  10H AH = 10H         None             EGA, VGA.
  11838.    registers.           AL = 02H
  11839.                         ES:DX -> table
  11840.                         of palette
  11841.                         values
  11842.    ──────────────────────────────────────────────────────────────────────────
  11843.    Select           10H AH = 10H         None             EGA, VGA.
  11844.    background           AL = 03H
  11845.    intensity or         To enable
  11846.    Video Services              Register
  11847.                     Int Input            Output           Notes
  11848.    ──────────────────────────────────────────────────────────────────────────
  11849.   intensity or         To enable
  11850.    blink attribute.     background
  11851.                         intensity:
  11852.                         BL = 00H
  11853.                         To enable
  11854.                         blinking:
  11855.                         BL = 01H
  11856.    ──────────────────────────────────────────────────────────────────────────
  11857.    Read one palette 10H AH = 10H         BH = palette     VGA only.
  11858.    register.            AL = 07H         register value
  11859.                         BL = palette
  11860.                         register number
  11861.    ──────────────────────────────────────────────────────────────────────────
  11862.    Read border      10H AH = 10H         BH = border      VGA only.
  11863.    register.            AL = 08H         color
  11864.                                          value
  11865.    ──────────────────────────────────────────────────────────────────────────
  11866.    Read all palette 10H AH = 10H         ES:DX -> table   VGA only.
  11867.    Video Services              Register
  11868.                     Int Input            Output           Notes
  11869.    ──────────────────────────────────────────────────────────────────────────
  11870.   Read all palette 10H AH = 10H         ES:DX -> table   VGA only.
  11871.    registers.           AL = 09H         of palette
  11872.                                          register values
  11873.    ──────────────────────────────────────────────────────────────────────────
  11874.    Update one       10H AH = 10H         None             MCGA, VGA.
  11875.    video DAC            AL = 10H
  11876.    color register.      BX = color
  11877.                         register number
  11878.                         DH = red value
  11879.                         CH = green value
  11880.                         CL = blue value
  11881.    ──────────────────────────────────────────────────────────────────────────
  11882.    Update block     10H AH = 10H                          MCGA, VGA.
  11883.    of video DAC         AL = 12H
  11884.    color registers.     BX = first
  11885.                         register to
  11886.                         update
  11887.                         CX = number of
  11888.    Video Services              Register
  11889.                     Int Input            Output           Notes
  11890.    ──────────────────────────────────────────────────────────────────────────
  11891.                        CX = number of
  11892.                         registers to
  11893.                         update
  11894.                         ES:DX -> table
  11895.                         of
  11896.                         red-green-blue
  11897.                         values
  11898.    ──────────────────────────────────────────────────────────────────────────
  11899.    Set video DAC    10H AH = 10H         None             VGA only.
  11900.    color page.          AL = 13H
  11901.                         To select paging
  11902.                         mode:
  11903.                         BL = 00H
  11904.                         BH = 00H selects
  11905.                         4 pages of 64
  11906.                         registers, or
  11907.                         BH = 01H selects
  11908.                         16 pages of 16
  11909.    Video Services              Register
  11910.                     Int Input            Output           Notes
  11911.    ──────────────────────────────────────────────────────────────────────────
  11912.                        16 pages of 16
  11913.                         registers
  11914.                         To select page:
  11915.                         BL = 01H
  11916.                         BH = page number
  11917.    ──────────────────────────────────────────────────────────────────────────
  11918.    Read one video   10H AH = 10H         DH = red value   MCGA, VGA.
  11919.    DAC color            AL = 15H         CH = green value
  11920.    register.            BX = color       CL = blue value
  11921.                         register number
  11922.    ──────────────────────────────────────────────────────────────────────────
  11923.    Read block of    10H AH = 10H         Table at ES:DX   MCGA, VGA.
  11924.    video DAC color      AL = 17H         updated
  11925.    registers.           BX = first
  11926.                         register number
  11927.                         CX = number
  11928.                         of registers
  11929.                         ES:DX -> table
  11930.    Video Services              Register
  11931.                     Int Input            Output           Notes
  11932.    ──────────────────────────────────────────────────────────────────────────
  11933.                        ES:DX -> table
  11934.                         of
  11935.                         red-green-blue
  11936.                         values
  11937.    ──────────────────────────────────────────────────────────────────────────
  11938.    Get video DAC    10H AH = 10H         None             VGA only.
  11939.    color page.          AL = 1AH
  11940.                         BH = current
  11941.                         page
  11942.                         BL = current
  11943.                         paging mode
  11944.    ──────────────────────────────────────────────────────────────────────────
  11945.    Sum video DAC    10H AH = 10H         None             MCGA, VGA.
  11946.    color values to      AL = 1BH
  11947.    gray shades.         BX = first color
  11948.                         register
  11949.                         CX = number of
  11950.                         color registers
  11951.    Video Services              Register
  11952.                     Int Input            Output           Notes
  11953.    ──────────────────────────────────────────────────────────────────────────
  11954.                        color registers
  11955.    ──────────────────────────────────────────────────────────────────────────
  11956.    Load             10H AH = 11H         None             EGA, MCGA, VGA.
  11957.    user-specified       AL = 00H
  11958.    alphanumeric         BH = bytes per
  11959.    character set.       character in
  11960.                         table
  11961.                         BL = character
  11962.                         generator RAM
  11963.                         block
  11964.                         CX = number of
  11965.                         characters
  11966.                         DX = first
  11967.                         character
  11968.                         ES:BP ->
  11969.                         character
  11970.                         definition table
  11971.    ──────────────────────────────────────────────────────────────────────────
  11972.    Video Services              Register
  11973.                     Int Input            Output           Notes
  11974.    ──────────────────────────────────────────────────────────────────────────
  11975.   ──────────────────────────────────────────────────────────────────────────
  11976.    Load ROM BIOS    10H AH = 11H         None             EGA, VGA.
  11977.    8 x 14               AL = 01H
  11978.    alphanumeric         BL = character
  11979.    character set.       generator RAM
  11980.                         block
  11981.    ──────────────────────────────────────────────────────────────────────────
  11982.    Load ROM BIOS    10H AH = 11H         None             EGA, MCGA, VGA.
  11983.    8 x 8                AL = 02H
  11984.    alphanumeric         BL = character
  11985.    character set.       generator RAM
  11986.                         block
  11987.    ──────────────────────────────────────────────────────────────────────────
  11988.    Select displayed 10H AH = 11H         None             EGA, MCGA, VGA.
  11989.    alphanumeric         AL = 03H
  11990.    character sets.      BL = character
  11991.                         block generator
  11992.                         RAM
  11993.    Video Services              Register
  11994.                     Int Input            Output           Notes
  11995.    ──────────────────────────────────────────────────────────────────────────
  11996.                        RAM
  11997.    ──────────────────────────────────────────────────────────────────────────
  11998.    Load ROM BIOS    10H AH = 11H         None             MCGA, VGA.
  11999.    8 x 16               AL = 04H
  12000.    alphanumeric         BL = character
  12001.    character set.       generator RAM
  12002.                         block
  12003.    ──────────────────────────────────────────────────────────────────────────
  12004.    Load             10H AH = 11H         None             EGA, MCGA, VGA.
  12005.    user-specified       AL = 10H
  12006.    alphanumeric         BH = bytes per
  12007.    character set        character
  12008.    and adjust           definition
  12009.    displayed            BL = character
  12010.    character            generator RAM
  12011.    height.              block
  12012.                         CX = number of
  12013.                         characters
  12014.    Video Services              Register
  12015.                     Int Input            Output           Notes
  12016.    ──────────────────────────────────────────────────────────────────────────
  12017.                        characters
  12018.                         DX = first
  12019.                         character
  12020.                         ES:BP ->
  12021.                         character
  12022.                         definition table
  12023.    ──────────────────────────────────────────────────────────────────────────
  12024.    Load ROM BIOS    10H AH = 11H         None             EGA, VGA.
  12025.    8 x 14               AL = 11H
  12026.    alphanumeric         BL = character
  12027.    character set        generator RAM
  12028.    and adjust           block
  12029.    displayed
  12030.    character
  12031.    height.
  12032.    ──────────────────────────────────────────────────────────────────────────
  12033.    Load ROM BIOS    10H AH = 11H         None             EGA, VGA.
  12034.    8 x 8                AL = 12H
  12035.    Video Services              Register
  12036.                     Int Input            Output           Notes
  12037.    ──────────────────────────────────────────────────────────────────────────
  12038.   8 x 8                AL = 12H
  12039.    alphanumeric         BL = character
  12040.    character set        generator RAM
  12041.    and adjust           block
  12042.    displayed
  12043.    character
  12044.    height.
  12045.    ──────────────────────────────────────────────────────────────────────────
  12046.    Load ROM BIOS    10H AH = 11H         None             VGA only.
  12047.    8 x 16               AL = 14H
  12048.    alphanumeric         BL = character
  12049.    character set        generator RAM
  12050.    and adjust           block
  12051.    displayed
  12052.    character
  12053.    height.
  12054.    ──────────────────────────────────────────────────────────────────────────
  12055.    Load             10H AH = 11H         None             EGA, MCGA, VGA.
  12056.    Video Services              Register
  12057.                     Int Input            Output           Notes
  12058.    ──────────────────────────────────────────────────────────────────────────
  12059.   Load             10H AH = 11H         None             EGA, MCGA, VGA.
  12060.    user-specified       AL = 20H                          Copies ES:BP into
  12061.    8 x 8                ES:BP ->                          the interrupt 1FH
  12062.    graphics             character                         vector. Only
  12063.    character set.       definition table                  characters 80H
  12064.                                                           through FFH should
  12065.                                                           be defined.
  12066.    ──────────────────────────────────────────────────────────────────────────
  12067.    Load             10H AH = 11H         None             EGA, MCGA, VGA.
  12068.    user-specified       AL = 21H
  12069.    graphics             CX = bytes per
  12070.    character set.       character
  12071.                         definition
  12072.                         ES:BP ->
  12073.                         character
  12074.                         definition table
  12075.                         User-specified
  12076.                         number of
  12077.    Video Services              Register
  12078.                     Int Input            Output           Notes
  12079.    ──────────────────────────────────────────────────────────────────────────
  12080.                        number of
  12081.                         character rows:
  12082.                         BL = 00H
  12083.                         DL = number of
  12084.                         character rows
  12085.                         14 character
  12086.                         rows:
  12087.                         BL = 01H
  12088.                         25 character
  12089.                         rows:
  12090.                         BL = 02H
  12091.                         43 character
  12092.                         rows:
  12093.                         BL = 03H
  12094.    ──────────────────────────────────────────────────────────────────────────
  12095.    Load ROM BIOS    10H AH = 11H         None             EGA, VGA.
  12096.    8 x 14 graphics      AL = 22H
  12097.    character set.       BL = (as for
  12098.    Video Services              Register
  12099.                     Int Input            Output           Notes
  12100.    ──────────────────────────────────────────────────────────────────────────
  12101.   character set.       BL = (as for
  12102.                         AL = 21H)
  12103.                         DL = (as for
  12104.                         AL = 21H)
  12105.    ──────────────────────────────────────────────────────────────────────────
  12106.    Load ROM BIOS    10H AH = 11H         None             EGA, MCGA, VGA.
  12107.    8 x 8 graphics       AL = 23H
  12108.    character set.       BL = (as for
  12109.                         AL = 21H)
  12110.                         DL = (as for
  12111.                         AL = 21H)
  12112.    ──────────────────────────────────────────────────────────────────────────
  12113.    Load ROM BIOS    10H AH = 11H         None             MCGA, VGA.
  12114.    8 x 16 graphics      AL = 24H
  12115.    character set.       BL = (as for
  12116.                         AL = 21H)
  12117.                         DL = (as for
  12118.                         AL = 21H)
  12119.    Video Services              Register
  12120.                     Int Input            Output           Notes
  12121.    ──────────────────────────────────────────────────────────────────────────
  12122.                        AL = 21H)
  12123.    ──────────────────────────────────────────────────────────────────────────
  12124.    Get character    10H AH = 11H         CX = points      EGA, MCGA, VGA.
  12125.    generator            AL = 30H         DL = displayed
  12126.    information.         Contents of      character rows -
  12127.                         interrupt 1FH    1
  12128.                         vector:          ES:BP ->
  12129.                         BH = 00H         character table
  12130.                         Contents of
  12131.                         interrupt 43H
  12132.                         vector:
  12133.                         BH = 01H
  12134.                         Address of ROM
  12135.                         8 x 14
  12136.                         characters:
  12137.                         BH = 02H
  12138.                         Address of ROM
  12139.                         8 x 8
  12140.    Video Services              Register
  12141.                     Int Input            Output           Notes
  12142.    ──────────────────────────────────────────────────────────────────────────
  12143.                        8 x 8
  12144.                         characters:
  12145.                         1BH = 03H
  12146.                         Address of
  12147.                         second half of
  12148.                         ROM 8 x 8 table:
  12149.                         BH = 04H
  12150.                         Address of ROM
  12151.                         9 x 14 alternate
  12152.                         characters:
  12153.                         BH = 05H
  12154.                         Address of ROM
  12155.                         8 x 16
  12156.                         characters:
  12157.                         BH = 06H
  12158.                         Address of ROM
  12159.                         9 x 16 alternate
  12160.                         characters:
  12161.    Video Services              Register
  12162.                     Int Input            Output           Notes
  12163.    ──────────────────────────────────────────────────────────────────────────
  12164.                        characters:
  12165.                         BH = 07H
  12166.    ──────────────────────────────────────────────────────────────────────────
  12167.    Return video     10H AH = 12H         BH = default     EGA, VGA.
  12168.    configuration        BL = 10H         BIOS video mode
  12169.    information.                          (00H = color,
  12170.                                          01H =
  12171.                                          monochrome)
  12172.                                          BL = amount of
  12173.                                          video RAM (00H =
  12174.                                          64 KB, 01H = 128
  12175.                                          KB,
  12176.                                          02H = 192 KB,
  12177.                                          03H = 256 KB)
  12178.                                          CH = feature
  12179.                                          bits
  12180.                                          CL =
  12181.                                          configuration
  12182.    Video Services              Register
  12183.                     Int Input            Output           Notes
  12184.    ──────────────────────────────────────────────────────────────────────────
  12185.                                         configuration
  12186.                                          switches
  12187.    ──────────────────────────────────────────────────────────────────────────
  12188.    Select alternate 10H AH = 12H         None             EGA, MCGA, VGA.
  12189.    print screen         BL = 20H                          Updates INT 05H
  12190.    routine.                                               vector.
  12191.    ──────────────────────────────────────────────────────────────────────────
  12192.    Select scan      10H AH = 12H         AL = 12H         VGA only.
  12193.    lines for            BL = 30H
  12194.    alphanumeric         200 scan lines:
  12195.    modes.               AL = 00H
  12196.                         350 scan lines:
  12197.                         AL = 01H
  12198.                         400 scan lines:
  12199.                         AL = 02H
  12200.    ──────────────────────────────────────────────────────────────────────────
  12201.    Select default   10H AH = 12H         AL = 12H         MCGA, VGA.
  12202.    palette loading.     BL = 31H
  12203.    Video Services              Register
  12204.                     Int Input            Output           Notes
  12205.    ──────────────────────────────────────────────────────────────────────────
  12206.   palette loading.     BL = 31H
  12207.                         Enable default
  12208.                         palette loading:
  12209.                         AL = 00H
  12210.                         Disable default
  12211.                         palette loading:
  12212.                         AL = 01H
  12213.    ──────────────────────────────────────────────────────────────────────────
  12214.    Enable/disable   10H AH = 12H         AL = 12H         MCGA, VGA.
  12215.    video                BL = 32H
  12216.    addressing.          Enable video
  12217.                         addressing:
  12218.                         AL = 00H
  12219.                         Disable video
  12220.                         addressing:
  12221.                         AL = 01H
  12222.    ──────────────────────────────────────────────────────────────────────────
  12223.    Enable/disable   10H AH = 12H         AL = 12H         MCGA, VGA.
  12224.    Video Services              Register
  12225.                     Int Input            Output           Notes
  12226.    ──────────────────────────────────────────────────────────────────────────
  12227.   Enable/disable   10H AH = 12H         AL = 12H         MCGA, VGA.
  12228.    gray-scale           BL = 33H
  12229.    summing.             Enable gray-
  12230.                         scale summing:
  12231.                         AL = 00H
  12232.                         Disable gray-
  12233.                         scale summing:
  12234.                         AL = 01H
  12235.    ──────────────────────────────────────────────────────────────────────────
  12236.    Enable/disable   10H AH = 12H         AL = 12H         VGA only.
  12237.    BIOS cursor          BL = 34H
  12238.    emulation.           Enable cursor
  12239.                         emulation:
  12240.                         AL = 00H
  12241.                         Disable cursor
  12242.                         emulation:
  12243.                         AL = 01H
  12244.    ──────────────────────────────────────────────────────────────────────────
  12245.    Video Services              Register
  12246.                     Int Input            Output           Notes
  12247.    ──────────────────────────────────────────────────────────────────────────
  12248.   ──────────────────────────────────────────────────────────────────────────
  12249.    Display switch   10H AH = 12H         AL = 12H         MCGA, VGA.
  12250.    interface.           BL = 35H
  12251.                         Initial adapter
  12252.                         video off:
  12253.                         AL = 00H
  12254.                         Initial planar
  12255.                         video on: AL =
  12256.                         01H
  12257.                         Switch active
  12258.                         video off: AL =
  12259.                         02H
  12260.                         Switch inactive
  12261.                         video on:
  12262.                         AL = 03H
  12263.                         ES:DX->128-byte
  12264.                         save area
  12265.    ──────────────────────────────────────────────────────────────────────────
  12266.    Video Services              Register
  12267.                     Int Input            Output           Notes
  12268.    ──────────────────────────────────────────────────────────────────────────
  12269.   ──────────────────────────────────────────────────────────────────────────
  12270.    Enable/disable   10H AH = 12H         AL = 12H         VGA only.
  12271.    video refresh.       BL = 36H
  12272.                         Enable refresh:
  12273.                         AL = 00H
  12274.                         Disable refresh:
  12275.                         AL = 01H
  12276.    ──────────────────────────────────────────────────────────────────────────
  12277.    Write string;    10H AH = 13H         None             PC/AT, EGA, MCGA,
  12278.    don't move           AL = 00H                          VGA.
  12279.    cursor.              BL = attribute
  12280.                         BH = display
  12281.                         page
  12282.                         DX = starting
  12283.                         cursor position
  12284.                         CX = length of
  12285.                         string
  12286.                         ES:BP -> start
  12287.    Video Services              Register
  12288.                     Int Input            Output           Notes
  12289.    ──────────────────────────────────────────────────────────────────────────
  12290.                        ES:BP -> start
  12291.                         of string
  12292.    ──────────────────────────────────────────────────────────────────────────
  12293.    Write string;    10H AH = 13H         None             PC/AT, EGA, MCGA,
  12294.    move cursor          AL = 01H                          VGA.
  12295.    after string.        BL = attribute
  12296.                         BH = display
  12297.                         page
  12298.                         DX = starting
  12299.                         cursor position
  12300.                         CX = length of
  12301.                         string
  12302.                         ES:BP -> start
  12303.                         of string
  12304.    ──────────────────────────────────────────────────────────────────────────
  12305.    Write string of  10H AH = 13H         None             PC/AT, EGA, MCGA,
  12306.    alternating          AL = 02H                          VGA.
  12307.    characters and       BH = display
  12308.    Video Services              Register
  12309.                     Int Input            Output           Notes
  12310.    ──────────────────────────────────────────────────────────────────────────
  12311.   characters and       BH = display
  12312.    attributes;          page
  12313.    don't move           DX = starting
  12314.    cursor.              cursor position
  12315.                         CX = length of
  12316.                         string
  12317.                         ES:BP -> start
  12318.                         of string
  12319.    ──────────────────────────────────────────────────────────────────────────
  12320.    Write string of  10H AH = 13H         None             PC/AT, EGA, MCGA,
  12321.    alternating          AL = 03H                          VGA.
  12322.    characters and       BH = display
  12323.    attributes;          page
  12324.    move cursor.         DX = starting
  12325.                         cursor position
  12326.                         CX = length of
  12327.                         string
  12328.                         ES:BP -> start
  12329.    Video Services              Register
  12330.                     Int Input            Output           Notes
  12331.    ──────────────────────────────────────────────────────────────────────────
  12332.                        ES:BP -> start
  12333.                         of string
  12334.    ──────────────────────────────────────────────────────────────────────────
  12335.    Get display      10H AH = 1AH         AL = 1AH         MCGA, VGA.
  12336.    combination          AL = 00H         BL = active      Values returned in
  12337.    code.                                 display          BL and BH:
  12338.                                          BH = inactive    00H: no display.
  12339.                                          display          01H: MDA or
  12340.                                                           compatible.
  12341.                                                           02H: CGA or
  12342.                                                           compatible.
  12343.                                                           04H: EGA with color
  12344.                                                           display.
  12345.                                                           05H: EGA with
  12346.                                                           monochrome display.
  12347.                                                           06H: Professional
  12348.                                                           Graphics
  12349.                                                           Controller.
  12350.    Video Services              Register
  12351.                     Int Input            Output           Notes
  12352.    ──────────────────────────────────────────────────────────────────────────
  12353.                                                          Controller.
  12354.                                                           07H: VGA with
  12355.                                                           monochrome display.
  12356.                                                           08H: VGA with color
  12357.                                                           display.
  12358.                                                           0BH: MCGA with
  12359.                                                           monochrome display.
  12360.                                                           0CH: MCGA with
  12361.                                                           color display.
  12362.                                                           FFH: unknown.
  12363.    ──────────────────────────────────────────────────────────────────────────
  12364.    Set display      10H AH = 1AH         AL = 1AH         MCGA, VGA. See
  12365.    combination          AL = 01H                          table above for
  12366.    code.                BL = active                       values in BL and
  12367.                         display                           BH.
  12368.                         BH = inactive
  12369.                         display
  12370.    ──────────────────────────────────────────────────────────────────────────
  12371.    Video Services              Register
  12372.                     Int Input            Output           Notes
  12373.    ──────────────────────────────────────────────────────────────────────────
  12374.   ──────────────────────────────────────────────────────────────────────────
  12375.    BIOS             10H AH = 1BH         AL = 1BH         MCGA, VGA. See the
  12376.    functionality/       BX = 00H         Buffer at ES:DI  IBM BIOS Interface
  12377.    state                ES:DI -> 64-byte updated          Technical Reference
  12378.    information.         buffer                            Manual for table
  12379.                                                           format.
  12380.    ──────────────────────────────────────────────────────────────────────────
  12381.    Return           10H AH = 1CH         AL = 1CH         VGA only. Use this
  12382.    save/restore         AL = 00H         (if function     service before
  12383.    buffer size.         CX = requested   supported)       saving the current
  12384.                         states           BX =             video state.
  12385.                         (bit 0 = video   save/restore
  12386.                         hardware state;  buffer size in
  12387.                         bit 1 = video    64-byte blocks
  12388.                         BIOS data area;
  12389.                         bit 2 = video
  12390.                         DAC and color
  12391.                         registers)
  12392.    Video Services              Register
  12393.                     Int Input            Output           Notes
  12394.    ──────────────────────────────────────────────────────────────────────────
  12395.                        registers)
  12396.    ──────────────────────────────────────────────────────────────────────────
  12397.    Save current     10H AH = 1CH                          VGA only. May
  12398.    video state.         AL = 01H                          disrupt current
  12399.                         CX = requested                    video state, so
  12400.                         states                            follow a call to
  12401.                         ES:BX ->                          this service with a
  12402.                         save/restore                      call to the
  12403.                         buffer                            "Restore Current
  12404.                                                           Video State"
  12405.                                                           service.
  12406.    ──────────────────────────────────────────────────────────────────────────
  12407.    Restore current  10H AH = 1CH         None             VGA only.
  12408.    video state.         AL = 02H
  12409.                         CX = requested
  12410.                         states
  12411.                         ES:BX ->
  12412.                         save/restore
  12413.    Video Services              Register
  12414.                     Int Input            Output           Notes
  12415.    ──────────────────────────────────────────────────────────────────────────
  12416.                        save/restore
  12417.                         buffer
  12418.  
  12419. ╓┌─┌────────────────┌───┌────────────────┌────────────────┌──────────────────╖
  12420.    Equipment-List              Register
  12421.    Service          Int Input            Output           Notes
  12422.    ──────────────────────────────────────────────────────────────────────────
  12423.    Get list of      11H None             AX = equipment   Bit settings in AX:
  12424.    peripheral                            list, bit-coded  00 = diskette drive
  12425.    attached                                               installed.
  12426.    equipment.                                             01 = math
  12427.                                                           coprocessor
  12428.                                                           installed.
  12429.                                                           02, 03 = system
  12430.                                                           board RAM in 16 KB
  12431.                                                           blocks (PCs with 64
  12432.                                                           KB motherboard
  12433.                                                           only).
  12434.    Equipment-List              Register
  12435.    Service          Int Input            Output           Notes
  12436.    ──────────────────────────────────────────────────────────────────────────
  12437.                                                          only).
  12438.                                                           02 = pointing
  12439.                                                           device installed
  12440.                                                           (PS/2s only).
  12441.                                                           04, 05 = initial
  12442.                                                           video mode:
  12443.                                                           00 = unused;
  12444.                                                           01 = 40 x 25 color;
  12445.                                                           10 = 80 x 25 color;
  12446.                                                           11 = 80 x 25
  12447.                                                           monochrome.
  12448.                                                           06, 07 = number of
  12449.                                                           diskette drives -
  12450.                                                           1.
  12451.                                                           08 = (not used).
  12452.                                                           09, 10, 11 = number
  12453.                                                           of
  12454.                                                           RS-232 cards in
  12455.    Equipment-List              Register
  12456.    Service          Int Input            Output           Notes
  12457.    ──────────────────────────────────────────────────────────────────────────
  12458.                                                          RS-232 cards in
  12459.                                                           system.
  12460.                                                           12 = game I/O
  12461.                                                           attached
  12462.                                                           (PC and PC/XT
  12463.                                                           only).
  12464.                                                           13 = internal modem
  12465.                                                           installed.
  12466.                                                           14, 15 = number of
  12467.                                                           parallel printers
  12468.                                                           attached.
  12469.  
  12470. ╓┌─┌────────────────┌───┌────────────────┌────────────────┌──────────────────╖
  12471.    Memory Service              Register
  12472.                     Int Input            Output           Notes
  12473.    ──────────────────────────────────────────────────────────────────────────
  12474.    Get base         12H None             AX = memory size See also "Get
  12475.    memory size.                          (KB)             extended memory
  12476.    Memory Service              Register
  12477.                     Int Input            Output           Notes
  12478.    ──────────────────────────────────────────────────────────────────────────
  12479.   memory size.                          (KB)             extended memory
  12480.                                                           size" (INT 15H,
  12481.                                                           AH = 88H).
  12482.  
  12483. ╓┌─┌────────────────┌───┌────────────────┌────────────────┌──────────────────╖
  12484.    Disk Services               Register
  12485.                     Int Input            Output           Notes
  12486.    ──────────────────────────────────────────────────────────────────────────
  12487.    Reset disk       13H AH = 00H         CF = success/    See INT 13H,
  12488.    system.              DL = drive       failure flag     service 01H, for
  12489.                         number           AH = status code status code values.
  12490.    ──────────────────────────────────────────────────────────────────────────
  12491.    Get disk status. 13H AH = 01H         AH = status code (F) = fixed disk
  12492.                         DL = drive       Status values    only.
  12493.                         number           (hex):           (D) = diskette
  12494.                                          AH = 00H: no     only.
  12495.                                          error
  12496.                                          AH = 01H: bad
  12497.    Disk Services               Register
  12498.                     Int Input            Output           Notes
  12499.    ──────────────────────────────────────────────────────────────────────────
  12500.                                         AH = 01H: bad
  12501.                                          command
  12502.                                          AH = 02H:
  12503.                                          address mark not
  12504.                                          found
  12505.                                          AH = 03H: write
  12506.                                          attempted on
  12507.                                          write-protected
  12508.                                          disk (D)
  12509.                                          AH = 04H: sector
  12510.                                          not found
  12511.                                          AH = 05H: reset
  12512.                                          failed (F)
  12513.                                          AH = 06H:
  12514.                                          diskette removed
  12515.                                          (D)
  12516.                                          AH = 07H: bad
  12517.                                          parameter table
  12518.    Disk Services               Register
  12519.                     Int Input            Output           Notes
  12520.    ──────────────────────────────────────────────────────────────────────────
  12521.                                         parameter table
  12522.                                          (F)
  12523.                                          AH = 08H: DMA
  12524.                                          overrun
  12525.                                          AH = 09H: DMA
  12526.                                          across 64 KB
  12527.                                          boundary
  12528.                                          AH = 0AH: bad
  12529.                                          sector flag (F)
  12530.                                          AH = 0BH: bad
  12531.                                          cylinder (F)
  12532.                                          AH = 0CH: bad
  12533.                                          media type (D)
  12534.                                          AH = 0DH:
  12535.                                          invalid number
  12536.                                          of sectors on
  12537.                                          format (F)
  12538.                                          AH = 0EH:
  12539.    Disk Services               Register
  12540.                     Int Input            Output           Notes
  12541.    ──────────────────────────────────────────────────────────────────────────
  12542.                                         AH = 0EH:
  12543.                                          control data
  12544.                                          address mark
  12545.                                          detected (F)
  12546.                                          AH = 0FH: DMA
  12547.                                          arbitration
  12548.                                          level out of
  12549.                                          range (F)
  12550.                                          AH = 10H: bad
  12551.                                          CRC or ECC
  12552.                                          AH = 11H: ECC
  12553.                                          corrected data
  12554.                                          error (F)
  12555.                                          AH = 20H:
  12556.                                          controller
  12557.                                          failed
  12558.                                          AH = 40H: seek
  12559.                                          failed
  12560.    Disk Services               Register
  12561.                     Int Input            Output           Notes
  12562.    ──────────────────────────────────────────────────────────────────────────
  12563.                                         failed
  12564.                                          AH = 80H: time
  12565.                                          out (F) or drive
  12566.                                          not ready (D)
  12567.                                          AH = AAH: drive
  12568.                                          not ready (F)
  12569.                                          AH = BBH:
  12570.                                          undefined error
  12571.                                          (F)
  12572.                                          AH = CCH: write
  12573.                                          fault (F)
  12574.                                          AH = E0H: status
  12575.                                          error (F)
  12576.                                          AH = FFH: sense
  12577.                                          operation failed
  12578.                                          (F)
  12579.    ──────────────────────────────────────────────────────────────────────────
  12580.    Read disk        13H AH = 02H         CF = success/    Status codes in AH:
  12581.    Disk Services               Register
  12582.                     Int Input            Output           Notes
  12583.    ──────────────────────────────────────────────────────────────────────────
  12584.   Read disk        13H AH = 02H         CF = success/    Status codes in AH:
  12585.    sectors.             AL = number      failure flag     See INT 13H,
  12586.                         of sectors       AH = status code service 01H.
  12587.                         CH = track       AL = number of
  12588.                         number           sectors read
  12589.                         CL = sector
  12590.                         number
  12591.                         DH = head
  12592.                         number
  12593.                         DL = drive
  12594.                         number
  12595.                         ES:BX = pointer
  12596.                         to buffer
  12597.    ──────────────────────────────────────────────────────────────────────────
  12598.    Write disk       13H AH = 03H         CF = success/    Status codes in AH:
  12599.    sectors.             AL = number of   failure flag     See INT 13H,
  12600.                         sectors          AH = status code service 01H.
  12601.                         CH = track       AL = number of
  12602.    Disk Services               Register
  12603.                     Int Input            Output           Notes
  12604.    ──────────────────────────────────────────────────────────────────────────
  12605.                        CH = track       AL = number of
  12606.                         number           sectors written
  12607.                         CL = sector
  12608.                         number
  12609.                         DH = head
  12610.                         number
  12611.                         DL = drive
  12612.                         number
  12613.                         ES:BX = pointer
  12614.                         to buffer
  12615.    ──────────────────────────────────────────────────────────────────────────
  12616.    Verify disk      13H AH = 04H         CF = success/    Status codes in AH:
  12617.    sectors.             AL = number      failure flag     See INT 13H,
  12618.                         of sectors       AH = status code service 01H.
  12619.                         CH = track       AL = number of
  12620.                         number           sectors verified
  12621.                         CL = sector
  12622.                         number
  12623.    Disk Services               Register
  12624.                     Int Input            Output           Notes
  12625.    ──────────────────────────────────────────────────────────────────────────
  12626.                        number
  12627.                         DH = head number
  12628.                         DL = drive
  12629.                         number
  12630.    ──────────────────────────────────────────────────────────────────────────
  12631.    Format disk      13H AH = 05H         CF = success/    Status codes in AH:
  12632.    track                AL = interleave  failure flag     See INT 13H,
  12633.    (cylinder).          value (PC/XT     AH = status code service 01H.
  12634.                         only)                             See Chapter 10 for
  12635.                         CH = cylinder                     contents
  12636.                         number (bits                      of table.
  12637.                         0─7)
  12638.                         CL = cylinder
  12639.                         number (bits
  12640.                         8─9)
  12641.                         DH = head number
  12642.                         DL = drive
  12643.                         number
  12644.    Disk Services               Register
  12645.                     Int Input            Output           Notes
  12646.    ──────────────────────────────────────────────────────────────────────────
  12647.                        number
  12648.                         ES:BX -> table
  12649.                         of sector format
  12650.                         information
  12651.    ──────────────────────────────────────────────────────────────────────────
  12652.    Format disk      13H AH = 06H         CF = success/    PC/XT fixed disk
  12653.    track and set        AL = interleave  failure flag     only.
  12654.    bad sector           value            AH = status code
  12655.    flags.               CH = cylinder
  12656.                         number (bits
  12657.                         0─7)
  12658.                         CL = cylinder
  12659.                         number (bits
  12660.                         8─9)
  12661.                         DH = head number
  12662.                         DL = drive
  12663.                         number
  12664.    ──────────────────────────────────────────────────────────────────────────
  12665.    Disk Services               Register
  12666.                     Int Input            Output           Notes
  12667.    ──────────────────────────────────────────────────────────────────────────
  12668.   ──────────────────────────────────────────────────────────────────────────
  12669.    Format drive     13H AH = 07H         CF = success/    PC/XT fixed disk
  12670.    starting at          AL = interleave  failure flag     only.
  12671.    specified            value            AH = status code
  12672.    cylinder.            CH = cylinder
  12673.                         number (bits
  12674.                         0─7)
  12675.                         CL = cylinder
  12676.                         number (bits
  12677.                         8─9)
  12678.                         DH = head number
  12679.                         DL = drive
  12680.                         number
  12681.    ──────────────────────────────────────────────────────────────────────────
  12682.    Get current      13H AH = 08H         CF = success/    Status codes in AH:
  12683.    drive                                 failure flag     See INT 13H,
  12684.    parameters.                           AH = status code service 01H.
  12685.                                          DL = number of
  12686.    Disk Services               Register
  12687.                     Int Input            Output           Notes
  12688.    ──────────────────────────────────────────────────────────────────────────
  12689.                                         DL = number of
  12690.                                          drives
  12691.                                          DH = max.
  12692.                                          read/write head
  12693.                                          number
  12694.                                          CL (bits 6─7) =
  12695.                                          max. cylinder
  12696.                                          number
  12697.                                          (bits 8─9)
  12698.                                          CL (bits 0─5) =
  12699.                                          max.
  12700.                                          sector number
  12701.                                          CH = max. number
  12702.                                          of cylinders
  12703.                                          (bits 0─7)
  12704.    ──────────────────────────────────────────────────────────────────────────
  12705.    Initialize       13H AH = 09H         CF = success/    Interrupt 41H
  12706.    fixed-disk           DL = drive       failure flag     points to table for
  12707.    Disk Services               Register
  12708.                     Int Input            Output           Notes
  12709.    ──────────────────────────────────────────────────────────────────────────
  12710.   fixed-disk           DL = drive       failure flag     points to table for
  12711.    base tables.         number           AH = status code drive 0.
  12712.                                                           Interrupt 46H
  12713.                                                           points to table for
  12714.                                                           drive 1.
  12715.                                                           Status codes in AH:
  12716.                                                           See INT 13H,
  12717.                                                           service 01H.
  12718.    ──────────────────────────────────────────────────────────────────────────
  12719.    Read long.       13H AH = 0AH         CF = success/    Status codes in AH:
  12720.                         DL = drive       failure flag     See INT 13H,
  12721.                         number           AH = status code service 01H.
  12722.                         DH = head
  12723.                         number
  12724.                         CH = cylinder
  12725.                         number
  12726.                         CL = sector
  12727.                         number
  12728.    Disk Services               Register
  12729.                     Int Input            Output           Notes
  12730.    ──────────────────────────────────────────────────────────────────────────
  12731.                        number
  12732.                         ES:BX -> buffer
  12733.    ──────────────────────────────────────────────────────────────────────────
  12734.    Write long.      13H AH = 0BH         CF = success/    Status codes in AH:
  12735.                         DL = drive       failure flag     See INT 13H,
  12736.                         number           AH = status code service 01H.
  12737.                         DH = head
  12738.                         number
  12739.                         CH = cylinder
  12740.                         number
  12741.                         CL = sector
  12742.                         number
  12743.                         ES:BX -> buffer
  12744.    ──────────────────────────────────────────────────────────────────────────
  12745.    Seek to          13H AH = 0CH         CF = success/    Status codes in AH:
  12746.    cylinder.            DL = drive       failure flag     See INT 13H,
  12747.                         number           AH = status code service 01H.
  12748.                         DH = head
  12749.    Disk Services               Register
  12750.                     Int Input            Output           Notes
  12751.    ──────────────────────────────────────────────────────────────────────────
  12752.                        DH = head
  12753.                         number
  12754.                         CH = cylinder
  12755.                         number
  12756.    ──────────────────────────────────────────────────────────────────────────
  12757.    Alternate        13H AH = 0DH         CF = success/    Status codes in AH:
  12758.    disk reset.          DL = drive       failure flag     See INT 13H,
  12759.                         number           AH = status code service 01H.
  12760.    ──────────────────────────────────────────────────────────────────────────
  12761.    Test for         13H AH = 10H         CF = success/    Status codes in AH:
  12762.    drive ready.         DL = drive       failure flag     See INT 13H,
  12763.                         number           AH = status code service 01H.
  12764.    ──────────────────────────────────────────────────────────────────────────
  12765.    Recalibrate      13H AH = 11H         CF = success/    Status codes in AH:
  12766.    drive.               DL = drive       failure flag     See INT 13H,
  12767.                         number           AH = status code service 01H.
  12768.    ──────────────────────────────────────────────────────────────────────────
  12769.    Controller       13H AH = 14H         CF = success/    Status codes in AH:
  12770.    Disk Services               Register
  12771.                     Int Input            Output           Notes
  12772.    ──────────────────────────────────────────────────────────────────────────
  12773.   Controller       13H AH = 14H         CF = success/    Status codes in AH:
  12774.    diagnostics.                          failure flag     See INT 13H,
  12775.                                          AH = status code service 01H.
  12776.    ──────────────────────────────────────────────────────────────────────────
  12777.    Get disk type.   13H AH = 15H         CF = success/    Disk types:
  12778.                         DL = drive       failure flag     AH = 00H: disk not
  12779.                         number           AH = disk type   there.
  12780.                                          CX, DX = number  AH = 01H: diskette,
  12781.                                          of 512-byte      no change detection
  12782.                                          sectors          present.
  12783.                                          (fixed-disk      AH = 02H: diskette,
  12784.                                          only)            change detection
  12785.                                                           present.
  12786.                                                           AH = 03H: fixed
  12787.                                                           disk.
  12788.    ──────────────────────────────────────────────────────────────────────────
  12789.    Change of        13H AH = 16H         AH = diskette
  12790.    diskette status.     DL = drive       change status:
  12791.    Disk Services               Register
  12792.                     Int Input            Output           Notes
  12793.    ──────────────────────────────────────────────────────────────────────────
  12794.   diskette status.     DL = drive       change status:
  12795.                         number           00H = no
  12796.                                          diskette change
  12797.                                          01H = invalid
  12798.                                          parameter
  12799.                                          06H = diskette
  12800.                                          changed
  12801.                                          80H = drive not
  12802.                                          ready
  12803.    ──────────────────────────────────────────────────────────────────────────
  12804.    Set diskette     13H AH = 17H         CF = success/    Diskette type set
  12805.    type for format.     AL = diskette    failure flag     in AL:
  12806.                         type             AH = status code AL = 01H: 360 KB
  12807.                         DL = drive                        diskette in 360 KB
  12808.                         number                            drive.
  12809.                                                           AL = 02H: 360 KB
  12810.                                                           diskette in 1.2 MB
  12811.                                                           drive.
  12812.    Disk Services               Register
  12813.                     Int Input            Output           Notes
  12814.    ──────────────────────────────────────────────────────────────────────────
  12815.                                                          drive.
  12816.                                                           AL = 03H: 1.2 MB
  12817.                                                           diskette in 1.2 MB
  12818.                                                           drive.
  12819.                                                           AL = 04H: 720 KB
  12820.                                                           diskette in 720 KB
  12821.                                                           drive.
  12822.    ──────────────────────────────────────────────────────────────────────────
  12823.    Set media type   13H AH = 18H         CF = success/    Only in PC/AT BIOS
  12824.    for diskette         CH = number of   failure flag     dated 11/15/85 and
  12825.    format.              tracks (bits     AH = status code later, PC/XT BIOS
  12826.                         0─7)             ES:DI -> 11-byte dated 1/10/86 and
  12827.                         CL (bits 6─7) =  parameter table  later, and PS/2s.
  12828.                         number of tracks (disk-base
  12829.                         (bits 8─9)       table)
  12830.                         CL (bits 0─5) =
  12831.                         sectors per
  12832.                         track
  12833.    Disk Services               Register
  12834.                     Int Input            Output           Notes
  12835.    ──────────────────────────────────────────────────────────────────────────
  12836.                        track
  12837.                         DL = drive
  12838.                         number
  12839.    ──────────────────────────────────────────────────────────────────────────
  12840.    Park heads.      13H AH = 19H         CF = success/    PS/2s only.
  12841.                         DL = drive       failure flag
  12842.                         number           AH = status code
  12843.    ──────────────────────────────────────────────────────────────────────────
  12844.    Format Unit.     13H AH = 1AH         None             For PS/2 fixed
  12845.                                                           disks used with IBM
  12846.                                                           Enhanced Small
  12847.                                                           Device Interface
  12848.                                                           (ESDI) adapter. See
  12849.                                                           the IBM BIOS
  12850.                                                           Interface
  12851.                                                           Technical Reference
  12852.                                                           Manual.
  12853.  
  12854. ╓┌─┌────────────────┌───┌────────────────┌────────────────┌──────────────────╖
  12855.    Serial Port                 Register
  12856.    Services         Int Input            Output           Notes
  12857.    ──────────────────────────────────────────────────────────────────────────
  12858.    Initialize       14H AH = 00H         AX = serial port Serial port
  12859.    serial port.         AL = serial port status           parameter
  12860.                         parameters                        bit settings:
  12861.                         DX = serial port                  bits 0─1 = word
  12862.                         number                            length:
  12863.                                                           10 = 7 bits; 11 = 8
  12864.                                                           bits.
  12865.                                                           bit 2 = stop bits:
  12866.                                                           0 = 1; 1 = 2.
  12867.                                                           bits 3─4 = parity:
  12868.                                                           00, 10 = none; 01 =
  12869.                                                           odd;
  12870.                                                           11 = even.
  12871.                                                           bits 5─7 = baud
  12872.                                                           rate:
  12873.                                                           000 = 110;
  12874.                                                           001 = 150;
  12875.    Serial Port                 Register
  12876.    Services         Int Input            Output           Notes
  12877.    ──────────────────────────────────────────────────────────────────────────
  12878.                                                          001 = 150;
  12879.                                                           010 = 300;
  12880.                                                           011 = 600;
  12881.                                                           100 = 1200;
  12882.                                                           101 = 2400;
  12883.                                                           110 = 4800;
  12884.                                                           111 = 9600.
  12885.                                                           For PC/XT/AT family
  12886.                                                           only. For PS/2s,
  12887.                                                           use subservice 04H,
  12888.                                                           "Extended serial
  12889.                                                           port initialize."
  12890.                                                           See page 280.
  12891.    ──────────────────────────────────────────────────────────────────────────
  12892.    Send one         14H AH = 01H         AH = status code Status bit
  12893.    character to         AL = character                    settings: See INT
  12894.    serial port.         DX = serial port                  14H, service 03H.
  12895.                         number
  12896.    Serial Port                 Register
  12897.    Services         Int Input            Output           Notes
  12898.    ──────────────────────────────────────────────────────────────────────────
  12899.                        number
  12900.    ──────────────────────────────────────────────────────────────────────────
  12901.    Receive one      14H AH = 02H         AH = status code Status bit
  12902.    character from       DX = serial port AL = character   settings: See INT
  12903.    serial port.         number                            14H, service 03H.
  12904.    ──────────────────────────────────────────────────────────────────────────
  12905.    Get serial port  14H AH = 03H         AX = status code Status code bit
  12906.    status.              DX = serial port                  settings:
  12907.                         number                            AH bit settings:
  12908.                                                           bit 0 = data ready.
  12909.                                                           bit 1 = overrun
  12910.                                                           error.
  12911.                                                           bit 2 = parity
  12912.                                                           error.
  12913.                                                           bit 3 = framing
  12914.                                                           error.
  12915.                                                           bit 4 = break
  12916.                                                           detected.
  12917.    Serial Port                 Register
  12918.    Services         Int Input            Output           Notes
  12919.    ──────────────────────────────────────────────────────────────────────────
  12920.                                                          detected.
  12921.                                                           bit 5 =
  12922.                                                           transmission buffer
  12923.                                                           register empty.
  12924.                                                           bit 6 =
  12925.                                                           transmission shift
  12926.                                                           register empty.
  12927.                                                           bit 7 = time out.
  12928.                                                           AL bit settings:
  12929.                                                           bit 0 = delta
  12930.                                                           clear-to-send.
  12931.                                                           bit 1 = delta
  12932.                                                           data-set-ready.
  12933.                                                           bit 2 =
  12934.                                                           trailing-edge ring
  12935.                                                           detected.
  12936.                                                           bit 3 = change,
  12937.                                                           receive line signal
  12938.    Serial Port                 Register
  12939.    Services         Int Input            Output           Notes
  12940.    ──────────────────────────────────────────────────────────────────────────
  12941.                                                          receive line signal
  12942.                                                           detected.
  12943.                                                           bit 4 =
  12944.                                                           clear-to-send.
  12945.                                                           bit 5 =
  12946.                                                           data-set-ready.
  12947.                                                           bit 6 = ring
  12948.                                                           detected.
  12949.                                                           bit 7 = receive
  12950.                                                           line signal
  12951.                                                           detected.
  12952.    ──────────────────────────────────────────────────────────────────────────
  12953.    Extended serial  14H AH = 04H         AH = line status PS/2s only. See
  12954.    port initialize.     AL = break       AL = modem       Chapter 12
  12955.                         BH = parity      status           for details.
  12956.                         BL = stop bit
  12957.                         CH = word length
  12958.                         CL = baud rate
  12959.    Serial Port                 Register
  12960.    Services         Int Input            Output           Notes
  12961.    ──────────────────────────────────────────────────────────────────────────
  12962.                        CL = baud rate
  12963.                         DX = serial port
  12964.                         number (0─3)
  12965.    ──────────────────────────────────────────────────────────────────────────
  12966.    Extended serial  14H AH = 05H         AH = line status For PS/2s only. See
  12967.    port control.        DX = serial port AL = modem       Chapter 12 for
  12968.                         number           status           details.
  12969.                         (0, 1, 2, 3)     If called with
  12970.                         To read modem    AL = 00H:
  12971.                         control          BL = modem
  12972.                         register:        control register
  12973.                         AL = 00H         value
  12974.                         To write modem
  12975.                         control
  12976.                         register:
  12977.                         AL = 01H
  12978.                         BL = value for
  12979.                         modem control
  12980.    Serial Port                 Register
  12981.    Services         Int Input            Output           Notes
  12982.    ──────────────────────────────────────────────────────────────────────────
  12983.                        modem control
  12984.                         register
  12985.  
  12986. ╓┌─┌────────────────┌───┌────────────────┌────────────────┌──────────────────╖
  12987.    System                      Register
  12988.    Services        Int Input            Output           Notes
  12989.    ──────────────────────────────────────────────────────────────────────────
  12990.    Turn on cassette 15H AH = 00H         AH = 00H         IBM PC only.
  12991.    motor.                                CF = 0
  12992.    ──────────────────────────────────────────────────────────────────────────
  12993.    Turn off         15H AH = 01H         AH = 00H         IBM PC only.
  12994.    cassette motor.                       CF = 0
  12995.    ──────────────────────────────────────────────────────────────────────────
  12996.    Read cassette    15H AH = 02H         ES:BX -> last    IBM PC only.
  12997.    data blocks.         CX = number      byte
  12998.                         of bytes         read + 1
  12999.                         ES:BX -> data    DX = number of
  13000.                         area             bytes read
  13001.    System                      Register
  13002.    Services        Int Input            Output           Notes
  13003.    ──────────────────────────────────────────────────────────────────────────
  13004.                        area             bytes read
  13005.                                          CF = 0 (no
  13006.                                          error)
  13007.                                          or 1 (error)
  13008.    ──────────────────────────────────────────────────────────────────────────
  13009.    Write cassette   15H AH = 03H         CF = success/    IBM PC only.
  13010.    data blocks.         CX = number of   failure flag
  13011.                         bytes            ES:BX -> last
  13012.                         ES:BX -> data    byte
  13013.                         area             written + 1
  13014.                                          CX = 00H
  13015.    ──────────────────────────────────────────────────────────────────────────
  13016.    Read/Write       15H AH = 21H         AH = 00H         PS/2 models 50, 60,
  13017.    power-on             To read error    If called with   80.
  13018.    self-test error      log:             AL = 00H:
  13019.    log.                 AL = 00H         BX = number of
  13020.                         To write error   POST
  13021.                         log:             error codes
  13022.    System                      Register
  13023.    Services        Int Input            Output           Notes
  13024.    ──────────────────────────────────────────────────────────────────────────
  13025.                        log:             error codes
  13026.                         AL = 01H         logged
  13027.                         BH = device code ES:DI -> POST
  13028.                         BL = error code  error log
  13029.                                          If called with
  13030.                                          AL = 01H:
  13031.                                          CF = status (0:
  13032.                                          no error; 1: log
  13033.                                          full)
  13034.    ──────────────────────────────────────────────────────────────────────────
  13035.    Keyboard         15H AH = 4FH                          See Chapter 12 for
  13036.    intercept.                                             details.
  13037.  
  13038.    ──────────────────────────────────────────────────────────────────────────
  13039.    Device open.     15H AH = 80H                          See Chapter 12 for
  13040.                                                           details.
  13041.    ──────────────────────────────────────────────────────────────────────────
  13042.    Device close.    15H AH = 81H                          See Chapter 12 for
  13043.    System                      Register
  13044.    Services        Int Input            Output           Notes
  13045.    ──────────────────────────────────────────────────────────────────────────
  13046.   Device close.    15H AH = 81H                          See Chapter 12 for
  13047.                                                           details.
  13048.    ──────────────────────────────────────────────────────────────────────────
  13049.    Program          15H AH = 82H                          See Chapter 12 for
  13050.    termination.                                           details.
  13051.    ──────────────────────────────────────────────────────────────────────────
  13052.    Start/stop       15H AH = 83H         If called with   PC/AT and PS/2
  13053.    interval timer       To start         AL = 00H:        models 50, 60, 80.
  13054.    (event wait).        interval timer:  CF = 0 (if timer At completion of
  13055.                         AL = 00H         started) or      specified interval,
  13056.                         CX,DX = time in  CF = 1 (if timer the high-order bit
  13057.                         microseconds     already running  of the byte at
  13058.                         ES:BX -> 1-byte  or               ES:BX is set to 1.
  13059.                         flag             function not
  13060.                         To stop interval supported)
  13061.                         timer:           If called with
  13062.                         AL = 01H         AL = 01H:
  13063.                                          CF = 0 (if timer
  13064.    System                      Register
  13065.    Services        Int Input            Output           Notes
  13066.    ──────────────────────────────────────────────────────────────────────────
  13067.                                         CF = 0 (if timer
  13068.                                          canceled)
  13069.                                          CF = 1 (if
  13070.                                          function
  13071.                                          not supported)
  13072.    ──────────────────────────────────────────────────────────────────────────
  13073.    Joystick         15H AH = 84H         If called with   Not supported by PC
  13074.    support.             To read          DX = 00H:        or XT BIOS prior to
  13075.                         switches:        AL = switch      01/10/86.
  13076.                         DX = 00H         settings
  13077.                         To read          (bits 4─7)
  13078.                         resistive        CF = 0 (if
  13079.                         inputs:          switches
  13080.                         DX = 00H         successfully
  13081.                                          read)
  13082.                                          or CF = 1
  13083.                                          (if
  13084.                                          unsuccessful)
  13085.    System                      Register
  13086.    Services        Int Input            Output           Notes
  13087.    ──────────────────────────────────────────────────────────────────────────
  13088.                                         unsuccessful)
  13089.                                          If called with
  13090.                                          DX = 01H:
  13091.                                          AX = stick A
  13092.                                          x-value
  13093.                                          BX = stick A
  13094.                                          y-value
  13095.                                          CX = stick B
  13096.                                          x-value
  13097.                                          DX = stick B
  13098.                                          y-value
  13099.    ──────────────────────────────────────────────────────────────────────────
  13100.    Sys Req          15H AH = 85H                          See Chapter 12 for
  13101.    keystroke.           AL = key status                   details.
  13102.    ──────────────────────────────────────────────────────────────────────────
  13103.    Wait during      15H AH = 86H         CF = 0 (if       PC/AT and PS/2s
  13104.    a specified          CX,DX = time in  successful)      only.
  13105.    interval.            microseconds     CF = 1 (timer
  13106.    System                      Register
  13107.    Services        Int Input            Output           Notes
  13108.    ──────────────────────────────────────────────────────────────────────────
  13109.   interval.            microseconds     CF = 1 (timer
  13110.                                          already running
  13111.                                          or
  13112.                                          function not
  13113.                                          supported)
  13114.    ──────────────────────────────────────────────────────────────────────────
  13115.    Protected-mode   15H AH = 87H                          PC/AT and PS/2
  13116.    data move.                                             models 50, 60, 80.
  13117.                                                           See the IBM BIOS
  13118.                                                           Technical Reference
  13119.                                                           Manual for details.
  13120.    ──────────────────────────────────────────────────────────────────────────
  13121.    Get extended     15H AH = 88H         AX = memory size PC/AT and PS/2
  13122.    memory size.                          (KB)             models 50, 60, 80.
  13123.    ──────────────────────────────────────────────────────────────────────────
  13124.    Switch to        15H AH = 89H                          PC/AT and PS/2
  13125.    protected mode.                                        models 50, 60, 80.
  13126.                                                           See the IBM BIOS
  13127.    System                      Register
  13128.    Services        Int Input            Output           Notes
  13129.    ──────────────────────────────────────────────────────────────────────────
  13130.                                                          See the IBM BIOS
  13131.                                                           Technical Reference
  13132.                                                           Manual for details.
  13133.    ──────────────────────────────────────────────────────────────────────────
  13134.    Device busy.     15H AH = 90H                          See Chapter 12 for
  13135.                                                           details.
  13136.    ──────────────────────────────────────────────────────────────────────────
  13137.    Interrupt        15H AH = 91H                          See Chapter 12 for
  13138.    complete.                                              details.
  13139.    ──────────────────────────────────────────────────────────────────────────
  13140.    Get system       15H AH = C0H         AH = 0           See Chapter 12 for
  13141.    configuration                         CF = 0           details. Not
  13142.    parameters.                           ES:BX -> ROM     supported in PC, XT
  13143.                                          BIOS system      BIOS prior to
  13144.                                          configuration    01/10/86, or AT
  13145.                                          parameters       prior to 06/10/85.
  13146.    ──────────────────────────────────────────────────────────────────────────
  13147.    Get extended     15H AH = C1H         CF = 0           PS/2s only.
  13148.    System                      Register
  13149.    Services        Int Input            Output           Notes
  13150.    ──────────────────────────────────────────────────────────────────────────
  13151.   Get extended     15H AH = C1H         CF = 0           PS/2s only.
  13152.    BIOS data                             ES = extended
  13153.    segment.                              BIOS data
  13154.                                          segment address
  13155.    ──────────────────────────────────────────────────────────────────────────
  13156.    Enable/disable   15H AH = C2H         CF = 0 if        PS/2s only.
  13157.    pointing device.     AL = 00H         successful;
  13158.                         To enable:       1 if error
  13159.                         BH = 00H         AH = status:
  13160.                         To disable:      00H: no error
  13161.                         BH = 01H         01H: invalid
  13162.                                          function call
  13163.                                          02H: invalid
  13164.                                          input
  13165.                                          03H: interface
  13166.                                          error
  13167.                                          04H: resend
  13168.                                          05H: no device
  13169.    System                      Register
  13170.    Services        Int Input            Output           Notes
  13171.    ──────────────────────────────────────────────────────────────────────────
  13172.                                         05H: no device
  13173.                                          driver installed
  13174.    ──────────────────────────────────────────────────────────────────────────
  13175.    Reset pointing   15H AH = C2H         CF = 0 if        PS/2s only.
  13176.    device.              AL = 01H         successful;
  13177.                                          1 if error
  13178.                                          AH = status
  13179.                                          (as above)
  13180.                                          BH = 00H (device
  13181.                                          ID)
  13182.                                          BL = undefined
  13183.    ──────────────────────────────────────────────────────────────────────────
  13184.    Set pointing-    15H AH = C2H         CF = 0 if        PS/2s only.
  13185.    device sample        AL = 02H         successful;
  13186.    rate.                BH = sample      1 if error
  13187.                         rate:            AH = status
  13188.                         00H: 10/second   (as above)
  13189.                         01H: 20/second
  13190.    System                      Register
  13191.    Services        Int Input            Output           Notes
  13192.    ──────────────────────────────────────────────────────────────────────────
  13193.                        01H: 20/second
  13194.                         02H: 40/second
  13195.                         03H: 60/second
  13196.                         04H: 80/second
  13197.                         05H: 100/second
  13198.                         06H: 200/second
  13199.    ──────────────────────────────────────────────────────────────────────────
  13200.    Set pointing-    15H AH = C2H         CF = 0 if        PS/2s only.
  13201.    device               AL = 03H         successful;
  13202.    resolution.          BH = resolution: 1 if error
  13203.                         00H: 1           AH = status
  13204.                         count/millimeter (as above)
  13205.                         01H: 2
  13206.                         count/millimeter
  13207.                         02H: 4
  13208.                         count/millimeter
  13209.                         03H: 8
  13210.                         count/millimeter
  13211.    System                      Register
  13212.    Services        Int Input            Output           Notes
  13213.    ──────────────────────────────────────────────────────────────────────────
  13214.                        count/millimeter
  13215.    ──────────────────────────────────────────────────────────────────────────
  13216.    Get              15H AH = C2H         CF = 0 if        PS/2s only.
  13217.    pointing-device      AL = 04H         successful; 1 if
  13218.    type.                                 error
  13219.                                          AH = status (as
  13220.                                          above)
  13221.                                          BH = device ID
  13222.    ──────────────────────────────────────────────────────────────────────────
  13223.    Initialize       15H AH = C2H         CF = 0 if        PS/2s only.
  13224.    pointing device.     AL = 05H         successful; 1 if
  13225.                         BH = data packet error
  13226.                         size (1─8 bytes) AH = status (as
  13227.                                          above)
  13228.    ──────────────────────────────────────────────────────────────────────────
  13229.    Extended         15H AH = C2H         CF = 0 if        PS/2s only. See
  13230.    pointing-device      AL = 06H         successful;      Chapter 12 for
  13231.    commands.            To get status:   1 if error       contents of status
  13232.    System                      Register
  13233.    Services        Int Input            Output           Notes
  13234.    ──────────────────────────────────────────────────────────────────────────
  13235.   commands.            To get status:   1 if error       contents of status
  13236.                         BH = 00H         AH = status (as  bytes.
  13237.                         To set scaling   above)
  13238.                         to 1:1:          If called with
  13239.                         BH = 01H         BH = 00H:
  13240.                         To set scaling   BL = status byte
  13241.                         to 2:1:          1
  13242.                         BH = 02H         CL = status byte
  13243.                                          2
  13244.                                          DL = status byte
  13245.                                          3
  13246.    ──────────────────────────────────────────────────────────────────────────
  13247.    Pass             15H AH = C2H         CF = 0 if        PS/2s only.
  13248.    pointing-device      AL = 07H         successful;
  13249.    driver address       ES:BX -> device  1 if error
  13250.    to BIOS.             driver           AH = status (as
  13251.                                          above)
  13252.    ──────────────────────────────────────────────────────────────────────────
  13253.    System                      Register
  13254.    Services        Int Input            Output           Notes
  13255.    ──────────────────────────────────────────────────────────────────────────
  13256.   ──────────────────────────────────────────────────────────────────────────
  13257.    Enable/disable   15H AH = C3H         CF = 0           PS/2 models 50, 60,
  13258.    watchdog timer.      BX = timer count if successful    80 only.
  13259.                         (01H─FFH)
  13260.                         To enable:
  13261.                         AL = 01H
  13262.                         To disable:
  13263.                         AL = 00H
  13264.    ──────────────────────────────────────────────────────────────────────────
  13265.    Programmable     15H AH = C4H         If called with   PS/2 models 50, 60,
  13266.    Option Select        To get POS       AL = 00H:        80 only.
  13267.    (POS) interface.     register base    AL = 00H
  13268.                         address:         DX = base POS
  13269.                         AL = 00H         register address
  13270.                         To enable slot   If called with
  13271.                         for POS setup:   AL = 01H:
  13272.                         AL = 01H         AL = 01H
  13273.                         To enable an     BL = slot number
  13274.    System                      Register
  13275.    Services        Int Input            Output           Notes
  13276.    ──────────────────────────────────────────────────────────────────────────
  13277.                        To enable an     BL = slot number
  13278.                         adapter:         If called with
  13279.                         AL = 02H         AL = 02H:
  13280.                                          AL = 02H
  13281.  
  13282. ╓┌─┌────────────────┌───┌────────────────┌────────────────┌──────────────────╖
  13283.    Keyboard                    Register
  13284.    Services         Int Input            Output           Notes
  13285.    ──────────────────────────────────────────────────────────────────────────
  13286.    Read next        16H AH = 00H         AH = scan code
  13287.    keystroke.                            AL = ASCII
  13288.                                          character code
  13289.    ──────────────────────────────────────────────────────────────────────────
  13290.    Report whether   16H AH = 01H         ZF = 0 if
  13291.    keystroke ready.                      keystroke
  13292.                                          available
  13293.                                          AH = scan code
  13294.                                          (if ZF = 0)
  13295.    Keyboard                    Register
  13296.    Services         Int Input            Output           Notes
  13297.    ──────────────────────────────────────────────────────────────────────────
  13298.                                         (if ZF = 0)
  13299.                                          AL = ASCII
  13300.                                          character code
  13301.                                          (if ZF = 0)
  13302.    ──────────────────────────────────────────────────────────────────────────
  13303.    Get shift        16H AH = 02H         AL = shift       Shift status bits:
  13304.    status.                               status bits      bit 7 = 1: Insert
  13305.                                                           state active
  13306.                                                           bit 6 = 1: Caps
  13307.                                                           Lock active
  13308.                                                           bit 5 = 1: Num Lock
  13309.                                                           active
  13310.                                                           bit 4 = 1: Scroll
  13311.                                                           Lock active
  13312.                                                           bit 3 = 1: Alt
  13313.                                                           pressed
  13314.                                                           bit 2 = 1: Ctrl
  13315.                                                           pressed
  13316.    Keyboard                    Register
  13317.    Services         Int Input            Output           Notes
  13318.    ──────────────────────────────────────────────────────────────────────────
  13319.                                                          pressed
  13320.                                                           bit 1 = 1: left
  13321.                                                           Shift pressed
  13322.                                                           bit 0 = 1: right
  13323.                                                           Shift pressed
  13324.    ──────────────────────────────────────────────────────────────────────────
  13325.    Set typematic    16H AH = 03H         None             PC/AT (BIOS dated
  13326.    rate and delay.      AL = 05H                          11/15/85 and later)
  13327.                         BL = typematic                    and PS/2s only. See
  13328.                         rate                              Chapter 11 for
  13329.                         BH = delay value                  rate and values.
  13330.    ──────────────────────────────────────────────────────────────────────────
  13331.    Write to         16H AH = 05H         AL = 00H         PC/XT (BIOS dated
  13332.    keyboard buffer.     CH = scan code   (success);       01/10/86 and
  13333.                         CL = ASCII       AL = 01H         later), PC/AT (BIOS
  13334.                         character code   (keyboard        dated 11/15/85 and
  13335.                                          buffer full)     later), and PS/2s
  13336.                                                           only.
  13337.    Keyboard                    Register
  13338.    Services         Int Input            Output           Notes
  13339.    ──────────────────────────────────────────────────────────────────────────
  13340.                                                          only.
  13341.    ──────────────────────────────────────────────────────────────────────────
  13342.    Extended         16H AH = 10H         AH = scan code   PC/XT (BIOS dated
  13343.    keyboard read.                        AL = ASCII       01/10/86 and
  13344.                                          character code   later), PC/AT (BIOS
  13345.                                                           dated 11/15/85 and
  13346.                                                           later), and PS/2s
  13347.                                                           only.
  13348.    ──────────────────────────────────────────────────────────────────────────
  13349.    Extended         16H AH = 11H         If no keystroke  PC/XT (BIOS dated
  13350.    keyboard status.                      available:       01/10/86 and
  13351.                                          ZF = 1           later), PC/AT (BIOS
  13352.                                          If keystroke     dated 11/15/85 and
  13353.                                          available:       later), and PS/2s
  13354.                                          ZF = 0           only.
  13355.                                          AH = scan code
  13356.                                          AL = ASCII
  13357.                                          character code
  13358.    Keyboard                    Register
  13359.    Services         Int Input            Output           Notes
  13360.    ──────────────────────────────────────────────────────────────────────────
  13361.                                         character code
  13362.    ──────────────────────────────────────────────────────────────────────────
  13363.    Extended shift   16H AH = 12H         AL = shift       PC/XT (BIOS dated
  13364.    status.                               status           01/10/86 and
  13365.                                          (as above)       later), PC/AT (BIOS
  13366.                                          AH = extended    dated 11/15/85 and
  13367.                                          shift            later), and PS/2s
  13368.                                          status:          only.
  13369.                                          bit 7: Sys Req
  13370.                                          is pressed
  13371.                                          bit 6: CapsLock
  13372.                                          is pressed
  13373.                                          bit 5: NumLock
  13374.                                          is pressed
  13375.                                          bit 4:
  13376.                                          ScrollLock
  13377.                                          is pressed
  13378.                                          bit 3: right Alt
  13379.    Keyboard                    Register
  13380.    Services         Int Input            Output           Notes
  13381.    ──────────────────────────────────────────────────────────────────────────
  13382.                                         bit 3: right Alt
  13383.                                          is pressed
  13384.                                          bit 2: right
  13385.                                          Ctrl
  13386.                                          is pressed
  13387.                                          bit 1: left Alt
  13388.                                          is pressed
  13389.                                          bit 0: left Ctrl
  13390.                                          is pressed
  13391.  
  13392. ╓┌─┌────────────────┌───┌────────────────┌────────────────┌──────────────────╖
  13393.    Printer Services            Register
  13394.                     Int Input            Output           Notes
  13395.    ──────────────────────────────────────────────────────────────────────────
  13396.    Send 1 byte to   17H AH = 00H         AH = success/    Status bit
  13397.    printer.             AL = character   failure status   settings:
  13398.                         DX = printer     flags            bit 7 = 1: not busy
  13399.                         number                            bit 6 = 1:
  13400.    Printer Services            Register
  13401.                     Int Input            Output           Notes
  13402.    ──────────────────────────────────────────────────────────────────────────
  13403.                        number                            bit 6 = 1:
  13404.                                                           acknowledge
  13405.                                                           bit 5 = 1: out of
  13406.                                                           paper
  13407.                                                           bit 4 = 1: selected
  13408.                                                           bit 3 = 1: I/O
  13409.                                                           error
  13410.                                                           bit 2 = unused
  13411.                                                           bit 1 = unused
  13412.                                                           bit 0 = time out
  13413.    ──────────────────────────────────────────────────────────────────────────
  13414.    Initialize       17H AH = 01H         AH = status code Status code bit
  13415.    printer.             DX = printer                      settings as above.
  13416.                         number
  13417.    ──────────────────────────────────────────────────────────────────────────
  13418.    Get printer      17H AH = 02H         AH = status code Status code bit
  13419.    status.              DX = printer                      settings as above.
  13420.                         number
  13421.    Printer Services            Register
  13422.                     Int Input            Output           Notes
  13423.    ──────────────────────────────────────────────────────────────────────────
  13424.                        number
  13425.  
  13426.  
  13427.  
  13428.  
  13429.  
  13430. ╓┌─┌────────────────┌───┌────────────────┌────────────────┌──────────────────╖
  13431.    Miscellaneous               Register
  13432.    Services         Int Input            Output           Notes
  13433.    ──────────────────────────────────────────────────────────────────────────
  13434.    Switch control   18H None             N/A              No return, so no
  13435.    to                                                     possible output.
  13436.    ROM BASIC.
  13437.    ──────────────────────────────────────────────────────────────────────────
  13438.    Reboot computer. 19H None             N/A              No return, so no
  13439.                                                           possible output.
  13440.  
  13441.  
  13442.    Miscellaneous               Register
  13443.    Services         Int Input            Output           Notes
  13444.    ──────────────────────────────────────────────────────────────────────────
  13445. 
  13446.  
  13447.  
  13448.  
  13449.  
  13450. ╓┌─┌────────────────┌───┌────────────────┌────────────────┌──────────────────╖
  13451.    Time-of-Day                 Register
  13452.    Services         Int Input            Output           Notes
  13453.    ──────────────────────────────────────────────────────────────────────────
  13454.    Read current     1AH AH = 00H         AL > 00H if time Timer-tick
  13455.    clock count.                          of day has       frequency is about
  13456.                                          passed           18.2 ticks/second,
  13457.                                          midnight         or about 65,543
  13458.                                          CX = tick count, ticks/hour.
  13459.                                          high word
  13460.                                          DX = tick count,
  13461.                                          low word
  13462.    ──────────────────────────────────────────────────────────────────────────
  13463.    Time-of-Day                 Register
  13464.    Services         Int Input            Output           Notes
  13465.    ──────────────────────────────────────────────────────────────────────────
  13466.   ──────────────────────────────────────────────────────────────────────────
  13467.    Set current      1AH AH = 01H         None
  13468.    clock count.         CX = tick count,
  13469.                         high word
  13470.                         DX = tick count,
  13471.                         low word
  13472.    ──────────────────────────────────────────────────────────────────────────
  13473.    Read real-time   1AH AH = 02H         CH = hours       PC/AT and PS/2s
  13474.    clock.                                (in BCD)         only. Daylight
  13475.                                          CL = minutes     savings option not
  13476.                                          (in BCD)         available in PC/AT
  13477.                                          DH = seconds     BIOS dated
  13478.                                          (in BCD)         01/10/84.
  13479.                                          CF = 1 if clock
  13480.                                          not operating
  13481.                                          DL = 01H if
  13482.                                          daylight savings
  13483.                                          time option set
  13484.    Time-of-Day                 Register
  13485.    Services         Int Input            Output           Notes
  13486.    ──────────────────────────────────────────────────────────────────────────
  13487.                                         time option set
  13488.    ──────────────────────────────────────────────────────────────────────────
  13489.    Set real-time    1AH AH = 03H                          Input values in
  13490.    clock.               CH = hours                        BCD.
  13491.                         CL = minutes                      PC/AT and PS/2s
  13492.                         DH = seconds                      only. Daylight
  13493.                         DL = 01H for                      savings option not
  13494.                         automatic                         available in PC/AT
  13495.                         adjustment for                    BIOS dated
  13496.                         daylight savings                  01/10/84.
  13497.                         time
  13498.    ──────────────────────────────────────────────────────────────────────────
  13499.    Read date from   1AH AH = 04H         DL = day (in     PC/AT and PS/2s
  13500.    real-time clock.                      BCD)             only.
  13501.                                          DH = month (in
  13502.                                          BCD)
  13503.                                          CL = year (in
  13504.                                          BCD)
  13505.    Time-of-Day                 Register
  13506.    Services         Int Input            Output           Notes
  13507.    ──────────────────────────────────────────────────────────────────────────
  13508.                                         BCD)
  13509.                                          CH = century (19
  13510.                                          or 20 in BCD)
  13511.                                          CF = 1 if clock
  13512.                                          not operating
  13513.    ──────────────────────────────────────────────────────────────────────────
  13514.    Set date in      1AH AH = 05H                          PC/AT and PS/2s
  13515.    real-time clock.     DL = day                          only.
  13516.                         (in BCD)
  13517.                         DH = month
  13518.                         (in BCD)
  13519.                         CL = year
  13520.                         (in BCD)
  13521.                         CH = century (19
  13522.                         or 20, in BCD)
  13523.    ──────────────────────────────────────────────────────────────────────────
  13524.    Set alarm.       1AH AH = 06H         CF = 1 if clock  Place address for
  13525.                         CH = hours       not operating or alarm routine in
  13526.    Time-of-Day                 Register
  13527.    Services         Int Input            Output           Notes
  13528.    ──────────────────────────────────────────────────────────────────────────
  13529.                        CH = hours       not operating or alarm routine in
  13530.                         (in BCD)         alarm already    interrupt 4AH
  13531.                         CL = minutes     set              vector before using
  13532.                         (in BCD)                          this service.
  13533.                         DH = seconds
  13534.                         (in BCD)
  13535.    ──────────────────────────────────────────────────────────────────────────
  13536.    Reset alarm.     1AH AH = 07H         None             Disables alarm
  13537.                                                           previously set with
  13538.                                                           INT 1AH, service
  13539.                                                           06H.
  13540.    ──────────────────────────────────────────────────────────────────────────
  13541.    Get alarm time   1AH AH = 09H         CH = hours (in   PS/2 models 25, 30
  13542.    and status.                           BCD)             only.
  13543.                                          CL = minutes (in
  13544.                                          BCD)
  13545.                                          DH = seconds (in
  13546.                                          BCD)
  13547.    Time-of-Day                 Register
  13548.    Services         Int Input            Output           Notes
  13549.    ──────────────────────────────────────────────────────────────────────────
  13550.                                         BCD)
  13551.                                          DL = alarm
  13552.                                          status:
  13553.                                          00H: alarm not
  13554.                                          enabled
  13555.                                          01H: alarm
  13556.                                          enabled
  13557.    ──────────────────────────────────────────────────────────────────────────
  13558.  
  13559.  
  13560.  
  13561.  
  13562.  ────────────────────────────────────────────────────────────────────────────
  13563.  Chapter 14  DOS Basics
  13564.  
  13565.    The Pros and Cons of Using the DOS Services
  13566.      DOS: A Disk-Service Cornucopia
  13567.      DOS and Video: A Difficult Match
  13568.  
  13569.    DOS Version Differences
  13570.  
  13571.    Diskette Format Considerations
  13572.  
  13573.    Comments
  13574.  
  13575.    Chapters 15 through 18 focus on the program support services provided by
  13576.    DOS. These DOS services are the entire set of operations that DOS provides
  13577.    to programs. The last chapter in the series, Chapter 18, summarizes their
  13578.    technical details. In this chapter, we introduce some of the main concerns
  13579.    a programmer often faces when working with the DOS services.
  13580.  
  13581.    Programs access DOS services through a set of interrupts. Interrupt
  13582.    numbers 20H through 3FH (decimal 32 through 63) are reserved for use by
  13583.    DOS. Although 10 of these interrupts can be used in programs, most DOS
  13584.    services are invoked in much the same way as the ROM BIOS services:
  13585.    through one umbrella interrupt, interrupt 21H (decimal 33). You can access
  13586.    a variety of DOS functions by specifying a function number in register AH
  13587.    at the time you call interrupt 21H.
  13588.  
  13589.  
  13590.  The Pros and Cons of Using the DOS Services
  13591.  
  13592.    The question of whether or not to use the DOS services arises naturally
  13593.    during the design and development of sophisticated programs. Our general
  13594.    advice, echoed throughout this book, is for you to use the highest
  13595.    available services that will accomplish what you need. This means that,
  13596.    whenever possible, you should use the built-in services of your
  13597.    programming language first, resorting only when necessary to direct use of
  13598.    the DOS services or the ROM BIOS services, and resorting only in extreme
  13599.    circumstances to direct programming of the computer's hardware.
  13600.  
  13601.    In practical terms, either a program can be written entirely within the
  13602.    confines of the programming language's facilities or nearly all of its I/O
  13603.    work must be done outside the programming language, at a lower level. When
  13604.    a lower level of programming is needed, with very few exceptions the DOS
  13605.    services are best suited for disk operations. When you are working with
  13606.    the keyboard or other I/O devices, either the DOS routines or the ROM BIOS
  13607.    routines will be adequate, depending on the application. But for low-level
  13608.    video-display programming, the situation is more complex. Satisfactory
  13609.    screen output almost always seems to call for the ROM BIOS services and
  13610.    direct hardware programming, even though in some cases screen output is
  13611.    best left in the hands of DOS. We'll see why in a moment.
  13612.  
  13613.  DOS: A Disk-Service Cornucopia
  13614.  
  13615.    When you inspect the full range of tools and services placed in your hands
  13616.    by programming languages, by DOS, by the ROM BIOS, and by the computer's
  13617.    hardware, it becomes quite clear that the richest concentration of
  13618.    disk-oriented services exists at the DOS level. This almost goes without
  13619.    saying, because DOS, as a disk operating system, is inherently strongest
  13620.    in its support of disk operations.
  13621.  
  13622.    As discussed in Chapters 16 and 17, the majority of services that DOS
  13623.    performs are directly connected to the manipulation of disk files. Even
  13624.    some services that are nominally controlled by a program, such as loading
  13625.    and executing another program (interrupt 21H, function 4BH), involve
  13626.    disk-file operations. From this perspective, DOS is not so much a disk
  13627.    operating system as it is a system of disk services designed for use by
  13628.    your programs. When you are developing programs for the IBM personal
  13629.    computer family, you should approach DOS from this standpoint: Think of
  13630.    DOS as a cornucopia of disk operations placed at your service.
  13631.  
  13632.  DOS and Video: A Difficult Match
  13633.  
  13634.    Unfortunately, DOS does not provide much in the way of video output
  13635.    services. In fact, the available DOS services are limited to a
  13636.    character-only, "glass teletype" interface that is rapidly becoming an
  13637.    anachronism in these days of high-resolution color graphics.
  13638.  
  13639.    To achieve attractive, high-performance video output, you must rely on the
  13640.    ROM BIOS or on direct programming of the video hardware. As we have seen,
  13641.    IBM has maintained a fairly consistent programming interface to its video
  13642.    hardware, so many programmers make a practice of bypassing DOS and using
  13643.    lower-level video programming techniques.
  13644.  
  13645.    But when you bypass DOS, you encounter a problem: Two different programs
  13646.    can't reliably share the video hardware. Consider what can happen, for
  13647.    example, if you write a program that configures the video hardware in a
  13648.    way that conflicts with the configuration used by a memory-resident
  13649.    "pop-up" program like SideKick. If your program runs in a video mode that
  13650.    the pop-up program doesn't recognize, the pop-up program's output may
  13651.    appear incomprehensible on the screen. Worse, the pop-up program may
  13652.    reconfigure the video subsystem for its own purposes and leave your
  13653.    program's video output in limbo.
  13654.  
  13655.    The problem is amplified in multitasking operating environments, such as
  13656.    Microsoft Windows or OS/2, where programs generally share access to the
  13657.    screen. In these environments, a program can bypass the operating system
  13658.    and gain complete control of the screen only if the operating system
  13659.    suspends video output from all other concurrently executing programs. Thus
  13660.    a program that ties up the video hardware can delay the multitasking
  13661.    execution of background programs.
  13662.  
  13663.    The designers of OS/2 and Microsoft Windows attacked this problem by
  13664.    providing a sophisticated gamut of video output services. These video
  13665.    output services not only resolve conflicts between programs that want to
  13666.    access the video display, but they also provide very good performance. To
  13667.    get the best video performance in the world of DOS, however, you must
  13668.    either resort to ROM BIOS calls and direct hardware programming or else
  13669.    rely on the video output services provided by your programming language
  13670.    (which themselves bypass DOS).
  13671.  
  13672.    When trying to decide which method to use, you should consider the
  13673.    probable lifetime of your programs and the range of machines they might be
  13674.    used on. For a PC-specific game program with an expected life of a few
  13675.    months (common for games), you have little reason to worry about these
  13676.    issues. This is not the case for a generalized business or professional
  13677.    application, which should be usable for many years and in many
  13678.    environments. Make your choice and place your bets.
  13679.  
  13680.  
  13681.  DOS Version Differences
  13682.  
  13683.    DOS has evolved since the release of version 1.0 in 1981. Even though each
  13684.    new release has contained both improvements and bug-fixes, the driving
  13685.    force behind each release has been a hardware change, and a hardware
  13686.    change has usually involved a disk-drive change. (See Figure 14-1.)
  13687.  
  13688.    In all but versions 2.1 and 3.1, changes to DOS involved significant
  13689.    modifications to disk support (including new disk-storage formats). The
  13690.    main change to 2.1 was relatively minor, but was disk-related: The
  13691.    diskette control head-settle time was adjusted to allow for differences in
  13692.    the performance of the half-height drives used in the PCjr and Portable
  13693.    PC. Version 2.1 also corrected a few of the known bugs in 2.0. Version 3.1
  13694.    incorporated networking functions that were designed for version 3.0, but
  13695.    not ready when 3.0 was released. The following list summarizes the main
  13696.    differences between these versions:
  13697.  
  13698.    Version        Release Date   Hardware Change
  13699.    ──────────────────────────────────────────────────────────────────────────
  13700.    1.0            August 1981    Original IBM PC (single-sided diskette
  13701.                                  drive)
  13702.    1.1            May 1982       Double-sided diskette drive
  13703.    2.0            March 1983     PC/XT
  13704.    2.1            October 1983   PCjr and Portable PC
  13705.    3.0            August 1984    PC/AT
  13706.    3.1            March 1985     PC Network
  13707.    3.2            January 1986   Support for 3-1/2-inch diskette drives
  13708.    3.3            April 1987     PS/2s
  13709.    ──────────────────────────────────────────────────────────────────────────
  13710.  
  13711.    Figure 14-1.  DOS releases and associated changes to hardware.
  13712.  
  13713.    Version 1.0 supported the single-sided, 8-sector diskette format. All
  13714.    basic DOS services were included in this release.
  13715.  
  13716.    Version 1.1 added support for double-sided diskettes. The DOS services
  13717.    remained the same.
  13718.  
  13719.    Version 2.0 added support for 9-sector diskettes (both single- and
  13720.    double-sided) and for the PC/XT fixed disk. The DOS services were enhanced
  13721.    extensively in this version. (See Chapter 17.)
  13722.  
  13723.    Version 2.1 added neither new disk formats nor new DOS services; it did,
  13724.    however, adjust its disk operation timing to benefit the PCjr and the
  13725.    Portable PC.
  13726.  
  13727.    Version 3.0 added support for the PC/AT's 1.2 MB diskette drive and
  13728.    additional fixed-disk formats. It also laid the groundwork for network
  13729.    disks.
  13730.  
  13731.    Version 3.1 added network disks, which include a file-sharing capability.
  13732.  
  13733.    Version 3.2 introduced support for 3-1/2-inch diskette drives.
  13734.  
  13735.    Version 3.3 was announced concurrently with IBM's introduction of the
  13736.    PS/2s. Several new commands and functions were included specifically to
  13737.    support the PS/2 hardware.
  13738.  
  13739.    ──────────────────────────────────────────────────────────────────────────
  13740.    NOTE:
  13741.      Each version of DOS is compatible with prior versions, except in some
  13742.      very detailed respects (these sorts of details always seem to be
  13743.      unavoidable).
  13744.    ──────────────────────────────────────────────────────────────────────────
  13745.  
  13746.    With each release of DOS, there has been a question among software
  13747.    developers about which version of DOS to target.
  13748.  
  13749.    In particular, DOS versions 2.0 and later supported a much wider variety
  13750.    of disk hardware and provided significantly more programming services than
  13751.    did versions 1.0 and 1.1, so programs that used the more advanced features
  13752.    of the later DOS versions wouldn't run at all on versions 1.0 and 1.1.
  13753.    Fortunately, the number of people still using version 1.0 or 1.1 is very
  13754.    small, so most software developers target their applications toward
  13755.    versions 2.0 and later. The differences between these later DOS versions
  13756.    are relatively minor and can usually be accommodated in software that
  13757.    verifies which version of DOS is running.
  13758.  
  13759.    Far-sighted software developers must also tackle the question of
  13760.    compatibility with future versions of DOS. Both IBM and Microsoft are
  13761.    looking toward OS/2 as the logical successor to DOS. In this view, DOS is
  13762.    considered a "mature" product; that is, enhancements to future versions
  13763.    aren't likely to affect existing DOS programs.
  13764.  
  13765.    Microsoft has published guidelines to help DOS software developers write
  13766.    programs that can later be converted for use under OS/2. In our
  13767.    discussions of DOS services in the next few chapters, we'll point out
  13768.    several techniques that can help ensure the future compatibility of your
  13769.    DOS programs.
  13770.  
  13771.    In any case, a program can detect which version of DOS it is running under
  13772.    by using DOS function 30H (decimal 48). Unless you can be sure of your
  13773.    audience, you should include this safeguard in your programs and always
  13774.    check to be certain that the correct DOS version is installed.
  13775.  
  13776.  
  13777.  Diskette Format Considerations
  13778.  
  13779.    If you're planning to share or sell your programs, you must decide which
  13780.    diskette format you'll use to distribute your software. Initially, most
  13781.    software vendors used single-sided 5-1/4-inch diskettes with eight sectors
  13782.    per track, because this format was the lowest common denominator that
  13783.    could be read by all versions of DOS. Later, as single-sided diskette
  13784.    drives became virtually extinct, software publishers adopted the
  13785.    double-sided 5-1/4-inch diskette format as an acceptable medium.
  13786.  
  13787.    If you sell software for both PCs and PS/2s, however, you must contend
  13788.    with 3-1/2-inch as well as 5-1/4-inch diskette formats. In this case, you
  13789.    should probably stick to the 720 KB format for 3-1/2-inch disks. You
  13790.    should also offer a choice of diskette sizes, because both 5-1/4-inch and
  13791.    3-1/2-inch formats are in widespread use and will be for some time to
  13792.    come.
  13793.  
  13794.  
  13795.  Comments
  13796.  
  13797.    Technical information about DOS has become much easier to find since the
  13798.    early days, when the only reliable sources of information were the DOS
  13799.    technical reference manuals. Nowadays, many PC programming magazines
  13800.    discuss DOS programming techniques. Several good reference books on
  13801.    various detailed aspects of DOS programming, including memory-resident
  13802.    programs, installable device drivers, and exception handlers, are also
  13803.    available.
  13804.  
  13805.    ──────────────────────────────────────────────────────────────────────────
  13806.    NOTE:
  13807.      Two "official" sources of detailed information about DOS are the DOS
  13808.      technical reference manuals distributed by IBM and The MS-DOS
  13809.      Encyclopedia (published by Microsoft Press).
  13810.    ──────────────────────────────────────────────────────────────────────────
  13811.  
  13812.  
  13813.  
  13814.  ────────────────────────────────────────────────────────────────────────────
  13815.  Chapter 15  DOS Interrupts
  13816.  
  13817.    The Five Main DOS Interrupts
  13818.      Interrupt 20H (decimal 32): Program Terminate
  13819.      Interrupt 21H (decimal 33): General DOS Services
  13820.      Interrupts 25H and 26H (decimal 37 and 38): Absolute Disk Read and
  13821.      Write
  13822.      Interrupt 27H (decimal 39): Terminate and Stay Resident
  13823.  
  13824.    The Multiplex Interrupt
  13825.  
  13826.    The Three DOS Address Interrupts
  13827.      Interrupt 22H (decimal 34): Terminate Address
  13828.      Interrupt 23H (decimal 35): Ctrl-C Handler Address
  13829.      Interrupt 24H (decimal 36): Critical Error-Handler Address
  13830.  
  13831.    The DOS Idle Interrupt
  13832.  
  13833.    The Program Segment Prefix (PSP)
  13834.      The Internal Structure of the PSP
  13835.  
  13836.    An Example
  13837.  
  13838.    In this chapter we'll describe how to communicate with DOS through
  13839.    interrupts. (See Figure 15-1.) DOS reserves all 32 interrupt numbers from
  13840.    20H through 3FH (decimal 32 through decimal 63) for its own use. DOS
  13841.    provides system services through five of these interrupts (20H, 21H, 25H,
  13842.    26H, and 27H). These interrupts can be called directly from a program with
  13843.    the INT instruction. DOS uses the interrupt vectors for four others (22H,
  13844.    23H, 24H, and 28H) to contain the addresses of routines called by DOS
  13845.    itself; you can substitute your own routines for the default DOS routines
  13846.    by updating one of these interrupt vectors. Interrupt 2FH is reserved for
  13847.    communication between memory-resident programs. The other 22 interrupts
  13848.    reserved by DOS are not intended for use in your programs.
  13849.  
  13850.    Interrupt  Number
  13851.    Hex        Dec        Description
  13852.    ──────────────────────────────────────────────────────────────────────────
  13853.    20H        32         Program Terminate
  13854.    21H        33         General DOS Services
  13855.    22H        34         Terminate Address
  13856.    23H        35         Ctrl-C Handler Address
  13857.    24H        36         Critical Error-Handler Address
  13858.    25H        37         Absolute Disk Read
  13859.    26H        38         Absolute Disk Write
  13860.    27H        39         Terminate and Stay Resident
  13861.    28H        40         DOS Idle Interrupt
  13862.    2FH        47         Multiplex Interrupt
  13863.    ──────────────────────────────────────────────────────────────────────────
  13864.  
  13865.    Figure 15-1.  DOS interrupts.
  13866.  
  13867.    ──────────────────────────────────────────────────────────────────────────
  13868.    NOTE:
  13869.      You can use any of the 10 interrupts described in this chapter in your
  13870.      programs. Nevertheless, there is some overlap between the services
  13871.      provided through the separate interrupts described in this chapter and
  13872.      the functions available through interrupt 21H. When you have a choice,
  13873.      use the interrupt 21H functions described in Chapters 16 and 17. We'll
  13874.      point out why as we describe each DOS interrupt.
  13875.    ──────────────────────────────────────────────────────────────────────────
  13876.  
  13877.  
  13878.  The Five Main DOS Interrupts
  13879.  
  13880.    Of the DOS interrupts described in this chapter, five have built-in
  13881.    interrupt-handling programs, each of which performs a particular task.
  13882.  
  13883.  Interrupt 20H (decimal 32): Program Terminate
  13884.  
  13885.    Interrupt 20H (decimal 32) is used to exit from a program and pass control
  13886.    back to DOS. It is similar to interrupt 21H, function 00H. (See page
  13887.    325.) These services can be used interchangeably with any version of DOS
  13888.    to end a program.
  13889.  
  13890.    Interrupt 20H does not automatically close files opened with interrupt
  13891.    21H, functions 0FH or 16H when it terminates a program, so you should
  13892.    always use interrupt 21H, function 10H to close such files before
  13893.    exiting. If a modified file is not formally closed, its new length will
  13894.    not be recorded in the file directory.
  13895.  
  13896.    A program can set three operational addresses through DOS interrupts 22H,
  13897.    23H, and 24H, as we will see shortly. As part of the clean-up operations
  13898.    performed by DOS for interrupt 20H, these addresses are restored to the
  13899.    values they had before the program was executed. Resetting these addresses
  13900.    is essential if the program that invoked interrupt 20H was executed as the
  13901.    "child" of another program. It serves to protect the "parent" program from
  13902.    using routines intended for the "child." (See DOS function 4BH [decimal
  13903.    75] in Chapter 17.)
  13904.  
  13905.    ──────────────────────────────────────────────────────────────────────────
  13906.    NOTE:
  13907.      When DOS executes a program, it constructs a program segment prefix
  13908.      (PSP), a 256-byte block of memory that contains control information
  13909.      that, among other things, is referenced by DOS when a program is
  13910.      terminated. (We discuss the PSP in detail at the end of this chapter.)
  13911.      DOS depends on the CS register to point to the PSP when the interrupt
  13912.      20H terminate service is invoked. If the CS register points elsewhere,
  13913.      DOS may crash.
  13914.  
  13915.      In practice, we recommend that you terminate your programs with
  13916.      interrupt 21H, function 4CH, which is more flexible and less
  13917.      restrictive than interrupt 20H. The only reason to use interrupt 20H is
  13918.      to maintain compatibility with DOS version 1.0.
  13919.    ──────────────────────────────────────────────────────────────────────────
  13920.  
  13921.  Interrupt 21H (decimal 33): General DOS Services
  13922.  
  13923.    You can take advantage of a wide range of DOS functions through interrupt
  13924.    21H (decimal 33). Each function has a unique number you specify when you
  13925.    execute interrupt 21H. Chapters 16 and 17 cover the gamut of interrupt
  13926.    21H services in detail.
  13927.  
  13928.  Interrupts 25H and 26H (decimal 37 and 38): Absolute Disk Read and Write
  13929.  
  13930.    Interrupt 25H (decimal 37) and its companion, interrupt 26H (decimal 38),
  13931.    are used to read and write specific disk sectors. They are the only DOS
  13932.    services that ignore the logical structure of a disk and work only with
  13933.    individual sectors, paying no attention to the locations of files, file
  13934.    directories, or the File Allocation Table.
  13935.  
  13936.    Interrupts 25H and 26H are similar to the corresponding ROM BIOS disk
  13937.    services, except that the sectors are located by a different numbering
  13938.    method. With the ROM BIOS services, the sectors are selected by their
  13939.    three-dimensional coordinate locations (cylinder, head, and sector),
  13940.    whereas with interrupts 25H and 26H, the sectors are selected by their
  13941.    sequential logical sector numbers. (DOS's sector-numbering system is
  13942.    discussed on page 109.)
  13943.  
  13944.    The following BASIC formula converts three-dimensional coordinates used by
  13945.    the ROM BIOS to logical sector numbers used by DOS:
  13946.  
  13947.    LOGICAL.SECTOR = (SECTOR - 1) + (HEAD * SECTORS.PER.TRACK) +
  13948.    (CYLINDER * SECTORS.PER.TRACK * NUMBER.OF.HEADS)
  13949.  
  13950.    And here are the formulas for converting logical sector numbers to
  13951.    three-dimensional coordinates:
  13952.  
  13953.    SECTOR = 1 + LOGICAL.SECTOR MOD SECTORS.PER.TRACK
  13954.    HEAD = (LOGICAL.SECTOR \ SECTORS.PER.TRACK) MOD NUMBER.OF.HEADS
  13955.    CYLINDER = LOGICAL.SECTOR \ (SECTORS.PER.TRACK * NUMBER.OF.HEADS)
  13956.  
  13957.    ──────────────────────────────────────────────────────────────────────────
  13958.    NOTE:
  13959.      Don't forget that the ROM BIOS counts heads and cylinders from 0 but
  13960.      counts sectors from 1; DOS logical sectors are numbered from 0.
  13961.    ──────────────────────────────────────────────────────────────────────────
  13962.  
  13963.    To use interrupt 25H or 26H to read or write a block of logical sectors,
  13964.    load the necessary parameters into the CPU registers and execute the
  13965.    interrupt. The number of sectors is specified in the CX register, the
  13966.    starting sector number is specified in DX, and the memory address for data
  13967.    transfer is specified in DS:BX. The disk drive is selected by placing a
  13968.    number in the AL register: Drive A is 0, drive B is 1, and so on.
  13969.  
  13970.    Although ROM BIOS services work with true physical drives, DOS services
  13971.    work with logical drive numbers. DOS assumes every computer has at least
  13972.    two logical drives. If no physical drive B exists, DOS will simulate it by
  13973.    using the one physical drive as either A or B, whichever is needed. You
  13974.    can then remap these logical drives by using the DOS ASSIGN command.
  13975.  
  13976.    The results of interrupts 25H and 26H are reported in the carry flag (CF)
  13977.    and the AL and AH registers. If no error occurred, CF = 0. If an error did
  13978.    occur (CF = 1), AL and AH contain the error codes in two somewhat
  13979.    redundant groups. The AL codes in Figure 15-2 are based on those used by
  13980.    the DOS critical-error handler through interrupt 24H (see page 308), and
  13981.    the AH codes in Figure 15-3 are based on the error codes reported by the
  13982.    ROM BIOS (see page 201).
  13983.  
  13984.    Error Code         Meaning
  13985.    Hex    Dec
  13986.    ──────────────────────────────────────────────────────────────────────────
  13987.    00H     0          Write-protect error: attempt to write on protected
  13988.                       diskette
  13989.    01H     1          Unknown unit: invalid drive number
  13990.    02H     2          Drive not ready (e.g. no disk, or door open)
  13991.    04H     4          CRC (cyclical redundancy check) error: parity error
  13992.    06H     6          Seek error: move to requested cylinder failed
  13993.    07H     7          Unknown media: disk format not recognized
  13994.    08H     8          Sector not found
  13995.    0AH    10          Write error
  13996.    0BH    11          Read error
  13997.    0CH    12          General, nonspecific error
  13998.    0FH    15          Invalid disk change
  13999.    ──────────────────────────────────────────────────────────────────────────
  14000.  
  14001.    Figure 15-2.  The error-code values and meanings returned in the AL
  14002.    register following an error in a disk read or write through DOS interrupt
  14003.    25H or 26H.
  14004.  
  14005.    Error Code
  14006.    Hex    Dec         Meaning
  14007.    ──────────────────────────────────────────────────────────────────────────
  14008.    02H      2         Bad address mark: sector ID marking invalid or not
  14009.                       found
  14010.    03H      3         Write-protect error: attempt to write on protected disk
  14011.    04H      4         Bad sector: requested sector not on disk
  14012.    08H      8         DMA (direct memory access) failure
  14013.    10H     16         Bad CRC: read found invalid parity check of data
  14014.    20H     32         Controller failed: disk drive controller malfunction
  14015.    40H     64         Bad seek: move to requested track failed
  14016.    80H    128         Time out: drive did not respond
  14017.    ──────────────────────────────────────────────────────────────────────────
  14018.  
  14019.    Figure 15-3.  The error-code values and meanings returned in the AH
  14020.    register following an error in a disk read or write through DOS interrupt
  14021.    25H or 26H.
  14022.  
  14023.    Normally, interrupt handlers and other service routines leave the stack
  14024.    clean when they exit, returning it to its original size and contents. DOS
  14025.    interrupts 25H and 26H deliberately do not clean up the stack. Instead,
  14026.    they finish and return to the program with one word left on the stack.
  14027.    This word holds the contents of the flag register, showing how the flags
  14028.    were set when the program invoked the service. This is purportedly done to
  14029.    preserve the program's flag status before the service was used, because
  14030.    interrupts 25H and 26H use the flags for their return codes. We think this
  14031.    is a silly precaution because any program that needs to preserve the flags
  14032.    can simply do what programs normally do when they need something saved:
  14033.    PUSH them onto the stack themselves. Any program that uses interrupts 25H
  14034.    and 26H should POP the two extra flag-status bytes off the stack after the
  14035.    interrupt returns. These bytes can either be placed in the flags register
  14036.    with a POPF command (which should be done after testing CF for an error)
  14037.    or be discarded by incrementing the stack pointer register by 2 (ADD
  14038.    SP,2).
  14039.  
  14040.  Interrupt 27H (decimal 39): Terminate and Stay Resident
  14041.  
  14042.    Interrupt 27H (decimal 39) invokes one of the most interesting of all the
  14043.    services provided by DOS.
  14044.  
  14045.    Like interrupt 20H, interrupt 27H ends a program, but does not erase it
  14046.    from memory. Instead, it leaves a specified portion of the program in
  14047.    memory (the program stays resident). The program and data that are made
  14048.    resident using interrupt 27H become, in effect, an extension of DOS and
  14049.    will not be overwritten by other programs.
  14050.  
  14051.    ──────────────────────────────────────────────────────────────────────────
  14052.    NOTE:
  14053.      As with interrupt 20H, DOS versions 2.0 and later provide a more
  14054.      flexible alternative to interrupt 27H. This is interrupt 21H, function
  14055.      31H, which we recommend instead of interrupt 27H unless you are
  14056.      concerned about compatibility with DOS version 1.0. See Chapter 17 for
  14057.      more about interrupt 21H, function 31H.
  14058.    ──────────────────────────────────────────────────────────────────────────
  14059.  
  14060.    Interrupt 27H (or its function-call equivalent) is used by a number of
  14061.    sophisticated "pop-up" programs like SideKick. Terminate-and-stay-resident
  14062.    (TSR) programs typically use this service to establish new
  14063.    interrupt-handling routines that are meant to stay in effect indefinitely.
  14064.    Most often, these interrupt-handling routines replace existing DOS or ROM
  14065.    BIOS interrupt handlers in order to change or extend their operation. But
  14066.    the resident item is not limited to interrupt handlers and program
  14067.    instructions; it could just as easily be data. For example, the same
  14068.    programming technique could be used to load status information into a
  14069.    common area that various programs would share, allowing them to
  14070.    communicate indirectly.
  14071.  
  14072.    Normally, a TSR program is designed in two parts: a resident portion that
  14073.    remains in memory and a transient portion that installs the resident
  14074.    portion by updating interrupt vectors, initializing data, and calling the
  14075.    Terminate-and-Stay-Resident service. The transient portion does not remain
  14076.    in memory after interrupt 27H is executed.
  14077.  
  14078.    To accommodate this process, TSR programs are designed with the resident
  14079.    portion first (that is, at lower addresses). The transient portion
  14080.    computes the size of the resident portion and places this value in
  14081.    register DX when it executes interrupt 27H. DOS then leaves the resident
  14082.    portion in memory but reclaims the memory occupied by the transient
  14083.    portion for executing other programs.
  14084.  
  14085.    Anything left resident by this service normally remains resident as long
  14086.    as DOS is also resident. It is not unusual for several different programs
  14087.    to leave part of themselves resident. Programs that use this technique are
  14088.    usually sophisticated and complicated, so it is also not unusual for them
  14089.    to interfere with each other. To operate such a group of resident programs
  14090.    successfully, you must sometimes load them in a particular order──an order
  14091.    you may have to discover through experimentation (an unfair trick to play
  14092.    on an unsuspecting user).
  14093.  
  14094.    As with interrupt 20H, the ordinary terminate service, DOS resets the
  14095.    address vectors for interrupts 22H through 24H when it performs this
  14096.    terminate-and-stay-resident service. Therefore, you can't use this service
  14097.    to create resident interrupt handlers for the address interrupts. Although
  14098.    seemingly a limitation, this is actually fairly reasonable: The address
  14099.    interrupts are not meant to be used globally; they are meant to be used
  14100.    only by individual programs. (See the DOS address interrupts section that
  14101.    follows for further discussion.)
  14102.  
  14103.  
  14104.  The Multiplex Interrupt
  14105.  
  14106.    The multiplex interrupt, interrupt 2FH (decimal 47), is used to
  14107.    communicate with memory-resident programs. This interrupt wasn't used in
  14108.    DOS version 1, but in version 2 the RAM-resident print spooler PRINT used
  14109.    it. In DOS versions 3.0 and later, the protocol for using interrupt 2FH
  14110.    was standardized to allow multiple memory-resident programs to share the
  14111.    interrupt. (That's why this interrupt is called the multiplex interrupt.)
  14112.  
  14113.    ──────────────────────────────────────────────────────────────────────────
  14114.    NOTE:
  14115.      Most of the material in this chapter applies to all versions of DOS;
  14116.      however, interrupt 2FH is available only with DOS versions 3.0 and
  14117.      later.
  14118.    ──────────────────────────────────────────────────────────────────────────
  14119.  
  14120.    To use the multiplex interrupt, you must write a memory-resident TSR
  14121.    program that contains an interrupt handler for interrupt 2FH. (Use the DOS
  14122.    Terminate-and-Stay-Resident service to do this.) The transient portion of
  14123.    the TSR program must copy the address of the previous interrupt 2FH
  14124.    handler from the interrupt 2FH vector (0000:00BCH) to a variable in the
  14125.    resident portion. The transient portion then updates the interrupt 2FH
  14126.    vector with the address of the resident portion's interrupt 2FH handler so
  14127.    that when interrupt 2FH is subsequently executed, the TSR's handler gets
  14128.    control.
  14129.  
  14130.    When interrupt 2FH is executed, the resident interrupt 2FH handler does
  14131.    the following:
  14132.  
  14133.    IF      AH=IDnumber
  14134.    THEN    process the value in AL
  14135.            return from the interrupt (IRET)
  14136.    ELSE    jump to the previous interrupt 2FH handler
  14137.  
  14138.    This simple logic lets several memory-resident programs use the multiplex
  14139.    interrupt to communicate. The key is that every memory-resident program
  14140.    must have a unique ID number. Your program's interrupt 2FH handler should
  14141.    recognize one of the 64 values between C0H and FFH. (There are 256
  14142.    possible ID numbers, of course, but Microsoft and IBM reserve numbers 00H
  14143.    through BFH for use by DOS utilities.)
  14144.  
  14145.    When your program's interrupt 2FH handler gains control, it must first
  14146.    check the value in register AH. If the value in AH matches the program's
  14147.    ID number, the handler looks in AL to decide what to do next. If the
  14148.    values don't match, the handler simply jumps to the address of the
  14149.    previous interrupt 2FH handler.
  14150.  
  14151.    The interrupt 2FH handler considers the value in AL to be a function
  14152.    number and processes it accordingly, as described in the following
  14153.    paragraphs:
  14154.  
  14155.    Function 00H has a special meaning. It instructs the interrupt handler to
  14156.    return one of two values in AL:
  14157.  
  14158.    ■  A value of FFH indicates that an interrupt 2FH handler is resident in
  14159.       memory and available to process other function numbers.
  14160.  
  14161.    ■  A value of 01H indicates that the ID number in AH is in use.
  14162.  
  14163.    So, to detect whether a particular TSR program is installed in memory, a
  14164.    program executes interrupt 2FH with the TSR's ID number in AH and with AL
  14165.    = 00H. If the TSR is present in memory, it returns AL = FFH. If another
  14166.    TSR is using the ID number for its own purposes, that TSR returns AL =
  14167.    01H. Otherwise, any interrupt 2FH handlers in memory simply ignore the
  14168.    interrupt, causing the interrupt to return AL = 00H.
  14169.  
  14170.    The best-documented example of how to use the multiplex interrupt is the
  14171.    PRINT program supplied with DOS versions 3.0 and later. By examining how
  14172.    PRINT uses the multiplex interrupt, you can make better use of this
  14173.    interrupt in your own memory-resident programs.
  14174.  
  14175.    PRINT's multiplex ID number is 1. Any time interrupt 2FH is executed with
  14176.    this ID number in AH, PRINT's memory-resident interrupt handler processes
  14177.    the interrupt. Because six different functions are defined by PRINT (see
  14178.    Figure 15-4), a call to PRINT consists of executing interrupt 2FH with AH
  14179.    = 01H and a function number in AL.
  14180.  
  14181.    Each time you run PRINT, the program executes interrupt 2FH with AH = 01H
  14182.    and AL = 00H. The first time you run the program, the value returned in AL
  14183.    by the interrupt is 00H, so the program installs itself in memory. When
  14184.    you invoke PRINT a second time, the value returned in AL as a result of
  14185.    executing the multiplex interrupt with AH = 01H is FFH. This value is
  14186.    placed there by the memory-resident copy of PRINT, so the second
  14187.    invocation of the program knows not to install itself in memory.
  14188.  
  14189.    The second and subsequent invocations of PRINT can request any of five
  14190.    different functions by passing a function number to the first,
  14191.    memory-resident copy of the program. You could also use these functions in
  14192.    your own programs by placing the value 01H (PRINT's multiplex ID) in
  14193.    register AH, the function number in register AL, and then issuing
  14194.    interrupt 2FH.
  14195.  
  14196.    Function Number                      Description
  14197.    ──────────────────────────────────────────────────────────────────────────
  14198.    00H                                  Get installed status.
  14199.    01H                                  Submit file to print.
  14200.    02H                                  Remove file from print queue.
  14201.    03H                                  Cancel all files in print queue.
  14202.    04H                                  Hold print queue.
  14203.    05H                                  Release print queue.
  14204.    ──────────────────────────────────────────────────────────────────────────
  14205.  
  14206.    Figure 15-4.  PRINT functions defined through the multiplex interrupt.
  14207.  
  14208.    Function 01H submits a file to the print spooler for printing. To tell
  14209.    PRINT what is to be printed, you set the register pair DS:DX to point to a
  14210.    5-byte area called a submit packet. The first byte of the submit packet is
  14211.    a level code (which should be 0). The remaining 4 bytes of the submit
  14212.    packet are the segmented address of an ASCIIZ string (see page 350) that
  14213.    defines the pathname of the file to be printed. The pathname must be a
  14214.    single file. The global filename characters * and ? are not allowed.
  14215.  
  14216.    When a file is submitted using this function, it is added to the end of
  14217.    the queue, or list, of files to be printed. The files are printed in turn
  14218.    and are dropped from the queue after they're printed.
  14219.  
  14220.    Function 02H cancels individual files queued for printing. The register
  14221.    pair DS:DX points to the ASCIIZ string that defines which file is to be
  14222.    removed from the queue. In this case, the global filename characters * and
  14223.    ? can be used. In function 02H, DS:DX points directly to the filename
  14224.    string, rather than to a submit packet that points to the string.
  14225.  
  14226.    Function 03H cancels all files queued for printing. For both functions 02H
  14227.    and 03H, if the file currently being printed is canceled, PRINT stops
  14228.    printing the file and prints a short message to that effect.
  14229.  
  14230.    Function 04H gives programs access to the print queue so they can inspect
  14231.    it. The queue is frozen when this function is requested, so you don't have
  14232.    to worry about the list changing while you inspect it. Issuing any other
  14233.    PRINT function call will unfreeze the queue. Function 04H returns a
  14234.    pointer in the register pair DS:SI that points to a list of filenames
  14235.    queued for printing. Entries in the list are strings with a fixed length
  14236.    of 64 bytes. The end of the list is indicated by an entry that begins with
  14237.    a zero byte.
  14238.  
  14239.    The queue freeze imposed by function 04H doesn't need to halt the printing
  14240.    operation. But function 04H will suspend the removal from the queue of a
  14241.    file that is finished printing.
  14242.  
  14243.    Function 05H is essentially a null function that does nothing but unfreeze
  14244.    the queue of filenames frozen by function 04H. (The other four functions
  14245.    can do this, too.)
  14246.  
  14247.  
  14248.  The Three DOS Address Interrupts
  14249.  
  14250.    DOS uses three interrupts, 22H through 24H (decimal 34 through 36), to
  14251.    handle three exceptional circumstances: the end of a program, a "break"
  14252.    keyboard action (Ctrl-Break or Ctrl-C on the standard PC keyboard), and
  14253.    any "critical error" (usually a disk error of some kind). Your programs
  14254.    can affect the action taken in each of these three circumstances by
  14255.    changing the corresponding interrupt vector to point to any operation you
  14256.    choose. This is why we call these interrupts the address interrupts.
  14257.  
  14258.    DOS maintains a default address setting for each of these interrupts,
  14259.    which is preserved at the beginning of a program's operation and restored
  14260.    after the program is finished. This allows your programs to freely change
  14261.    these vectors according to their needs without disturbing the operation of
  14262.    subsequent programs or the operation of DOS itself.
  14263.  
  14264.  Interrupt 22H (decimal 34): Terminate Address
  14265.  
  14266.    The address associated with interrupt 22H (decimal 34) specifies where
  14267.    control of the computer will be passed when a program's execution ends
  14268.    with a call to DOS interrupt 20H or 27H, or with interrupt 21H, function
  14269.    00H, 31H, or 4CH. Interrupt 22H isn't designed to be executed directly by
  14270.    a program using the INT instruction. Instead, DOS uses the interrupt 22H
  14271.    vector to store the address of its own program termination routine.
  14272.  
  14273.    It's not a good idea to manipulate the DOS terminate address. The inner
  14274.    workings of the default DOS program termination routine are not
  14275.    documented, so writing a substitute routine that terminates a program
  14276.    cleanly without confounding DOS is difficult. If you are qualified to use
  14277.    this feature, then you probably understand it better than we can explain
  14278.    it.
  14279.  
  14280.  Interrupt 23H (decimal 35): Ctrl-C Handler Address
  14281.  
  14282.    The address associated with interrupt 23H (decimal 35) points to the
  14283.    interrupt-handling routine that DOS invokes in response to the Ctrl-C key
  14284.    combination. Thus interrupt 23H is intended to be executed only by DOS,
  14285.    not by an application program. A few old-fashioned programs, such as the
  14286.    DOS editor EDLIN, use Ctrl-C as a command keystroke, but in most
  14287.    applications the Ctrl-C combination signals that the user wants to
  14288.    interrupt an ongoing process.
  14289.  
  14290.    DOS is a bit quirky about when it will respond to a Ctrl-C keystroke.
  14291.    Normally, DOS acts on a break only when it is reading from or writing to a
  14292.    character I/O device (the screen, keyboard, printer, or communications
  14293.    port). However, the BREAK ON command allows DOS versions 2.0 and later to
  14294.    act on Ctrl-C at the time of most other DOS system calls.
  14295.  
  14296.    DOS's default Ctrl-C handler terminates the program or batch file you are
  14297.    executing. However, if your program provides its own interrupt 23H
  14298.    handler, it can have DOS take any action you want.
  14299.  
  14300.    In general, a Ctrl-C handler can take three different courses of action:
  14301.  
  14302.    ■  It can perform some useful action, such as setting a flag, and then
  14303.       return to DOS with an interrupt return (IRET) instruction. In this
  14304.       case, DOS picks up where it left off, without terminating your
  14305.       program's execution.
  14306.  
  14307.    ■  It can set or clear the carry flag and then return to DOS with a far
  14308.       return instruction (RET 2) that discards the flags pushed on the stack
  14309.       when the interrupt 23H handler was called by DOS. If the carry flag is
  14310.       set, DOS terminates the interrupted program. If the carry flag is
  14311.       clear, DOS continues execution.
  14312.  
  14313.    ■  It can keep control without returning to DOS. This option is tricky,
  14314.       however, because you don't usually know what was on the stack at the
  14315.       moment DOS detected the Ctrl-C keystroke. An interrupt 23H handler that
  14316.       doesn't return to DOS should generally restore the stack pointer
  14317.       register (SP) to a predetermined value. It should also execute
  14318.       interrupt 21H, function 0DH, to flush DOS file buffers so that the DOS
  14319.       disk I/O system will be in a known state.
  14320.  
  14321.    The usual reason to write your own Ctrl-C handler is to let your program
  14322.    handle a keyboard break itself. Even if you want your program to terminate
  14323.    immediately after Ctrl-C is pressed, you may still need to clean up before
  14324.    your program terminates. For example, if you use interrupt 21H, functions
  14325.    0FH or 16H, to open a file, you should write your own Ctrl-C handler to
  14326.    close it because the default DOS Ctrl-C handler won't do so. Also, if you
  14327.    installed your own interrupt handlers for ROM BIOS or hardware interrupts,
  14328.    the DOS Ctrl-C handler won't restore them before it terminates your
  14329.    program. Again, your Ctrl-C handler should do this if necessary.
  14330.  
  14331.    If you do write your own Ctrl-C handler, don't forget the relationship
  14332.    between Ctrl-C and the keyboard Ctrl-Break combination. When you press
  14333.    Ctrl-Break, the ROM BIOS keyboard interrupt handler generates interrupt
  14334.    1BH. DOS's interrupt 1BH handler inserts a Ctrl-C key code into the
  14335.    keyboard input buffer. The next time DOS checks the keyboard buffer, it
  14336.    finds Ctrl-C and executes interrupt 23H. Thus, in effect, pressing
  14337.    Ctrl-Break has the same effect as pressing Ctrl-C, except that DOS detects
  14338.    the break generated by Ctrl-Break without first processing the intervening
  14339.    characters in the keyboard buffer.
  14340.  
  14341.  Interrupt 24H (decimal 36): Critical Error-Handler Address
  14342.  
  14343.    The address associated with interrupt 24H (decimal 36) points to the
  14344.    interrupt-handling routine invoked whenever DOS detects a "critical
  14345.    error"── an emergency situation that prevents DOS from continuing with
  14346.    normal processing. Typically, the critical error is a disk error, but
  14347.    other errors are also reported, as we'll see.
  14348.  
  14349.    Like interrupt 23H, interrupt 24H is intended to be invoked only by DOS,
  14350.    not by an application program. However, an application can substitute its
  14351.    own interrupt 24H handler for the default DOS handler. The DOS default
  14352.    handler produces a familiar message (shown on the following page).
  14353.  
  14354.    Abort, Retry, Ignore?           (in DOS versions prior to 3.3)
  14355.  
  14356.    or
  14357.  
  14358.    Abort, Retry, Fail?             (in DOS versions 3.3 and later)
  14359.  
  14360.    If you substitute a customized interrupt 24H handler for the one DOS
  14361.    provides, you can tailor critical-error handling to the needs of your
  14362.    program.
  14363.  
  14364.    When DOS transfers control to a critical-error handler, it provides
  14365.    several sources of information about the error itself, and about the state
  14366.    of the system before the error occurred. These sources include the
  14367.    register pair BP:SI, the stack, the AH register, and the DI register. We
  14368.    will cover them one by one because this process is quite complicated.
  14369.  
  14370.    If you are operating under DOS version 2.0 or later, the register pair
  14371.    BP:SI is set to point to a device-header control block. Your
  14372.    critical-error handler can inspect the device header to learn more about
  14373.    the device (disk drive, printer, and so forth) that experienced the error.
  14374.    (See the DOS technical reference manuals for more about the device
  14375.    header.)
  14376.  
  14377.    When the critical-error handler gains control, the stack contains the
  14378.    complete register set of the program that issued the DOS function call
  14379.    that ended in the critical error. This information can be quite useful to
  14380.    an error handler that is intimately integrated with the active program.
  14381.    The usual method of accessing the information on the stack is to address
  14382.    the stack through register BP. You can access the stack as shown in Figure
  14383.    15-5 on the following page if the first two instructions in your
  14384.    critical-error handler are
  14385.  
  14386.    PUSH    BP
  14387.    MOV     BP,SP
  14388.  
  14389.    DOS indicates the nature of a critical error primarily through a
  14390.    combination of the high-order bit of the AH register and the low-order
  14391.    byte of the DI register (a curious choice, for sure). If the high-order
  14392.    bit of AH is 0, the error is related to a disk operation. If the same bit
  14393.    (bit 7 of AH) is 1, the error is something other than a disk error, as we
  14394.    shall discuss shortly.
  14395.  
  14396.    When the error is a disk-device error (high-order bit of AH is 0),
  14397.    register AL identifies the drive number (0 is drive A, 1 is drive B, and
  14398.    so on). Bits 0 through 5 of AH indicate further information about the
  14399.    error, as shown in Figure 15-6.
  14400.  
  14401.              ┌─────────────┐ ──┐
  14402.    [BP + 30] │    Flags    │   │
  14403.              ├─────────────┤   │
  14404.    [BP + 28] │     CS      │   ├── Flags and CS:IP pushed by the
  14405.              ├─────────────┤   │   interrupt 21H call that generated
  14406.    [BP + 26] │     IP      │   │   the error
  14407.              ├─────────────┤ ──┤
  14408.    [BP + 24] │     ES      │   │
  14409.              ├─────────────┤   │
  14410.    [BP + 22] │     DS      │   │
  14411.              ├─────────────┤   │
  14412.    [BP + 20] │     BP      │   │
  14413.              ├─────────────┤   │
  14414.    [BP + 18] │     DI      │   │
  14415.              ├─────────────┤   │
  14416.    [BP + 16] │     SI      │   ├── Registers at point of interrupt 21H call
  14417.              ├─────────────┤   │
  14418.    [BP + 14] │     DX      │   │
  14419.              ├─────────────┤   │
  14420.    [BP + 12] │     CX      │   │
  14421.              ├─────────────┤   │
  14422.    [BP + 10] │     BX      │   │
  14423.              ├─────────────┤   │
  14424.     [BP + 8] │     AX      │   │
  14425.              ├─────────────┤ ──┤
  14426.     [BP + 6] │    Flags    │   │
  14427.              ├─────────────┤   │
  14428.     [BP + 4] │     CS      │   ├── Flags and CS:IP pushed by DOS when it
  14429.              ├─────────────┤   │   called the critical-error handler
  14430.     [BP + 2] │     IP      │   │
  14431.              ├─────────────┤ ──┘
  14432.         [BP] │ Previous BP │
  14433.              └─────────────┘
  14434.  
  14435.    Figure 15-5.  Information passed on the stack to an interrupt 24H
  14436.    (critical-error) handler.
  14437.  
  14438.            Bit
  14439.    5 4 3 2 1 0        Value             Meaning
  14440.    ──────────────────────────────────────────────────────────────────────────
  14441.    . . . . . 0        0                 Read error
  14442.    . . . . . 1        1                 Write error
  14443.    . . . 0 0 .        0                 Error involved DOS system files
  14444.    . . . 0 1 .        1                 Error involved file allocation table
  14445.    . . . 1 0 .        2                 Error involved root directory
  14446.    . . . 1 1 .        3                 Error involved files area of disk
  14447.    . . 1 . . .        1                 Fail response allowed
  14448.    . 1 . . . .        1                 Retry response allowed
  14449.    1 . . . . .        1                 Ignore response allowed
  14450.    ──────────────────────────────────────────────────────────────────────────
  14451.  
  14452.    Figure 15-6.  The bit values and associated errors indicated in bits 0
  14453.    through 5 of the AH register when DOS invokes interrupt 24H.
  14454.  
  14455.    DOS returns additional information about the error in the low-order byte
  14456.    of register DI (Figure 15-7). The error codes in DI cover a variety of
  14457.    input/output devices, so you must rely on a combination of the information
  14458.    in AH and in DI to determine the exact nature of the critical error.
  14459.  
  14460.    If bit 7 of AH is set, the error is probably not a disk error, though it
  14461.    may be disk related. One disk-related error normally reported when bit 7
  14462.    of AH is set is an error in the disk's FAT. In DOS version 1, this is
  14463.    always the case. For versions 2.0 and later, the error handler should
  14464.    inspect bit 15 of the word that is offset 4 bytes into the device header
  14465.    (BP: [SI + 4]). If this bit is clear, the device is a block device (disk)
  14466.    and the error is a FAT error. If this bit is set, the device is a
  14467.    character device, in which case the low-order byte of DI defines the exact
  14468.    problem (the high-order byte should be ignored). DI error-code values
  14469.    shown in Figure 15-7 are essentially the same as those reported in AL for
  14470.    interrupts 25H and 26H (decimal 37 and 38).
  14471.  
  14472.    You can use the following interrupt 21H functions in your critical-error
  14473.    handler to report what's going on to the program's user:
  14474.  
  14475.    ■  Functions 01H through 0CH, which provide simple keyboard and display
  14476.       services
  14477.  
  14478.    ■  Function 30H, which returns the DOS version number
  14479.  
  14480.    ■  Function 59H, which returns extended error information in DOS versions
  14481.       3.0 and later
  14482.  
  14483.    Error Code
  14484.    Hex    Dec         Description
  14485.    ──────────────────────────────────────────────────────────────────────────
  14486.    00H     0          Write-protect error; attempt to write on protected
  14487.                       diskette
  14488.    01H     1          Unknown unit (invalid drive number)
  14489.    02H     2          Drive not ready (no diskette or drive door open)
  14490.    03H     3          Unknown command requested
  14491.    04H     4          Data error (CRC)
  14492.    05H     5          Bad request structure length
  14493.    06H     6          Seek error; move to requested cylinder failed
  14494.    07H     7          Unknown disk format
  14495.    08H     8          Sector not found
  14496.    09H     9          Printer out of paper
  14497.    0AH    10          Write fault
  14498.    0BH    11          Read fault
  14499.    0CH    12          General, nonspecific error
  14500.    0FH    15          Invalid disk change (DOS version 3.0 or later)
  14501.    ──────────────────────────────────────────────────────────────────────────
  14502.  
  14503.    Figure 15-7.  Errors indicated in the low-order byte of register DI when
  14504.    DOS invokes interrupt 24H.
  14505.  
  14506.    Don't call other DOS services within your critical-error handler, however,
  14507.    because other services may overwrite internal buffers or stacks that DOS
  14508.    will need when the error handler returns.
  14509.  
  14510.    Normally, an error-handler routine returns to DOS after doing whatever it
  14511.    chooses to do. DOS can then take one of four courses of action: It can
  14512.    ignore the error, try the operation again, terminate the program, or fail
  14513.    the requested operation and return to the program (DOS versions 3.1 and
  14514.    later). You tell DOS which course you want it to take by loading a value
  14515.    from Figure 15-8 into the AL register before executing an IRET to return
  14516.    to DOS.
  14517.  
  14518.    If you use a custom critical-error handler, it will remain in effect only
  14519.    as long as the program that installs it is running. When the program
  14520.    terminates, DOS replaces the contents of the interrupt 24H vector with the
  14521.    address of the default critical-error handler.
  14522.  
  14523.    AL                 Description
  14524.    ──────────────────────────────────────────────────────────────────────────
  14525.    00H                Ignore the error and press onward.
  14526.    01H                Retry the operation.
  14527.    02H                Terminate the program.
  14528.    03H                Fail the operation (DOS versions 3.1 and later).
  14529.    ──────────────────────────────────────────────────────────────────────────
  14530.  
  14531.    Figure 15-8.  Values that can be returned to DOS in register AL by an
  14532.    interrupt 24H (critical-error) handler.
  14533.  
  14534.  
  14535.  The DOS Idle Interrupt
  14536.  
  14537.    DOS executes interrupt 28H (decimal 40) within interrupt 21H services that
  14538.    loop while waiting for an expected event, such as a keystroke. For
  14539.    example, if you execute the DOS keyboard-input service (interrupt 21H,
  14540.    service 01H), DOS executes interrupt 28H within an idle loop that waits
  14541.    for the next keystroke.
  14542.  
  14543.    The default DOS handler for interrupt 28H is merely an IRET instruction;
  14544.    that is, executing interrupt 28H normally does nothing at all. You can
  14545.    substitute your own interrupt 28H handler, however, that does something
  14546.    useful while DOS is otherwise idle. In particular, a memory-resident
  14547.    program can contain an interrupt 28H handler that is executed repeatedly
  14548.    whenever DOS is waiting for keyboard output.
  14549.  
  14550.    The biggest problem with installing your own interrupt 28H handler is that
  14551.    the handler can execute interrupt 21H to access DOS services only under
  14552.    very specific circumstances. Unfortunately, you must know many details
  14553.    about the way DOS internally processes interrupt 21H requests in order to
  14554.    use these safely within an interrupt 28H handler.
  14555.  
  14556.  
  14557.  The Program Segment Prefix (PSP)
  14558.  
  14559.    When DOS loads a program, it sets aside a 256-byte block of memory for the
  14560.    program: the program segment prefix (PSP). The PSP contains a hodgepodge
  14561.    of information that DOS uses to help run the program. A PSP is associated
  14562.    with every DOS program, no matter what language the program is written in.
  14563.    However, for programming purposes, the information stored in the PSP is
  14564.    more relevant to programs written in assembly language than to programs
  14565.    written in high-level languages. This is because with high-level
  14566.    languages, the language is normally in charge of the program's working
  14567.    environment, memory usage, and file control──all the information that the
  14568.    PSP is concerned with. Therefore, you can normally make good use of the
  14569.    PSP only if your program is assembly-language based.
  14570.  
  14571.    Before we describe the different elements of the PSP, we need to look at
  14572.    the relationship between the PSP and the program it supports.
  14573.  
  14574.    DOS always builds a program's PSP in memory just below the memory area
  14575.    allocated to the program itself. When the program receives control from
  14576.    DOS, segment registers DS and ES point to the beginning of the PSP.
  14577.    Because it sometimes needs to locate PSP information, DOS keeps a copy of
  14578.    the PSP segment value internally.
  14579.  
  14580.    The best way to explain how the PSP and the program work together is to
  14581.    jump right into the PSP's internal structure. We will reveal the purpose
  14582.    and potential use of each element as we explain it.
  14583.  
  14584.  The Internal Structure of the PSP
  14585.  
  14586.    As you will soon discover, the PSP contains a rather confusing mixture of
  14587.    items. (See Figure 15-9.) The background and history of DOS pull it in
  14588.    different directions──backward to the earlier CP/M system and forward to
  14589.    UNIX-type operating environments. As a result, the PSP contains elements
  14590.    that serve different purposes and are oriented to different programming
  14591.    methods. We'll discuss the elements in the order in which they appear.
  14592.  
  14593.    The field at offset 00H (2 bytes) contains bytes CDH and 20H, the
  14594.    interrupt 20H instruction. As we saw in the discussion of interrupt 20H in
  14595.    this chapter, this interrupt is only one of several standard ways for a
  14596.    program to terminate. This instruction is placed at the beginning of the
  14597.    PSP (at offset 00H) so that a program can end itself simply by jumping to
  14598.    this location when the CS points to the PSP. As you might guess, this is
  14599.    not the most sensible thing for a program to do; it's always best to go
  14600.    through the appropriate interrupt or function call. This odd method of
  14601.    terminating a program is a relic of the days when CP/M compatibility was
  14602.    important.
  14603.  
  14604.         Offset              Length
  14605.    Hex         Dec          (bytes)     Description
  14606.    ──────────────────────────────────────────────────────────────────────────
  14607.    00H           0            2         INT 20H instruction
  14608.    02H           2            2         Size of memory (in paragraphs)
  14609.    04H           4            1         (Reserved; normally 0)
  14610.    05H           5            5         Call to DOS function dispatcher
  14611.    0AH          10            4         Interrupt 22H (Terminate) address
  14612.    0EH          14            4         Interrupt 23H (Ctrl-C) address
  14613.    12H          18            4         Interrupt 24H (Critical Error)
  14614.                                         address
  14615.    16H          22           22         (Reserved)
  14616.    2CH          44            2         Environment segment address
  14617.    2EH          46           34         Reserved
  14618.    50H          80            3         INT 21H, RETF instructions
  14619.    53H          83            9         (Reserved)
  14620.    5CH          92           16         FCB #1
  14621.    6CH         108           20         FCB #2
  14622.    80H         128          128         Command-line parameters and default
  14623.                                         Disk Transfer Area (DTA)
  14624.    ──────────────────────────────────────────────────────────────────────────
  14625.  
  14626.    Figure 15-9.  The parts of the program segment prefix (PSP).
  14627.  
  14628.    The field at offset 02H (2 bytes) contains the segment address of the last
  14629.    paragraph of memory allocated to the program. DOS normally loads a program
  14630.    in the first free area of memory large enough to contain the program. A
  14631.    program can use this field to determine the actual size of the memory area
  14632.    allocated to it.
  14633.  
  14634.    In practice, there's a better way to determine the amount of memory
  14635.    allocated to a program. Interrupt 21H, function 4AH can return the size
  14636.    of any block of memory, not just the block into which a program is loaded.
  14637.    (See Chapter 17 for more on this DOS service.)
  14638.  
  14639.    The field at offset 05H (5 bytes) contains a long call to the DOS function
  14640.    dispatcher, the internal DOS routine that examines the function number you
  14641.    pass to DOS and executes the corresponding service routine. This field,
  14642.    too, is a remnant of the days when CP/M compatibility was important to DOS
  14643.    programmers. A program can make a near CALL to offset 05H in the PSP with
  14644.    a function number in register CL and get the same result as if it had
  14645.    loaded AH with the function number and executed interrupt 21H.
  14646.  
  14647.    Needless to say, this technique is not very useful in real-world DOS
  14648.    programs.
  14649.  
  14650.    The fields at offsets 0AH, 0EH, and 12H (4 bytes each) contain the
  14651.    segmented addresses of the default handlers for interrupt 22H (Terminate),
  14652.    23H (Ctrl-C), and 24H (Critical Error). These addresses are stored in the
  14653.    PSP for your convenience. If you substitute a customized interrupt handler
  14654.    for one of the DOS handlers, you can restore the default handler by
  14655.    copying its address from the PSP into the corresponding interrupt vector.
  14656.  
  14657.    In DOS versions 2.0 and later, the field at offset 2CH (2 bytes) contains
  14658.    the paragraph address of the program's environment block. The environment
  14659.    block contains a list of ASCIIZ strings (strings of ASCII characters, each
  14660.    terminated with a zero byte) that define various kinds of information. The
  14661.    end of the environment block is marked by a zero-length string (a single
  14662.    zero byte) where you would expect to find the first byte of the next
  14663.    string. Environment blocks that begin with a zero-length string contain no
  14664.    strings.
  14665.  
  14666.    Each environment string is of the form NAME = value, where NAME is
  14667.    capitalized and of any reasonable length and value can be almost anything.
  14668.    The environment thus consists of a list of global variables, each of which
  14669.    contains information that your program may be able to use. For example, if
  14670.    the environment block contains the PATH environment variable (that is, a
  14671.    string that starts with PATH=), any program──including DOS itself──can
  14672.    examine its environment block to determine which directories to search for
  14673.    executable files (and in what order). In this way the environment block
  14674.    provides a simple means of passing information to any program that
  14675.    examines it. (You can change the contents of the environment block with
  14676.    the DOS SET command.)
  14677.  
  14678.    DOS makes a copy of the environment block whenever it loads a program to
  14679.    be executed, and places the copy's paragraph address (segment) in the
  14680.    program's PSP. To obtain information from the environment block, a program
  14681.    must first obtain its segment from the PSP and then examine each of the
  14682.    zero-terminated strings. Some high-level languages contain functions that
  14683.    do this for you. For example, in C, the getenv() library function does all
  14684.    the work.
  14685.  
  14686.    Many sophisticated DOS programs rely on information in the environment
  14687.    block. Also, the concept of the environment is found in other powerful
  14688.    operating systems, including UNIX and OS/2. Whenever you need to pass
  14689.    user-configurable information to a program, we highly recommend the use of
  14690.    the environment block.
  14691.  
  14692.    The field at offset 50H contains two executable 8086 instructions: INT 21H
  14693.    and RETF (far return).
  14694.  
  14695.    This is another kludge that lets you invoke DOS functions somewhat
  14696.    indirectly. To use this feature, set up everything necessary to invoke a
  14697.    DOS interrupt 21H function (selecting the function in AH, and so forth).
  14698.    Then, instead of bravely performing an interrupt 21H (a 2-byte
  14699.    instruction), do a far call to offset 50H in the PSP (a 5-byte
  14700.    instruction).
  14701.  
  14702.    You might expect that this feature is another flash from the past, a bit
  14703.    of CP/M compatibility, but actually it was introduced with DOS version 2.0
  14704.    and will not work with previous versions of DOS. You might find that
  14705.    making a far call to offset 50H in the PSP is handy if you intend to patch
  14706.    the address of a different function dispatcher into your code, but in most
  14707.    cases, a simple INT 21H will suffice.
  14708.  
  14709.    The fields at offsets 5CH and 6CH support old-fashioned file processing,
  14710.    using file control blocks, or FCBs. FCBs can be used for file I/O with any
  14711.    version of DOS, but their use is discouraged with DOS versions 2.0 and
  14712.    later, where more modern file I/O is available through the use of file
  14713.    handles. See page 341 for more on file control blocks, and see page 350
  14714.    for more on file handles.
  14715.  
  14716.    This area of the PSP was designed to make life easier for programs that
  14717.    receive one or two filenames as parameters. The basic idea, and a good one
  14718.    we think, is to let DOS construct the necessary FCBs out of the first two
  14719.    command-line parameters (the parameters given on the command line,
  14720.    following the program name). If a program needs either or both FCBs, it
  14721.    can open and use them without having to decode the command-line parameters
  14722.    and construct the FCBs itself.
  14723.  
  14724.    If you use this feature of the PSP, you should be aware of three potential
  14725.    complications: First, the two FCBs overlap where they are placed. If your
  14726.    program needs only the first, fine; but if it needs the second FCB as
  14727.    well, one or both of them should be moved elsewhere before they are used.
  14728.    Second, these FCBs can involve FCB extensions, a fact overlooked in most
  14729.    DOS documentation for the PSP. Finally, if you use a DOS function that
  14730.    requires an extended FCB, you should be careful to copy the default FCBs
  14731.    to another area of memory where the FCB extensions won't overlap other
  14732.    data in the PSP.
  14733.  
  14734.    Keep in mind that the use of FCBs is considered obsolete, but if you want
  14735.    to use them, this information should help.
  14736.  
  14737.    The field at offset 80H serves two purposes: When DOS first builds the
  14738.    PSP, it fills this field with the command-line parameters typed by the
  14739.    user when the program was invoked. The length of the command line is in
  14740.    the byte at offset 80H. A string containing the command-line parameters
  14741.    follows at offset 81H.
  14742.  
  14743.    This string has some peculiarities: It does not contain the name of the
  14744.    program that was invoked. Instead, it begins with the character that
  14745.    immediately follows the program name, which is usually a blank.
  14746.    Separators, such as blanks or commas, are not stripped out or compressed.
  14747.    If you use the command line, you have to be prepared to scan through it,
  14748.    recognizing standard separators. Fortunately, high-level languages often
  14749.    provide functions that parse the command parameter string for you. In C,
  14750.    for example, the values argc and argv are passed to the main startup
  14751.    routine in every C program. These two values contain the number of
  14752.    command-line parameters and the address of a list of individual
  14753.    parameters. It's usually easier to rely on your high-level language to
  14754.    extract command-line parameters from the PSP than it is to do it yourself
  14755.    in assembly language.
  14756.  
  14757.    Starting with DOS version 2.0, the command line is modified in a
  14758.    particular way: DOS strips any redirection parameters (such as < or >) and
  14759.    reconstructs the parameter line as if these items were not there. As a
  14760.    result of these two operations on the command string, a program can
  14761.    neither find out if its standard I/O is being redirected nor find out its
  14762.    own name.
  14763.  
  14764.    The other purpose served by the field at offset 80H in the PSP is that of
  14765.    the default Disk Transfer Area. This default buffer area is established by
  14766.    DOS just in case you use a DOS service that calls for a DTA and haven't
  14767.    yet set up your own DTA buffer. See Chapters 16 and 17 for descriptions
  14768.    of the services that use or manipulate the DTA.
  14769.  
  14770.  
  14771.  An Example
  14772.  
  14773.    This chapter's interface example shows how you can use an interrupt
  14774.    handler to process Ctrl-C keystrokes. The example consists of two
  14775.    assembly-language routines.
  14776.  
  14777.    The first routine, INT23Handler, gains control when DOS executes INT 23H
  14778.    in response to a Ctrl-C keystroke. This handler simply increments the
  14779.    value in a flag and then returns to DOS with an IRET instruction.
  14780.  
  14781.    Note how the flag _INT23Flag is addressed through the segment group
  14782.    DGROUP. In many languages, segments with different names are grouped
  14783.    together in one logical group so that they can all be addressed with the
  14784.    same segment register. In the case of Microsoft C, this group of segments
  14785.    is named DGROUP, and it includes the data segment (_DATA) used by the
  14786.    compiled C program.
  14787.  
  14788.    The second assembly-language routine, _Install() is designed to be called
  14789.    by a C program. This short routine calls a DOS interrupt 21H function that
  14790.    updates the interrupt 23H vector with the address of the interrupt
  14791.    handler. (The next few chapters contain more about this DOS function and
  14792.    about interrupt 21H services in general.)
  14793.  
  14794.    DGROUP          GROUP   _DATA
  14795.  
  14796.    _TEXT           SEGMENT byte public 'CODE'
  14797.                    ASSUME  cs:_TEXT,ds:DGROUP
  14798.  
  14799.    ;
  14800.    ; the interrupt 23H handler:
  14801.  
  14802.    INT23Handler    PROC    far
  14803.                    push    ds                      ; preserve all registers us
  14804.                    push    ax                      ; ... in this interrupt han
  14805.  
  14806.                    mov     ax,seg DGROUP           ; set DS to the segment whe
  14807.                    mov     ds,ax                   ; ... the flag is located
  14808.                    inc     word ptr _INT23flag     ; increment the flag
  14809.  
  14810.                    pop     ax                      ; restore regs and return
  14811.                    pop     ds
  14812.                    iret
  14813.  
  14814.    INT23Handler    ENDP
  14815.  
  14816.    ;
  14817.    ; the C-callable installation routine:
  14818.  
  14819.                    PUBLIC  _Install
  14820.    _Install        PROC    near
  14821.  
  14822.                    push    bp                      ; the usual C prologue
  14823.                    mov     bp,sp
  14824.                    push    ds                      ; preserve DS
  14825.  
  14826.                    push    cs                      ; set DS:DX to point to ...
  14827.                    pop     ds
  14828.                    mov     dx,offset INT23Handler  ; ... the interrupt handler
  14829.                    mov     ax,2523h                ; AH = DOS function number
  14830.                                                    ; AL = interrupt number
  14831.                    int     21h                     ; call DOS to update the ..
  14832.                                                    ; ... interrupt vector
  14833.                    pop     ds
  14834.                    pop     bp                      ; restore regs and return
  14835.                    ret
  14836.  
  14837.    _Install        ENDP
  14838.  
  14839.    _TEXT           ENDS
  14840.    ;
  14841.    ; the flag set by the interrupt 23H handler when Ctrl-C is pressed:
  14842.  
  14843.    _DATA           SEGMENT word public 'DATA'
  14844.  
  14845.                    PUBLIC  _INT23flag
  14846.    _INT23flag      DW      0                    ; flag (initial value = 0)
  14847.    _DATA           ENDS
  14848.  
  14849.    The snippet of C code that follows shows how you could use this interrupt
  14850.    23H handler in a program. This C program does nothing but wait for you to
  14851.    press Ctrl-C. When you do, the assembly-language interrupt 23H handler
  14852.    increments the flag. When the loop in the C program sees that the flag is
  14853.    nonzero, it displays a message and decrements the flag.
  14854.  
  14855.    extern int INT23flag;                         /* flag set when Ctrl-C is pr
  14856.  
  14857.    main()
  14858.    {
  14859.            int     KeyCode;
  14860.  
  14861.  
  14862.            Install();                            /* install the interrupt 23H
  14863.  
  14864.            do
  14865.            {
  14866.              while( INT23flag > 0 )
  14867.              {
  14868.                printf( "\nCtrl-C was pressed" );   /* ... show a message ... *
  14869.                --INT23flag;                        /* ... and decrement the fl
  14870.              }
  14871.  
  14872.              if( kbhit() )                         /* look for a keypress */
  14873.                KeyCode = getch();
  14874.              else
  14875.                KeyCode = 0;
  14876.            }
  14877.            while( KeyCode != 0x0D );               /* loop until Enter is pres
  14878.    }
  14879.  
  14880.    Although the C code is short, it suggests two important points. One is
  14881.    that you must give DOS the chance to detect a Ctrl-C keystroke each time
  14882.    you test your interrupt 23H flag. (Remember that DOS is guaranteed to
  14883.    check for Ctrl-C only when it reads or writes to a character input/output
  14884.    device.) In this program, C's kbhit() function calls DOS to check for
  14885.    keyboard activity and, at the same time, lets DOS check for Ctrl-C as
  14886.    well.
  14887.  
  14888.    Also, note how the interrupt handler increments the flag instead of merely
  14889.    setting it to "true" or "false." This lets the loop in the C program
  14890.    process rapid, successive interrupts without losing track of how many
  14891.    interrupts have occurred.
  14892.  
  14893.  
  14894.  
  14895.  ────────────────────────────────────────────────────────────────────────────
  14896.  Chapter 16  DOS Functions: Version 1
  14897.  
  14898.    Interrupt 21H Functions: DOS Version 1
  14899.      Function 00H (decimal 0): Terminate
  14900.      Function 01H (decimal 1): Character Input with Echo
  14901.      Function 02H (decimal 2): Character Output
  14902.      Function 03H (decimal 3): Auxiliary Input
  14903.      Function 04H (decimal 4): Auxiliary Output
  14904.      Function 05H (decimal 5): Printer Output
  14905.      Function 06H (decimal 6): Direct Console Input/Output
  14906.      Function 07H (decimal 7): Direct Console Input Without Echo
  14907.      Function 08H (decimal 8): Console Input Without Echo
  14908.      Function 09H (decimal 9): String Output
  14909.      Function 0AH (decimal 10): Buffered Keyboard Input
  14910.      Function 0BH (decimal 11): Check Keyboard Status
  14911.      Function 0CH (decimal 12): Flush Keyboard Buffer, Read Keyboard
  14912.      Function 0DH (decimal 13): Flush Disk Buffers
  14913.      Function 0EH (decimal 14): Select Disk Drive
  14914.      Function 0FH (decimal 15): Open File
  14915.      Function 10H (decimal 16): Close File
  14916.      Function 11H (decimal 17): Find First Matching Directory Entry
  14917.      Function 12H (decimal 18): Find Next Matching Directory Entry
  14918.      Function 13H (decimal 19): Delete File
  14919.      Function 14H (decimal 20): Sequential Read
  14920.      Function 15H (decimal 21): Sequential Write
  14921.      Function 16H (decimal 22): Create File
  14922.      Function 17H (decimal 23): Rename File
  14923.      Function 19H (decimal 25): Get Current Disk
  14924.      Function 1AH (decimal 26): Set Disk Transfer Area
  14925.      Function 1BH (decimal 27): Get Default Drive Information
  14926.      Function 1CH (decimal 28): Get Specified Drive Information
  14927.      Function 21H (decimal 33): Read Random Record
  14928.      Function 22H (decimal 34): Write Random Record
  14929.      Function 23H (decimal 35): Get File Size
  14930.      Function 24H (decimal 36): Set FCB Random Record Field
  14931.      Function 25H (decimal 37): Set Interrupt Vector
  14932.      Function 26H (decimal 38): Create New Program Segment Prefix
  14933.      Function 27H (decimal 39): Read Random Records
  14934.      Function 28H (decimal 40): Write Random Records
  14935.      Function 29H (decimal 41): Parse Filename
  14936.      Function 2AH (decimal 42): Get Date
  14937.      Function 2BH (decimal 43): Set Date
  14938.      Function 2CH (decimal 44): Get Time
  14939.      Function 2DH (decimal 45): Set Time
  14940.      Function 2EH (decimal 46): Set Verify Flag
  14941.  
  14942.    The File Control Block
  14943.      FCB Fields
  14944.      Extended FCB Fields
  14945.  
  14946.    An Example
  14947.  
  14948.    The next three chapters describe the DOS functions accessed through
  14949.    interrupt 21H. DOS version 1 had 42 interrupt 21H functions. This variety
  14950.    of functions was strongly rooted in the 8-bit microcomputer tradition
  14951.    typified by the CP/M operating system, whose services many of the DOS
  14952.    functions resembled.
  14953.  
  14954.    DOS version 1 was adequate for diskette-based microcomputers with
  14955.    keyboards and video displays, but the advent of high-capacity fixed disks
  14956.    and a wider variety of diskette formats called for a new set of
  14957.    sophisticated disk file-management functions. These were supplied in DOS
  14958.    version 2, and roughly patterned after the disk file-management services
  14959.    used in the UNIX operating system. In version 3, DOS continued to evolve,
  14960.    but offered only a few new functions, primarily in support of new hardware
  14961.    such as the PC/AT, networks, and the PS/2s.
  14962.  
  14963.    Although some interrupt 21H functions introduced in later versions of DOS
  14964.    provide services similar to those in earlier versions, all version 1
  14965.    functions continue to be supported in later versions. When you have a
  14966.    choice between two similar functions, you should, in general, use the
  14967.    higher-numbered, more recent function. We'll point out why as we go along.
  14968.  
  14969.  
  14970.  Interrupt 21H Functions: DOS Version 1
  14971.  
  14972.    All DOS function calls are invoked by interrupt 21H (decimal 33).
  14973.    Individual functions are selected by placing the appropriate function
  14974.    number in the AH register.
  14975.  
  14976.    The interrupt 21H function calls in DOS version 1 are organized into the
  14977.    logical groups shown in Figure 16-1. In an effort to make this figure as
  14978.    clear as possible, we have organized and described these function calls in
  14979.    a slightly different manner than does the DOS technical reference manual.
  14980.    Figure 16-2 lists the individual function calls.
  14981.  
  14982.              Function
  14983.    Hex                Dec               Group
  14984.    ──────────────────────────────────────────────────────────────────────────
  14985.    00H                0                 Nondevice function
  14986.    01H─0CH            1─12              Character device I/O
  14987.    0DH─24H            13─36             File management
  14988.    25H─26H            37─38             More nondevice functions
  14989.    27H─29H, 2EH       39─41, 46         More file management
  14990.    2AH─2DH            42─45             More nondevice functions
  14991.    ──────────────────────────────────────────────────────────────────────────
  14992.  
  14993.    Figure 16-1.  The logical groups of DOS version 1 function calls.
  14994.  
  14995. ╓┌─┌──────────────┌──────────────┌───────────────────────────────────────────╖
  14996.          Function
  14997.    Hex            Dec            Description
  14998.    ──────────────────────────────────────────────────────────────────────────
  14999.    00H             0             Terminate
  15000.    01H             1             Character Input with Echo
  15001.    02H             2             Character Output
  15002.    03H             3             Auxiliary Input
  15003.    04H             4             Auxiliary Output
  15004.    05H             5             Printer Output
  15005.    06H             6             Direct Character Input/Output
  15006.    07H             7             Direct Character Input Without Echo
  15007.    08H             8             Character Input Without Echo
  15008.    09H             9             String Output
  15009.    0AH            10             Buffered Keyboard Input
  15010.    0BH            11             Check Keyboard Status
  15011.    0CH            12             Flush Keyboard Buffer, Read Keyboard
  15012.    0DH            13             Flush Disk Buffers
  15013.    0EH            14             Select Disk Drive
  15014.    0FH            15             Open File
  15015.    10H            16             Close File
  15016.    11H            17             Find First Matching Directory Entry
  15017.          Function
  15018.    Hex            Dec            Description
  15019.    ──────────────────────────────────────────────────────────────────────────
  15020.   11H            17             Find First Matching Directory Entry
  15021.    12H            18             Find Next Matching Directory Entry
  15022.    13H            19             Delete File
  15023.    14H            20             Sequential Read
  15024.    15H            21             Sequential Write
  15025.    16H            22             Create File
  15026.    17H            23             Rename File
  15027.    19H            25             Get Current Disk
  15028.    1AH            26             Set Disk Transfer Area
  15029.    1BH            27             Get Default Drive Information
  15030.    1CH            28             Get Specified Drive Information
  15031.    21H            33             Read Random Record
  15032.    22H            34             Write Random Record
  15033.    23H            35             Get File Size
  15034.    24H            36             Set FCB Random Record Field
  15035.    25H            37             Set Interrupt Vector
  15036.    26H            38             Create New Program Segment Prefix
  15037.    27H            39             Read Random Records
  15038.          Function
  15039.    Hex            Dec            Description
  15040.    ──────────────────────────────────────────────────────────────────────────
  15041.   27H            39             Read Random Records
  15042.    28H            40             Write Random Records
  15043.    29H            41             Parse Filename
  15044.    2AH            42             Get Date
  15045.    2BH            43             Set Date
  15046.    2CH            44             Get Time
  15047.    2DH            45             Set Time
  15048.    2EH            46             Set Verify Flag
  15049.    ──────────────────────────────────────────────────────────────────────────
  15050.  
  15051.  
  15052.    Figure 16-2.  DOS version 1 functions available through interrupt 21H.
  15053.  
  15054.    The design and organization of a few of these functions, particularly
  15055.    numbers 01H through 0CH, are screwball──to put it mildly. They are this
  15056.    way for historical reasons. Many details of DOS, and especially the
  15057.    details of DOS function calls, were designed to closely mimic the services
  15058.    provided by CP/M. This was an important and deliberate choice, made to
  15059.    make it much easier for 8-bit CP/M software to be converted to the 16-bit
  15060.    IBM PC and DOS. Although the creation of DOS provided a timely opportunity
  15061.    to break with and clean up the mistakes of the past, the real departure
  15062.    from the 8-bit tradition came with DOS version 2, as you will see in
  15063.    Chapter 17.
  15064.  
  15065.    The following pages describe the 42 original DOS function calls,
  15066.    universally used in all versions of DOS.
  15067.  
  15068.  Function 00H (decimal 0): Terminate
  15069.  
  15070.    Function 00H (decimal 0) ends a program and passes control back to DOS. It
  15071.    is functionally identical to DOS interrupt 20H, discussed on page 299.
  15072.    Either can be used interchangeably to exit a program.
  15073.  
  15074.    DOS versions 2.0 and later provide an enhanced terminate service through
  15075.    function 4CH, which leaves a return code (an error code) in register AL
  15076.    when a program ends. DOS batch files can act on the return codes with the
  15077.    DOS subcommand ERRORLEVEL. Use function 4CH instead of function 00H if
  15078.    you want to use a return code to record errors that occur when a program
  15079.    ends. (See page 377.)
  15080.  
  15081.    Like DOS interrupt 20H, function 00H does not close files opened with
  15082.    functions 0FH or 16H. To ensure that the proper length of such files is
  15083.    recorded in the file directory, use function 10H to close them before
  15084.    calling function 00H. Also, as with interrupt 20H, you must be sure the
  15085.    PSP segment address is in the CS register before exiting.
  15086.  
  15087.  Function 01H (decimal 1): Character Input with Echo
  15088.  
  15089.    Function 01H (decimal 1) waits for character input from the standard input
  15090.    device and returns it in the AL register when available. This function
  15091.    should be compared with the other keyboard function calls, particularly
  15092.    functions 06H, 07H, and 08H.
  15093.  
  15094.    ──────────────────────────────────────────────────────────────────────────
  15095.    NOTE:
  15096.      In DOS version 1, the standard input device is always the keyboard; the
  15097.      standard output device is always the video screen. In later DOS
  15098.      versions, however, standard input and output can be redirected to other
  15099.      devices such as files. DOS processes characters from the standard input
  15100.      device without distinguishing whether the actual input source is the
  15101.      keyboard or a stream of characters redirected from a file.
  15102.    ──────────────────────────────────────────────────────────────────────────
  15103.  
  15104.    Here is how function 01H works: Keystrokes that result in an ASCII
  15105.    character are returned as 1 byte in AL and immediately reported by this
  15106.    function. The keystrokes that result in something other than an ASCII
  15107.    character (see page 135) generate 2 bytes, which must be obtained through
  15108.    two consecutive calls to this function.
  15109.  
  15110.    The usual way to use this function is to test whether it returns 00H in
  15111.    AL. If AL is not 00H, you have an ASCII character. If AL = 00H, you have a
  15112.    non-ASCII keystroke (which should be recorded), and this function should
  15113.    be repeated immediately to get the pseudo-scan code that represents the
  15114.    special key action. (See page 135 for a list of the actions, codes, and
  15115.    their meanings.) As with all the DOS keyboard input services, the scan
  15116.    code for ASCII characters is not available, even if the corresponding ROM
  15117.    BIOS keyboard services make it available. (See page 135.)
  15118.  
  15119.    The various DOS keyboard service functions are distinguished primarily by
  15120.    three criteria: whether they wait for input (or report no input when none
  15121.    is available); whether they echo input onto the display screen; and
  15122.    whether the standard break-key operation is active for that service.
  15123.    Function 01H performs all three operations: It waits for input, echoes
  15124.    input to the screen, and lets DOS execute interrupt 23H if Ctrl-C is
  15125.    pressed.
  15126.  
  15127.    Remember, function 01H always waits for the user to press a key before it
  15128.    returns to a program. If you don't want to wait, either use function
  15129.    0BH──before you call function 01H──to test whether a key was pressed, or
  15130.    use function 06H. Also, see functions 08H and 0CH for related services.
  15131.  
  15132.  Function 02H (decimal 2): Character Output
  15133.  
  15134.    Function 02H (decimal 2) copies a single ASCII character from register DL
  15135.    to the standard output device. In DOS version 1, the standard output
  15136.    device is always the video screen; in later DOS versions, output can also
  15137.    be redirected to a file.
  15138.  
  15139.    In general, this function treats the ASCII control characters, such as
  15140.    backspace or carriage return, as commands. In the case of the backspace
  15141.    character, the display screen cursor is moved backward one column without
  15142.    erasing the previous character.
  15143.  
  15144.  Function 03H (decimal 3): Auxiliary Input
  15145.  
  15146.    Function 03H (decimal 3) reads one character into AL from AUX the standard
  15147.    auxiliary device. The default auxiliary device is COM1, the first RS-232
  15148.    serial communications port. You can, however, use the DOS MODE command to
  15149.    assign other devices, such as COM2, to the auxiliary device.
  15150.  
  15151.    ──────────────────────────────────────────────────────────────────────────
  15152.    NOTE:
  15153.      This function waits for input. It does not report status information
  15154.      about the many miseries that a serial port can suffer. If you want to
  15155.      know the status of the serial port, use the ROM BIOS communications-port
  15156.      services.
  15157.    ──────────────────────────────────────────────────────────────────────────
  15158.  
  15159.  Function 04H (decimal 4): Auxiliary Output
  15160.  
  15161.    Function 04H (decimal 4) writes one character from register DL to the
  15162.    standard auxiliary device. See the remarks under function 03H.
  15163.  
  15164.  Function 05H (decimal 5): Printer Output
  15165.  
  15166.    Function 05H (decimal 5) writes 1 byte from DL to the standard printer
  15167.    device, which is normally known as PRN: or LPT1: (although printer output
  15168.    can be redirected with the DOS MODE command to other devices). The default
  15169.    standard printer is always the first parallel printer, even if a serial
  15170.    port is used for printer output.
  15171.  
  15172.  Function 06H (decimal 6): Direct Console Input/Output
  15173.  
  15174.    Function 06H (decimal 6) is a complex function that combines the
  15175.    operations of keyboard input and display output into one untidy package.
  15176.    As with everything else in DOS versions 2.0 and later, the I/O is not
  15177.    connected to the keyboard and display, but rather to the standard input
  15178.    and output devices (which default to the keyboard and display).
  15179.  
  15180.    Here is how this function works: The AL register is used for input and the
  15181.    DL register for output. If you call function 06H with DL = FFH (decimal
  15182.    255), the function performs input:
  15183.  
  15184.    ■  If a key was pressed, function 06H returns the corresponding ASCII code
  15185.       in AL and clears the zero flag.
  15186.  
  15187.    ■  If no key was pressed, function 06H sets the zero flag.
  15188.  
  15189.    If you call function 06H with any other value in DL, the function performs
  15190.    output: The character in DL is copied to the standard output device.
  15191.  
  15192.    Function 06H does not wait for keyboard input, and it does not echo input
  15193.    to the display screen. In addition, function 06H does not interpret Ctrl-C
  15194.    as a keyboard break; instead, it returns the value 03H (the ASCII value of
  15195.    Ctrl-C) in AL.
  15196.  
  15197.    Compare this function with functions 01H, 07H, and 08H. See function
  15198.    0CH for a variation of this service.
  15199.  
  15200.  Function 07H (decimal 7): Direct Console Input Without Echo
  15201.  
  15202.    Function 07H (decimal 7) waits for character input from the standard input
  15203.    device and returns it in the AL register when available. It does not echo
  15204.    input to the display screen, and it does not recognize Ctrl-C as a
  15205.    keyboard break character.
  15206.  
  15207.    Function 07H works in the same way as function 01H: ASCII character key
  15208.    actions are returned as single bytes in AL and are immediately reported by
  15209.    this function. The non-ASCII function keystrokes (see page 135) generate
  15210.    2 bytes, which must be obtained through two consecutive calls to function
  15211.    07H.
  15212.  
  15213.    Compare this function with functions 01H, 06H, and 08H. If you want to
  15214.    use this function but don't want to wait when input is not ready, see
  15215.    function 0BH, which reports whether or not input is ready. See function
  15216.    0CH for a variation of this function.
  15217.  
  15218.  Function 08H (decimal 8): Console Input Without Echo
  15219.  
  15220.    Function 08H (decimal 8) waits for input, does not echo, and breaks on a
  15221.    Ctrl-C. It is identical to function 01H, except it does not echo the input
  15222.    to the display screen (or standard output device).
  15223.  
  15224.    See the discussion under function 01H for a description of this function.
  15225.    Compare this function with functions 01H, 06H, and 07H. If you want to
  15226.    use this function but don't want to wait when input is not ready, see
  15227.    function 0BH, which reports whether or not input is ready. See function
  15228.    0CH for a variation of this function.
  15229.  
  15230.  Function 09H (decimal 9): String Output
  15231.  
  15232.    Function 09H (decimal 9) sends a string of characters to the standard
  15233.    output device (which defaults to the display screen). The register pair
  15234.    DS:DX provides the address of the string. A $ character, ASCII 24H
  15235.    (decimal 36), marks the end of the string.
  15236.  
  15237.    Although this function can be far more convenient than the byte-by-byte
  15238.    display services (functions 02H and 06H), it is flawed by the use of a
  15239.    real, displayable character, $, as its string delimiter. This is not a
  15240.    recent mistake; it's another by-product of CP/M compatibility. You should
  15241.    never use this function with programs that output dollar signs.
  15242.  
  15243.  Function 0AH (decimal 10): Buffered Keyboard Input
  15244.  
  15245.    Function 0AH (decimal 10) puts the power of the DOS editing keys to work
  15246.    in your programs. The function gets a complete string of input, which is
  15247.    presented to your programs whole, rather than character by character. If
  15248.    you assume that the input is actually from live keyboard action and is not
  15249.    redirected elsewhere, the full use of the DOS editing keys is available to
  15250.    the person who is typing the input string. When the Enter key is pressed
  15251.    (or a carriage return, ASCII 0DH (decimal 13), is encountered in the input
  15252.    file), the input operation is complete and the entire string is presented
  15253.    to your program.
  15254.  
  15255.    This function provides many advantages, particularly to those programs
  15256.    needing complete, coherent strings of keyboard input, rather than
  15257.    byte-by-byte input. The two foremost benefits are that you are spared the
  15258.    effort of writing detailed input-handling code, and your programs' users
  15259.    are given a familiar set of input editing tools: the DOS editing
  15260.    conventions.
  15261.  
  15262.    To use this function, you must provide DOS with an input buffer area where
  15263.    the input string will be built. The register pair DS:DX points to this
  15264.    buffer when you call the function. The first 3 bytes of this buffer have
  15265.    specific purposes:
  15266.  
  15267.    ■  The first byte indicates the working size of the buffer (the number of
  15268.       bytes that DOS can use for input).
  15269.  
  15270.    ■  The second byte is updated by DOS to indicate the actual number of
  15271.       bytes input.
  15272.  
  15273.    ■  The third byte is the beginning of the input string, which consists
  15274.       entirely of ASCII characters. The end of the input string is signaled
  15275.       by the carriage-return character, ASCII 0DH. Although the carriage
  15276.       return is placed in the buffer, it is not included in the character
  15277.       count that DOS returns in the second byte.
  15278.  
  15279.    By these rules, the longest buffer you can give DOS is 255 working bytes,
  15280.    and the longest string that DOS can return is 1 byte less than the working
  15281.    length. Because the first 2 bytes of the buffer are used for status
  15282.    information, the actual working size of the buffer is 2 bytes less than
  15283.    the buffer's overall size. This may explain some of the mysteries of the
  15284.    input conventions in both DOS and BASIC.
  15285.  
  15286.    If input continues beyond what DOS can place in the buffer (which is 1
  15287.    byte short of its working length), then DOS will discard any further
  15288.    input, beeping all the while, until a carriage return is encountered.
  15289.  
  15290.    See function 0CH for a variation of this function.
  15291.  
  15292.  Function 0BH (decimal 11): Check Keyboard Status
  15293.  
  15294.    Function 0BH (decimal 11) reports whether input is ready from the keyboard
  15295.    (or standard input device). If a character is ready, AL = FFH (decimal
  15296.    255). If no input is ready, AL = 00H.
  15297.  
  15298.    DOS checks for Ctrl-C when you execute function 0BH, so a loop that
  15299.    contains a call to this function can be interrupted by a keyboard break.
  15300.  
  15301.  Function 0CH (decimal 12): Flush Keyboard Buffer, Read Keyboard
  15302.  
  15303.    Function 0CH (decimal 12) clears the keyboard buffer in RAM and then
  15304.    invokes one of five DOS functions: function 01H, 06H, 07H, 08H, or 0AH.
  15305.    The AL register is used to select which of these functions will be
  15306.    performed after the keyboard buffer is flushed. With the keyboard buffer
  15307.    clear of extraneous characters, function 0CH forces the system to wait for
  15308.    new input before it acts on the invoked function.
  15309.  
  15310.    Because function 06H is supported, the follow-up service need not be
  15311.    keyboard input: It can be display output.
  15312.  
  15313.  Function 0DH (decimal 13): Flush Disk Buffers
  15314.  
  15315.    Function 0DH (decimal 13) flushes (writes to disk) all internal DOS file
  15316.    buffers. However, this function does not update directory entries or close
  15317.    any open files. To ensure that the proper length of a changed file is
  15318.    recorded in the file directory, use the close-file functions 10H or 3EH.
  15319.  
  15320.  Function 0EH (decimal 14): Select Disk Drive
  15321.  
  15322.    Function 0EH (decimal 14) selects a new current default drive. It also
  15323.    reports the number of drives installed. The drive is specified in DL, with
  15324.    00H indicating drive A, 01H drive B, and so on. The number of drives is
  15325.    reported in AL.
  15326.  
  15327.    Keep a few things in mind when using this function:
  15328.  
  15329.    ■  The drive IDs used by DOS are consecutively numbered.
  15330.  
  15331.    ■  If only one physical diskette drive exists, DOS will simulate a second
  15332.       drive, drive number 1 (drive B). Thus the first fixed-disk drive is
  15333.       always drive number 2, corresponding to drive letter C.
  15334.  
  15335.    ■  If you use the value in AL to determine the number of drives in your
  15336.       system, beware: In DOS versions 3.0 and later, the minimum value
  15337.       returned by this function is 05H.
  15338.  
  15339.  Function 0FH (decimal 15): Open File
  15340.  
  15341.    Function 0FH (decimal 15) opens a file using a file control block (FCB).
  15342.    An FCB is a data structure used by DOS to track input and output for a
  15343.    particular file. Among other things, an FCB contains a file's name and
  15344.    disk drive number. (See page 341 in this chapter for details on the
  15345.    contents of FCBs.)
  15346.  
  15347.    ──────────────────────────────────────────────────────────────────────────
  15348.    NOTE:
  15349.      Function 0FH is one of 15 DOS functions that use an FCB to track file
  15350.      input and output. You should avoid the DOS functions that use FCBs.
  15351.      These functions were made obsolete by the more powerful handle-based
  15352.      file functions introduced in DOS version 2.0. Furthermore, unlike
  15353.      handle-based functions, FCB-based functions are not supported in OS/2
  15354.      protected mode. Use the FCB-based functions only if compatibility with
  15355.      DOS version 1 is important.
  15356.    ──────────────────────────────────────────────────────────────────────────
  15357.  
  15358.    To use an FCB to open a file, you must reserve memory for the FCB and
  15359.    place the file's name and disk drive number in the proper fields in the
  15360.    data structure. Then call function 0FH with the segmented address of
  15361.    the FCB in the register pair DS:DX. DOS attempts to open the file, using
  15362.    the drive and filename you specified in the FCB. If the file is opened, AL
  15363.    = 00H; if the file cannot be opened, AL = FFH.
  15364.  
  15365.    If the file is opened successfully, DOS initializes several fields in the
  15366.    FCB, including the drive number field (with a value of 1 for drive A, 2
  15367.    for drive B, and so on), the date and time fields, and the logical
  15368.    record-size field (which is set to 128). You can either use this record
  15369.    size or change it, depending on your application.
  15370.  
  15371.  Function 10H (decimal 16): Close File
  15372.  
  15373.    Function 10H (decimal 16) closes a file and updates the file's directory
  15374.    entry. Call this function with the segmented address of the file's FCB in
  15375.    DS:DX. DOS returns AL = 00H if the function successfully closed the file
  15376.    or AL = FFH if an error occurred.
  15377.  
  15378.    It is good practice to use function 10H to explicitly close all files you
  15379.    opened with function 0FH or 16H. This ensures that the file contents are
  15380.    updated from DOS internal file buffers and that the corresponding
  15381.    directory entries are current.
  15382.  
  15383.  Function 11H (decimal 17): Find First Matching Directory Entry
  15384.  
  15385.    Function 11H (decimal 17) searches the current directory for a specified
  15386.    directory entry. The name you specify to function 11H can contain the
  15387.    wildcard characters ? and *. The ? character matches any single ASCII
  15388.    character (as a wild card in a poker game matches any other card) and the
  15389.    * matches any string of characters, so DOS can match a name that contains
  15390.    one or more wildcard characters with several different directory entries.
  15391.    If more than one directory entry matches, DOS reports only the first
  15392.    match. You must then use function 12H to continue the search for
  15393.    subsequent matching directory entries.
  15394.  
  15395.    Before you call function 11H, store the address of an FCB in DS:DX. The
  15396.    filename field of this FCB must contain the name you want DOS to search
  15397.    for. DOS reports a successful match by returning AL = 00H; if no directory
  15398.    entries match the specified name, DOS returns AL = FFH. When DOS finds a
  15399.    matching directory entry, it creates a new FCB in the current disk
  15400.    transfer area (DTA) and copies the matching name from the directory entry
  15401.    into the new FCB's filename field.
  15402.  
  15403.    If the FCB has an FCB extension (see page 344), then you can specify the
  15404.    attributes of the file that you wish to search for. If you specify any
  15405.    combination of the hidden, system, or directory attribute bits, the search
  15406.    matches normal files and also any files with those attributes. If you
  15407.    specify the volume-label attribute, this function searches only for a
  15408.    directory entry with that attribute. With DOS versions prior to 2.0,
  15409.    neither the directory nor the volume-label attributes can be used in the
  15410.    file search operation. The archive and read-only attributes cannot be used
  15411.    as search criteria in any DOS release.
  15412.  
  15413.  Function 12H (decimal 18): Find Next Matching Directory Entry
  15414.  
  15415.    Function 12H (decimal 18) finds the next of a series of files, following
  15416.    the set-up preparation performed by function 11H. As with function 11H,
  15417.    you must call function 12H with the address of an FCB in DS:DX. For
  15418.    function 12H, the FCB should be the same as the one you used for a
  15419.    successful call to function 11H.
  15420.  
  15421.    DOS reports a successful match by returning AL = 00H; if no match exists,
  15422.    DOS returns AL = FFH. This lets you combine functions 11H and 12H to
  15423.    perform a complete directory search by using the following logic:
  15424.  
  15425.    initialize FCB
  15426.    call function 11H
  15427.    WHILE AL = 0
  15428.            use current contents of DTA
  15429.            call function 12H
  15430.  
  15431.  Function 13H (decimal 19): Delete File
  15432.  
  15433.    Function 13H (decimal 19) deletes all files that match the name specified
  15434.    in the FCB pointed to by the register pair DS:DX. The filename in the FCB
  15435.    can contain wildcard characters so that multiple files can be deleted with
  15436.    a single call to function 13H. The function returns AL = 00H if the
  15437.    operation is a success and all matching file directory entries are
  15438.    deleted. AL = FFH if the operation is a failure, meaning that no directory
  15439.    entries matched.
  15440.  
  15441.  Function 14H (decimal 20): Sequential Read
  15442.  
  15443.    Function 14H (decimal 20) reads records sequentially from a file. To use
  15444.    this function, open a file using function 0FH. Then initialize the
  15445.    current-record and record-size fields of the FCB. For example, to read the
  15446.    first 256-byte record from a file, set the record-size field to 100H
  15447.    (decimal 256) and the current-record field to 00H before you call function
  15448.    14H.
  15449.  
  15450.    After the FCB is initialized, you can call function 14H once for each
  15451.    record you want to read. Each time you call function 14H, pass the address
  15452.    of the file's FCB in DS:DX. DOS reads the next record from the file and
  15453.    stores the data in the current disk transfer area (DTA). At the same time,
  15454.    DOS tracks its current position in the file by updating the current-block
  15455.    and current-record fields in the FCB.
  15456.  
  15457.    AL reports the results of the read. Complete success is signaled when AL =
  15458.    00H; AL = 01H signals an end-of-file, indicating that no data was read; AL
  15459.    = 02H signals that data could have been read, but wasn't, because
  15460.    insufficient memory remained in the DTA segment; AL = 03H signals an
  15461.    end-of-file with a partial record read (the record is padded with zero
  15462.    bytes).
  15463.  
  15464.  Function 15H (decimal 21): Sequential Write
  15465.  
  15466.    Function 15H (decimal 21) writes a sequential record and is the companion
  15467.    to function 14H. As with function 14H, DOS tracks its current position in
  15468.    the file by updating the FCB whose address you pass in DS:DX. DOS copies
  15469.    the data from the current DTA to the file and reports the status of the
  15470.    write operation in AL.
  15471.  
  15472.    If AL = 00H, the write operation was a success. If AL = 01H, the disk was
  15473.    full and the record was not written. If AL = 02H, the amount of memory
  15474.    remaining in the DTA's segment was less than the record size, so DOS
  15475.    aborted the write operation.
  15476.  
  15477.    It's important to note that data is logically written by this function,
  15478.    but not necessarily physically written. DOS buffers output data until it
  15479.    has a complete disk sector to write──only then does DOS actually transfer
  15480.    the data to the disk.
  15481.  
  15482.  Function 16H (decimal 22): Create File
  15483.  
  15484.    Function 16H (decimal 22) opens an empty file with a specified name. If
  15485.    the file exists in the current directory, function 16H truncates it to
  15486.    zero length. If the file does not exist, function 16H creates a directory
  15487.    entry for the new file. As with the other FCB-based file functions, you
  15488.    call function 16H with DS:DX pointing to an FCB containing the name of the
  15489.    file. The function returns AL = 00H to indicate successful operation. If
  15490.    AL = FFH, the function failed, possibly because the filename you specified
  15491.    in the FCB is not valid.
  15492.  
  15493.    If you want to avoid inadvertently losing the contents of an existing
  15494.    file, you should determine if the file already exists by calling function
  15495.    11H before you use function 16H.
  15496.  
  15497.  Function 17H (decimal 23): Rename File
  15498.  
  15499.    Function 17H (decimal 23) renames files or subdirectories in a modified
  15500.    FCB pointed to by DS:DX. For the rename operation, the FCB has a special
  15501.    format. The drive and original name are located in their usual positions,
  15502.    but the new name and extension are placed at offsets 11H through 1BH in
  15503.    the FCB.
  15504.  
  15505.    AL = 00H signals complete success, and AL = FFH signals that the original
  15506.    name wasn't found or the new name is already in use.
  15507.  
  15508.    If the new name contains wildcard characters (?), they are interpreted as
  15509.    ditto-from-old-name, and the characters in the original name that
  15510.    correspond to the positions of the wildcard characters are not changed.
  15511.  
  15512.  Function 19H (decimal 25): Get Current Disk
  15513.  
  15514.    Function 19H (decimal 25) reports the current drive number in AL, using
  15515.    the standard numeric code of drive A = 00H, drive B = 01H, and so forth.
  15516.  
  15517.  Function 1AH (decimal 26): Set Disk Transfer Area
  15518.  
  15519.    Function 1AH (decimal 26) establishes the disk transfer area that DOS will
  15520.    use for file I/O. The location of the DTA is specified by the register
  15521.    pair DS:DX. Normally, you should specify a DTA address before you use any
  15522.    of the interrupt 21H functions that access a DTA. If you do not, DOS uses
  15523.    the default 128-byte DTA at offset 80H in the program segment prefix.
  15524.  
  15525.  Function 1BH (decimal 27): Get Default Drive Information
  15526.  
  15527.    Function 1BH (decimal 27) returns important information about the disk in
  15528.    the current drive. Function 1CH performs the identical service for any
  15529.    drive. Function 36H performs a nearly identical service. (See Chapter
  15530.    17.)
  15531.  
  15532.    The following information is returned through this function call:
  15533.  
  15534.    ■  AL contains the number of sectors per cluster.
  15535.  
  15536.    ■  CX contains the size, in bytes, of the disk sectors (512 bytes for all
  15537.       standard PC formats).
  15538.  
  15539.    ■  DX contains the total number of clusters on the disk.
  15540.  
  15541.    ■  DS:BX points to a byte in DOS's work area containing the DOS media
  15542.       descriptor. Prior to DOS version 2.0, the DS:BX register pair pointed
  15543.       to the complete disk FAT (which could be guaranteed to be in memory,
  15544.       complete), whose first byte would be the ID byte. In later DOS
  15545.       versions, DS:BX points only to the single ID byte.
  15546.  
  15547.    Beware: Function 1BH uses the DS register to return the address of the
  15548.    media descriptor byte. If your program relies on the DS register to point
  15549.    to data──and most high-level and assembly-language programs do──then you
  15550.    should be careful to preserve the contents of the DS register while you
  15551.    call function 1BH.
  15552.  
  15553.    The following example shows how to do this:
  15554.  
  15555.    push    ds              ; preserve DS
  15556.    mov     ah,1Bh
  15557.    int     21h             ; call function 1BH; DS:BX -> media descriptor
  15558.    mov     ah,[bx]         ; get a copy of the media descriptor byte
  15559.    pop     ds              ; restore DS
  15560.  
  15561.  Function 1CH (decimal 28): Get Specified Drive Information
  15562.  
  15563.    Function 1CH works in the same way as function 1BH except that it reports
  15564.    on any drive, not only the current drive. Before calling this function,
  15565.    set DL to the drive ID number, where 0 = the current drive, 1 = drive A, 2
  15566.    = drive B, and so forth.
  15567.  
  15568.  Function 21H (decimal 33): Read Random Record
  15569.  
  15570.    Function 21H (decimal 33) reads one record from a random location in a
  15571.    file. To use this function, open a file with an FCB. Then store the record
  15572.    number of the record you want to read in the random-record field of the
  15573.    FCB. When you call function 21H with DS:DX pointing to the FCB, DOS reads
  15574.    the specified record into the DTA.
  15575.  
  15576.    AL is set with the same codes as it is for a sequential read: AL = 00H
  15577.    indicates a successful read; AL = 01H indicates end-of-file, with no more
  15578.    data available; AL = 02H means that insufficient space exists in the DTA
  15579.    segment; and AL = 03H indicates an end-of-file, with a partial data record
  15580.    available.
  15581.  
  15582.    Contrast this function with function 27H, which can read more than one
  15583.    random record at a time, or with function 14H, which reads sequential
  15584.    records. See function 24H for more on setting the random-record field.
  15585.  
  15586.  Function 22H (decimal 34): Write Random Record
  15587.  
  15588.    Function 22H (decimal 34) writes one record to a random location in a
  15589.    file. As with function 21H, you must initialize the random-record field in
  15590.    the file's FCB and then call this function with DS:DX pointing to the FCB.
  15591.    DOS then writes data from the DTA to the file at the position specified in
  15592.    the FCB.
  15593.  
  15594.    AL is set with the same codes used for a sequential write: AL = 00H
  15595.    indicates a successful write; AL = 01H means the disk is full; AL = 02H
  15596.    indicates insufficient space in the DTA segment.
  15597.  
  15598.    Contrast this function with function 28H, which can write more than one
  15599.    random record, or with function 15H, which writes sequential records. See
  15600.    function 24H for more on setting the random-record field.
  15601.  
  15602.  Function 23H (decimal 35): Get File Size
  15603.  
  15604.    Function 23H (decimal 35) reports the size of a file in terms of the
  15605.    number of records in the file. DS:DX points to the FCB of the file you
  15606.    want to know about. Before calling the function, the FCB should be left
  15607.    unopened and the record-size field in the FCB filled in. If you set the
  15608.    record size to 1, the file size is reported in bytes, which is most likely
  15609.    what you want.
  15610.  
  15611.    If the operation is successful, AL = 00H and the file size is inserted
  15612.    into the FCB. If the file is not found, AL = FFH.
  15613.  
  15614.  Function 24H (decimal 36): Set FCB Random Record Field
  15615.  
  15616.    Function 24H (decimal 36) sets the random-record field to correspond to
  15617.    the current sequential block and record fields in an FCB. This facilitates
  15618.    switching from sequential to random I/O. The DS:DX registers point to the
  15619.    FCB of an open file.
  15620.  
  15621.  Function 25H (decimal 37): Set Interrupt Vector
  15622.  
  15623.    Function 25H (decimal 37) sets an interrupt vector. Before you call
  15624.    function 25H, place the segmented address of an interrupt handler in DS:DX
  15625.    and an interrupt number in AL. DOS stores the segment and offset of your
  15626.    interrupt handler in the proper interrupt vector.
  15627.  
  15628.    When updating an interrupt vector, you should use function 25H instead of
  15629.    simply computing the address of the vector and updating it directly. Not
  15630.    only is it simpler to call this function than to do the work yourself, but
  15631.    this function gives the operating system the chance to detect when an
  15632.    important interrupt vector is modified.
  15633.  
  15634.    To examine the contents of an interrupt vector, see function 35H in the
  15635.    next chapter.
  15636.  
  15637.  Function 26H (decimal 38): Create New Program Segment Prefix
  15638.  
  15639.    Function 26H is used within a program to prepare for loading and executing
  15640.    another subprogram, or overlay. When you call function 26H, DX must
  15641.    contain the paragraph address of the start of the memory area where you
  15642.    want DOS to build the new PSP. DOS builds a new PSP at the location you
  15643.    specify. You can then load an executable program from a file into the
  15644.    memory above the new PSP and transfer control to it.
  15645.  
  15646.    ──────────────────────────────────────────────────────────────────────────
  15647.    NOTE:
  15648.      Function 26H is obsolete. You should use function 4BH (Chapter 17) to
  15649.      load and execute a new program from within another executing program.
  15650.    ──────────────────────────────────────────────────────────────────────────
  15651.  
  15652.  Function 27H (decimal 39): Read Random Records
  15653.  
  15654.    Unlike function 21H, function 27H reads one or more records, starting at a
  15655.    random file location. DS:DX points to the FCB for the file to be read and
  15656.    the random-record number is then taken from this FCB. CX contains the
  15657.    number of records desired, which should be more than 0.
  15658.  
  15659.    The return codes are the same as they are for function 21H: AL = 00H means
  15660.    the read was successful; AL = 01H indicates end-of-file, with no more data
  15661.    (if the records were read, the last record is complete); AL = 02H
  15662.    indicates that the DTA segment was too small; and AL = 03H indicates the
  15663.    end-of-file, where the last record read is incomplete and padded with
  15664.    zeros.
  15665.  
  15666.    No matter what the result, CX is set to the number of records read,
  15667.    including any partial record, and the random-record field in the FCB is
  15668.    set to the next sequential record.
  15669.  
  15670.    Contrast this with function 21H, which reads only one record.
  15671.  
  15672.  Function 28H (decimal 40): Write Random Records
  15673.  
  15674.    Unlike function 22H, function 28H (decimal 40) writes one or more records,
  15675.    starting at a specified random file location. DS:DX points to the FCB for
  15676.    the file to be written, and the random record number is then taken from
  15677.    this FCB. CX contains the number of records desired and in this case, CX
  15678.    can be 00H. CX = 00H signals DOS to adjust the file's length to the
  15679.    position of the specified random record. This adjustment makes it easier
  15680.    for a program to manage random files: If you have logically deleted
  15681.    records at the end of a file, this service allows you to truncate the file
  15682.    at that point by setting the file's length in CX, thereby freeing disk
  15683.    space.
  15684.  
  15685.    The return codes are the same as they are for function 22H: AL = 00H
  15686.    indicates a successful write; AL = 01H means that no more disk space is
  15687.    available; and AL = 02H indicates that the DTA segment was too small. No
  15688.    matter what the result, CX is always set to the number of records written.
  15689.  
  15690.    Contrast this function with function 22H, which writes only one random
  15691.    record.
  15692.  
  15693.  Function 29H (decimal 41): Parse Filename
  15694.  
  15695.    Function 29H (decimal 41) parses a string for a filename with the form
  15696.    DRIVE:FILENAME.EXT. Call this function with DS:SI pointing to a text
  15697.    string and ES:DI pointing to the drive-identifier byte in an unopened FCB.
  15698.    Function 29H attempts to extract the drive and filename information from
  15699.    the string, and to use it to initialize the drive and name fields of the
  15700.    FCB. If the function executes successfully, it returns AL = 00H if the
  15701.    string contains no wildcard characters or AL = 01H if the string contains
  15702.    at least one * or ? wildcard character. If the drive letter specifies an
  15703.    invalid drive, the function returns AL = FFH.
  15704.  
  15705.    Function 29H also updates DS:SI to point to the byte after the end of the
  15706.    filename in the string. This facilitates processing a string that contains
  15707.    multiple filenames. Also, if the parsing was unsuccessful, the FCB
  15708.    contains a blank filename.
  15709.  
  15710.    Function 29H lets you control four different aspects of the filename
  15711.    parsing. When you call the function, the 4 low-order bits of the value in
  15712.    AL specify how function 29H parses the string:
  15713.  
  15714.    ■  If bit 0 is set, the function scans past separator characters (for
  15715.       example, leading blank spaces) to find the file specification. If bit 0
  15716.       is 0, the scan operation is not performed, and the file specification
  15717.       is expected to start in the first byte of the string.
  15718.  
  15719.    ■  If bit 1 is set, then the drive byte in the FCB will be set only if it
  15720.       is specified in the file specification being scanned. This allows the
  15721.       FCB to specify a default drive.
  15722.  
  15723.    ■  If bit 2 is set, the filename in the FCB is changed only if a valid
  15724.       filename is found in the string. This lets the FCB specify a default
  15725.       filename, which can be overridden by the filename in the string.
  15726.  
  15727.    ■  If bit 3 is set, the filename extension in the FCB is changed only if a
  15728.       valid extension is found in the file specification. This allows the FCB
  15729.       to specify a default extension.
  15730.  
  15731.    ──────────────────────────────────────────────────────────────────────────
  15732.    NOTE:
  15733.      Although this service can be handy, it is intended for use only with
  15734.      FCB-based file functions. You don't need this function if you rely on
  15735.      the handle-based file functions described in Chapter 17.
  15736.    ──────────────────────────────────────────────────────────────────────────
  15737.  
  15738.  Function 2AH (decimal 42): Get Date
  15739.  
  15740.    Function 2AH (decimal 42) reports DOS's record of the current date. The
  15741.    date is reported in CX and DX. DH contains the month number (1 through
  15742.    12); DL contains the day of the month (1 through 28, 29, 30, or 31, as
  15743.    appropriate); and CX contains the year (1980 through 2099).
  15744.  
  15745.    This function reports the day of the week by returning a value from 0
  15746.    through 6, which signifies Sunday through Saturday, in register AL. This
  15747.    day-of-the-week feature is somewhat of an orphan. It has been present in
  15748.    DOS since version 1.1, but was not even mentioned until DOS version 2.0.
  15749.    In both the 2.0 and 2.1 manuals, it is incorrectly described as a part of
  15750.    the get-time function and not as part of the get-date function. Starting
  15751.    with DOS 3.0, the manual tells it as it is. Turn to the example on page
  15752.    346 to see how this function can be used.
  15753.  
  15754.  Function 2BH (decimal 43): Set Date
  15755.  
  15756.    Function 2BH (decimal 43) sets DOS's record of the current date, using the
  15757.    same registers as function 2AH. The date is set in CX and DX. DH contains
  15758.    the month number (1 through 12); DL contains the day of the month (1
  15759.    through 28, 29, 30, or 31, as appropriate); CX contains the year (1980
  15760.    through 2099). This function returns AL = 00H if the date is successfully
  15761.    updated, or AL = FFH if you specified an invalid date.
  15762.  
  15763.    Starting in DOS version 3.3, this function also updates the real-time
  15764.    clock/calendar in the PC/AT and PS/2. In earlier versions, you must still
  15765.    use ROM BIOS interrupt 1AH services to change the real-time clock date.
  15766.  
  15767.  Function 2CH (decimal 44): Get Time
  15768.  
  15769.    Function 2CH (decimal 44) reports the time of day. The time is calculated
  15770.    from the ROM BIOS timer-tick count. (See page 59.) DOS responds to the
  15771.    ROM BIOS's midnight-passed signal and updates the date every 24 hours.
  15772.  
  15773.    The timer-tick count is converted into a meaningful time and placed in
  15774.    registers CX and DX. CH contains the hour (0 through 23, on a 24-hour
  15775.    clock); CL contains the minutes (0 through 59); DH contains the seconds (0
  15776.    through 59); and DL contains hundredths of seconds (0 through 99). This
  15777.    function returns AL = 00H if the time is successfully updated, or AL = FFH
  15778.    if you specified an invalid time.
  15779.  
  15780.    The IBM PC timer ticks 18.2 times per second, so the time of day reported
  15781.    by DOS is only as accurate as the timer tick──roughly 5.4 hundredths of a
  15782.    second. Nevertheless, even with this relatively low accuracy, you can use
  15783.    DOS function 2CH to measure time intervals in many applications.
  15784.  
  15785.  Function 2DH (decimal 45): Set Time
  15786.  
  15787.    Function 2DH (decimal 45) sets the time of day. The time is specified in
  15788.    registers CX and DX. CH contains the hour (0 through 23, on a 24-hour
  15789.    clock); CL contains the minutes (0 through 59); DH contains the seconds (0
  15790.    through 59); DL contains hundredths of seconds (0 through 99).
  15791.  
  15792.    Starting in DOS version 3.3, this function also updates the real-time
  15793.    clock in the PC/AT and PS/2. In earlier versions, you must still use ROM
  15794.    BIOS interrupt 1AH services to change the real-time clock time.
  15795.  
  15796.  Function 2EH (decimal 46): Set Verify Flag
  15797.  
  15798.    Function 2EH (decimal 46) controls verification of disk-write operations.
  15799.    Call this function with AL = 01H to set DOS's internal verify flag and
  15800.    enable verification; call it with AL = 00H to turn off the flag and
  15801.    verification. Also, in DOS versions 1 and 2, you must zero DL before you
  15802.    call function 2EH.
  15803.  
  15804.    The disk-verify operation requires the disk controller to perform a
  15805.    cyclical redundancy check (CRC) each time it writes data to the disk. This
  15806.    process involves reading the data just written, which significantly
  15807.    decreases the speed of disk writes.
  15808.  
  15809.    With DOS versions 2.0 and later, function 54H can be used to report the
  15810.    current setting of the verify flag. (See page 379.)
  15811.  
  15812.  
  15813.  The File Control Block
  15814.  
  15815.    As mentioned several times in this chapter, file control blocks and the
  15816.    DOS functions that use them are obsolete. We recommend that you use the
  15817.    handle-based file I/O functions introduced in DOS version 2.0 and
  15818.    described in the next chapter. Usually, the only reason to concern
  15819.    yourself with FCBs is when compatibility with DOS version 1 is an issue.
  15820.  
  15821.    With that in mind, let's take a look at the structure of the FCB. The
  15822.    usual FCB is a 37-byte data structure that contains a variety of
  15823.    information DOS can use to control file input/output. (See Figure 16-3.)
  15824.    A 44-byte, extended FCB is also used in some DOS functions: 7 extra bytes
  15825.    are tacked onto the beginning of the usual FCB data structure. (See Figure
  15826.    16-4.)
  15827.  
  15828.    The situation with the FCB extension is more than a little peculiar. The
  15829.    extension is used only when you work with the attribute field in a
  15830.    directory entry in which read-only files, hidden files, system files,
  15831.    volume labels, and subdirectories are identified. In general, you need to
  15832.    use extended FCBs only if you are performing directory searches or
  15833.    otherwise working with directory entries rather than the contents of
  15834.    files. However, all FCB-based functions recognize the extended FCB format
  15835.    if you should choose to use it.
  15836.  
  15837.    Offset             Field Width       Description
  15838.    ──────────────────────────────────────────────────────────────────────────
  15839.    00H                1                 Drive identifier
  15840.    01H                8                 Filename
  15841.    09H                3                 File extension
  15842.    0CH                2                 Current-block number
  15843.    0EH                2                 Record size in bytes
  15844.    10H                4                 File size in bytes
  15845.    14H                2                 Date
  15846.    16H                2                 Time
  15847.    18H                8                 (Reserved)
  15848.    20H                1                Current-record number
  15849.    21H                4                 Random-record number
  15850.    ──────────────────────────────────────────────────────────────────────────
  15851.  
  15852.    Figure 16-3.  Structure of a file control block.
  15853.  
  15854.    Offset             Field Width       Description
  15855.    ──────────────────────────────────────────────────────────────────────────
  15856.    00H                1                 Extended FCB flag (always FFH)
  15857.    01H                5                 (Reserved)
  15858.    06H                1                 Attribute
  15859.    07H                1                 Drive identifier
  15860.    08H                8                 Filename
  15861.    10H                3                 File extension
  15862.    13H                2                 Current-block number
  15863.    15H                2                 Record size in bytes
  15864.    17H                4                 File size in bytes
  15865.    1BH                2                 Date
  15866.    1DH                2                 Time
  15867.    1FH                8                 (Reserved)
  15868.    27H                1                Current-record number
  15869.    28H                4                 Random-record number
  15870.    ──────────────────────────────────────────────────────────────────────────
  15871.  
  15872.    Figure 16-4.  Structure of an extended file control block. The first three
  15873.    fields distinguish this data structure from a normal FCB.
  15874.  
  15875.    With two exceptions, all fields in an extended FCB are identical to those
  15876.    in a normal FCB. Only the offsets are different: In an extended FCB, the
  15877.    offset of a particular field is 7 bytes greater than the offset of the
  15878.    same field in a normal FCB.
  15879.  
  15880.    The following sections describe the fields in normal extended FCBs.
  15881.  
  15882.  FCB Fields
  15883.  
  15884.    Offset 00H. The first field in a normal (nonextended) FCB is the disk
  15885.    drive identifier. Values for the drive identifier start at 1; a value of 1
  15886.    indicates drive A, 2 indicates drive B, and so on. If this field contains
  15887.    0 at the time an FCB is opened, DOS uses the current default drive and
  15888.    updates this field with the corresponding drive identifier.
  15889.  
  15890.    Offsets 01H and 09H. The two fields at offsets 01H and 09H contain an
  15891.    8-byte name and a 3-byte extension. These fields are left-justified and
  15892.    padded on the right with blanks. Following DOS convention, either upper-
  15893.    or lowercase letters may be used. If the filename is a device name that
  15894.    DOS recognizes, such as CON, AUX, COM1, COM2, LPT1, LPT2, PRN, or NUL, DOS
  15895.    will use that device rather than a disk file.
  15896.  
  15897.    ──────────────────────────────────────────────────────────────────────────
  15898.    NOTE:
  15899.      This is a reasonably good place to point out that the FCB mechanism has
  15900.      no provision for working with pathnames. Whenever you use FCBs, they
  15901.      always apply to the current directory in any drive. For flexible use of
  15902.      paths and subdirectories, see the new, extended functions in Chapter
  15903.      17.
  15904.    ──────────────────────────────────────────────────────────────────────────
  15905.  
  15906.    Offsets 0CH and 20H. For sequential file operations, the current-block and
  15907.    current-record fields keep track of the location in the file. The use of
  15908.    these fields is rather odd. Instead of using one integrated record number,
  15909.    the record number is divided into a high and low portion, referred to as
  15910.    the block number and record number. The record number is a 7-bit value, so
  15911.    record numbers range from 0 through 127. Thus the first record in a file
  15912.    is block 0, record 0; the 128th record is block 1, record 0.
  15913.  
  15914.    Before you use the sequential read and write functions 14H and 15H, be
  15915.    sure to initialize the current block and record fields to the desired
  15916.    starting location in the file.
  15917.  
  15918.    Offset 0EH. The record-size field contains a 2-byte value that specifies
  15919.    the size, in bytes, of the logical records in the file. When DOS reads or
  15920.    writes a record, the logical size of the record is the number of bytes
  15921.    transferred between DOS's disk buffers and the DTA.
  15922.  
  15923.    The same file data can be worked on using a variety of record sizes. When
  15924.    a file is opened through functions 0FH or 16H, DOS sets the record size to
  15925.    128 bytes by default. If you want another size, such as 1 for single-byte
  15926.    operations, you must change the record-size field after the file is
  15927.    opened.
  15928.  
  15929.    Offset 10H. The file-size field at offset 10H indicates the file size in
  15930.    bytes. The value is taken from a file's directory entry and is placed in
  15931.    the FCB when DOS opens the file. For an output file, this field is changed
  15932.    by DOS as the file grows. When the file is closed, the value is copied
  15933.    from the FCB to the file's directory entry.
  15934.  
  15935.    By changing this field, you can gain some last-minute control over the
  15936.    size of an output file, but be careful when doing this. You can, for
  15937.    example, truncate a file you have updated by decreasing the file-size
  15938.    value in this field. Also, be careful not to use function 17H to rename an
  15939.    open file: This function requires that you specify the file's new name in
  15940.    the same part of the FCB used for the file size.
  15941.  
  15942.    Offsets 14H and 16H. The 2-byte fields at offset 14H (date) and offset 16H
  15943.    (time) record when a file was last updated. These fields use the same
  15944.    format as the corresponding fields in a directory entry. (See Chapter 5.)
  15945.    The initial values in these fields are copied from a file's directory
  15946.    entry when the file is opened. They are subsequently updated each time you
  15947.    write to the file. If the file was updated, DOS copies the values from the
  15948.    FCB to the directory entry when the file is closed.
  15949.  
  15950.    Offset 21H. The random-record field is used during random read and write
  15951.    operations, just as the current record and block numbers are used during
  15952.    sequential operations. This field is in the form of a 4-byte, 32-bit
  15953.    integer. Records are numbered from 0, which makes it easy to calculate the
  15954.    file offset to any record by multiplying the random-record number by the
  15955.    record size. You must set this field before any random file operation. DOS
  15956.    leaves it undisturbed.
  15957.  
  15958.  Extended FCB Fields
  15959.  
  15960.    An extended FCB has two additional fields not found in a normal FCB:
  15961.  
  15962.    ■  The first field of an extended FCB is a flag byte whose contents must
  15963.       be FFH. DOS distinguishes between normal and extended FCBs by examining
  15964.       this byte. (In a normal FCB, the first field is the disk-drive
  15965.       specifier, which should never be FFH.)
  15966.  
  15967.    ■  Offset 06H in an extended FCB is a 1-byte field that consists of an
  15968.       attribute byte whose bits signify file, volume label, and subdirectory
  15969.       attributes. This byte's format is identical to the attribute byte in a
  15970.       directory entry. (See Chapter 5.)
  15971.  
  15972.    ──────────────────────────────────────────────────────────────────────────
  15973.    NOTE:
  15974.      One rare situation in which you would use FCB-based functions instead of
  15975.      handle-based functions is when you work with a disk's volume label. DOS
  15976.      versions 2.0 and later do not provide any special services for
  15977.      manipulating a volume label. You must use function 16H with an extended
  15978.      FCB to create a volume label, function 17H to rename it, and function
  15979.      13H to rename it.
  15980.    ──────────────────────────────────────────────────────────────────────────
  15981.  
  15982.  
  15983.  An Example
  15984.  
  15985.    For our assembly-language example in this section, we've chosen something
  15986.    rather interesting. It's a routine used within the Norton Utility
  15987.    programs, so you'll be seeing some actual production code.
  15988.  
  15989.    The purpose of this routine is to calculate the day of the week for any
  15990.    day within DOS's working range, which is stated to be from Tuesday,
  15991.    January 1, 1980, through Thursday, December 31, 2099. Occasionally, it's
  15992.    valuable for a program to be able to report the day of the week, either
  15993.    for the current date or for any other date that may be in question. For
  15994.    example, DOS keeps track of the date and time each file was last changed.
  15995.    Because people often use this information to find out when they last
  15996.    worked with a file, it can be handy to know the day of the week as well.
  15997.    In fact, the day of the week is often more immediately meaningful than the
  15998.    actual date.
  15999.  
  16000.    Although several interesting and clever algorithms let you calculate the
  16001.    day of the week, the actual work of writing a day-of-the-week program is
  16002.    usually rather tedious. Beginning with version 1.10, DOS incorporated a
  16003.    day-of-the-week calculation, which spared us the chore of writing our own.
  16004.    DOS's routine is available only in a form that reports the current day of
  16005.    the week, but that is no obstacle: We can temporarily change DOS's date to
  16006.    the date we're interested in and then have DOS report the day of the week.
  16007.    That is what the following assembly-language routine does for us.
  16008.  
  16009.    Besides being slightly foxy, this routine is interesting because it
  16010.    illustrates how three DOS function calls operate together to produce one
  16011.    result. It also illustrates the minor intricacies involved in saving and
  16012.    restoring things on the stack. As we will see here, stack use occasionally
  16013.    has to be carefully orchestrated so that different values don't get in
  16014.    each others' way.
  16015.  
  16016.    This particular subroutine, named Weekday, is set up in the form needed
  16017.    for use with the Microsoft C compiler. The routine is called with three
  16018.    integer variables, which specify the month, day, and year we are
  16019.    interested in. The routine returns the day of the week in the form of an
  16020.    integer in the range of 0 through 6 (signifying Sunday through Saturday).
  16021.    This conforms to the C language convention for arrays, providing an index
  16022.    to an array of strings that give the names of the days. Therefore, we
  16023.    could use this subroutine in this way:
  16024.  
  16025.    DayName[ Weekday( month, day, year ) ]
  16026.  
  16027.    It is important to note that this routine works blindly with the date,
  16028.    checking neither for a valid date nor for the range of dates accepted by
  16029.    DOS. Here is the subroutine:
  16030.  
  16031.    _TEXT           SEGMENT byte public 'CODE'
  16032.                    ASSUME  cs:_TEXT
  16033.  
  16034.                    PUBLIC  _Weekday
  16035.    _Weekday        PROC    near
  16036.  
  16037.                    push    bp              ; establish stack addressing ..
  16038.                    mov     bp,sp           ; .. through BP
  16039.  
  16040.                    mov     ah,2Ah          ; get current date
  16041.                    int     21h
  16042.  
  16043.                    push    cx              ; save current date on the stack
  16044.                    push    dx
  16045.  
  16046.                    mov     cx,[bp+8]       ; CX = year
  16047.                    mov     dl,[bp+6]       ; DL = day
  16048.                    mov     dh,[bp+4]       ; DH = month
  16049.  
  16050.                    mov     ah,2Bh          ; set the date specified
  16051.                    int     21h
  16052.  
  16053.                    mov     ah,2Ah          ; get the date back from DOS
  16054.                    int     21h             ; (AL = day of the week)
  16055.  
  16056.                    pop     dx              ; restore the current date ..
  16057.                    pop     cx              ; .. in CX and DX
  16058.                    push    ax              ; save day of week on the stack
  16059.  
  16060.                    mov     ah,2Bh          ; set the current date
  16061.                    int     21h
  16062.  
  16063.                    pop     ax              ; AL = day of week
  16064.                    mov     ah,0            ; AX = day of week
  16065.  
  16066.                    pop     bp              ; restore BP and return
  16067.                    ret
  16068.  
  16069.    _Weekday        ENDP
  16070.  
  16071.    _TEXT           ENDS
  16072.  
  16073.  
  16074.  
  16075.  ────────────────────────────────────────────────────────────────────────────
  16076.  Chapter 17  DOS Functions: Versions 2.0 and Later
  16077.  
  16078.    Enhancements in DOS Versions 2 and 3
  16079.      Consistent Error Codes
  16080.      ASCIIZ Strings
  16081.      File Handles
  16082.      Installable Device Drivers
  16083.  
  16084.    Interrupt 21H Functions: DOS Versions 2.0 and Later
  16085.      Function 2FH (decimal 47): Get DTA Address
  16086.      Function 30H (decimal 48): Get DOS Version Number
  16087.      Function 31H (decimal 49): Terminate and Stay Resident
  16088.      Function 33H (decimal 51): Get/Set Ctrl-C Flag
  16089.      Function 35H (decimal 53): Get Interrupt Vector
  16090.      Function 36H (decimal 54): Get Disk Free Space
  16091.      Function 38H (decimal 56): Get/Set Country-Dependent Information
  16092.      Function 39H (decimal 57): Create Directory
  16093.      Function 3AH (decimal 58): Remove Directory
  16094.      Function 3BH (decimal 59): Change Current Directory
  16095.      Function 3CH (decimal 60): Create File
  16096.      Function 3DH (decimal 61): Open Handle
  16097.      Function 3EH (decimal 62): Close Handle
  16098.      Function 3FH (decimal 63): Read from File or Device
  16099.      Function 40H (decimal 64): Write to File or Device
  16100.      Function 41H (decimal 65): Delete File
  16101.      Function 42H (decimal 66): Move File Pointer
  16102.      Function 43H (decimal 67): Get/Set File Attributes
  16103.      Function 44H (decimal 68): IOCTL──I/O Control for Devices
  16104.      Function 45H (decimal 69): Duplicate Handle
  16105.      Function 46H (decimal 70): Force Duplicate Handle
  16106.      Function 47H (decimal 71): Get Current Directory
  16107.      Function 48H (decimal 72): Allocate Memory Block
  16108.      Function 49H (decimal 73): Free Memory Block
  16109.      Function 4AH (decimal 74): Resize Memory Block
  16110.      Function 4BH (decimal 75): EXEC──Load and Execute a Program
  16111.      Function 4CH (decimal 76): Terminate with Return Code
  16112.      Function 4DH (decimal 77): Get Return Code
  16113.      Function 4EH (decimal 78): Find First Matching Directory Entry
  16114.      Function 4FH (decimal 79): Find Next Matching Directory Entry
  16115.      Function 54H (decimal 84): Get Verify Flag
  16116.      Function 56H (decimal 86): Rename File
  16117.      Function 57H (decimal 87): Get/Set File Date and Time
  16118.      Function 58H (decimal 88): Get/Set Memory Allocation Strategy
  16119.      Function 59H (decimal 89): Get Extended Error Information
  16120.      Function 5AH (decimal 90): Create Temporary File
  16121.      Function 5BH (decimal 91): Create New File
  16122.      Function 5CH (decimal 92): Lock/Unlock File Region
  16123.      Function 5EH (decimal 94): Network Machine Name and Printer Setup
  16124.      Function 5FH (decimal 95): Network Redirection
  16125.      Function 62H (decimal 98): Get PSP Address
  16126.      Function 65H (decimal 101): Get Extended Country Information
  16127.      Function 66H (decimal 102): Get/Set Global Code Page
  16128.      Function 67H (decimal 103): Set Handle Count
  16129.      Function 68H (decimal 104): Commit File
  16130.  
  16131.    In this chapter we'll discuss the interrupt 21H functions introduced in
  16132.    DOS versions 2.0 and later. These functions provide a wide range of
  16133.    operating system services within a more sophisticated and flexible
  16134.    framework than the original 42 functions we described in Chapter 16.
  16135.  
  16136.    Almost every DOS upgrade has increased the number of services provided to
  16137.    programmers. DOS 2.0 initiated the most dramatic changes: It added 33 new
  16138.    functions to the existing 42; it changed the way you access file
  16139.    information as a result of these new functions; and it made it possible to
  16140.    adapt DOS to work with almost any hardware device through the use of
  16141.    programs called installable device drivers. Before discussing the newer
  16142.    DOS functions in detail, we'll briefly cover how some of these
  16143.    enhancements can affect your programming practices.
  16144.  
  16145.  
  16146.  Enhancements in DOS Versions 2 and 3
  16147.  
  16148.    The services introduced with DOS versions 2 and 3 have three important new
  16149.    features that directly affect the way you use the services:
  16150.  
  16151.    ■  Most of the functions return a set of consistent error codes in the AX
  16152.       register.
  16153.  
  16154.    ■  All functions that use string input require a special string format
  16155.       known as the ASCIIZ format──a string of ASCII characters terminated by
  16156.       a single zero byte.
  16157.  
  16158.    ■  The newer DOS functions use a 16-bit number called a handle, instead of
  16159.       an FCB, to identify the files and I/O devices that a program
  16160.       communicates with.
  16161.  
  16162.    We'll discuss each of these enhancements on the next few pages.
  16163.  
  16164.  Consistent Error Codes
  16165.  
  16166.    When you call an interrupt 21H function in DOS versions 2.0 and later, the
  16167.    function returns an error status code in the AX register. These functions
  16168.    also set the carry flag to signal that an error has occurred. You should
  16169.    generally follow each call to these interrupt 21H functions with a test of
  16170.    the carry flag; if the flag is set, the value in AX describes what caused
  16171.    the error.
  16172.  
  16173.    In DOS versions 3.0 and later, you can also use interrupt 21H, function
  16174.    59H, to obtain extended error information from DOS. You can call function
  16175.    59H after any interrupt 21H function reports an error; you can also use it
  16176.    inside a critical-error (interrupt 24H) handler to determine the nature of
  16177.    a DOS critical error. In both situations, function 59H returns an extended
  16178.    error code and also suggests possible actions to alleviate the problem.
  16179.  
  16180.    For a complete list of extended error codes and how to use them, see the
  16181.    discussion of function 59H on page 381.
  16182.  
  16183.  ASCIIZ Strings
  16184.  
  16185.    Many interrupt 21H functions introduced in DOS versions 2 and 3 require
  16186.    you to pass file and directory names in the form of ASCIIZ strings. An
  16187.    ASCIIZ string is simply a string of ASCII characters terminated by a
  16188.    single zero byte that marks the end of the string. For example, the ASCIIZ
  16189.    representation of the pathname C:\COMMAND.COM would consist of the
  16190.    following 15 hexadecimal bytes:
  16191.  
  16192.                                                                     null
  16193.                                                                     byte
  16194.                                                                     │
  16195.                          ┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬─┐
  16196.    Characters───────────│C │: │\ │C │O │M │M │A │N │D │. │C │O │M │  │
  16197.                          └──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┘
  16198.    ASCII values (hex)─── 43 3A 5C 43 4F 4D 4D 41 4E 44 2E 43 4F 4D 00
  16199.  
  16200.    The ASCIIZ string format is commonly used within the UNIX operating system
  16201.    and the C programming language; it is only one of many new elements with a
  16202.    C/UNIX flavor introduced in DOS version 2.0.
  16203.  
  16204.  File Handles
  16205.  
  16206.    The newer interrupt 21H functions in DOS versions 2.0 and later rely on
  16207.    the notion of handles. Handles are 16-bit numbers that DOS uses to
  16208.    identify open files. Handles can also identify other sources of input and
  16209.    output for a program, including the keyboard and the video display.
  16210.    (They're also another example of the UNIX influence: In UNIX, file handles
  16211.    are called "file descriptors" but are used in essentially the same way as
  16212.    they are in DOS.)
  16213.  
  16214.    The use of handles allows DOS to be more flexible in its file management
  16215.    services than it was with FCB-based file services. In particular,
  16216.    capabilities such as file redirection and support for hierarchical
  16217.    directories would have been very difficult to graft onto the fixed-format
  16218.    FCB data structure. Furthermore, the use of handles actually simplifies
  16219.    file management by making the mechanics of file input/output──parsing
  16220.    filenames, keeping track of the current file position, and so on──the
  16221.    responsibility of DOS instead of your programs.
  16222.  
  16223.    DOS assigns a new handle number whenever you create or open a file. Five
  16224.    standard handles, numbered 0 through 4, are automatically available to
  16225.    every program. (See Figure 17-1.) Other handles, with higher handle
  16226.    numbers, are issued by DOS as needed.
  16227.  
  16228.    Handle         Use                                         Default Device
  16229.    ──────────────────────────────────────────────────────────────────────────
  16230.    0              Standard input (normally keyboard input)    CON
  16231.    1              Standard output (normally screen output)    CON
  16232.    2              Standard error output (always to the        CON
  16233.                   screen)
  16234.    3              Standard auxiliary device (AUX device)      AUX
  16235.    4              Standard printer (LPT1 or PRN device)       PRN
  16236.    ──────────────────────────────────────────────────────────────────────────
  16237.  
  16238.    Figure 17-1.  The five standard DOS handles.
  16239.  
  16240.    ──────────────────────────────────────────────────────────────────────────
  16241.    NOTE:
  16242.      Of the five standard DOS handles, only the first three are supported in
  16243.      OS/2 protected mode. If you are programming with upward compatibility in
  16244.      mind, you should avoid using handles 3 and 4 by default. Instead, open
  16245.      the serial port and printer devices explicitly, as you would any other
  16246.      file or input/output device.
  16247.    ──────────────────────────────────────────────────────────────────────────
  16248.  
  16249.    DOS limits the use of handles in regard to how many files or devices your
  16250.    program can open at one time:
  16251.  
  16252.    ■  DOS maintains an internal data structure that controls I/O for each
  16253.       file or other input/output device associated with a handle. The default
  16254.       size of this data structure allows for only 8 handles. Fortunately, the
  16255.       FILES command in the CONFIG.SYS file lets you increase the number of
  16256.       possible handles (99 in DOS versions prior to 3.0; 255 in versions 3.0
  16257.       and later).
  16258.  
  16259.    ■  DOS uses a reserved area in each program's PSP to maintain a table of
  16260.       handles associated with the program. This table has room for a maximum
  16261.       of 20 handles. Thus, even if you specify FILES = 30 in your CONFIG.SYS
  16262.       file, your programs will still be able to use only 20 handles at a
  16263.       time. (DOS 3.3 provides a way around this through interrupt 21H,
  16264.       function 67H. See page 392 for details.) Fortunately, few applications
  16265.       require more than 20 different files to be open at once, so these
  16266.       limitations are not usually important.
  16267.  
  16268.  Installable Device Drivers
  16269.  
  16270.    In DOS versions 2.0 and later, you can write a routine that provides a
  16271.    consistent interface between DOS's handle-based I/O functions and almost
  16272.    any I/O device that can input or output a stream of data. Such a routine
  16273.    is called a device driver. DOS comes with several built-in device drivers
  16274.    for the keyboard, video display, printer, communications port, and disks.
  16275.    You can also install device drivers for other devices by including their
  16276.    names in DEVICE commands in the CONFIG.SYS file.
  16277.  
  16278.    DOS I/O device drivers allow handles to be associated not only with disk
  16279.    files but with any input/output device. When you use a handle-based DOS
  16280.    function to open a device, DOS searches its list of device drivers before
  16281.    it searches for a disk filename. Familiar names like "CON", "LPT1", and
  16282.    "NUL" are all part of the default list of device drivers. Opening a device
  16283.    for input/output thus consists only of passing a name to a DOS function
  16284.    and receiving a handle from DOS in return, regardless of whether the
  16285.    device is a disk file or is associated with some other type of hardware.
  16286.  
  16287.    ──────────────────────────────────────────────────────────────────────────
  16288.    NOTE:
  16289.      Incidentally, this explains why you can't open a file named "CON" or
  16290.      "PRN": DOS searches for device names before it searches for filenames,
  16291.      so it always finds a named device before it finds a file with the same
  16292.      name.
  16293.    ──────────────────────────────────────────────────────────────────────────
  16294.  
  16295.    You don't have to know much about the implementation of device drivers to
  16296.    use the handle-based DOS functions, so we will save a more detailed
  16297.    discussion of device drivers for Appendix A. Keep in mind that by placing
  16298.    the discussion of device drivers at the end of the book, we in no way mean
  16299.    to diminish their importance. All programmers concerned with the range and
  16300.    longevity of their programs should at least be familiar with the use and
  16301.    operation of DOS device drivers.
  16302.  
  16303.  
  16304.  Interrupt 21H Functions: DOS Versions 2.0 and Later
  16305.  
  16306.    All DOS function calls described in this chapter are invoked through
  16307.    interrupt 21H (decimal 33). The individual functions are selected by
  16308.    placing the function number in the AH register. Any program that uses
  16309.    these functions should test the DOS version number first to be sure the
  16310.    functions are supported. (Function 30H provides this service.)
  16311.  
  16312.    The functions can be organized into the groups shown in Figure 17-2. In
  16313.    an effort to make the logical groupings of the function calls as clear as
  16314.    possible, we organized and described them in a slightly different manner
  16315.    than that in IBM's DOS technical reference manuals. You may want to
  16316.    compare this organization with IBM's, to be sure you understand. Figure
  16317.    17-3 lists the individual function calls.
  16318.  
  16319.          Function
  16320.    Hex            Dec            Group
  16321.    ──────────────────────────────────────────────────────────────────────────
  16322.    2FH─38H        47─56          Miscellaneous functions
  16323.    39H─3BH        57─59          Directory functions
  16324.    3CH─46H        60─70          File-management functions
  16325.    47H            71             Directory function
  16326.    48H─4BH        72─75          Memory-management functions
  16327.    4CH─5BH        76─91          Miscellaneous functions
  16328.    5CH─5FH        92─95          Network support
  16329.    62H─68H        98─104         Miscellaneous functions
  16330.    ──────────────────────────────────────────────────────────────────────────
  16331.  
  16332.    Figure 17-2.  The logical groups of extended DOS function calls.
  16333.  
  16334. ╓┌─┌──────────────┌───────────────────────────────────────────┌──────────────╖
  16335.     Function                                                  DOS
  16336.    Hex    Dec     Description                                 Version
  16337.    ──────────────────────────────────────────────────────────────────────────
  16338.    2FH    47      Get DTA Address                            2.0
  16339.    30H    48      Get DOS Version Number                     2.0
  16340.     Function                                                  DOS
  16341.    Hex    Dec     Description                                 Version
  16342.    ──────────────────────────────────────────────────────────────────────────
  16343.   30H    48      Get DOS Version Number                     2.0
  16344.    31H    49      Terminate and Stay Resident                2.0
  16345.    33H    51      Get/Set Ctrl-C Flag                        2.0
  16346.    35H    53      Get Interrupt Vector                       2.0
  16347.    36H    54      Get Disk Free Space                        2.0
  16348.    38H    56      Get/Set Country-Dependent Information      2.0
  16349.    39H    57      Create Directory                           2.0
  16350.    3AH    58      Remove Directory                           2.0
  16351.    3BH    59      Change Current Directory                   2.0
  16352.    3CH    60      Create File                                2.0
  16353.    3DH    61      Open Handle                                2.0
  16354.    3EH    62      Close Handle                               2.0
  16355.    3FH    63      Read from File or Device                   2.0
  16356.    40H    64      Write to File or Device                    2.0
  16357.    41H    65      Delete File                                2.0
  16358.    42H    66      Move File Pointer                          2.0
  16359.    43H    67      Get/Set File Attributes                    2.0
  16360.    44H    68      IOCTL──I/O Control for Devices             2.0
  16361.     Function                                                  DOS
  16362.    Hex    Dec     Description                                 Version
  16363.    ──────────────────────────────────────────────────────────────────────────
  16364.   44H    68      IOCTL──I/O Control for Devices             2.0
  16365.    45H    69      Duplicate File Handle                      2.0
  16366.    46H    70      Force Duplicate File Handle                2.0
  16367.    47H    71      Get Current Directory                      2.0
  16368.    48H    72      Allocate Memory Block                      2.0
  16369.    49H    73      Free Memory Block                          2.0
  16370.    4AH    74      Resize Memory Block                        2.0
  16371.    4BH    75      EXEC──Load and Execute a Program           2.0
  16372.    4CH    76      Terminate with Return Code                 2.0
  16373.    4DH    77      Get Return Code                            2.0
  16374.    4EH    78      Find First Matching Directory Entry        2.0
  16375.    4FH    79      Find Next Matching Directory Entry         2.0
  16376.    54H    84      Get Verify Flag                            2.0
  16377.    56H    86      Rename File                                2.0
  16378.    57H    87      Get/Set File Date and Time                 2.0
  16379.    58H    88      Get/Set Memory Allocation Strategy         3.0
  16380.    59H    89      Get Extended Error Information             3.0
  16381.    5AH    90      Create Temporary File                      3.0
  16382.     Function                                                  DOS
  16383.    Hex    Dec     Description                                 Version
  16384.    ──────────────────────────────────────────────────────────────────────────
  16385.   5AH    90      Create Temporary File                      3.0
  16386.    5BH    91      Create New File                            3.0
  16387.    5CH    92      Lock/Unlock File Region                    3.0
  16388.    5EH    94      Network Machine Name and Printer Setup     3.1
  16389.    5FH    95      Network Redirection                        3.1
  16390.    62H    98      Get PSP Address                            3.0
  16391.    65H    101     Get Extended Country Information           3.3
  16392.    66H    102     Get/Set Global Code Page                   3.3
  16393.    67H    103     Set Handle Count                           3.3
  16394.    68H    104     Commit File                                3.3
  16395.    ──────────────────────────────────────────────────────────────────────────
  16396.  
  16397.  
  16398.    Figure 17-3.  Interrupt 21H functions available in DOS versions 2.0 and
  16399.    later.
  16400.  
  16401.  Function 2FH (decimal 47): Get DTA Address
  16402.  
  16403.    Function 2FH (decimal 47) returns the address of the disk transfer area
  16404.    (DTA) currently used by DOS. The address is returned in the register pair
  16405.    ES:BX. Contrast this with function 1AH, discussed on page 335.
  16406.  
  16407.  Function 30H (decimal 48): Get DOS Version Number
  16408.  
  16409.    Function 30H (decimal 48) returns the DOS major and minor version numbers.
  16410.    The major version number is in AL, and the minor version number is in AH;
  16411.    BX and CX contain a serial number (0 in IBM's versions of DOS; other
  16412.    possible values in non-IBM versions). For example, if you execute function
  16413.    30H in DOS version 3.3, the function returns AL = 03H (the major version
  16414.    number), AH = 1EH (30, the minor version number), BX = 00H, and CX = 00H.
  16415.    In the OS/2 compatibility box, function 30H returns AL = 0AH; that is, the
  16416.    major version number is 10.
  16417.  
  16418.    In DOS version 1, function 30H was unsupported. Nevertheless, you can
  16419.    still test for DOS version 1 by executing function 30H; in DOS version 1,
  16420.    function 30H is guaranteed to return AL = 00H. Thus, a simple test of the
  16421.    value returned in AL is sufficient to distinguish between version 1 and
  16422.    later versions:
  16423.  
  16424.    mov ah,30h              ; AH = 30H (interrupt 21H function number)
  16425.    int 21h                 ; get DOS version number
  16426.    cmp al,2
  16427.    jl  EarlyVersion        ; jump if DOS version 1
  16428.  
  16429.    Any program that uses interrupt 21H functions with numbers above 2EH can
  16430.    use function 30H to determine if the appropriate DOS version is being
  16431.    used.
  16432.  
  16433.  Function 31H (decimal 49): Terminate and Stay Resident
  16434.  
  16435.    Function 31H (decimal 49) terminates a program and leaves part of the
  16436.    program resident in memory. Except for the fact that function 31H lets you
  16437.    reserve memory for a memory-resident program, its function is the same as
  16438.    that of the program termination function (function 4CH). You call
  16439.    function 31H with a return code value in AL and with the number of
  16440.    paragraphs of memory to reserve for the program in DX.
  16441.  
  16442.    Before you use function 31H, you should generally carry out the following
  16443.    steps:
  16444.  
  16445.    1.  Call function 30H to verify that the DOS version is 2.0 or later.
  16446.        Function 31H isn't supported in DOS version 1.
  16447.  
  16448.    2.  Call function 49H to free the memory allocated to the program's
  16449.        environment block. (The word at offset 2CH in the program's PSP
  16450.        contains the paragraph address of the environment block.)
  16451.  
  16452.    3.  Determine the amount of memory to reserve for the resident program.
  16453.        This value must include the 16 paragraphs reserved for the program's
  16454.        PSP in addition to contiguous memory reserved for the program itself.
  16455.        This value does not include memory allocated dynamically by the
  16456.        program using function 48H.
  16457.  
  16458.    4.  Call function 31H to terminate the program.
  16459.  
  16460.    Like function 4CH, function 31H restores the interrupt vectors for
  16461.    interrupts 22H (Terminate Address), 23H (Ctrl-C Handler), and 24H
  16462.    (Critical Error Handler) to the DOS default values; therefore, you cannot
  16463.    use this function to install memory-resident handlers for these
  16464.    interrupts.
  16465.  
  16466.    Function 31H is much more flexible than the Terminate-and-Stay-Resident
  16467.    service supported through interrupt 27H. You should always use function
  16468.    31H in your TSR programs unless you are concerned about maintaining
  16469.    compatibility with DOS version 1.
  16470.  
  16471.  Function 33H (decimal 51): Get/Set Ctrl-C Flag
  16472.  
  16473.    Function 33H (decimal 51) lets you test or update DOS's internal Ctrl-C
  16474.    flag. When you call function 33H with AL = 00H, DOS reports the current
  16475.    state of the Ctrl-C flag in DL:
  16476.  
  16477.    ■  If the flag is clear (DL = 00H), DOS checks for Ctrl-C keystrokes only
  16478.       when transmitting a character to or from a character device (interrupt
  16479.       21H functions 00H through 0CH).
  16480.  
  16481.    ■  If the flag is set (DL = 01H), DOS also checks for Ctrl-C when it
  16482.       responds to other service requests, such as file I/O operators.
  16483.  
  16484.    When you call function 33H with AL = 01H, DOS expects DL to contain the
  16485.    desired value for the break flag:
  16486.  
  16487.    ■  DL = 00H disables the break check.
  16488.  
  16489.    ■  DL = 01H enables the break check.
  16490.  
  16491.  Function 35H (decimal 53): Get Interrupt Vector
  16492.  
  16493.    Function 35H (decimal 53) returns the interrupt vector for the interrupt
  16494.    number you specify in register AL. The vector is returned in the register
  16495.    pair ES:BX.
  16496.  
  16497.    Function 35H provides a complementary service to function 25H, which
  16498.    updates an interrupt vector. (See Chapter 16.)
  16499.  
  16500.  Function 36H (decimal 54): Get Disk Free Space
  16501.  
  16502.    Function 36H (decimal 54) is similar to function 1CH (which gets disk
  16503.    information), but also provides information about unused disk space, which
  16504.    function 1CH does not. Before calling this function, select the drive that
  16505.    you are interested in with the DL register: DL = 00H indicates the default
  16506.    drive, DL = 01H indicates drive A, DL = 02H indicates drive B, and so on.
  16507.  
  16508.    If you specify an invalid drive, function 36H returns FFFFH in the AX
  16509.    register. Otherwise, AX contains the number of sectors per cluster, CX
  16510.    contains the number of bytes per sector, BX contains the number of
  16511.    available clusters, and DX contains the total number of clusters.
  16512.  
  16513.    From these numbers you can make many interesting calculations, as follows:
  16514.  
  16515.      CX * AX = bytes per cluster
  16516.      CX * AX * BX = total number of free bytes
  16517.      CX * AX * DX = total storage space in bytes
  16518.      (BX * 100) / DX = percentage of free space
  16519.  
  16520.    If S were the size of a file in bytes, you could calculate the number of
  16521.    occupied clusters in this way:
  16522.  
  16523.      (S + CX * AX - 1) \ (CX * AX)
  16524.  
  16525.    Similar formulas would give you the number of sectors and the amount and
  16526.    proportion of space allocated to a file but not used (the slack space).
  16527.  
  16528.  Function 38H (decimal 56): Get/Set Country-Dependent Information
  16529.  
  16530.    Function 38H (decimal 56) allows DOS to adjust to different international
  16531.    currency and date format conventions. In DOS version 2, this function
  16532.    reports a very small set of country-dependent information. In DOS version
  16533.    3, function 38H reports a more detailed list of country-dependent items;
  16534.    in this version of DOS, a program can also change the country-dependent
  16535.    information with a call to function 38H.
  16536.  
  16537.    To get country-dependent information from DOS, call function 38H with
  16538.    DS:DX containing the address of a 32-byte buffer. (In DOS versions 3.0 and
  16539.    later, the size of the buffer must be 34 bytes.) Register AL must be set
  16540.    to 00H to get the current country information. For DOS versions 3.0 and
  16541.    later, register AL can also be set to a predefined country code. (The
  16542.    country code is the same 3-digit code used as the country's international
  16543.    telephone access code.) To specify a country code of 255 or greater, AL
  16544.    can be set to FFH (decimal 255), and the country code can be put into
  16545.    register BX.
  16546.  
  16547.    If the requested country code is invalid, DOS sets the carry flag (CF) and
  16548.    places an error code in AX. Otherwise, register BX contains the country
  16549.    code, and the buffer at DS:DX is filled in with the country-specific
  16550.    information shown in Figures 17-4 and 17-5.
  16551.  
  16552.    To set the current country code in DOS version 3, set DX equal to FFFFH
  16553.    and call function 38H with AL equal to the country code (or if the code is
  16554.    greater than 254, set AL equal to FFH and register BX equal to the country
  16555.    code).
  16556.  
  16557.    The country-dependent information is used by DOS utilities like DATE and
  16558.    TIME. A program can call function 38H to obtain the information DOS uses
  16559.    to configure itself for country-dependent conventions.
  16560.  
  16561.    The date format is an integer word whose value specifies the display
  16562.    format for the date. This word has three predefined values and three
  16563.    corresponding date formats. (See Figure 17-6.) Room is reserved so that
  16564.    others might be added in the future.
  16565.  
  16566.    The currency symbol is the symbol used in displaying an amount of money:
  16567.    In the United States, the currency symbol is a dollar sign ($); in the
  16568.    United Kingdom, it's the pound symbol (j); in Japan, it's the yen symbol
  16569.    (J). In DOS versions 2.0 and 2.1, the currency symbol can only be a single
  16570.    character, but in DOS version 3, a string up to four characters in length
  16571.    can be used. For example, one of the currency strings that could be used
  16572.    in DOS version 3.3 is DKR, which stands for Danish kroner.
  16573.  
  16574.      Offset           Size
  16575.    Hex      Dec       (bytes)  Description
  16576.    ──────────────────────────────────────────────────────────────────────────
  16577.    00H      0          2       Date format
  16578.    02H      2          2       Currency symbol string (ASCIIZ format)
  16579.    04H      4          2       Thousands separator string (ASCIIZ format)
  16580.    06H      6          2       Decimal separator string (ASCIIZ format)
  16581.    08H      8         24       (Reserved)
  16582.    ──────────────────────────────────────────────────────────────────────────
  16583.  
  16584.    Figure 17-4.  The country-dependent information reported by function 38H
  16585.    in DOS version 2.
  16586.  
  16587.      Offset           Size
  16588.    Hex      Dec       (bytes)  Description
  16589.    ──────────────────────────────────────────────────────────────────────────
  16590.    00H       0         2       Date format
  16591.    02H       2         5       Currency symbol string (ASCIIZ format)
  16592.    07H       7         2       Thousands separator string (ASCIIZ format)
  16593.    09H       9         2       Decimal separator string (ASCIIZ format)
  16594.    0BH      11         2       Date separator string (ASCIIZ format)
  16595.    0DH      13         2       Time separator string (ASCIIZ format)
  16596.    0FH      15         1       Currency symbol location
  16597.    10H      16         1       Currency decimal places
  16598.    11H      17         1       Time format: 1 = 24-hour clock; 0 = 12-hour
  16599.    12H      18         4       Extended ASCII map call address
  16600.    16H      22         2       List separator string (ASCIIZ format)
  16601.    18H      24        10       (Reserved)
  16602.    ──────────────────────────────────────────────────────────────────────────
  16603.  
  16604.    Figure 17-5.  The country-dependent information returned by function 38H
  16605.    in DOS version 3.
  16606.  
  16607.    Value              Use               Date
  16608.    ──────────────────────────────────────────────────────────────────────────
  16609.    00H                American          month day year
  16610.    01H                European          day month year
  16611.    02H                Japanese          year month day
  16612.    ──────────────────────────────────────────────────────────────────────────
  16613.  
  16614.    Figure 17-6.  The three predefined date formats returned by function 38H.
  16615.  
  16616.    The thousands separator is the symbol used to punctuate the thousands mark
  16617.    in numbers. The U.S. uses a comma as a thousands separator, as in the
  16618.    number 12,345; other countries use a period or a blank.
  16619.  
  16620.    The decimal separator is the symbol used to punctuate decimal places. The
  16621.    U.S. uses a period as a decimal separator, as in 3.0; other countries use
  16622.    a comma.
  16623.  
  16624.    The date separator and time separator are the punctuation used in
  16625.    displaying the date (for example, ─ as in 7─4─1988) and in displaying the
  16626.    time (for example, : as in 12:34).
  16627.  
  16628.    The currency symbol location indicates where the currency symbol should be
  16629.    placed. A value of 00H places the currency symbol immediately before the
  16630.    amount (J1500); 01H places the symbol immediately after the amount (15¢);
  16631.    02H places the symbol before the amount with an intervening space (FFr
  16632.    15); 03H places the symbol after the amount with an intervening space (15
  16633.    DKR); and 04H replaces the decimal separator with the currency symbol.
  16634.  
  16635.    The currency decimal places value specifies how many decimal places are
  16636.    used in the currency. For example, the value would be 02H for U.S.
  16637.    currency (dollars and cents) and 00H for Italian currency (lire).
  16638.  
  16639.    The time format field specifies whether time appears in a 12-hour or
  16640.    24-hour format. Only the low-order bit (bit 0) is currently used; if the
  16641.    bit is set to 0, a 12-hour clock is used; if it is set to 1, a 24-hour
  16642.    clock is used.
  16643.  
  16644.    The extended ASCII map call address is the segmented address of a routine
  16645.    that maps ASCII characters 80H through FFH to characters in the range 00H
  16646.    through 7FH. Not all printers or plotters can display extended ASCII
  16647.    characters in the range 80H─FFH, so the routine at this address is called
  16648.    when it is necessary to map such characters into the usual range of ASCII
  16649.    characters (00H─7FH).
  16650.  
  16651.    The list separator indicates the symbol used to separate items in a list,
  16652.    such as the commas in the list A, B, C, and D.
  16653.  
  16654.  Function 39H (decimal 57): Create Directory
  16655.  
  16656.    Function 39H (decimal 57) creates a subdirectory, just as the DOS command
  16657.    MKDIR does. To invoke this service, create an ASCIIZ string containing the
  16658.    pathname of the new directory. The register pair DS:DX contains the
  16659.    address of the ASCIIZ string. If an error occurs, function 39H sets the
  16660.    carry flag and returns an error code in AX. The possible error codes are
  16661.    03H (path not found) and 05H (access denied).
  16662.  
  16663.  Function 3AH (decimal 58): Remove Directory
  16664.  
  16665.    Function 3AH (decimal 58) removes (deletes) a subdirectory exactly as the
  16666.    DOS command RMDIR does. To invoke this function, create an ASCIIZ string
  16667.    containing the pathname of the directory you want to remove. The register
  16668.    pair DS:DX points to the ASCIIZ string. If an error occurs, function 3AH
  16669.    sets the carry flag and returns an error code in AX. The possible error
  16670.    codes are 03H (path not found), 05H (access denied), and 10H (attempt to
  16671.    remove current directory).
  16672.  
  16673.  Function 3BH (decimal 59): Change Current Directory
  16674.  
  16675.    Function 3BH (decimal 59) changes the current directory exactly as the DOS
  16676.    command CHDIR does. To invoke this function, create an ASCIIZ string
  16677.    containing the pathname of the new directory. DS:DX contains the address
  16678.    of the ASCIIZ string. If an error occurs, function 3BH sets the carry flag
  16679.    and returns an error code in AX. The one possible error code is 03H (path
  16680.    not found).
  16681.  
  16682.  Function 3CH (decimal 60): Create File
  16683.  
  16684.    Function 3CH (decimal 60) opens an empty file using a specified name. If
  16685.    the file exists, function 3CH truncates it to zero length. If the file
  16686.    does not exist, function 3CH creates a new file. This function parallels
  16687.    function 16H (discussed on page 334).
  16688.  
  16689.    To invoke this function, create an ASCIIZ string containing the pathname
  16690.    and filename. The register pair DS:DX contains the address of the ASCIIZ
  16691.    string. CX contains the file attribute. (See page 113 for more on file
  16692.    attributes and attribute bit settings.) When function 3CH executes
  16693.    successfully, it clears the carry flag and returns a handle in AX.
  16694.    Otherwise, this function sets the carry flag and leaves an error code in
  16695.    AX. Possible error codes are 03H (path not found), 04H (no handle
  16696.    available), and 05H (access denied). Code 05H can indicate either that
  16697.    there is no room for a new directory entry or that the existing file is
  16698.    marked read-only and can't be opened for output.
  16699.  
  16700.    Be aware that by using function 3CH you can accidentally truncate an
  16701.    existing file to zero length. The best way to avoid this mistake is simply
  16702.    to call function 4EH to search the directory for an existing file before
  16703.    you call function 3CH. Or, if you are using DOS 3.0 or later, you have two
  16704.    other alternatives: You can call function 5BH, which works like function
  16705.    3CH but won't open an existing file, or you can use function 5AH to
  16706.    create a temporary file with a unique filename.
  16707.  
  16708.  Function 3DH (decimal 61): Open Handle
  16709.  
  16710.    Function 3DH (decimal 61) opens an existing file or device. You provide
  16711.    the pathname and filename in the form of an ASCIIZ string. As with all
  16712.    other file I/O functions, DS:DX points to this string. You also indicate
  16713.    how you want to use the file by placing a file-access code in register AL.
  16714.    The 8 bits of AL are divided into the four fields shown in Figure 17-7 on
  16715.    the following page.
  16716.  
  16717.          Bit
  16718.    7 6 5 4 3 2 1 0          Use
  16719.    ──────────────────────────────────────────────────────────────────────────
  16720.    I . . . . . . .          Inheritance flag (DOS version 3 only)
  16721.    . S S S . . . .          Sharing mode (DOS version 3 only)
  16722.    . . . . R . . .          (Reserved)
  16723.    . . . . . A A A          Access code
  16724.    ──────────────────────────────────────────────────────────────────────────
  16725.  
  16726.    Figure 17-7.  File-access and sharing codes for function 3DH.
  16727.  
  16728.    The file-access code for DOS version 2 is simple: Only the access bits
  16729.    (bits 0─2) are used; all other bits are set to 0. The three access-code
  16730.    settings are defined in Figure 17-8.
  16731.  
  16732.     Bit
  16733.    2 1 0                    Use
  16734.    ──────────────────────────────────────────────────────────────────────────
  16735.    0 0 0                    Read (only) access
  16736.    0 0 1                    Write (only) access
  16737.    0 1 0                    Read or write access
  16738.    ──────────────────────────────────────────────────────────────────────────
  16739.  
  16740.    Figure 17-8.  File-access modes for function 3DH.
  16741.  
  16742.    DOS version 3 uses the inheritance and sharing codes as well as the access
  16743.    code. The inheritance and sharing codes give you control over how
  16744.    different programs access the same file at the same time.
  16745.  
  16746.    Bit 7, the inheritance bit, indicates whether or not a child process can
  16747.    inherit the use of this file. (For more about parent and child processes,
  16748.    see the discussion of function 4BH later in this chapter.) When a child
  16749.    process inherits a handle, it inherits the file's access and sharing
  16750.    codes: If bit 7 = 0, a child process can use the same handle to access the
  16751.    file as the parent process; if bit 7 = 1, the child process must itself
  16752.    open the file to obtain a different handle.
  16753.  
  16754.    Bits 4 through 6, the sharing-mode bits (SSS in Figure 17-7), define what
  16755.    will happen when more than one program tries to open the same file. There
  16756.    are five sharing modes: compatibility mode (SSS = 000), deny read/write
  16757.    mode (SSS = 001), deny write mode (SSS = 010), deny read mode (SSS = 011),
  16758.    and deny none mode (SSS = 100). When a second attempt is made to open the
  16759.    file, DOS compares the file's sharing code with the access requested in
  16760.    the second open operation. DOS allows the second open operation to succeed
  16761.    only if the sharing mode and the requested access mode are compatible.
  16762.  
  16763.    ──────────────────────────────────────────────────────────────────────────
  16764.    NOTE:
  16765.      DOS performs this file-sharing validation only if it is running on a
  16766.      network or if the SHARE utility is installed. See the DOS technical
  16767.      reference manual for more details on networking and the SHARE utility.
  16768.    ──────────────────────────────────────────────────────────────────────────
  16769.  
  16770.    Bit 3, marked as "Reserved" in Figure 17-7, should be set to 0.
  16771.  
  16772.    Like function 3CH, function 3DH clears the carry flag and returns a handle
  16773.    in AX when it successfully opens a file or device. Otherwise, this
  16774.    function sets the carry flag and leaves an error code in AX. The possible
  16775.    return codes from function 3DH are 02H (file not found), 03H (path not
  16776.    found), 04H (no handles available), 05H (access denied), and 0CH (invalid
  16777.    access code).
  16778.  
  16779.    If SHARE or network file sharing is in force in DOS version 3, DOS signals
  16780.    a sharing violation by executing interrupt 24H.
  16781.  
  16782.  Function 3EH (decimal 62): Close Handle
  16783.  
  16784.    Function 3EH (decimal 62) closes a file or device associated with the
  16785.    handle in BX. This function flushes all file buffers and updates the
  16786.    directory if necessary. The only error code this function can return is
  16787.    06H (invalid handle).
  16788.  
  16789.  Function 3FH (decimal 63): Read from File or Device
  16790.  
  16791.    Function 3FH (decimal 63) reads the file or device associated with the
  16792.    handle in BX. The CX register specifies the number of bytes to read; DS:DX
  16793.    points to the buffer where data that is read will be placed. If the read
  16794.    operation is successful, function 3FH clears the carry flag and returns
  16795.    the number of bytes read in AX. If this value is 0, the function has tried
  16796.    to read from the end of a file. If the read operation fails, this function
  16797.    sets the carry flag and leaves an error code in AX. The possible error
  16798.    codes are 05H (access denied) and 06H (invalid handle).
  16799.  
  16800.  Function 40H (decimal 64): Write to File or Device
  16801.  
  16802.    Function 40H (decimal 64) writes to the file or device associated with the
  16803.    handle in BX. CX specifies the number of bytes to be written; DS:DX points
  16804.    to the address of the data bytes.
  16805.  
  16806.    When the write operation is complete, function 40H updates the file
  16807.    pointer to point past the data just written.
  16808.  
  16809.    You must examine both the carry flag and the value in AX returned by
  16810.    function 40H to determine the success of the write operation:
  16811.  
  16812.    ■  If the carry flag is clear and AX = CX, the operation completed
  16813.       successfully.
  16814.  
  16815.    ■  If the carry flag is clear but AX < CX, then the output was written to
  16816.       a disk file that had insufficient disk space to complete the write
  16817.       operation.
  16818.  
  16819.    ■  If the carry flag is set, AX contains an error code of 05H (access
  16820.       denied) or 06H (invalid handle).
  16821.  
  16822.    The fact that function 40H updates the file pointer has an interesting
  16823.    side effect: You can set the size of a file to any arbitrary value by
  16824.    executing function 40H with CX = 00H. The usual technique is to call
  16825.    function 42H to set the file pointer location and then to immediately call
  16826.    function 40H with CX = 00H to update the file size.
  16827.  
  16828.  Function 41H (decimal 65): Delete File
  16829.  
  16830.    Function 41H (decimal 65) deletes the directory entry of a file. The file
  16831.    is specified by an ASCIIZ string containing the path and filename. The
  16832.    register pair DS:DX points to the string. Unlike function 13H, function
  16833.    41H does not support wildcard characters in the file specification: With
  16834.    function 41H you can delete only one file at a time.
  16835.  
  16836.    You cannot delete read-only files with this function. To delete a
  16837.    read-only file, first remove the read-only attribute using function 43H,
  16838.    and then use function 41H.
  16839.  
  16840.    Function 41H can return three error codes in AX: 02H (file not found), 03H
  16841.    (path not found), and 05H (access denied).
  16842.  
  16843.  Function 42H (decimal 66): Move File Pointer
  16844.  
  16845.    Function 42H (decimal 66) changes the logical read/write position in a
  16846.    file. To invoke this service, load BX with a handle and then specify the
  16847.    new pointer location by placing a reference location in AL and an offset
  16848.    relative to the reference location in register pair CX:DX. The byte offset
  16849.    in CX:DX is a 32-bit, long integer. CX is the high-order part of the
  16850.    offset (which is 0, unless the offset amount is more than 65,535) and DX
  16851.    is the low-order part.
  16852.  
  16853.    You can specify the reference location in AL in three different ways: If
  16854.    AL = 00H, the offset is taken relative to the beginning of the file and
  16855.    the file pointer is moved CX:DX bytes from that point; if AL = 01H, the
  16856.    offset is taken relative to the current file pointer location; if AL =
  16857.    02H, the offset is taken from the current end of file.
  16858.  
  16859.    If the function executes successfully, it clears the carry flag and
  16860.    returns in the register pair DX:AX the current file pointer location
  16861.    relative to the beginning of the file. The pointer is returned as a 32-bit
  16862.    long integer, with the high-order part in DX and the low-order part in AX.
  16863.    If the function fails, it sets the carry flag and returns an error code in
  16864.    AX. Possible error codes are 01H (invalid function number, which means AL
  16865.    did not contain 00H, 01H, or 02H) and 06H (invalid handle).
  16866.  
  16867.    You can use function 42H in several different ways:
  16868.  
  16869.    ■  To place the file pointer at an arbitrary location in the file, call
  16870.       function 42H with AL = 00H and CX:DX specifying the desired offset
  16871.       relative to the start of the file.
  16872.  
  16873.    ■  To position the file pointer at the end of the file, call function 42H
  16874.       with AL = 02H and 00H in CX:DX.
  16875.  
  16876.    ■  To determine the current location of the file pointer, use AL = 01H and
  16877.       00H in CX:DX; the value returned in DX:AX is the current file pointer
  16878.       location.
  16879.  
  16880.    DOS does not validate the resulting location of the file pointer. In
  16881.    particular, you can end with a negative file pointer offset (that is, a
  16882.    file pointer at a position before the logical start of the file). However,
  16883.    it's not a good idea to use negative file pointers for two reasons: If you
  16884.    perform a subsequent read or write operation, you'll be in error; and your
  16885.    program will be harder to adapt for OS/2, where an attempt to move a file
  16886.    pointer to a negative offset generates an error.
  16887.  
  16888.    ──────────────────────────────────────────────────────────────────────────
  16889.    NOTE:
  16890.      The operation of moving a logical file pointer to a specified location
  16891.      in a file is sometimes called a "seek," but the same word is also used
  16892.      in the sense of moving the read/write heads of a disk drive to a
  16893.      specified cylinder on a disk. The two operations aren't the same.
  16894.    ──────────────────────────────────────────────────────────────────────────
  16895.  
  16896.  Function 43H (decimal 67): Get/Set File Attributes
  16897.  
  16898.    Function 43H (decimal 67) gets or sets the attributes of a file. (See page
  16899.    113 for details about file attributes.) DS:DX points to an ASCIIZ string
  16900.    that specifies the file in question. (Global filename characters ? and *
  16901.    cannot be used.) Calling function 43H with AL = 00H returns the file's
  16902.    attributes in CX; AL = 01H sets the attribute values you specify in CX.
  16903.  
  16904.    If function 43H fails, the carry flag is set and AX contains one of four
  16905.    error codes: 01H (invalid function), 02H (file not found), 03H (path not
  16906.    found), and 05H (access denied).
  16907.  
  16908.  Function 44H (decimal 68): IOCTL──I/O Control for Devices
  16909.  
  16910.    Function 44H (decimal 68) performs input/output control operations, mostly
  16911.    for devices. (See Figure 17-9.) AL selects one of 16 subfunctions,
  16912.    numbered 00H through 0FH; some of these subfunctions have sub-subfunctions
  16913.    you specify with a "minor code" in CL.
  16914.  
  16915.    The main purpose of the IOCTL function is to provide a consistent
  16916.    interface between DOS programs and device drivers. In general, you
  16917.    shouldn't use IOCTL calls unless you know something about how device
  16918.    drivers are structured──a topic we'll cover in Appendix A. A few IOCTL
  16919.    calls, however, are useful even if you don't understand the details of
  16920.    device-driver operations. We'll point these out as we summarize the
  16921.    various IOCTL calls.
  16922.  
  16923.    ──────────────────────────────────────────────────────────────────────────
  16924.    NOTE:
  16925.      Not all IOCTL subfunctions are supported in earlier versions of DOS.
  16926.      Figure 17-9 indicates the DOS versions in which the various IOCTL
  16927.      subfunctions were introduced.
  16928.    ──────────────────────────────────────────────────────────────────────────
  16929.  
  16930.    Subfunction                                                      DOS
  16931.    Hex     Dec        Description                                   Version
  16932.    ──────────────────────────────────────────────────────────────────────────
  16933.    00H      0         Get device data.                             2.0
  16934.    01H      1         Set device data.                             2.0
  16935.    02H      2         Receive control data from character device.  2.0
  16936.    03H      3         Send control data to character device.       2.0
  16937.    04H      4         Receive control data from block device.      2.0
  16938.    05H      5         Send control data to block device.           2.0
  16939.    06H      6         Check input status.                          2.0
  16940.    07H      7         Check output status.                         2.0
  16941.    08H      8         Check if block device is removable.          3.0
  16942.    09H      9         Check if block device is remote.             3.1
  16943.    0AH     10         Check if handle is remote.                   3.1
  16944.    0BH     11         Change sharing retry count.                  3.0
  16945.    0CH     12         Generic I/O control for handles.             3.2
  16946.    0DH     13         Generic I/O control for block devices.       3.2
  16947.    0EH     14         Get logical drive map.                       3.2
  16948.    0FH     15         Set logical drive map.                       3.2
  16949.    ──────────────────────────────────────────────────────────────────────────
  16950.  
  16951.    Figure 17-9.  Subfunctions available under interrupt 21H, function 44H
  16952.    (IOCTL).
  16953.  
  16954.    Subfunctions 00H and 01H. These subfunctions get and set device
  16955.    information formatted in DX by a complicated set of bit coding. Bit 7 is
  16956.    set to 1 for devices and to 0 for disk files. For devices, bits 0 through
  16957.    5 are specified as shown in Figure 17-10. For disk files, bits 0 through
  16958.    5 provide the disk-drive number: A value of 0 represents drive A, a value
  16959.    of 1 represents drive B, and so on. Both subfunctions should be called
  16960.    with a file or device handle in BX. Subfunction 00H can be called for both
  16961.    disk files and devices; subfunction 01H can be called only for character
  16962.    devices.
  16963.  
  16964. ╓┌─┌──────────────────────────────────────────────────────────────┌──────────
  16965.                          Bit
  16966.    15 14 13 12 11 10  9  8   7  6  5  4  3  2  1  0               Use
  16967.    ───────────────────────────────────────────────────────────────────────────
  16968.     .  .  .  .  .  .  .  .   .  .  .  .  .  .  .  X               1 = standard
  16969.     .  .  .  .  .  .  .  .   .  .  .  .  .  .  X  .               1 = standard
  16970.                          Bit
  16971.    15 14 13 12 11 10  9  8   7  6  5  4  3  2  1  0               Use
  16972.    ───────────────────────────────────────────────────────────────────────────
  16973.    .  .  .  .  .  .  .  .   .  .  .  .  .  .  X  .               1 = standard
  16974.     .  .  .  .  .  .  .  .   .  .  .  .  .  X  .  .               1 = null dev
  16975.     .  .  .  .  .  .  X  .   .  .  .  .  X  .  .  .               1 = clock de
  16976.     .  .  .  .  .  .  .  .   .  .  .  X  .  .  .  .               (Reserved)
  16977.     .  .  .  .  .  .  .  .   .  .  X  .  .  .  .  .               1 = data os
  16978.                                                                   control-char
  16979.                                                                   = data is "c
  16980.                                                                   control-char
  16981.     .  .  .  .  .  .  .  .   .  X  .  .  .  .  .  .               0 = end of f
  16982.                                                                   file (for in
  16983.     .  .  .  .  .  .  .  .   X  .  .  .  .  .  .  .               1 = device;
  16984.     .  .  .  .  .  .  .  R   .  .  .  .  .  .  .  .               (Reserved)
  16985.     .  .  .  .  .  .  R  .   .  .  .  .  .  .  .  .               (Reserved)
  16986.     .  .  .  .  .  R  .  .   .  .  .  .  .  .  .  .               (Reserved)
  16987.     .  .  .  .  R  .  .  .   .  .  .  .  .  .  .  .               (Reserved)
  16988.     .  .  .  R  .  .  .  .   .  .  .  .  .  .  .  .               (Reserved)
  16989.     .  .  R  .  .  .  .  .   .  .  .  .  .  .  .  .               (Reserved)
  16990.     .  X  .  .  .  .  .  .   .  .  .  .  .  .  .  .               1 = device c
  16991.                          Bit
  16992.    15 14 13 12 11 10  9  8   7  6  5  4  3  2  1  0               Use
  16993.    ───────────────────────────────────────────────────────────────────────────
  16994.    .  X  .  .  .  .  .  .   .  .  .  .  .  .  .  .               1 = device c
  16995.                                                                   strings tran
  16996.                                                                   subfunctions
  16997.     R  .  .  .  .  .  .  .   .  .  .  .  .  .  .  .               (Reserved)
  16998.    ───────────────────────────────────────────────────────────────────────────
  16999.  
  17000.  
  17001.    Figure 17-10.  The bit settings of the device data word DX for subfunction
  17002.    00H or 01H of interrupt 21H, function 44H.
  17003.  
  17004.    You can modify how DOS processes I/O for the CON device (the keyboard/
  17005.    video display combination) by setting "raw" input/output mode for the
  17006.    device. Do this by clearing bit 5 of the device data word in DX and
  17007.    calling subfunction 01H:
  17008.  
  17009.    mov     ax,4400h        ; AH = 44H (interrupt 21H function number)
  17010.                            ; AL = 0 (subfunction number)
  17011.    mov     bx,0            ; BX = 0 (handle for CON device)
  17012.    int     21h             ; get device data into DX
  17013.    or      dx,0020h        ; set bit 5 ("raw" mode)
  17014.    and     dx,00FFh        ; zero reserved bits 8─15
  17015.    mov     ax,4401h        ; set up for subfunction 1
  17016.    mov     bx,0            ; BX = CON device handle
  17017.    int     21h             ; set device data for CON
  17018.  
  17019.    After you execute this sequence of code, DOS no longer recognizes Ctrl-P
  17020.    and Ctrl-S characters, nor does it expand tabs on output.
  17021.  
  17022.    Subfunctions 02H through 05H. These subfunctions transfer control data
  17023.    between your program and a device driver. Subfunctions 02H and 03H get and
  17024.    send control data for character-oriented devices; subfunctions 04H and 05H
  17025.    get and send control data for block-oriented devices. In all four
  17026.    subfunctions you specify the subfunction number in AL, the address of a
  17027.    data buffer in DS:DX, and the number of bytes to transfer in CX. For
  17028.    subfunctions 02H and 03H, you must specify a handle in BX; for
  17029.    subfunctions 04H and 05H, you must specify a drive number in BL (00H =
  17030.    default drive, 01H = drive A, and so on).
  17031.  
  17032.    The control data you transfer to or from a device driver is not
  17033.    necessarily part of the device's input/output data stream: The control
  17034.    data is often used to obtain the device status or to control
  17035.    hardware-specific features such as printer font characteristics or tape
  17036.    drive rewind.
  17037.  
  17038.    These subfunctions can be used only if the device can process control
  17039.    strings. This capability is indicated by bit 14 in the device data word
  17040.    returned by subfunction 00H.
  17041.  
  17042.    Subfunctions 06H and 07H. These subfunctions return the current input or
  17043.    output status of a device or file. Call them with a handle in BX:
  17044.    Subfunction 06H returns the current input status; subfunction 07H returns
  17045.    the current output status.
  17046.  
  17047.    Both of these subfunctions use the carry flag to indicate a successful
  17048.    call. If the carry flag is clear, AL contains the status: AL = 00H means
  17049.    the device is not ready for input or output; AL = FFH means the device is
  17050.    ready. (For a file, input status AL = 00H means end-of-file; output status
  17051.    is always "ready" regardless of the value in AL.) If the carry flag is
  17052.    set, AX contains an error code: 01H (invalid function), 05H (access
  17053.    denied), 06H (invalid handle), or 0DH (invalid data).
  17054.  
  17055.    Subfunction 08H. This subfunction, supported only in DOS versions 3.0 and
  17056.    later, indicates whether a block-oriented device has removable media or
  17057.    not. (The floppy diskettes in a diskette drive are removable; the fixed
  17058.    disk in a fixed-disk drive is not.) Subfunction 08H can be extremely
  17059.    useful because it lets a program know if it has to check for a disk change
  17060.    or if it can rely on the same disk always being there. Call subfunction
  17061.    08H with a drive number in BL (00H = default drive, 01H = drive A, and so
  17062.    on). The subfunction clears the carry flag on a successful return and
  17063.    leaves AX = 00H if the storage medium is removable or AX = 01H if the
  17064.    storage medium is nonremovable. If the carry flag is set, AX contains an
  17065.    error code: 01H (invalid function) or 0FH (invalid drive).
  17066.  
  17067.    Subfunction 09H. In a network configuration, this subfunction determines
  17068.    whether a particular block device is local (attached to the computer
  17069.    running the program) or remote (redirected to a network server). You must
  17070.    specify a drive number in BL when you call this subfunction.
  17071.  
  17072.    Subfunction 09H clears the carry flag to indicate a successful call. In
  17073.    this case, bit 12 of the value in DX indicates whether the device is
  17074.    remote (bit 12 = 1) or local (bit 12 = 0). If the carry flag is set, AX
  17075.    contains an error code: 01H (invalid function) or 0FH (invalid drive).
  17076.    Subfunction 09H is available in DOS 3.1 and later.
  17077.  
  17078.    Subfunction 0AH (decimal 10). This subfunction is similar to subfunction
  17079.    09H but is used with a device handle instead of a drive number. Specify
  17080.    the handle in BX when you call this subfunction.
  17081.  
  17082.    Like subfunction 09H, subfunction 0AH clears the carry flag and returns a
  17083.    value in DX that indicates whether the device is local or remote. Bit 15
  17084.    of DX indicates whether the device is remote (bit 15 = 1) or local (bit 15
  17085.    = 0). If an error occurs, the function sets the carry flag and returns an
  17086.    error code in AX: 01H (invalid function) or 06H (invalid handle).
  17087.    Subfunction 09H is available in DOS 3.1 and later.
  17088.  
  17089.    Subfunction 0BH (decimal 11). This subfunction, which is supported only in
  17090.    DOS versions 3.0 and later, controls the way DOS attempts to resolve
  17091.    file-sharing conflicts. Because some programs lock files only briefly,
  17092.    file-sharing conflicts can be very transitory. DOS can try more than once
  17093.    to gain access to a shared file before reporting a conflict, in the hope
  17094.    that the lock condition goes away in the meantime.
  17095.  
  17096.    Subfunction 0BH can help you empirically tune a network in which you
  17097.    expect transient file-sharing conflicts to occur. Call this subfunction
  17098.    with DX containing the number of times you want DOS to retry access to a
  17099.    shared file before it gives up and reports an error. CX should specify the
  17100.    delay value between retries. DOS creates a delay by executing an empty
  17101.    loop 65,536 times; the value in CX indicates the number of times you want
  17102.    DOS to execute the empty delay loop. (The DOS defaults are three retries
  17103.    and one delay loop between retries.)
  17104.  
  17105.    If the subfunction executes successfully, it clears the carry flag. If the
  17106.    carry flag is set, AX contains an error code of 01H (invalid function).
  17107.  
  17108.    Subfunction 0CH (decimal 12). This subfunction provides miscellaneous
  17109.    control functions for character-oriented devices. Each control function is
  17110.    designated by a minor code in CL and a major code (also called a category
  17111.    code) in CH. The various major and minor codes are listed in Figure 17-11.
  17112.  
  17113.    Hex            Dec            Description
  17114.    ──────────────────────────────────────────────────────────────────────────
  17115.    Major Code (specified in CH)
  17116.    00H            0              Unknown
  17117.    01H            1              Serial port (COM1, COM2, COM3, COM4)
  17118.    03H            3              Console (CON)
  17119.    05H            5              Printer (LPT1, LPT2, LPT3)
  17120.  
  17121.    Minor Code (specified in CL)
  17122.    45H            69             Set iteration count.
  17123.    4AH            74             Select code page.
  17124.    4CH            76             Start code page preparation.
  17125.    4DH            77             End code page preparation.
  17126.    65H            101            Get iteration count.
  17127.    6AH            106            Query selected code page.
  17128.    6BH            107            Query prepare list.
  17129.    ──────────────────────────────────────────────────────────────────────────
  17130.  
  17131.    Figure 17-11.  Major and minor codes for IOCTL subfunction 0CH (generic
  17132.    I/O control for handles).
  17133.  
  17134.    Minor codes 45H and 65H were introduced in DOS version 3.2. They apply
  17135.    only to print devices (major code 05H). They deal with the number of times
  17136.    DOS attempts to send a character to a printer before it assumes the
  17137.    printer is busy. The remaining minor codes were introduced in DOS version
  17138.    3.3. They provide detailed support for defining and loading code pages for
  17139.    output devices that can use multiple character sets or fonts.
  17140.  
  17141.    For details on the use of the services provided in this IOCTL subfunction,
  17142.    see the DOS technical reference manual.
  17143.  
  17144.    Subfunction 0DH (decimal 13). Subfunction 0DH provides six generic
  17145.    services for block-oriented devices. Each service is designated by a major
  17146.    code in CH and a minor code in CL. (See Figure 17-12.) In general, these
  17147.    services are similar to services provided by the ROM BIOS for diskettes
  17148.    and fixed disks, but these IOCTL services provide a consistent interface
  17149.    to any block-oriented device with a device driver that supports these
  17150.    IOCTL calls.
  17151.  
  17152.    Subfunction 0DH is available in DOS 3.2 and later. See the DOS technical
  17153.    reference manual for details on subfunction 0DH services.
  17154.  
  17155.    Hex            Dec            Description
  17156.    ──────────────────────────────────────────────────────────────────────────
  17157.    Major Code (specified in CH)
  17158.    08H            8              Disk drive
  17159.  
  17160.    Minor Code (specified in CL)
  17161.    40H            64             Set parameters for block device.
  17162.    41H            65             Write track on logical drive.
  17163.    42H            66             Format and verify track on logical drive.
  17164.    60H            96             Get parameters for block device.
  17165.    61H            97             Read track on logical drive.
  17166.    62H            98             Verify track on logical drive.
  17167.    ──────────────────────────────────────────────────────────────────────────
  17168.  
  17169.    Figure 17-12.  Major and minor codes for IOCTL subfunction 0DH (generic
  17170.    I/O control for block devices).
  17171.  
  17172.    Subfunctions 0EH and 0FH (decimal 14 and 15). These two subfunctions
  17173.    relate logical mapping of drive letter assignments to physical drives. For
  17174.    example, in systems with only one diskette drive, DOS maps drive letter B
  17175.    to physical drive A.
  17176.  
  17177.    Call these subfunctions with a logical drive ID in BL (01H represents
  17178.    drive A, 02H represents drive B, and so on). Subfunction 0EH returns a
  17179.    logical drive ID that is currently mapped to the drive you specified in
  17180.    BL. Subfunction 0FH also updates DOS's internal logical map so that the
  17181.    drive ID you specified becomes the new logical drive ID. Both subfunctions
  17182.    use AL to return the logical drive ID; if AL = 00H, only one logical drive
  17183.    is associated with the drive ID you specified in BL. If an error occurs,
  17184.    the carry flag is set and AX contains an error code: 01H (invalid
  17185.    function) or 0FH (invalid drive).
  17186.  
  17187.    For example, if you execute the following instructions on a system with
  17188.    only one diskette drive, DOS associates drive B with the diskette drive:
  17189.  
  17190.    mov bl,2                ; BL = logical drive number
  17191.    mov ax,440Fh            ; set logical drive map
  17192.    int 21h                 ; update the logical drive ID
  17193.                            ; (DOS returns AL = 02H)
  17194.  
  17195.  Function 45H (decimal 69): Duplicate Handle
  17196.  
  17197.    Function 45H (decimal 69) duplicates an open file handle and returns a new
  17198.    handle number that refers to the same file or device. All actions
  17199.    performed with one handle will be reflected in the other handle──the new
  17200.    handle does not act independently in any way.
  17201.  
  17202.    Call function 45H with an open handle in BX. If the function executes
  17203.    successfully, it clears the carry flag and leaves a new handle number in
  17204.    AX. If an error occurs, the carry flag is set and AX contains an error
  17205.    code: 04H (no more handles) or 06H (invalid handle).
  17206.  
  17207.    You can use function 45H along with function 46H to implement
  17208.    input/output redirection. You can also use it to commit an open file to
  17209.    disk by duplicating the open file's handle and then closing the duplicate
  17210.    handle. This has the effect of flushing the file's disk buffers and
  17211.    updating the directory, without the overhead of closing the file,
  17212.    reopening it (which involves a directory search), and repositioning the
  17213.    file pointer:
  17214.  
  17215.    mov bx,Handle           ; BX = handle of open file
  17216.    mov ah,45h
  17217.    int 21h                 ; get duplicate handle into AX
  17218.    jc  Error
  17219.    mov bx,ax               ; BX = duplicate handle
  17220.    mov ah,3Eh
  17221.    int 21h                 ; close duplicate handle
  17222.                            ;   (original handle remains open)
  17223.  
  17224.  Function 46H (decimal 70): Force Duplicate Handle
  17225.  
  17226.    Function 46H (decimal 70) has a somewhat misleading name because it really
  17227.    does not create a duplicate handle as does function 45H. Instead, function
  17228.    46H associates an existing open handle with a different device. This is
  17229.    the key to implementing input/output redirection in DOS.
  17230.  
  17231.    Call function 46H with an open handle in BX and a second handle in CX.
  17232.    When function 46H returns, the handle in CX is associated with the same
  17233.    device as the open handle in BX. If the handle in CX was previously
  17234.    associated with an open device, function 46H closes the device (which
  17235.    might otherwise be without a handle). If no errors occur, the function
  17236.    clears the carry flag. Otherwise, the carry flag is set, and AX contains
  17237.    an error code: 04H (no more handles) or 06H (invalid handle).
  17238.  
  17239.    To see how function 46H works, consider how you would redirect output from
  17240.    the standard output device (the video screen) to a file:
  17241.  
  17242.    mov bx,stdout           ; BX = handle of standard output device
  17243.    mov ah,45h              ; AH = function number ("Duplicate Handle")
  17244.    int 21h                 ; get duplicate handle into AX
  17245.    jc  Error               ; (trap errors)
  17246.    mov stdoutDup,ax        ; save the duplicate handle in a memory variable
  17247.  
  17248.    mov bx,FileHandle       ; BX = handle of open file
  17249.    mov cx,stdout           ; CX = handle to be redirected
  17250.    mov ah,46h              ; AH = function number ("Force Duplicate Handle")
  17251.    int 21h                 ; redirect stdout to the file
  17252.    jc  Error
  17253.                            ; at this point, all output to stdout
  17254.                            ;   goes into the file
  17255.  
  17256.    To undo this redirection, associate the standard output device with the
  17257.    saved duplicate:
  17258.  
  17259.    mov bx,stdoutDup        ; BX = duplicate of previous stdout
  17260.    mov cx,stdout           ; CX = handle to be redirected
  17261.    mov ah,46h              ; AH = function number ("Force Duplicate Handle")
  17262.    int 21h                 ; restore stdout to what it was
  17263.    jc  Error
  17264.  
  17265.    mov bx,stdoutDup        ; BX = duplicate
  17266.    mov ah,3Eh              ; AH = function number ("Close")
  17267.    int 21h                 ; discard duplicate handle
  17268.  
  17269.  Function 47H (decimal 71): Get Current Directory
  17270.  
  17271.    Function 47H (decimal 71) reports the current directory in the form of an
  17272.    ASCIIZ string. Call function 47H with a drive number in DL (00H = default
  17273.    drive, 01H = drive A, and so on) and the address of a 64-byte buffer in
  17274.    DS:SI. The function normally clears the carry flag and fills the buffer
  17275.    with an ASCIIZ string indicating the path from the root to the current
  17276.    directory. If you specify an invalid drive number, the function sets the
  17277.    carry flag and returns an error code of 0FH in AX.
  17278.  
  17279.    Because the path returned by this function starts at the root directory,
  17280.    the string at DS:SI includes neither the drive letter (as in A:) nor the
  17281.    start-from-the-root backslash (as in A:\). By these rules, if the current
  17282.    directory is the root directory, then this function returns a null string.
  17283.    If you want an intelligible display of the current directory, you can
  17284.    prefix the information returned by this function with the drive-and-root
  17285.    indicators (as in A:\).
  17286.  
  17287.  Function 48H (decimal 72): Allocate Memory Block
  17288.  
  17289.    Function 48H (decimal 72) dynamically allocates memory. You request the
  17290.    number of paragraphs (16-byte units) you want allocated in BX. On return,
  17291.    AX contains the segment of the allocated memory block.
  17292.  
  17293.    If an error occurs, the carry flag is set and AX contains an error code:
  17294.    07H (memory control blocks destroyed) or 08H (insufficient memory). If
  17295.    there is insufficient memory to satisfy your request, BX contains the
  17296.    size, in paragraphs, of the largest available block of memory.
  17297.  
  17298.    Memory blocks allocated to a program using function 48H are freed by DOS
  17299.    when the program terminates with function 00H or 4CH, but they remain
  17300.    allocated to a memory-resident program that terminates with the
  17301.    Terminate-and-Stay-Resident function, 31H.
  17302.  
  17303.  Function 49H (decimal 73): Free Memory Block
  17304.  
  17305.    Function 49H (decimal 73) frees a block of memory for subsequent reuse by
  17306.    DOS or by other programs. Call function 49H with ES containing the
  17307.    paragraph address (segment) of the start of the memory block. If the
  17308.    memory is successfully freed, the function clears the carry flag.
  17309.    Otherwise, the carry flag is set, and AX contains an error code: 07H
  17310.    (memory control blocks destroyed) or 09H (invalid memory-block address).
  17311.  
  17312.    Although function 49H is usually used to free memory previously allocated
  17313.    through function 48H, it will free any memory block. For example, a
  17314.    Terminate-and-Stay-Resident program can free its environment block by
  17315.    calling function 49H with ES containing the paragraph address of the
  17316.    environment block. (See the discussion of function 31H in this chapter.)
  17317.  
  17318.  Function 4AH (decimal 74): Resize Memory Block
  17319.  
  17320.    Function 4AH (decimal 74) is used to increase or decrease the size of a
  17321.    block of memory that was allocated by function 48H. Register ES contains
  17322.    the segment address of the block that will be changed. Register BX
  17323.    contains the desired size of the block in paragraphs (units of 16 bytes).
  17324.  
  17325.    The function clears the carry flag if the memory block can be resized as
  17326.    requested. If an error occurs, the carry flag is set, and AX contains an
  17327.    error code: 07H (memory control blocks destroyed), 08H (insufficient
  17328.    memory), or 09H (invalid memory-block address). If DOS reported that there
  17329.    was insufficient memory to increase the size of a memory block, BX
  17330.    contains the maximum size, in paragraphs, of the memory block.
  17331.  
  17332.  Function 4BH (decimal 75): EXEC──Load and Execute a Program
  17333.  
  17334.    Function 4BH (decimal 75) lets a parent program load a "child" program
  17335.    into memory and execute it. This function can also be used to load
  17336.    executable code or data into memory without executing it. In both cases,
  17337.    you call function 4BH with DS:DX pointing to an ASCIIZ string with the
  17338.    path and filename of the file to be loaded. The register pair ES:BX points
  17339.    to a parameter block that contains control information for the load
  17340.    operation. AL specifies whether the child program is to be executed after
  17341.    it is loaded.
  17342.  
  17343.    If AL = 00H, DOS allocates memory for the child program, creates a new
  17344.    program segment prefix at the start of the newly allocated memory, loads
  17345.    the child program into memory immediately above the PSP, and transfers
  17346.    control to it. The parent program regains control only when the child
  17347.    program terminates. If AL = 03H, DOS does not allocate memory, create a
  17348.    PSP for the child program, or transfer control to the program after it is
  17349.    loaded. For these reasons, the AL = 03H variation is normally used to load
  17350.    a program overlay. It is also an effective way to load data into memory.
  17351.  
  17352.    When AL = 00H, ES:BX points to a block 14 bytes long, which contains the
  17353.    information shown in Figure 17-13. When AL = 03H, ES:BX points to a block
  17354.    4 bytes long, which contains the information shown in Figure 17-14 on the
  17355.    following page.
  17356.  
  17357.      Offset           Size
  17358.    Hex      Dec       (bytes)  Description
  17359.    ──────────────────────────────────────────────────────────────────────────
  17360.    00H       0        2        Segment address of environment string
  17361.    02H       2        4        Segmented pointer to command line
  17362.    06H       6        4        Segmented pointer to first default FCB
  17363.    0AH      10        4        Segmented pointer to second default FCB
  17364.    ──────────────────────────────────────────────────────────────────────────
  17365.  
  17366.    Figure 17-13.  The information in the EXEC parameter block that is pointed
  17367.    to by ES:BX when AL = 00H. DOS builds this information into the PSP of the
  17368.    program that is being loaded.
  17369.  
  17370.      Offset           Size
  17371.    Hex      Dec       (bytes)  Description
  17372.    ──────────────────────────────────────────────────────────────────────────
  17373.    00H      0         2        Segment address where file is to be loaded
  17374.    02H      2         2        Relocation factor for program (applies only to
  17375.                                EXE-format programs)
  17376.    ──────────────────────────────────────────────────────────────────────────
  17377.  
  17378.    Figure 17-14.  The information in the EXEC parameter block that is pointed
  17379.    to by ES:BX when AL = 03H.
  17380.  
  17381.    Function 4BH clears the carry flag if it successfully loads a program.
  17382.    However, in DOS version 2, this function changes all registers, including
  17383.    SS:SP. For this reason, you should save the current SS and SP values in
  17384.    the code segment before you call function 4BH.
  17385.  
  17386.    If function 4BH fails, it sets the carry flag and returns one of the
  17387.    following error codes in AX: 01H (invalid function), 02H (file not found),
  17388.    03H (path not found), 05H (access denied), 08H (insufficient memory), 0AH
  17389.    (invalid environment block), or 0BH (invalid format).
  17390.  
  17391.    When a child program is loaded and executed, it inherits any handles
  17392.    opened by the parent program. (The only exception, in DOS versions 3.0 and
  17393.    later, is when a handle opened by the parent had the inheritance bit of
  17394.    its file-access code set to 1.) Because a child program inherits its
  17395.    parent's open handles, the parent program can redirect the standard I/O
  17396.    handles and use this technique to influence the operation of the child
  17397.    program. For example, a parent program might redirect the standard input
  17398.    and output devices to files and then use the DOS SORT filter to sort the
  17399.    data in one file and copy it to another.
  17400.  
  17401.    More commonly, however, a parent program uses EXEC to execute a copy of
  17402.    the DOS command interpreter, COMMAND.COM. The parent program can carry out
  17403.    any DOS command by passing the command to COMMAND.COM through the EXEC
  17404.    parameter block. You can even get fancy by making COMMAND.COM execute a
  17405.    batch file──one that the parent program might well have constructed
  17406.    dynamically. This batch file could, in turn, invoke other programs and
  17407.    then perform the EXIT command, which would end the execution of the
  17408.    command interpreter. At that point, the parent program would be back in
  17409.    control. This opens up vast and complicated possibilities.
  17410.  
  17411.    ──────────────────────────────────────────────────────────────────────────
  17412.    NOTE:
  17413.      Strangely enough, you can't use function 4BH to load overlays created
  17414.      with the DOS LINK program's overlay option: LINK builds all program
  17415.      overlays into a single executable file, not into separate files as would
  17416.      be needed with function 4BH.
  17417.    ──────────────────────────────────────────────────────────────────────────
  17418.  
  17419.  Function 4CH (decimal 76): Terminate with Return Code
  17420.  
  17421.    Function 4CH (decimal 76) ends a program and passes back the return code
  17422.    you specify in AL. If the program was invoked as a child program, the
  17423.    parent program can retrieve the return code through function 4DH. If the
  17424.    program was invoked as a DOS command, then the return code can be tested
  17425.    in a batch file using the DOS ERRORLEVEL option.
  17426.  
  17427.    When this function is performed, DOS does some cleanup work in case your
  17428.    program neglected to do so: It restores the interrupt 22H, 23H, and 24H
  17429.    vectors to default values, flushes the file buffers and closes all open
  17430.    files, and frees all memory allocated to the program.
  17431.  
  17432.    Because function 4CH is more flexible and easier to use than interrupt 20H
  17433.    or interrupt 21H, function 00H, you should normally use function 4CH to
  17434.    terminate your programs. The only exception to this rule is if you need to
  17435.    maintain compatibility with DOS version 1, which does not support function
  17436.    4CH. In that case, you should use either interrupt 20H or function 00H
  17437.    of interrupt 21H.
  17438.  
  17439.  Function 4DH (decimal 77): Get Return Code
  17440.  
  17441.    Function 4DH (decimal 77) gets the return code of a child program invoked
  17442.    with function 4BH and terminated with function 31H or 4CH. The information
  17443.    is returned in two parts. AL reports the return code issued by the child
  17444.    program; AH reports how the child program ended and has four possible
  17445.    values:
  17446.  
  17447.    ■  AH = 00H indicates a normal voluntary end.
  17448.  
  17449.    ■  AH = 01H indicates termination by DOS due to a keyboard break (Ctrl-C).
  17450.  
  17451.    ■  AH = 02H indicates termination by DOS within a critical-error handler.
  17452.  
  17453.    ■  AH = 03H indicates a voluntary end using a terminate-and-stay-resident
  17454.       service (interrupt 27H or function 31H).
  17455.  
  17456.    You should call this function only after you call function 4BH. Function
  17457.    4DH does not indicate an error if you call it when no previous child
  17458.    program has terminated. Also, you can call this function only once for
  17459.    each EXEC call. The second time you call it, you'll get garbage in AH and
  17460.    AL instead of return codes.
  17461.  
  17462.  Function 4EH (decimal 78): Find First Matching Directory Entry
  17463.  
  17464.    Function 4EH (decimal 78) searches a directory for a specified name and
  17465.    attribute. Call function 4EH with DS:DX pointing to an ASCIIZ string
  17466.    containing the path and name to be matched. (You can use both * and ?
  17467.    wildcard characters in the search name you specify.) In addition, you must
  17468.    place a directory attribute for the search in CX. You can search for
  17469.    hidden, system, subdirectory, and volume-label directory entries by
  17470.    setting the appropriate bits in CX. (See page 113 for a table of
  17471.    attribute bits.)
  17472.  
  17473.    ──────────────────────────────────────────────────────────────────────────
  17474.    NOTE:
  17475.      Before you call function 4EH, be sure that the current disk transfer
  17476.      area (DTA) is at least 43 bytes in size.
  17477.    ──────────────────────────────────────────────────────────────────────────
  17478.  
  17479.    If this function successfully matches the name you specify to a directory
  17480.    entry, it clears the carry flag and fills the DTA with the data shown in
  17481.    Figure 17-15. If the function fails, it sets the carry flag and returns
  17482.    an error code in AX: 02H (file not found), 03H (path not found), or 12H
  17483.    (no more files; no match found).
  17484.  
  17485.    This function is similar to function 11H. The file attributes in this
  17486.    search function are the same as they are with an extended FCB in function
  17487.    11H. (See page 332.)
  17488.  
  17489.    The attribute search follows a particular logic. If you specify any
  17490.    combination of the hidden, system, or directory attribute bits, the search
  17491.    matches normal files and also any files with the specified attributes. If
  17492.    you specify the volume-label attribute, the search matches only a
  17493.    directory entry with that attribute. The archive and read-only bits do not
  17494.    apply to the search operations.
  17495.  
  17496.         Offset              Size
  17497.    Hex         Dec          (bytes)     Description
  17498.    ──────────────────────────────────────────────────────────────────────────
  17499.    00H          0           21          Area used by DOS for find-next
  17500.                                         function 4FH
  17501.    15H         21            1          Attribute of file found
  17502.    16H         22            2          Time stamp of file (see page 116)
  17503.    18H         24            2          Date stamp of file (see page 116)
  17504.    1AH         26            4          File size in bytes
  17505.    1EH         30           13          Filename and extension (ASCIIZ
  17506.                                         string)
  17507.    ──────────────────────────────────────────────────────────────────────────
  17508.  
  17509.    Figure 17-15.  The information returned in the DTA by function 4EH.
  17510.  
  17511.  Function 4FH (decimal 79): Find Next Matching Directory Entry
  17512.  
  17513.    Function 4FH (decimal 79) continues a directory search with a name that
  17514.    may match more than one directory entry because it contains wildcard
  17515.    characters. When you call this function, the DTA must contain the data
  17516.    returned by a previous call to function 4EH or 4FH.
  17517.  
  17518.    If this function finds a matching directory entry, it clears the carry
  17519.    flag and updates the DTA accordingly. If it fails to find a match, it sets
  17520.    the carry flag and returns error code 12H (no more files) in AX.
  17521.  
  17522.    The usual logic for a wildcard search with functions 4EH and 4FH follows
  17523.    this pattern:
  17524.  
  17525.    initialize DTA address with function 1AH
  17526.    call function 4EH
  17527.    WHILE carry flag = 0
  17528.          use current contents of DTA
  17529.          call function 4FH
  17530.  
  17531.  Function 54H (decimal 84): Get Verify Flag
  17532.  
  17533.    Function 54H (decimal 84) reports the current state of the verify flag,
  17534.    which controls whether or not DOS verifies disk-write operations. AL = 00H
  17535.    indicates that disk writes will not be verified; AL = 01H indicates that
  17536.    they will be. This function complements function 2EH, which sets or
  17537.    resets the verify flag.
  17538.  
  17539.    This function brings up an annoying inconsistency in DOS services: While
  17540.    some get/set service pairs are integrated into one function (like function
  17541.    57H), others are split into two separate functions, like function 54H and
  17542.    function 2EH.
  17543.  
  17544.  Function 56H (decimal 86): Rename File
  17545.  
  17546.    Like the standard DOS RENAME command, function 56H (decimal 86) changes
  17547.    the name of a file. But it can also move a file's directory entry from one
  17548.    directory to another. The file itself is not moved, only the directory
  17549.    entry, which means the new and old directory paths must be on the same
  17550.    drive. This is a truly fabulous and useful feature, and it is rather
  17551.    disappointing that it's not a part of the RENAME command.
  17552.  
  17553.    This function needs two pieces of information: the old and new path and
  17554.    filenames. These can be full-blown file specifications, with drive and
  17555.    path components. The specified or implied drives must be the same so that
  17556.    the new directory entry will be on the same drive as the file. The
  17557.    wildcard characters * and ? cannot be used, because this function works on
  17558.    single files only.
  17559.  
  17560.    As usual, both file specifications are supplied in the form of ASCIIZ
  17561.    strings. The register pair DS:DX points to the old name string and ES:DI
  17562.    points to the new string.
  17563.  
  17564.    Function 56H clears the carry flag when it successfully renames a file. If
  17565.    an error occurs, the carry flag is set, and AX contains an error code: 02H
  17566.    (file not found), 03H (path not found), 05H (access denied), or 11H (not
  17567.    the same device). One error that might not be reported occurs if you use
  17568.    function 56H to rename an open file. Be sure to close an open file with
  17569.    function 10H or 3EH before you use function 56H to rename it.
  17570.  
  17571.  Function 57H (decimal 87): Get/Set File Date and Time
  17572.  
  17573.    Function 57H (decimal 87) gets or sets a file's date and time. Normally a
  17574.    file's directory entry contains the date and time the file was created or
  17575.    last changed. This function lets you inspect or explicitly update the
  17576.    recorded date and time. AL selects the operation: AL = 00H gets the date
  17577.    and time, and AL = 01H sets the date and time.
  17578.  
  17579.    The file is selected by placing the file handle in BX, which makes this
  17580.    function applicable only to files that were opened using the handle-based
  17581.    DOS functions covered in this chapter. Thus, setting a file's time stamp
  17582.    with this function will take effect only if the file is successfully
  17583.    closed.
  17584.  
  17585.    The date and time are placed in registers CX and DX in the same format
  17586.    used in the disk directory entries, though in a slightly different order.
  17587.    In this function, the time is placed in CX and the date in DX.
  17588.  
  17589.    Use the following formulas to build or break down the date and time:
  17590.  
  17591.      CX = HOUR * 2048 + MINUTE * 32 + SECOND / 2
  17592.      DX = (YEAR - 1980) * 512 + MONTH * 32 + DAY
  17593.  
  17594.    If this function fails, it returns an error code in AX: 01H (invalid
  17595.    function number──based on the subfunction selected in AL, not the main
  17596.    function number) or 06H (invalid handle).
  17597.  
  17598.  Function 58H (decimal 88): Get/Set Memory Allocation Strategy
  17599.  
  17600.    Function 58H (decimal 88) gets or sets the method DOS uses to allocate
  17601.    free memory to programs. You can choose from three different memory
  17602.    allocation strategies. (See Figure 17-16.) Each strategy assumes that
  17603.    memory resources are broken into blocks of various sizes and that each
  17604.    block can be randomly allocated to a program or freed, depending on the
  17605.    specific requirements of DOS and of each program. You might think that all
  17606.    free memory would be located in one large block just above where a program
  17607.    ends, but terminate-and-stay-resident programs and device drivers can
  17608.    reserve memory blocks and thereby fragment available memory into two or
  17609.    more smaller blocks.
  17610.  
  17611.    Value in Function 58H                Strategy
  17612.    ──────────────────────────────────────────────────────────────────────────
  17613.    0                                    First fit
  17614.    1                                    Best fit
  17615.    2                                    Last fit
  17616.    ──────────────────────────────────────────────────────────────────────────
  17617.  
  17618.    Figure 17-16.  DOS memory allocation strategies.
  17619.  
  17620.    When DOS responds to a request for memory allocation, it searches through
  17621.    a list of free-memory blocks, starting at the lowest available address and
  17622.    working upward. With the first-fit strategy, DOS allocates the first free
  17623.    block of memory large enough to accommodate the memory- allocation
  17624.    request. With the last-fit strategy, DOS allocates the last free block in
  17625.    the list that is large enough. With the best-fit strategy, DOS searches
  17626.    the entire list and allocates the smallest block that is large enough. DOS
  17627.    uses the first-fit strategy by default.
  17628.  
  17629.    To obtain the allocation strategy from DOS, call function 58H with AL =
  17630.    00H. DOS reports the current allocation strategy (00H, 01H, or 02H) in AX.
  17631.    To set the allocation strategy, call this function with AL = 01H and the
  17632.    desired strategy (00H, 01H, or 02H) in BX. The only error detected by this
  17633.    function occurs when you call it with AL > 01H, in which case the carry
  17634.    flag is set and AX contains an error code of 01H (invalid function). This
  17635.    function does not validate the value you pass in BX, so be careful to use
  17636.    a valid value (00H, 01H, or 02H) when you set the allocation strategy.
  17637.  
  17638.  Function 59H (decimal 89): Get Extended Error Information
  17639.  
  17640.    Function 59H (decimal 89) is used after an error occurs. It provides
  17641.    detailed information about the errors that occur under these
  17642.    circumstances: inside a critical-error (interrupt 24H) handler, after a
  17643.    DOS function call invoked with interrupt 21H reports an error by setting
  17644.    the carry flag (CF), and after old-style FCB file operations report a
  17645.    return code of FFH. It will not work with other DOS functions that do not
  17646.    report errors in CF, even though they may have ended in an error.
  17647.  
  17648.    This function is called in the standard way, by placing function code 59H
  17649.    in register AH. You must also specify a version code in the BX register.
  17650.    For DOS version 3, set the version code to 0.
  17651.  
  17652.    Four types of information are returned on completion of this service:
  17653.  
  17654.    ■  AX contains the extended error code.
  17655.  
  17656.    ■  BH indicates the class of error.
  17657.  
  17658.    ■  BL gives the code of any suggested action that your program should
  17659.       take.
  17660.  
  17661.    ■  CH gives a locus code, which attempts to show where the error occurred.
  17662.  
  17663.    Beware: Registers CL, DX, SI, DI, ES, and DS are also changed by function
  17664.    59H. Save these registers as necessary before you make a call to this
  17665.    function.
  17666.  
  17667.    The extended error codes can be organized into three groups: Codes 01H
  17668.    through 12H are returned by interrupt 21H functions. Codes 13H through 1FH
  17669.    are used in critical-error (interrupt 24H) handlers. The remaining error
  17670.    codes were introduced in DOS 3.0 and generally report network-related
  17671.    errors. Figure 17-17 lists the extended error codes, Figure 17-18 lists
  17672.    the error classes, Figure 17-19 lists the action codes, and Figure
  17673.    17-20 lists the locus codes.
  17674.  
  17675. ╓┌─┌──────────────┌──────────────────────────────────────────────────────────╖
  17676.     Error Code
  17677.    Hex     Dec    Description
  17678.    ──────────────────────────────────────────────────────────────────────────
  17679.    Returned by interrupt 21H functions:
  17680.    00H      0     (No error)
  17681.    01H      1     Invalid function number
  17682.    02H      2     File not found
  17683.    03H      3     Path not found
  17684.     Error Code
  17685.    Hex     Dec    Description
  17686.    ──────────────────────────────────────────────────────────────────────────
  17687.   03H      3     Path not found
  17688.    04H      4     No more handles (too many open files)
  17689.    05H      5     Access denied (e.g., attempt to write to read-only files)
  17690.    06H      6     Invalid handle
  17691.    07H      7     Memory control blocks destroyed
  17692.    08H      8     Not enough memory
  17693.    09H      9     Invalid memory-block address
  17694.    0AH     10     Invalid environment block
  17695.    0BH     11     Invalid format
  17696.    0CH     12     Invalid file-access code
  17697.    0DH     13     Invalid data
  17698.    0EH     14     (Reserved)
  17699.    0FH     15     Invalid drive specification
  17700.    10H     16     Attempt to remove the current directory
  17701.    11H     17     Not the same device
  17702.    12H     18     No more files
  17703.  
  17704.    Used in critical-error (interrupt 24H handlers:
  17705.     Error Code
  17706.    Hex     Dec    Description
  17707.    ──────────────────────────────────────────────────────────────────────────
  17708.   Used in critical-error (interrupt 24H handlers:
  17709.    13H     19     Disk is write-protected
  17710.    14H     20     Unknown disk unit ID
  17711.    15H     21     Disk drive not ready
  17712.    16H     22     Unknown disk command
  17713.    17H     23     Disk data error
  17714.    18H     24     Bad disk request structure length
  17715.    19H     25     Disk seek error
  17716.    1AH     26     Non-DOS disk
  17717.    1BH     27     Disk sector not found
  17718.    1CH     28     Printer out of paper
  17719.    1DH     29     Write error
  17720.    1EH     30     Read error
  17721.    1FH     31     General failure
  17722.  
  17723.    Used in DOS versions 3.0 and later:
  17724.    20H     32     File-sharing violation
  17725.    21H     33     File-locking violation
  17726.     Error Code
  17727.    Hex     Dec    Description
  17728.    ──────────────────────────────────────────────────────────────────────────
  17729.   21H     33     File-locking violation
  17730.    22H     34     Invalid disk change
  17731.    23H     35     No FCB available
  17732.    24H     36     Sharing buffer overflow
  17733.    25H─31H 37─49  (Reserved)
  17734.    32H     50     Network request not supported
  17735.    33H     51     Remote computer not listening
  17736.    34H     52     Duplicate name on network
  17737.    35H     53     Network name not found
  17738.    36H     54     Network busy
  17739.    37H     55     Network device no longer exists
  17740.    38H     56     Network BIOS command limit exceeded
  17741.    39H     57     Network adapter hardware error
  17742.    3AH     58     Incorrect response from network
  17743.    3BH     59     Unexpected network error
  17744.    3CH     60     Incompatible remote adapter
  17745.    3DH     61     Print queue full
  17746.    3EH     62     Not enough space for print file
  17747.     Error Code
  17748.    Hex     Dec    Description
  17749.    ──────────────────────────────────────────────────────────────────────────
  17750.   3EH     62     Not enough space for print file
  17751.    3FH     63     Print file was deleted
  17752.    40H     64     Network name was deleted
  17753.    41H     65     Access denied
  17754.    42H     66     Network device type incorrect
  17755.    43H     67     Network name not found
  17756.    44H     68     Network name limit exceeded
  17757.    45H     69     Net BIOS session limit exceeded
  17758.    46H     70     Sharing temporarily paused
  17759.    47H     71     Network request not accepted
  17760.    48H     72     Print or disk redirection is paused
  17761.    49H─4FH 73─79  (Reserved)
  17762.    50H     80     File already exists
  17763.    51H     81     (Reserved)
  17764.    52H     82     Cannot create directory entry
  17765.    53H     83     Fail on interrupt 24H
  17766.    54H     84     Out of network structures
  17767.    55H     85     Network device already assigned
  17768.     Error Code
  17769.    Hex     Dec    Description
  17770.    ──────────────────────────────────────────────────────────────────────────
  17771.   55H     85     Network device already assigned
  17772.    56H     86     Invalid password
  17773.    57H     87     Invalid parameter
  17774.    58H     88     Network data fault
  17775.    ──────────────────────────────────────────────────────────────────────────
  17776.  
  17777.  
  17778.    Figure 17-17.  DOS extended error codes.
  17779.  
  17780.       Code
  17781.    Hex     Dec     Meaning
  17782.    ──────────────────────────────────────────────────────────────────────────
  17783.    01H      1      Out of resource: no more of whatever you asked for
  17784.    02H      2      Temporary situation: Try again later
  17785.    03H      3      Authorization: You aren't allowed; someone else might be
  17786.    04H      4      Internal error in DOS: not your fault
  17787.    05H      5      Hardware failure
  17788.    06H      6      System software error: other DOS problems
  17789.    07H      7      Application software error: It's your fault
  17790.    08H      8      Item requested not found
  17791.    09H      9      Bad format (e.g., unrecognizable disk)
  17792.    0AH     10      Item locked
  17793.    0BH     11      Media error (e.g., disk reports CRC error)
  17794.    0CH     12      Already exists
  17795.    0DH     13      Error class is unknown
  17796.    ──────────────────────────────────────────────────────────────────────────
  17797.  
  17798.    Figure 17-18.  The error classes returned in register BH by function 59H.
  17799.  
  17800.      Code
  17801.    Hex    Dec   Meaning
  17802.    ──────────────────────────────────────────────────────────────────────────
  17803.    01H    1     Try again several times, then issue "Abort or Ignore" prompt.
  17804.    02H    2     Try again after a pause, then issue "Abort or Ignore" prompt.
  17805.    03H    3     Ask the user to change incorrect information (e.g., bad
  17806.                 filename).
  17807.    04H    4     Shut down the program, but OK to clean up (e.g., close
  17808.                 files).
  17809.    05H    5     Shut down immediately; don't try to clean up.
  17810.    06H    6     Ignore the error: It's for information only.
  17811.    07H    7     Retry after user action (e.g., change diskettes).
  17812.    ──────────────────────────────────────────────────────────────────────────
  17813.  
  17814.    Figure 17-19.  The suggested action codes returned in register BL by
  17815.    function 59H.
  17816.  
  17817.           Code
  17818.    Hex         Dec          Meaning
  17819.    ──────────────────────────────────────────────────────────────────────────
  17820.    01H         1            Unknown: sorry
  17821.    02H         2            Block device (e.g., disk drive)
  17822.    03H         3            Network
  17823.    04H         4            Serial device (e.g., printer)
  17824.    05H         5            Memory
  17825.    ──────────────────────────────────────────────────────────────────────────
  17826.  
  17827.    Figure 17-20.  The locus codes returned in register CH by function 59H.
  17828.  
  17829.  Function 5AH (decimal 90): Create Temporary File
  17830.  
  17831.    Function 5AH (decimal 90) was introduced in DOS version 3.0. It creates a
  17832.    file for temporary use. It generates a unique filename for the file by
  17833.    building the name from the current time of day. You provide two
  17834.    parameters: the file attribute, placed in the CX register, and the
  17835.    pathname of the directory where the file will be created. The pathname
  17836.    must be an ASCIIZ string and is pointed to by the register pair DS:DX.
  17837.  
  17838.    The pathname string must be ready to have the filename of the created file
  17839.    appended to it: The string must end with a backslash character and be
  17840.    followed by 13 bytes to allow enough room for DOS to add a filename to the
  17841.    string. If you don't want to specify a particular path, you can give DOS a
  17842.    null string, which tells it to use the current directory of the current
  17843.    drive.
  17844.  
  17845.    If function 5AH successfully creates a file, it clears the carry flag and
  17846.    returns the name of the file appended to the pathname you specified in
  17847.    DS:DX. If the function fails, it sets the carry flag and returns an error
  17848.    code in AX: 03H (path not found), 04H (no more handles), or 05H (access
  17849.    denied).
  17850.  
  17851.    This function is called "create temporary file" only to suggest its
  17852.    intended purpose. Actually, there is nothing temporary about the file that
  17853.    is created because DOS does not automatically delete it; your programs
  17854.    must look after that chore.
  17855.  
  17856.  Function 5BH (decimal 91): Create New File
  17857.  
  17858.    Function 5BH (decimal 91) was introduced in DOS version 3.0. It is similar
  17859.    to function 3CH, which is (inaccurately) called the "create-file
  17860.    function." Function 3CH is actually designed to find a file or to create
  17861.    one if the requested file does not exist. By contrast, function 5BH is a
  17862.    pure create-file function and will fail if the file already exists.
  17863.  
  17864.    As with function 3CH, the CX register is set to the file attribute, and
  17865.    DS:DX contains the address of the pathname and filename (which is stored
  17866.    as an ASCIIZ string). On return, if CF = 0, then AX = file handle for the
  17867.    new file. If CF = 1, then AX contains the error code: 03H (path not
  17868.    found), 04H (no more handles), 05H (access denied), or 50H (file already
  17869.    exists).
  17870.  
  17871.    You should use function 3CH if you want to reuse a file with a particular
  17872.    filename if it exists or create a file with that name if it doesn't exist.
  17873.    If, however, you simply want to open a file that does not already exist,
  17874.    use function 5BH.
  17875.  
  17876.  Function 5CH (decimal 92): Lock/Unlock File Region
  17877.  
  17878.    Function 5CH (decimal 92) locks certain parts of a file so that the file
  17879.    can be shared by several programs without one program interfering with the
  17880.    operations of another. If one program locks one part of a file, it can use
  17881.    or change that part of the file while it is locked, safe in the knowledge
  17882.    that no other program will be able to use that part while it remains
  17883.    locked. As you may guess, file locking is used only in conjunction with
  17884.    file-sharing operations, like those that can occur in a network.
  17885.  
  17886.    When you call function 5CH, AL indicates whether you are locking (AL =
  17887.    00H) or unlocking (AL = 01H) a portion of a file. BX gives the file
  17888.    handle. CX and DX are treated as a 4-byte integer that specifies the byte
  17889.    offset of the start of the locked portion of the file. SI and DI also form
  17890.    a 4-byte integer that specifies the length of the locked portion. The
  17891.    first register in each of these register pairs (CX or SI) gives the
  17892.    high-order part of the integer. When function 5CH successfully locks a
  17893.    portion of a file, it clears the carry flag. If an error occurs, the carry
  17894.    flag is set, and AX contains an error code: 01H (invalid function), 06H
  17895.    (invalid handle), 21H (file-locking violation), or 24H (sharing buffer
  17896.    overflow).
  17897.  
  17898.    You are not allowed to unlock file portions piecemeal or in combination;
  17899.    an unlock request should exactly match a previous lock request. You must
  17900.    also explicitly remove all locks before closing a file or terminating a
  17901.    program that does file locking.
  17902.  
  17903.    Use function 5CH to lock a file region before you read or write a file
  17904.    that may have been locked by another program; use function 5CH again to
  17905.    unlock the region after the read or write operation is complete. The first
  17906.    call to function 5CH tells you if the part of the file you intend to
  17907.    access is already locked; you should not rely on the read and write
  17908.    functions to return error codes if they access a previously locked region.
  17909.  
  17910.    Function 5CH is supported only in DOS versions 3.0 and later.
  17911.  
  17912.  Function 5EH (decimal 94): Network Machine Name and Printer Setup
  17913.  
  17914.    Function 5EH (decimal 94) first appeared in DOS version 3.1. It comprises
  17915.    several subfunctions that are useful only to programs running in a
  17916.    network. (See Figure 17-21.) You must specify a subfunction number in AL
  17917.    when you call function 5EH.
  17918.  
  17919.    Subfunction
  17920.    Hex     Dec              Description
  17921.    ──────────────────────────────────────────────────────────────────────────
  17922.    00H     0                Get machine name.
  17923.    02H     2                Set printer setup string.
  17924.    03H     3                Get printer setup string.
  17925.    ──────────────────────────────────────────────────────────────────────────
  17926.  
  17927.    Figure 17-21.  Subfunctions available through interrupt 21H, function 5EH.
  17928.  
  17929.    Subfunction 00H. This subfunction retrieves the network name of the
  17930.    computer on which the program is running. Call it with DS:DX pointing to
  17931.    an empty 16-byte buffer. If the function returns successfully, the buffer
  17932.    contains the machine name as an ASCIIZ string; CH contains a flag that, if
  17933.    nonzero, indicates that the machine name is a valid network name; and CL
  17934.    contains the NETBIOS number associated with the machine name.
  17935.  
  17936.    Subfunction 02H. This subfunction passes a printer setup string to DOS.
  17937.    DOS adds this string to the beginning of any files it sends to a network
  17938.    printer. Call this function with an assign-list index number in BX, the
  17939.    length of the setup string in CX, and DS:SI pointing to the string itself.
  17940.    The assign-list number identifies a particular printer on the network.
  17941.    (See function 5FH.) The maximum length of the string is 64 bytes.
  17942.  
  17943.    Subfunction 03H. This subfunction complements subfunction 02H. Call it
  17944.    with an assign-list index number in BX and with ES:DI pointing to an empty
  17945.    64-byte buffer. The subfunction places the requested printer setup string
  17946.    in the buffer and returns the length of the string in CX.
  17947.  
  17948.  Function 5FH (decimal 95): Network Redirection
  17949.  
  17950.    Like function 5EH, function 5FH (decimal 95) consists of subfunctions used
  17951.    by programs running in a network. (See Figure 17-22.) In a network
  17952.    environment, DOS maintains an internal table of devices that can be shared
  17953.    across the network; this is called an assign list or redirection list. The
  17954.    table associates local logical names for such devices with their network
  17955.    names. These subfunctions give a program access to the table.
  17956.  
  17957.    Subfunction
  17958.    Hex     Dec              Description
  17959.    ──────────────────────────────────────────────────────────────────────────
  17960.    02H     2                Get assign-list entry.
  17961.    03H     3                Make assign-list entry.
  17962.    04H     4                Cancel assign-list entry.
  17963.    ──────────────────────────────────────────────────────────────────────────
  17964.  
  17965.    Figure 17-22.  Subfunctions available through interrupt 21H, function 5FH.
  17966.  
  17967.    Subfunction 02H. This subfunction obtains the local name and network name
  17968.    for one of the devices in the assign-list table. Call this subfunction
  17969.    with an assign-list index number in BX, with DS:SI pointing to an empty
  17970.    16-bit buffer, and with ES:DI pointing to an empty 128-byte buffer. The
  17971.    subfunction returns the local device name in the 16-bit buffer and the
  17972.    network name in the 128-byte buffer. The subfunction also indicates the
  17973.    device status in BH (00H = valid device, 01H = invalid device) and the
  17974.    device type in BL (03H = printer, 04H = disk drive), and it updates CX
  17975.    with the user parameter associated with the device through subfunction
  17976.    03H.
  17977.  
  17978.    Subfunction 02H is designed to let you step through the assign-list table.
  17979.    The first table entry's assign-list index is 0. By incrementing the
  17980.    assign-list index each time you call this subfunction, you can examine
  17981.    each table entry in turn. When you request a table entry past the end of
  17982.    the table, subfunction 02H sets the carry flag and returns an error code
  17983.    of 12H (no more files) in AX.
  17984.  
  17985.    Beware: A successful call to subfunction 02H changes DX and BP.
  17986.  
  17987.    Subfunction 03H. This subfunction redirects a local device to a network
  17988.    device. Call this subfunction with DS:SI containing the address of a
  17989.    16-byte buffer that contains an ASCIIZ local device name (e.g., PRN or E)
  17990.    and ES:DI pointing to a 128-byte buffer containing an ASCIIZ network
  17991.    device name followed by an ASCIIZ password. You must also specify the
  17992.    device type in BL (03H = printer, 04H = drive) and place a user parameter
  17993.    in CX. (This parameter should be 00H if you are using IBM's Local Area
  17994.    Network software.)
  17995.  
  17996.    If subfunction 03H successfully establishes redirection of input/output to
  17997.    the network device, it adds a corresponding entry to its assign-list table
  17998.    and clears the carry flag. If the operation fails, the carry flag is set,
  17999.    and AX contains an error code.
  18000.  
  18001.    Subfunction 04H. This subfunction cancels network redirection of a device
  18002.    and removes the corresponding assign-list table entry. Call it with DS:SI
  18003.    pointing to an ASCIIZ string that specifies the local device whose
  18004.    redirection you want canceled. If the operation is successful, subfunction
  18005.    04H clears the carry flag.
  18006.  
  18007.    Function 5FH is supported only in DOS versions 3.1 and later.
  18008.  
  18009.  Function 62H (decimal 98): Get PSP Address
  18010.  
  18011.    Function 62H (decimal 98) returns the segment (paragraph address) of the
  18012.    program segment prefix in BX.
  18013.  
  18014.    When DOS transfers control to a program, registers DS and ES always
  18015.    contain the segment of the program's PSP. Function 62H provides an
  18016.    alternative method of determining this address in DOS versions 3.0 and
  18017.    later.
  18018.  
  18019.  Function 65H (decimal 101): Get Extended Country Information
  18020.  
  18021.    Function 65H (decimal 101) was introduced in DOS version 3.3 along with
  18022.    support for global code pages (user-configurable character sets for output
  18023.    devices). It returns a superset of the country information available
  18024.    through function 38H. Function 65H has subfunctions, each of which
  18025.    returns a different type of information. (See Figure 17-23.)
  18026.  
  18027.    Call function 65H with a subfunction number in AL, a code page number in
  18028.    BX, a buffer size in CX, a country ID in DX, and the address of an empty
  18029.    buffer in ES:DI. Calls with BX = -1 refer to the active code page; calls
  18030.    with DX = -1 return information for the default country ID.
  18031.  
  18032.    The size of the buffer you supply to this function depends on which
  18033.    subfunction you call. The function clears the carry flag and fills the
  18034.    buffer with the information you requested.
  18035.  
  18036.    Subfunction
  18037.    Hex     Dec    Description
  18038.    ──────────────────────────────────────────────────────────────────────────
  18039.    01H     1      Get extended country information.
  18040.    02H     2      Get pointer to character translation table.
  18041.    04H     4      Get pointer to filename character translation table.
  18042.    05H     5      (Reserved)
  18043.    06H     6      Get pointer to collating sequence.
  18044.    ──────────────────────────────────────────────────────────────────────────
  18045.  
  18046.    Figure 17-23.  Subfunctions available through interrupt 21H, function 65H.
  18047.  
  18048.    Subfunction 01H. This subfunction returns the same information as function
  18049.    38H, but also includes the current code page and country ID (Figure
  18050.    17-24).
  18051.  
  18052.     Offset         Size
  18053.    Hex     Dec     (bytes)  Description
  18054.    ──────────────────────────────────────────────────────────────────────────
  18055.    00H      0       1       Subfunction ID (always 01H)
  18056.    01H      1       2       Size of following information (38 bytes or less)
  18057.    03H      3       2       Country ID
  18058.    05H      5       2       Code page
  18059.    07H      7       2       Date format
  18060.    09H      9       5       Currency symbol string (ASCIIZ format)
  18061.    0EH     14       2       Thousands separator string (ASCIIZ format)
  18062.    10H     16       2       Decimal separator string (ASCIIZ format)
  18063.    12H     18       2       Date separator string (ASCIIZ format)
  18064.    14H     20       2       Time separator string (ASCIIZ format)
  18065.    16H     22       1       Currency symbol location
  18066.    17H     23       1       Currency decimal places
  18067.    18H     24       1       Time format
  18068.    19H     25       4       Extended ASCII map call address
  18069.    1DH     29       2       List separator string (ASCIIZ format)
  18070.    1FH     31      10       (Reserved)
  18071.    ──────────────────────────────────────────────────────────────────────────
  18072.  
  18073.    Figure 17-24.  Format of extended country information returned by function
  18074.    65H, subfunction 01H. The information starting at offset 7 is the same as
  18075.    that returned by interrupt 21H, function 38H.
  18076.  
  18077.    Subfunction 02H. This subfunction returns 5 bytes of data in the buffer at
  18078.    ES:DI. The first byte always has the value 02H (the subfunction number).
  18079.    The 4 remaining bytes contain the segmented address of a translation table
  18080.    used to convert extended ASCII characters (ASCII codes 80H through FFH) to
  18081.    characters with ASCII codes 00H through FFH. This table is used by the
  18082.    character-mapping routine whose address is returned by subfunction 01H.
  18083.  
  18084.    Subfunction 04H. This subfunction also fills the buffer at ES:DI with a
  18085.    single subfunction ID byte followed by the 4-byte segmented address of a
  18086.    translation table. This table serves the same purpose as the table whose
  18087.    address is returned by subfunction 02H, but this table is used for
  18088.    filenames.
  18089.  
  18090.    Subfunction 06H. Like subfunctions 02H and 04H, this subfunction fills the
  18091.    buffer at ES:DI with a subfunction ID byte followed by a segmented
  18092.    address. In this case, the address points to a table that specifies the
  18093.    collating sequence for the character set defined in the code page.
  18094.  
  18095.  Function 66H (decimal 102): Get/Set Global Code Page
  18096.  
  18097.    Function 66H (decimal 102), also introduced with DOS version 3.3, consists
  18098.    of two subfunctions that provide support for code page switching within a
  18099.    program. Call this function with a subfunction number (01H or 02H) in AL.
  18100.  
  18101.    Subfunction 01H. This subfunction returns the number of the active code
  18102.    page in BX. It also reports (in DX) the number of the default code page
  18103.    used when the system is first booted.
  18104.  
  18105.    Subfunction 02H. Call this subfunction with a new code page number in BX.
  18106.    DOS copies the new code page information from the COUNTRY.SYS file and
  18107.    uses it to update all devices configured for code page switching. For this
  18108.    subfunction to operate successfully, you must include the appropriate
  18109.    DEVICE and COUNTRY commands in your CONFIG.SYS file and also execute the
  18110.    MODE CP PREPARE and NLSFUNC commands. (See your DOS reference manual for
  18111.    details.)
  18112.  
  18113.  Function 67H (decimal 103): Set Handle Count
  18114.  
  18115.    Function 67H (decimal 103), introduced in DOS version 3.3, lets a program
  18116.    specify the maximum number of handles it can keep open at any one time.
  18117.    DOS maintains a table of the handles used by a program in a reserved area
  18118.    in the program's PSP. Normally, the limit is 20 handles, of which 5 are
  18119.    automatically opened by DOS for the standard input, output, error,
  18120.    auxiliary, and printer devices.
  18121.  
  18122.    To increase the maximum number of open handles, call function 67H with the
  18123.    maximum number of desired handles in BX. DOS will allocate a new block of
  18124.    memory and use it to store an expanded table of handles. The function
  18125.    clears the carry flag to indicate success; if the carry flag is set, AX
  18126.    contains an error code.
  18127.  
  18128.    Remember two points about function 67H:
  18129.  
  18130.    ■  If you are running a COM program that uses all available memory, it
  18131.       must call function 4AH to shrink its memory allocation before DOS can
  18132.       allocate a memory block for the handle table.
  18133.  
  18134.    ■  The size of DOS's internal file table imposes an upper limit on the
  18135.       number of handles you can open. You can increase the size of that table
  18136.       with the FILES command in your CONFIG.SYS file.
  18137.  
  18138.  Function 68H (decimal 104): Commit File
  18139.  
  18140.    Function 68H (decimal 104) was first supported in DOS version 3.3. When
  18141.    you call this function with an open file handle in BX, DOS flushes the
  18142.    disk buffer associated with the handle and updates the disk directory
  18143.    accordingly. This ensures that data written to the disk buffer but not yet
  18144.    physically written on a disk will not be lost should a power failure or
  18145.    other mishap occur.
  18146.  
  18147.    By executing function 68H, you obtain the same result that you would by
  18148.    using function 45H to duplicate a file handle and then using function
  18149.    3EH to close the duplicate handle.
  18150.  
  18151.  
  18152.  Chapter 18  DOS Functions Summary
  18153.  ────────────────────────────────────────────────────────────────────────────
  18154.  
  18155.    Short Summary
  18156.  
  18157.    Long Summary
  18158.  
  18159.    This chapter summarizes the DOS functions and is designed to be used as a
  18160.    quick reference guide. For details about the specific operation of each
  18161.    function, see Chapters 15 through 17. Once you understand the DOS
  18162.    functions, these tables should provide you with most of the programming
  18163.    information you'll need.
  18164.  
  18165.  
  18166.  
  18167.  Short Summary
  18168.  
  18169.  
  18170.    Figure 18-1 lists the five interrupts that can be executed to obtain
  18171.    various DOS functions. Of these, interrupt 21H is by far the most useful──
  18172.    it is the function-call interrupt that provides general access to nearly
  18173.    all DOS functions. Interrupts 25H and 26H, the absolute disk read/write
  18174.    interface, may occasionally be needed to bypass the usual DOS file
  18175.    interface. The remaining interrupts, 20H and 27H, provide
  18176.    program-termination services in DOS version 1 that were made obsolete by
  18177.    interrupt 21H functions introduced in DOS version 2.0. Chapter 15 covers
  18178.    the DOS interrupts in detail.
  18179.  
  18180.    Interrupt
  18181.    Hex  Dec  Description
  18182.    ──────────────────────────────────────────────────────────────────────────
  18183.    20H  32   Program terminate: Come to a normal ending.
  18184.    21H  33   General DOS functions.
  18185.    25H  37   Absolute disk read.
  18186.    26H  38   Absolute disk write.
  18187.    27H  39   Terminate and stay resident.
  18188.    ──────────────────────────────────────────────────────────────────────────
  18189.    Figure 18-1. The five main DOS interrupts.
  18190.  
  18191.    Figure 18-2 lists the interrupt 21H functions introduced with DOS version
  18192.    1 and supported in all versions of DOS. These functions are discussed in
  18193.    Chapter 16.
  18194.  
  18195.    Figure 18-3 lists the expanded set of interrupt 21H functions introduced
  18196.    in DOS version 2.0 and augmented in later DOS versions. Chapter 17
  18197.    describes these functions.
  18198.  
  18199.    All interrupt 21H functions are called by executing interrupt 21H with a
  18200.    function number in the AH register and other parameters as needed in the
  18201.    other 8086 registers. Most DOS functions return a completion code in the
  18202.    AL or AX register; most of the functions introduced in DOS versions 2.0
  18203.    and later also use the carry flag to report the success of a function
  18204.    call. See Chapters 16 and 17 for several program examples of interrupt
  18205.    21H calls.
  18206.  
  18207. ╓┌─┌────┌────┌───────────────────────────────────────────────────────────────╖
  18208.    Function
  18209.    Function
  18210.    Hex  Dec  Description
  18211.    ──────────────────────────────────────────────────────────────────────────
  18212.    00H   0   Terminate.
  18213.    01H   1   Character Input with Echo.
  18214.    02H   2   Character Output.
  18215.    03H   3   Auxiliary Input.
  18216.    04H   4   Auxiliary Output.
  18217.    05H   5   Printer Output.
  18218.    06H   6   Direct Character Input/Output.
  18219.    07H   7   Direct Character Input Without Echo.
  18220.    08H   8   Character Input Without Echo.
  18221.    09H   9   String Output.
  18222.    0AH  10   Buffered Keyboard Input.
  18223.    0BH  11   Check Keyboard Status.
  18224.    0CH  12   Flush Keyboard Buffer, Read Keyboard.
  18225.    0DH  13   Flush Disk Buffers.
  18226.    0EH  14   Select Disk Drive.
  18227.    0FH  15   Open File.
  18228.    10H  16   Close File.
  18229.    11H  17   Find First Matching Directory Entry.
  18230.    Function
  18231.    Hex  Dec  Description
  18232.    ──────────────────────────────────────────────────────────────────────────
  18233.   11H  17   Find First Matching Directory Entry.
  18234.    12H  18   Find Next Matching Directory Entry.
  18235.    13H  19   Delete File.
  18236.    14H  20   Sequential Read.
  18237.    15H  21   Sequential Write.
  18238.    16H  22   Create File.
  18239.    17H  23   Rename File.
  18240.    19H  25   Get Current Disk.
  18241.    1AH  26   Set DTA Address.
  18242.    1BH  27   Get Default Drive Information.
  18243.    1CH  28   Get Specified Drive Information.
  18244.    21H  33   Read Random Record.
  18245.    22H  34   Write Random Record.
  18246.    23H  35   Get File Size.
  18247.    24H  36   Set FCB Random Record Field.
  18248.    25H  37   Set Interrupt Vector.
  18249.    26H  38   Create New PSP.
  18250.    27H  39   Read Random Records.
  18251.    Function
  18252.    Hex  Dec  Description
  18253.    ──────────────────────────────────────────────────────────────────────────
  18254.   27H  39   Read Random Records.
  18255.    28H  40   Write Random Records.
  18256.    29H  41   Parse Filename.
  18257.    2AH  42   Get Date.
  18258.    2BH  43   Set Date.
  18259.    2CH  44   Get Time.
  18260.    2DH  45   Set Time.
  18261.    2EH  46   Set Verify Flag.
  18262.    ──────────────────────────────────────────────────────────────────────────
  18263.  
  18264.    Figure 18-2. Interrupt 21H functions available in all DOS versions.
  18265.  
  18266. ╓┌─┌────┌────┌────────────────────────────────────────────────────────┌──────╖
  18267.    Function                                                           DOS
  18268.    Hex  Dec  Description                                              Version
  18269.    ──────────────────────────────────────────────────────────────────────────
  18270.    2FH   47  Get DTA Address.                                        2.0
  18271.    30H   48  Get DOS Version Number.                                 2.0
  18272.    Function                                                           DOS
  18273.    Hex  Dec  Description                                              Version
  18274.    ──────────────────────────────────────────────────────────────────────────
  18275.   30H   48  Get DOS Version Number.                                 2.0
  18276.    31H   49  Terminate and Stay Resident.                            2.0
  18277.    33H   51  Get/Set Ctrl-C Flag.                                    2.0
  18278.    35H   53  Get Interrupt Vector.                                   2.0
  18279.    36H   54  Get Disk Free Space.                                    2.0
  18280.    38H   56  Get/Set Country-Dependent Information.                  2.0
  18281.    39H   57  Create Directory.                                       2.0
  18282.    3AH   58  Remove Directory.                                       2.0
  18283.    3BH   59  Change Current Directory.                               2.0
  18284.    3CH   60  Create File.                                            2.0
  18285.    3DH   61  Open File.                                              2.0
  18286.    3EH   62  Close File.                                             2.0
  18287.    3FH   63  Read from File or Device.                               2.0
  18288.    40H   64  Write to File or Device.                                2.0
  18289.    41H   65  Delete File.                                            2.0
  18290.    42H   66  Move File Pointer.                                      2.0
  18291.    43H   67  Get/Set File Attributes.                                2.0
  18292.    44H   68  IOCTL──I/O Control for Devices.                         2.0
  18293.    Function                                                           DOS
  18294.    Hex  Dec  Description                                              Version
  18295.    ──────────────────────────────────────────────────────────────────────────
  18296.   44H   68  IOCTL──I/O Control for Devices.                         2.0
  18297.    45H   69  Duplicate File Handle.                                  2.0
  18298.    46H   70  Force Duplicate File Handle.                            2.0
  18299.    47H   71  Get Current Directory.                                  2.0
  18300.    48H   72  Allocate Memory Block.                                  2.0
  18301.    49H   73  Free Memory Block.                                      2.0
  18302.    4AH   74  Resize Memory Block.                                    2.0
  18303.    4BH   75  Load and Execute a Program.                             2.0
  18304.    4CH   76  Terminate with Return Code.                             2.0
  18305.    4DH   77  Get Return Code.                                        2.0
  18306.    4EH   78  Find First Matching Directory Entry.                    2.0
  18307.    4FH   79  Find Next Matching Directory Entry.                     2.0
  18308.    54H   84  Get Verify Flag.                                        2.0
  18309.    56H   86  Rename File.                                            2.0
  18310.    57H   87  Get/Set File Date and Time.                             2.0
  18311.    58H   88  Get/Set Memory Allocation Strategy.                     3.0
  18312.    59H   89  Get Extended Error Information.                         3.0
  18313.    5AH   90  Create Temporary File.                                  3.0
  18314.    Function                                                           DOS
  18315.    Hex  Dec  Description                                              Version
  18316.    ──────────────────────────────────────────────────────────────────────────
  18317.   5AH   90  Create Temporary File.                                  3.0
  18318.    5BH   91  Create New File.                                        3.0
  18319.    5CH   92  Lock/Unlock File Region.                                3.0
  18320.    5EH   94  Network Machine Name and Printer Setup.                 3.1
  18321.    5FH   95  Network Redirection.                                    3.1
  18322.    62H   98  Get PSP Address.                                        3.0
  18323.    65H  101  Get Extended Country Information.                       3.3
  18324.    66H  102  Get/Set Global Code Page.                               3.3
  18325.    67H  103  Set Handle Count.                                       3.3
  18326.    68H  104  Commit File.                                            3.3
  18327.    ──────────────────────────────────────────────────────────────────────────
  18328.  
  18329.    Figure 18-3. Interrupt 21H functions available in DOS versions 2.0 and
  18330.    later.
  18331.  
  18332.  
  18333.  
  18334.  Long Summary
  18335.  
  18336.  
  18337.    In the last section, we briefly listed all the DOS functions so that
  18338.    individual functions could be found by their function number. In this
  18339.    section, we have expanded the listing to show the register values passed
  18340.    to and returned from interrupt 21H functions.
  18341.  
  18342.    Since most new versions of DOS have introduced new functions that cannot
  18343.    be used with earlier versions, we have included the DOS version number in
  18344.    which each function was introduced.
  18345.  
  18346. ╓┌─┌────────────────┌───┌────────────────┌────────────────┌───┌──────────────╖
  18347.    Program Control  Fun        Register                   DOS
  18348.    Functions        hex Input            Output           Ver Notes
  18349.    ──────────────────────────────────────────────────────────────────────────
  18350.    Terminate: End   00H AH = 00H                          1.0 Obsolete: Use
  18351.    program.             CS = segment of                       function 4CH
  18352.                         PSP                                   instead.
  18353.    ──────────────────────────────────────────────────────────────────────────
  18354.    Create new       26H AH = 26H                          1.0 Obsolete: Use
  18355.    program segment.     DX = segment                          function 4BH
  18356.    Program Control  Fun        Register                   DOS
  18357.    Functions        hex Input            Output           Ver Notes
  18358.    ──────────────────────────────────────────────────────────────────────────
  18359.   program segment.     DX = segment                          function 4BH
  18360.                         where new PSP                         instead.
  18361.                         starts
  18362.    ──────────────────────────────────────────────────────────────────────────
  18363.    Terminate and    31H AH = 31H                          2.0
  18364.    stay resident.       AL = return code
  18365.                         DX = # of
  18366.                         paragraphs
  18367.                         to keep resident
  18368.    ──────────────────────────────────────────────────────────────────────────
  18369.    Get/set Ctrl-C   33H AH = 33H         AL = result code 2.0
  18370.    flag.                To set flag:     If called with
  18371.                         AL = 01H         AL = 01H:
  18372.                         DL = value       DL = current
  18373.                         To get flag:     value of flag (0
  18374.                         AL = 00H         = off,
  18375.                                          1 = on)
  18376.    ──────────────────────────────────────────────────────────────────────────
  18377.    Program Control  Fun        Register                   DOS
  18378.    Functions        hex Input            Output           Ver Notes
  18379.    ──────────────────────────────────────────────────────────────────────────
  18380.   ──────────────────────────────────────────────────────────────────────────
  18381.    EXEC: Load and   4BH AH = 4BH         If no error:     2.0 Changes all
  18382.    execute a            DS:DX -> ASCIIZ  CF clear             registers,
  18383.    program.             command line     If error:            including
  18384.                         ES:BX -> control CF set               SS:SP.
  18385.                         block            AX = error code
  18386.                         To execute child
  18387.                         program:
  18388.                         AL = 00H
  18389.                         To load without
  18390.                         executing:
  18391.                         AL = 03H
  18392.    ──────────────────────────────────────────────────────────────────────────
  18393.    Terminate with   4CH AH = 4CH                          2.0
  18394.    return code.         AL = return code
  18395.    ──────────────────────────────────────────────────────────────────────────
  18396.    Get return code. 4DH AH = 4DH         AL = return code 2.0 Call only once
  18397.                                          AH = termination     after calling
  18398.    Program Control  Fun        Register                   DOS
  18399.    Functions        hex Input            Output           Ver Notes
  18400.    ──────────────────────────────────────────────────────────────────────────
  18401.                                         AH = termination     after calling
  18402.                                          method               function 4CH.
  18403.    ──────────────────────────────────────────────────────────────────────────
  18404.    Get PSP address. 62H AH = 62H         BX = PSP segment 3.0
  18405.  
  18406.  
  18407.  
  18408. ╓┌─┌────────────────┌───┌────────────────┌────────────────┌───┌──────────────╖
  18409.    Standard Input   Fun        Register                   DOS
  18410.    Functions        hex Input            Output           Ver Notes
  18411.    ──────────────────────────────────────────────────────────────────────────
  18412.    Character input  01H AH = 01H         AL = 8-bit       1.0
  18413.    with echo.                            character
  18414.    ──────────────────────────────────────────────────────────────────────────
  18415.    Direct character 07H AH = 07H         AL = 8-bit       1.0
  18416.    input without                         character
  18417.    echo.
  18418.    ──────────────────────────────────────────────────────────────────────────
  18419.    Standard Input   Fun        Register                   DOS
  18420.    Functions        hex Input            Output           Ver Notes
  18421.    ──────────────────────────────────────────────────────────────────────────
  18422.   ──────────────────────────────────────────────────────────────────────────
  18423.    Character input  08H AH = 08H         AL = 8-bit       1.0
  18424.    without echo.                         character
  18425.    ──────────────────────────────────────────────────────────────────────────
  18426.    Buffered         0AH AH = 0AH         Buffer contains  1.0 See Chapter
  18427.    keyboard input.      DS:DX -> input   keyboard input.      16 for input
  18428.                         buffer                                buffer format.
  18429.    ──────────────────────────────────────────────────────────────────────────
  18430.    Check keyboard   0BH AH = 0BH         If character     1.0
  18431.    status.                               available:
  18432.                                          AL = FFH
  18433.                                          If no character
  18434.                                          available:
  18435.                                          AL = 00H
  18436.    ──────────────────────────────────────────────────────────────────────────
  18437.    Flush keyboard   0CH AH = 0CH         (Depends on      1.0
  18438.    buffer, read         AL = function    function
  18439.    keyboard.            number           specified
  18440.    Standard Input   Fun        Register                   DOS
  18441.    Functions        hex Input            Output           Ver Notes
  18442.    ──────────────────────────────────────────────────────────────────────────
  18443.   keyboard.            number           specified
  18444.                         (01H, 06H, 07H,  in AL)
  18445.                         08H, or 0AH)
  18446.  
  18447.  
  18448.  
  18449.  
  18450. ╓┌─┌────────────────┌───┌────────────────┌────────────────┌───┌──────────────╖
  18451.    Standard Output  Fun        Register                   DOS
  18452.    Functions        hex Input            Output           Ver Notes
  18453.    ──────────────────────────────────────────────────────────────────────────
  18454.    Character        02H AH = 02H                          1.0
  18455.    output.              DL = 8-bit
  18456.                         character
  18457.    ──────────────────────────────────────────────────────────────────────────
  18458.    String output.   09H AH = 09H                          1.0
  18459.                         DS:DX -> string
  18460.                         terminated with
  18461.    Standard Output  Fun        Register                   DOS
  18462.    Functions        hex Input            Output           Ver Notes
  18463.    ──────────────────────────────────────────────────────────────────────────
  18464.                        terminated with
  18465.                         '$'
  18466.  
  18467.  
  18468.  
  18469.  
  18470.  
  18471.  
  18472.  
  18473.  
  18474.  
  18475.  
  18476.  
  18477.  
  18478. ╓┌─┌────────────────┌───┌────────────────┌────────────────┌───┌──────────────╖
  18479.    Console I/O      Fun        Register                   DOS
  18480.    Functions        hex Input            Output           Ver Notes
  18481.    ──────────────────────────────────────────────────────────────────────────
  18482.    Console I/O      Fun        Register                   DOS
  18483.    Functions        hex Input            Output           Ver Notes
  18484.    ──────────────────────────────────────────────────────────────────────────
  18485.    Direct character 06H AH = 06H         If called with   1.0
  18486.    input/output.        To input a       DL = FFH:
  18487.                         character:       AL = 8-bit
  18488.                         DL = FFH         character
  18489.                         To output a
  18490.                         character:
  18491.                         DL = 8-bit
  18492.                         character
  18493.                         (00H─FEH)
  18494.  
  18495.  
  18496.  
  18497.  
  18498.  
  18499.  
  18500.  
  18501.  
  18502.  
  18503.    Console I/O      Fun        Register                   DOS
  18504.    Functions        hex Input            Output           Ver Notes
  18505.    ──────────────────────────────────────────────────────────────────────────
  18506. 
  18507.  
  18508.  
  18509.  
  18510. ╓┌─┌────────────────┌───┌────────────────┌────────────────┌───┌──────────────╖
  18511.    Miscellaneous    Fun        Register                   DOS
  18512.    I/O Functions    hex Input            Output           Ver Notes
  18513.    ──────────────────────────────────────────────────────────────────────────
  18514.    Auxiliary input. 03H AH = 03H         AL = 8-bit       1.0
  18515.                                          character
  18516.    ──────────────────────────────────────────────────────────────────────────
  18517.    Auxiliary        04H AH = 04H                          1.0
  18518.    output.              DL = character
  18519.    ──────────────────────────────────────────────────────────────────────────
  18520.    Printer output.  05H AH = 05H                          1.0
  18521.                         DL = character
  18522.  
  18523.  
  18524.    Miscellaneous    Fun        Register                   DOS
  18525.    I/O Functions    hex Input            Output           Ver Notes
  18526.    ──────────────────────────────────────────────────────────────────────────
  18527. 
  18528.  
  18529.  
  18530.  
  18531.  
  18532.  
  18533.  
  18534.  
  18535.  
  18536.  
  18537.  
  18538.  
  18539.  
  18540. ╓┌─┌────────────────┌───┌────────────────┌────────────────┌───┌──────────────╖
  18541.    Disk Functions   Fun        Register                   DOS
  18542.                     hex Input            Output           Ver Notes
  18543.    ──────────────────────────────────────────────────────────────────────────
  18544.    Flush disk       0DH AH = 0DH                          1.0 See also
  18545.    Disk Functions   Fun        Register                   DOS
  18546.                     hex Input            Output           Ver Notes
  18547.    ──────────────────────────────────────────────────────────────────────────
  18548.    Flush disk       0DH AH = 0DH                          1.0 See also
  18549.    buffers.                                                   function 68H
  18550.    ──────────────────────────────────────────────────────────────────────────
  18551.    Select disk      0EH AH = 0EH         AL = number of   1.0 In DOS 3.0 and
  18552.    drive.               DL = drive ID    drives in system     later, AL >=
  18553.                                                               05H.
  18554.    ──────────────────────────────────────────────────────────────────────────
  18555.    Get current      19H AH = 19H         AL = drive ID    1.0
  18556.    disk.
  18557.    ──────────────────────────────────────────────────────────────────────────
  18558.    Set DTA address. 1AH AH = 1AH                          1.0
  18559.                         DS:DX -> DTA
  18560.    ──────────────────────────────────────────────────────────────────────────
  18561.    Get default      1BH AH = 1BH         AL = sectors     1.0 Obsolete: Use
  18562.    drive                                 per cluster          function 36H
  18563.    information.                          CX = bytes           instead.
  18564.                                          per sector
  18565.                                          DX = total
  18566.    Disk Functions   Fun        Register                   DOS
  18567.                     hex Input            Output           Ver Notes
  18568.    ──────────────────────────────────────────────────────────────────────────
  18569.                                         DX = total
  18570.                                          clusters
  18571.                                          on disk
  18572.                                          DS:BX -> media
  18573.                                          ID byte
  18574.    ──────────────────────────────────────────────────────────────────────────
  18575.    Get specified    1CH AH = 1CH         AL = sectors     1.0 Obsolete: Use
  18576.    drive                DL = drive ID    per cluster          function 36H
  18577.    information.                          CX = bytes           instead.
  18578.                                          per sector
  18579.                                          DX = total
  18580.                                          clusters on disk
  18581.                                          DS:BX -> media
  18582.                                          ID byte
  18583.    ──────────────────────────────────────────────────────────────────────────
  18584.    Set verify flag. 2EH AH = 2EH                          1.0 Call with
  18585.                         AL = value for                        DL = 00H in DOS
  18586.                         flag                                  versions prior
  18587.    Disk Functions   Fun        Register                   DOS
  18588.                     hex Input            Output           Ver Notes
  18589.    ──────────────────────────────────────────────────────────────────────────
  18590.                        flag                                  versions prior
  18591.                         (0 = off, 1 =                         to 3.0.
  18592.                         on)
  18593.                         DL = 00H
  18594.    ──────────────────────────────────────────────────────────────────────────
  18595.    Get DTA address. 2FH AH = 2FH         ES:BX -> DTA     2.0
  18596.    ──────────────────────────────────────────────────────────────────────────
  18597.    Get disk free    36H AH = 36H         If bad drive ID: 2.0
  18598.    space.               DL = drive ID    AX = FFFFH
  18599.                                          If no error:
  18600.                                          AX = sectors
  18601.                                          per cluster
  18602.                                          BX = unused
  18603.                                          clusters
  18604.                                          CX = bytes
  18605.                                          per sector
  18606.                                          DX = total
  18607.                                          clusters on disk
  18608.    Disk Functions   Fun        Register                   DOS
  18609.                     hex Input            Output           Ver Notes
  18610.    ──────────────────────────────────────────────────────────────────────────
  18611.                                         clusters on disk
  18612.    ──────────────────────────────────────────────────────────────────────────
  18613.    Get verify flag. 54H AH = 54H         AL = value of    2.0
  18614.                                          flag
  18615.                                          (0 = off, 1 =
  18616.                                          on)
  18617.  
  18618.  
  18619.  
  18620. ╓┌─┌────────────────┌───┌────────────────┌────────────────┌───┌──────────────╖
  18621.    File Management  Fun        Register                   DOS
  18622.    Functions        hex Input            Output           Ver Notes
  18623.    ──────────────────────────────────────────────────────────────────────────
  18624.    Delete file.     13H AH = 13H         If error:        1.0 Obsolete: Use
  18625.                         DS:DX -> FCB     AL = FFH             function 41H
  18626.                                          If no error:         instead.
  18627.                                          AL = 0
  18628.    ──────────────────────────────────────────────────────────────────────────
  18629.    File Management  Fun        Register                   DOS
  18630.    Functions        hex Input            Output           Ver Notes
  18631.    ──────────────────────────────────────────────────────────────────────────
  18632.   ──────────────────────────────────────────────────────────────────────────
  18633.    Create file.     16H AH = 16H         If error:        1.0 Obsolete: Use
  18634.                         DS:DX -> FCB     AL = FFH             function 3CH,
  18635.                                          If no error:         5AH, or 5BH
  18636.                                          AL = 00H             instead.
  18637.    ──────────────────────────────────────────────────────────────────────────
  18638.    Rename file.     17H AH = 17H         If error:        1.0 Obsolete: Use
  18639.                         DS:DX ->         AL = FFH             function 56H
  18640.                         modified FCB     If no error:         instead.
  18641.                                          AL = 00H
  18642.    ──────────────────────────────────────────────────────────────────────────
  18643.    Get file size.   23H AH = 23H         If error:        1.0 Obsolete: Use
  18644.                         DS:DX -> FCB     AL = FFH             function 42H
  18645.                                          If no error:         instead.
  18646.                                          AL = 00H
  18647.                                          FCB contains
  18648.                                          file size.
  18649.    ──────────────────────────────────────────────────────────────────────────
  18650.    File Management  Fun        Register                   DOS
  18651.    Functions        hex Input            Output           Ver Notes
  18652.    ──────────────────────────────────────────────────────────────────────────
  18653.   ──────────────────────────────────────────────────────────────────────────
  18654.    Parse filename.  29H AH = 29H         AL = error code  1.0 Cannot parse
  18655.                         AL = control     DS:SI -> byte        pathnames.
  18656.                         bits             past parsed
  18657.                         DS:SI -> string  string
  18658.                         to parse         ES:DI -> FCB
  18659.                         ES:DI -> FCB
  18660.    ──────────────────────────────────────────────────────────────────────────
  18661.    Create file.     3CH AH = 3CH         If error:        2.0
  18662.                         CX = attribute   CF set
  18663.                         DS:DX -> ASCIIZ  AX = error code
  18664.                         file             If no error:
  18665.                         specification    CF clear
  18666.                                          AX = handle
  18667.    ──────────────────────────────────────────────────────────────────────────
  18668.    Delete file.     41H AH = 41H         If error:        2.0
  18669.                         DS:DX -> ASCIIZ  CF set
  18670.                         file             AX = error code
  18671.    File Management  Fun        Register                   DOS
  18672.    Functions        hex Input            Output           Ver Notes
  18673.    ──────────────────────────────────────────────────────────────────────────
  18674.                        file             AX = error code
  18675.                         specification    If no error:
  18676.                                          CF clear
  18677.    ──────────────────────────────────────────────────────────────────────────
  18678.    Get/set file     43H AH = 43H         If error:        2.0
  18679.    attributes.          DS:DX -> ASCIIZ  CF set
  18680.                         file             AX = error code
  18681.                         specification    If no error:
  18682.                         To get           CF clear
  18683.                         attributes:      CX = attributes
  18684.                         AL = 00H         (if called with
  18685.                         To set           AL = 00H)
  18686.                         attributes:
  18687.                         AL = 01H
  18688.                         CX = attributes
  18689.    ──────────────────────────────────────────────────────────────────────────
  18690.    Rename file.     56H AH = 56H         If error:        2.0 May be used to
  18691.                         DS:DX -> old     CF set               move a file
  18692.    File Management  Fun        Register                   DOS
  18693.    Functions        hex Input            Output           Ver Notes
  18694.    ──────────────────────────────────────────────────────────────────────────
  18695.                        DS:DX -> old     CF set               move a file
  18696.                         ASCIIZ file      AX = error code      from one
  18697.                         specification    If no error:         directory to
  18698.                         ES:DI -> new     CF clear             another.
  18699.                         ASCIIZ file
  18700.                         specification
  18701.    ──────────────────────────────────────────────────────────────────────────
  18702.    Get/set file     57H AH = 57H         If error:        2.0
  18703.    date                 BX = handle      CF set
  18704.    and time.            To get date and  AX = error code
  18705.                         time:            If no error:
  18706.                         AL = 00H         CF clear
  18707.                         To set date and  If called with
  18708.                         time:            AL = 00H:
  18709.                         AL = 01H         CX = time
  18710.                         CX = time        DX = date
  18711.                         DX = date
  18712.    ──────────────────────────────────────────────────────────────────────────
  18713.    File Management  Fun        Register                   DOS
  18714.    Functions        hex Input            Output           Ver Notes
  18715.    ──────────────────────────────────────────────────────────────────────────
  18716.   ──────────────────────────────────────────────────────────────────────────
  18717.    Create temporary 5AH AH = 5AH         If error:        3.0
  18718.    file.                CX = attribute   CF set
  18719.                         DS:DX -> ASCIIZ  AX = error code
  18720.                         path followed by If no error:
  18721.                         13 empty bytes   CF clear
  18722.                                          AX = handle
  18723.                                          DS:DX -> ASCIIZ
  18724.                                          file
  18725.                                          specification
  18726.    ──────────────────────────────────────────────────────────────────────────
  18727.    Create new file. 5BH AH = 5BH         If error:        3.0
  18728.                         CX = attribute   CF set
  18729.                         DS:DX -> ASCIIZ  AX = error code
  18730.                         file             If no error:
  18731.                         specification    CF clear
  18732.                                          AX = handle
  18733.  
  18734.  
  18735.  
  18736. ╓┌─┌────────────────┌───┌────────────────┌────────────────┌───┌──────────────╖
  18737.    File I/O         Fun        Register                   DOS
  18738.    Functions        hex Input            Output           Ver Notes
  18739.    ──────────────────────────────────────────────────────────────────────────
  18740.    Open file.       0FH AH = 0FH         AL = result code 1.0 Obsolete: Use
  18741.                         DS:DX -> FCB                          function 3DH
  18742.                                                               instead.
  18743.    ──────────────────────────────────────────────────────────────────────────
  18744.    Close file.      10H AH = 10H         If no error:     1.0 Obsolete: Use
  18745.                         DS:DX -> FCB     AL = result code     function 3EH
  18746.                                                               instead.
  18747.    ──────────────────────────────────────────────────────────────────────────
  18748.    Sequential read. 14H AH = 14H         AL = result code 1.0 Obsolete: Use
  18749.                         DS:DX -> FCB     DTA contains         function 3FH
  18750.                                          data read.           instead.
  18751.    ──────────────────────────────────────────────────────────────────────────
  18752.    Sequential       15H AH = 15H         AL = result code 1.0 Obsolete: Use
  18753.    write.               DS:DX -> FCB                          function 40H
  18754.                         DTA contains                          instead.
  18755.    File I/O         Fun        Register                   DOS
  18756.    Functions        hex Input            Output           Ver Notes
  18757.    ──────────────────────────────────────────────────────────────────────────
  18758.                        DTA contains                          instead.
  18759.                         data
  18760.                         to write.
  18761.    ──────────────────────────────────────────────────────────────────────────
  18762.    Read random      21H AH = 21H         AL = result code 1.0 Obsolete: Use
  18763.    record.              DS:DX -> FCB     DTA contains         function 3FH
  18764.                                          data read.           instead.
  18765.    ──────────────────────────────────────────────────────────────────────────
  18766.    Write random     22H AH = 22H         AL = result code 1.0 Obsolete: Use
  18767.    record.              DS:DX -> FCB                          function 40H
  18768.                         DTA contains                          instead.
  18769.                         data
  18770.                         to write.
  18771.    ──────────────────────────────────────────────────────────────────────────
  18772.    Set FCB random   24H AH = 24H         AL = 00H         1.0 Obsolete: Use
  18773.    record field.        DS:DX -> FCB     FCB contains         function 42H
  18774.                                          updated random       instead.
  18775.                                          record field.
  18776.    File I/O         Fun        Register                   DOS
  18777.    Functions        hex Input            Output           Ver Notes
  18778.    ──────────────────────────────────────────────────────────────────────────
  18779.                                         record field.
  18780.    ──────────────────────────────────────────────────────────────────────────
  18781.    Read random      27H AH = 27H         AL = result code 1.0 Obsolete: Use
  18782.    records.             CX = record      CX = number of       function 3FH
  18783.                         count            records read         instead.
  18784.                         DS:DX -> FCB     DTA contains
  18785.                                          data read.
  18786.    ──────────────────────────────────────────────────────────────────────────
  18787.    Write random     28H AH = 28H         AL = result code 1.0 Obsolete: Use
  18788.    records.             CX = record      CX = number of       function 40H
  18789.                         count            records written      instead.
  18790.                         DS:DX -> FCB
  18791.                         DTA contains
  18792.                         data
  18793.                         to write.
  18794.    ──────────────────────────────────────────────────────────────────────────
  18795.    Open handle.     3DH AH = 3DH         If error:        2.0
  18796.                         AL = file access CF set
  18797.    File I/O         Fun        Register                   DOS
  18798.    Functions        hex Input            Output           Ver Notes
  18799.    ──────────────────────────────────────────────────────────────────────────
  18800.                        AL = file access CF set
  18801.                         code             AX = error code
  18802.                         DS:DX -> ASCIIZ  If no error:
  18803.                         file             CF clear
  18804.                         specification    AX = handle
  18805.    ──────────────────────────────────────────────────────────────────────────
  18806.    Close handle.    3EH AH = 3EH         If error:        2.0
  18807.                         BX = handle      CF set
  18808.                                          AX = error code
  18809.                                          If no error:
  18810.                                          CF clear
  18811.    ──────────────────────────────────────────────────────────────────────────
  18812.    Read from file   3FH AH = 3FH         If error:        2.0
  18813.    or device.           BX = handle      CF set
  18814.                         CX = number of   AX = error code
  18815.                         bytes to read    If no error:
  18816.                         DS:DX -> buffer  CF clear
  18817.                                          AX = number of
  18818.    File I/O         Fun        Register                   DOS
  18819.    Functions        hex Input            Output           Ver Notes
  18820.    ──────────────────────────────────────────────────────────────────────────
  18821.                                         AX = number of
  18822.                                          bytes read
  18823.                                          DS:DX -> buffer
  18824.    ──────────────────────────────────────────────────────────────────────────
  18825.    Write to file    40H AH = 40H         If error:        2.0
  18826.    or device.           BX = handle      CF set
  18827.                         CX = number of   AX = error code
  18828.                         bytes to write   If no error:
  18829.                         DS:DX -> buffer  CF clear
  18830.                                          AX = number of
  18831.                                          bytes written
  18832.    ──────────────────────────────────────────────────────────────────────────
  18833.    Move file        42H AH = 42H         If error:        2.0
  18834.    pointer.             BX = handle      CF set
  18835.                         CX:DX = offset   AX = error code
  18836.                         to move pointer  If no error:
  18837.                         Move relative to CF clear
  18838.                         start of file:   DX:AX = new file
  18839.    File I/O         Fun        Register                   DOS
  18840.    Functions        hex Input            Output           Ver Notes
  18841.    ──────────────────────────────────────────────────────────────────────────
  18842.                        start of file:   DX:AX = new file
  18843.                         AL = 00H         pointer
  18844.                         Move relative to
  18845.                         current
  18846.                         location:
  18847.                         AL = 01H
  18848.                         Move relative to
  18849.                         end of file:
  18850.                         AL = 02H
  18851.    ──────────────────────────────────────────────────────────────────────────
  18852.    Duplicate file   45H AH = 45H         If error:        2.0 See Chapter
  18853.    handle.              BX = handle      CF set               17 for
  18854.                                          AX = error code      details.
  18855.                                          If no error:
  18856.                                          CF clear
  18857.                                          AX = new handle
  18858.    ──────────────────────────────────────────────────────────────────────────
  18859.    Force duplicate  46H AH = 46H         If error:        2.0 See Chapter
  18860.    File I/O         Fun        Register                   DOS
  18861.    Functions        hex Input            Output           Ver Notes
  18862.    ──────────────────────────────────────────────────────────────────────────
  18863.   Force duplicate  46H AH = 46H         If error:        2.0 See Chapter
  18864.    file handle.         BX = handle      CF set               17 for
  18865.                         CX = handle to   AX = error code      details.
  18866.                         be forced        If no error:
  18867.                                          CF clear
  18868.    ──────────────────────────────────────────────────────────────────────────
  18869.    Lock/Unlock file 5CH AH = 5CH         If error:        3.0 Use with SHARE
  18870.    region.              BX = handle      CF set               or in network
  18871.                         CX:DX = start of AX = error code      environment.
  18872.                         region to        If no error:
  18873.                         lock/unlock      CF clear
  18874.                         SI:DI = size of
  18875.                         region to
  18876.                         lock/unlock
  18877.                         To lock region:
  18878.                         AL = 00H
  18879.                         To unlock
  18880.                         region:
  18881.    File I/O         Fun        Register                   DOS
  18882.    Functions        hex Input            Output           Ver Notes
  18883.    ──────────────────────────────────────────────────────────────────────────
  18884.                        region:
  18885.                         AL = 01H
  18886.    ──────────────────────────────────────────────────────────────────────────
  18887.    Set handle       67H AH = 67H         If error:        3.3
  18888.    count.               BX = number of   CF set
  18889.                         handles          AX = error code
  18890.                                          If no error:
  18891.                                          CF clear
  18892.    ──────────────────────────────────────────────────────────────────────────
  18893.    Commit file.     68H AH = 68H         If error:        3.3
  18894.                         BX = handle      CF set
  18895.                                          AX = error code
  18896.                                          If no error:
  18897.                                          CF clear
  18898.  
  18899.  
  18900.  
  18901. ╓┌─┌────────────────┌───┌────────────────┌────────────────┌───┌──────────────╖
  18902.    Directory        Fun        Register                   DOS
  18903.    Functions        hex Input            Output           Ver Notes
  18904.    ──────────────────────────────────────────────────────────────────────────
  18905.    Find first       11H AH = 11H         If error:        1.0 Obsolete: Use
  18906.    matching             DS:DX -> FCB     AL = FFH             function 4EH
  18907.    directory entry.                      If no error:         instead.
  18908.                                          AL = 00H
  18909.                                          DTA contains
  18910.                                          directory
  18911.                                          information.
  18912.    ──────────────────────────────────────────────────────────────────────────
  18913.    Find next        12H AH = 12H         If error:        1.0 Obsolete: Use
  18914.    matching             DS:DX -> FCB     AL = FFH             function 4FH
  18915.    directory entry.                      If no error:         instead.
  18916.                                          AL = 00H
  18917.                                          DTA contains
  18918.                                          directory
  18919.                                          information.
  18920.    ──────────────────────────────────────────────────────────────────────────
  18921.    Create           39H AH = 39H         If error:        2.0
  18922.    directory.           DS:DX -> ASCIIZ  CF set
  18923.    Directory        Fun        Register                   DOS
  18924.    Functions        hex Input            Output           Ver Notes
  18925.    ──────────────────────────────────────────────────────────────────────────
  18926.   directory.           DS:DX -> ASCIIZ  CF set
  18927.                         path             AX = error code
  18928.                                          If no error:
  18929.                                          CF clear
  18930.    ──────────────────────────────────────────────────────────────────────────
  18931.    Remove           3AH AH = 3AH         If error:        2.0
  18932.    directory.           DS:DX -> ASCIIZ  CF set
  18933.                         path             AX = error code
  18934.                                          If no error:
  18935.                                          CF clear
  18936.    ──────────────────────────────────────────────────────────────────────────
  18937.    Change current   3BH AH = 3BH         If error:        2.0
  18938.    directory.           DS:DX -> ASCIIZ  CF set
  18939.                         path             AX = error code
  18940.                                          If no error:
  18941.                                          CF clear
  18942.    ──────────────────────────────────────────────────────────────────────────
  18943.    Get current      47H AH = 47H         If error:        2.0
  18944.    Directory        Fun        Register                   DOS
  18945.    Functions        hex Input            Output           Ver Notes
  18946.    ──────────────────────────────────────────────────────────────────────────
  18947.   Get current      47H AH = 47H         If error:        2.0
  18948.    directory.           DL = drive ID    CF set
  18949.                         DS:SI -> empty   AX = error code
  18950.                         64-byte buffer   If no error:
  18951.                                          CF clear
  18952.                                          DS:SI -> ASCIIZ
  18953.                                          path
  18954.    ──────────────────────────────────────────────────────────────────────────
  18955.    Find first       4EH AH = 4EH         If error:        2.0
  18956.    matching             CX = attribute   CF set
  18957.    directory entry.     DS:DX -> ASCIIZ  AX = error code
  18958.                         file             If no error:
  18959.                         specification    CF clear
  18960.                                          DTA contains
  18961.                                          directory
  18962.                                          information.
  18963.    ──────────────────────────────────────────────────────────────────────────
  18964.    Find next        4FH AH = 4FH         If error:        2.0
  18965.    Directory        Fun        Register                   DOS
  18966.    Functions        hex Input            Output           Ver Notes
  18967.    ──────────────────────────────────────────────────────────────────────────
  18968.   Find next        4FH AH = 4FH         If error:        2.0
  18969.    matching             DTA contains     CF set
  18970.    directory entry.     information from AX = error code
  18971.                         previous call to If no error:
  18972.                         function 4EH     CF clear
  18973.                         or 4FH.          DTA contains
  18974.                                          directory
  18975.                                          information.
  18976.  
  18977.  
  18978.  
  18979. ╓┌─┌────────────────┌───┌────────────────┌────────────────┌───┌──────────────╖
  18980.    Date/Time        Fun        Register                   DOS
  18981.    Functions        hex Input            Output           Ver Notes
  18982.    ──────────────────────────────────────────────────────────────────────────
  18983.    Get date.        2AH AH = 2AH         AL = day of week 1.0
  18984.                                          CX = year
  18985.                                          DH = month
  18986.    Date/Time        Fun        Register                   DOS
  18987.    Functions        hex Input            Output           Ver Notes
  18988.    ──────────────────────────────────────────────────────────────────────────
  18989.                                         DH = month
  18990.                                          DL = day
  18991.    ──────────────────────────────────────────────────────────────────────────
  18992.    Set date.        2BH AH = 2BH         If error:        1.0
  18993.                         CX = year        AL = FFH
  18994.                         DH = month       If no error:
  18995.                         DL = day         AL = 00H
  18996.    ──────────────────────────────────────────────────────────────────────────
  18997.    Get time.        2CH AH = 2CH         CH = hours       1.0
  18998.                                          CL = minutes
  18999.                                          DH = seconds
  19000.                                          DL = 100ths
  19001.                                          of seconds
  19002.    ──────────────────────────────────────────────────────────────────────────
  19003.    Set time.        2DH AH = 2DH         If error:        1.0
  19004.                         CH = hours       AL = FFH
  19005.                         CL = minutes     If no error:
  19006.                         DH = seconds     AL = 00H
  19007.    Date/Time        Fun        Register                   DOS
  19008.    Functions        hex Input            Output           Ver Notes
  19009.    ──────────────────────────────────────────────────────────────────────────
  19010.                        DH = seconds     AL = 00H
  19011.                         DL = 100ths
  19012.                         of seconds
  19013.  
  19014.  
  19015.  
  19016. ╓┌─┌────────────────┌───┌────────────────┌────────────────┌───┌──────────────╖
  19017.    Miscellaneous    Fun        Register                   DOS
  19018.    Functions        hex Input            Output           Ver Notes
  19019.    ──────────────────────────────────────────────────────────────────────────
  19020.    Set interrupt    25H AH = 25H                          1.0
  19021.    vector.              AL = interrupt
  19022.                         number
  19023.                         DS:DX =
  19024.                         segmented
  19025.                         address for
  19026.                         specified
  19027.                         interrupt vector
  19028.    Miscellaneous    Fun        Register                   DOS
  19029.    Functions        hex Input            Output           Ver Notes
  19030.    ──────────────────────────────────────────────────────────────────────────
  19031.                        interrupt vector
  19032.    ──────────────────────────────────────────────────────────────────────────
  19033.    Get DOS version  30H AH = 30H         AH = minor       2.0 DOS version 1.0
  19034.    number.                               version number       returns
  19035.                                          AL = major           AL = 00H. OS/2
  19036.                                          version number       com-
  19037.                                          BX, CX = serial      patibility
  19038.                                          number               box returns
  19039.                                                               AL = 0AH.
  19040.    ──────────────────────────────────────────────────────────────────────────
  19041.    Get interrupt    35H AH = 35H         ES:BX = contents 2.0
  19042.    vector.              AL = interrupt   of specified
  19043.                         number           interrupt vector
  19044.    ──────────────────────────────────────────────────────────────────────────
  19045.    Get/set country- 38H AH = 38H         If error:        2.0 Calls with
  19046.    dependent            AL = country     CF set               DX = FFFFH or
  19047.    information.         code             AX = error code      AL = FFH
  19048.                         or FFH           If no error:         are supported
  19049.    Miscellaneous    Fun        Register                   DOS
  19050.    Functions        hex Input            Output           Ver Notes
  19051.    ──────────────────────────────────────────────────────────────────────────
  19052.                        or FFH           If no error:         are supported
  19053.                         BX = country     CF clear             only in DOS
  19054.                         code             If called with       versions 3.0
  19055.                         (if AL = FFH)    DX <> FFFFH:         and later. See
  19056.                         To get country   BX = country         also function
  19057.                         information:     code                 65H.
  19058.                         DS:DX -> empty   DS:DX -> country
  19059.                         34-byte buffer   information
  19060.                         To set country
  19061.                         information:
  19062.                         DX = FFFFH
  19063.    ──────────────────────────────────────────────────────────────────────────
  19064.    IOCTL.           44H AH = 44H         If no error:     2.0 See Chapter
  19065.                         AL = subfunction CF clear             17 for
  19066.                         number           (Other registers
  19067.                         (Other registers depend on            details.
  19068.                         depend on        subfunction.)
  19069.                         subfunction.)
  19070.    Miscellaneous    Fun        Register                   DOS
  19071.    Functions        hex Input            Output           Ver Notes
  19072.    ──────────────────────────────────────────────────────────────────────────
  19073.                        subfunction.)
  19074.    ──────────────────────────────────────────────────────────────────────────
  19075.    Get extended     59H AH = 59H         AX = extended    3.0 Alters CL,
  19076.    error                BX = 00H         error code           DX, SI, DI,
  19077.    information.                          BH = error class     ES, and DS.
  19078.                                          BL = suggested       See Chapter
  19079.                                          action               17
  19080.                                          CH = location        for details.
  19081.                                          of error
  19082.    ──────────────────────────────────────────────────────────────────────────
  19083.    Network machine  5EH AH = 5EH         If error:        3.1 Use in network
  19084.    name and printer     AL = subfunction CF set               environment
  19085.    setup.               number           AX = error code      only. See
  19086.                         (Other registers If no error:         Chapter 17 for
  19087.                         depend on        CF clear             details.
  19088.                         subfunction.)    (Other registers
  19089.                                          depend on
  19090.                                          subfunction.)
  19091.    Miscellaneous    Fun        Register                   DOS
  19092.    Functions        hex Input            Output           Ver Notes
  19093.    ──────────────────────────────────────────────────────────────────────────
  19094.                                         subfunction.)
  19095.    ──────────────────────────────────────────────────────────────────────────
  19096.    Network          5FH AH = 5FH         If error:        3.1 Use in network
  19097.    redirection.         AL = subfunction CF set               environment
  19098.                         number           AX = error code      only. See
  19099.                         (Other registers If no error:         Chapter 17 for
  19100.                         depend on        CF clear             details.
  19101.                         subfunction.)    (Other registers
  19102.                                          depend on
  19103.                                          subfunction.)
  19104.    ──────────────────────────────────────────────────────────────────────────
  19105.    Get extended     65H AH = 65H         If error:        3.3 See Chapter
  19106.    country              AL = information CF set               17 for
  19107.    information.         ID code          AX = error code      details.
  19108.                         BX = code page   If no error:
  19109.                         number           CF clear
  19110.                         CX = buffer      ES:DI ->
  19111.                         length           extended country
  19112.    Miscellaneous    Fun        Register                   DOS
  19113.    Functions        hex Input            Output           Ver Notes
  19114.    ──────────────────────────────────────────────────────────────────────────
  19115.                        length           extended country
  19116.                         DX = country ID  information
  19117.                         ES:DI -> buffer
  19118.    ──────────────────────────────────────────────────────────────────────────
  19119.    Get/set global   66H AH = 66H         If error:        3.3
  19120.    code page.           To get current   CF set
  19121.                         code page:       AX = error code
  19122.                         AL = 01H         If no error:
  19123.                         To set code      CF clear
  19124.                         page:            If called with
  19125.                         AL = 02H         AL = 01H:
  19126.                         BX = code page   BX = current
  19127.                         number           code page
  19128.                                          DX = default
  19129.                                          code page
  19130.  
  19131.  
  19132.  
  19133. ╓┌─┌────────────────┌───┌────────────────┌────────────────┌───┌──────────────╖
  19134.    Memory Functions Fun        Register                   DOS
  19135.                     hex Input            Output           Ver Notes
  19136.    ──────────────────────────────────────────────────────────────────────────
  19137.    Allocate memory  48H AH = 48H         If error:        2.0
  19138.    block.               BX = size of     CF set
  19139.                         block            AX = error code
  19140.                         in paragraphs    BX = size of
  19141.                                          largest
  19142.                                          available block
  19143.                                          If no error:
  19144.                                          CF clear
  19145.                                          AX = paragraph
  19146.                                          address of
  19147.                                          allocated block
  19148.    ──────────────────────────────────────────────────────────────────────────
  19149.    Free memory      49H AH = 49H         If error:        2.0
  19150.    block.               ES = paragraph   CF set
  19151.                         address of       AX = error code
  19152.                         memory block     If no error:
  19153.                                          CF clear
  19154.    Memory Functions Fun        Register                   DOS
  19155.                     hex Input            Output           Ver Notes
  19156.    ──────────────────────────────────────────────────────────────────────────
  19157.                                         CF clear
  19158.    ──────────────────────────────────────────────────────────────────────────
  19159.    Resize memory    4AH AH = 4AH         If error:        2.0
  19160.    block.               BX = new size    CF set
  19161.                         of memory block  AX = error code
  19162.                         in paragraphs    BX = size of
  19163.                         ES = paragraph   largest
  19164.                         address of       available block
  19165.                         memory block     (if increased
  19166.                                          size was
  19167.                                          requested)
  19168.                                          If no error:
  19169.                                          CF clear
  19170.    ──────────────────────────────────────────────────────────────────────────
  19171.    Get/set memory   58H AH = 58H         If error:        3.0 See Chapter
  19172.    allocation           To get           CF set               17 for
  19173.    strategy.            allocation       AX = error code      details.
  19174.                         strategy:        If no error:
  19175.    Memory Functions Fun        Register                   DOS
  19176.                     hex Input            Output           Ver Notes
  19177.    ──────────────────────────────────────────────────────────────────────────
  19178.                        strategy:        If no error:
  19179.                         AL = 00H         CF clear
  19180.                         To set           If called with
  19181.                         allocation       AL = 00H:
  19182.                         strategy:        AX = strategy
  19183.                         AL = 01H         code
  19184.                         BX = strategy
  19185.                         code
  19186.    ──────────────────────────────────────────────────────────────────────────
  19187.  
  19188.    Figure 18-4. A summary of the DOS interrupt 21H functions.
  19189.  
  19190.  
  19191.  
  19192.  ────────────────────────────────────────────────────────────────────────────
  19193.  Chapter 19  Program Building
  19194.  
  19195.    Structure of an Executable Program
  19196.      The Memory Map
  19197.      The Use of Registers
  19198.      Memory Models
  19199.  
  19200.    Subroutine Interfaces
  19201.  
  19202.    Combining Program Modules
  19203.      Step 1: Writing the Source Code
  19204.      Step 2: Translating the Source Code
  19205.      Step 3: Linking
  19206.      Step 4: Converting File Formats
  19207.      Step 5: Creating Object Libraries
  19208.  
  19209.    Using LINK
  19210.      Linking a Self-contained Program
  19211.      Linking a Program to a Library
  19212.      Linking Object Files
  19213.  
  19214.    As we've mentioned before, the wisest approach to programming the PC
  19215.    family is to write nearly all your programs in a high-level language (such
  19216.    as BASIC, Pascal, or C) and when necessary use the DOS or ROM BIOS
  19217.    services for whatever the high-level languages don't provide. On occasion,
  19218.    you may also want to create your own assembly-language routines to perform
  19219.    specialized tasks not available through your programming language or
  19220.    system services.
  19221.  
  19222.    When creating programs within the confines of a single programming
  19223.    language, you really don't need to know anything more about a language
  19224.    than what you can find in the manuals that come with it. However, if you
  19225.    need to break out of the bounds of a single language to access DOS or ROM
  19226.    BIOS routines, or perhaps to tie into a program that's written in a
  19227.    different language, you'll need to dig deeper into the technical aspects
  19228.    of both DOS (to learn how to link programs together) and the programming
  19229.    languages (to learn the requirements for program interfaces, which let the
  19230.    different languages communicate with each other).
  19231.  
  19232.    This chapter presents some overall considerations that apply to the
  19233.    advanced use of most programming languages. We'll start by describing the
  19234.    structure of the executable programs generated by compilers and
  19235.    assemblers. Later we'll consider the details of combining separate program
  19236.    modules into a unified program.
  19237.  
  19238.  
  19239.  Structure of an Executable Program
  19240.  
  19241.    Every language translator imposes a certain structure on each executable
  19242.    program it generates. This structure is partly determined by the structure
  19243.    of the source code, but it also reflects the way the 8086 addresses
  19244.    memory.
  19245.  
  19246.  The Memory Map
  19247.  
  19248.    DOS loads an executable program by reading the contents of a .COM or .EXE
  19249.    file directly into an area of free memory. The layout of executable code
  19250.    and data in memory──the memory map──reflects the structure of the
  19251.    executable file, which in turn is primarily determined by the language
  19252.    translator you use to compile or assemble your program. Although language
  19253.    translators differ, most of them produce executable programs in which
  19254.    logically separate portions of the program are mapped in different blocks
  19255.    of memory. (See Figure 19-1.)
  19256.  
  19257.    This memory map fits comfortably into the addressing schemes that are
  19258.    natural to the 8086: The executable code is addressed through the CS
  19259.    register; the program data is accessed through the DS and ES registers;
  19260.    and the SS register points to the stack.
  19261.  
  19262.    Higher addresses ┌────────────────────────┐
  19263.                     │                        │
  19264.                     │         Stack          │
  19265.                     ├────────────────────────┤
  19266.                     │                        │
  19267.                     │   Uninitialized data   │
  19268.                     ├────────────────────────┤
  19269.                     │                        │
  19270.                     │      Program data      │
  19271.                     ├────────────────────────┤
  19272.                     │                        │
  19273.                     │    Executable code     │
  19274.                     ├────────────────────────┤
  19275.                     │ Program Segment Prefix │
  19276.     Lower addresses └────────────────────────┘
  19277.  
  19278.    Figure 19-1.  Memory usage in a typical DOS program.
  19279.  
  19280.    ──────────────────────────────────────────────────────────────────────────
  19281.    NOTE:
  19282.      This memory map is also practical because it conforms to the memory
  19283.      conventions for programs that run in a protected-mode environment like
  19284.      OS/2. In protected mode, the 80286 and 80386 require you to use
  19285.      particular segment registers to address executable code and data. When
  19286.      you write a program to run in protected mode, you must avoid storing
  19287.      data values in a code segment or branching to executable code in a data
  19288.      segment.
  19289.    ──────────────────────────────────────────────────────────────────────────
  19290.  
  19291.  The Use of Registers
  19292.  
  19293.    An executable program whose code, data, and stack are mapped to distinct
  19294.    areas of memory can make efficient use of the 8086 registers. This is
  19295.    because the 8086's segment registers can each address a different portion
  19296.    of the memory map:
  19297.  
  19298.    ■  The CS and IP registers point to the currently executing instruction.
  19299.  
  19300.    ■  The DS register is used in combination with BX, SI, or DI to access
  19301.       program data.
  19302.  
  19303.    ■  The SS register is used in combination with the SP and BP registers to
  19304.       point to data in the program's stack. The SS:SP combination points to
  19305.       the top of the stack, and SS:BP can be used to access data above or
  19306.       below the top of the stack.
  19307.  
  19308.    These aren't hard-and-fast rules for register usage. They are a natural
  19309.    consequence of the way the 8086 register set is designed.
  19310.  
  19311.  Memory Models
  19312.  
  19313.    There are various ways to produce an executable program whose memory map
  19314.    comprises separate code, data, and stack segments. The way a particular
  19315.    program addresses the different areas of its memory map is determined by
  19316.    the program's memory model.
  19317.  
  19318.    A memory model specifically describes how executable code and data are
  19319.    addressed within a program. For example, the 8086 imposes a limit of 64 KB
  19320.    in any given segment, so a program with more than 64 KB of executable code
  19321.    must be mapped into more than one executable code segment. Similarly, a
  19322.    program with more than 64 KB of data must store that data in at least two
  19323.    different data segments. Thus the simple memory model shown in Figure
  19324.    19-1 can be elaborated upon──into four different memory models. (See
  19325.    Figure 19-2.)
  19326.  
  19327.    The memory model you use affects how your program uses segment registers.
  19328.    In a small-model program, the CS and DS registers can be initialized at
  19329.    the start of a program and left undisturbed for the duration. Contrast
  19330.    this with a large-model program, where the CS register must be changed
  19331.    whenever the program branches from one code segment to another, and the DS
  19332.    or ES registers must often be updated whenever data from different
  19333.    segments must be accessed.
  19334.  
  19335.    Some high-level language compilers let you specify which memory model to
  19336.    use. (See your compiler documentation for more information.) If you know
  19337.    your program contains fewer than 64 KB of executable code and fewer than
  19338.    64 KB of data, you can explicitly request such a compiler to generate a
  19339.    small-model executable program. (This is the memory model we have used in
  19340.    all the assembly-language examples in previous chapters.) Other compilers
  19341.    can use a compact, medium, or large model, regardless of the program size.
  19342.    Whatever the case, you should know what memory model your compiler uses if
  19343.    you want to understand how the different parts of an executable program
  19344.    fit together.
  19345.  
  19346.    Model          Number of Code Segments      Number of Data Segments
  19347.    ──────────────────────────────────────────────────────────────────────────
  19348.    Small          1                            1
  19349.    Compact        1                            More than 1
  19350.    Medium         More than 1                  1
  19351.    Large          More than 1                  More than 1
  19352.    ──────────────────────────────────────────────────────────────────────────
  19353.  
  19354.    Figure 19-2.  Four common memory models.
  19355.  
  19356.  
  19357.  Subroutine Interfaces
  19358.  
  19359.    A subroutine interface is a layer of assembly-language code that lets a
  19360.    program written in a high-level language communicate with an
  19361.    assembly-language subroutine. A subroutine interface has two main parts: a
  19362.    control interface and a data interface.
  19363.  
  19364.    The control interface handles the business of calling and returning; that
  19365.    is, of passing control of the computer from the calling program to a
  19366.    subroutine and back again. The control interface, by the way, can be
  19367.    tricky to program. It is remarkably simple if you know how to program
  19368.    properly, but you can create incredible messes if you make even minor
  19369.    programming errors.
  19370.  
  19371.    The data interface lets the calling program and a subroutine share data.
  19372.    In order to share successfully, you need to know how each side of the
  19373.    interface finds and works with data, and you must understand how data is
  19374.    formatted so that each side can interpret it in the same way. We'll be
  19375.    covering these topics in more detail in the next chapter.
  19376.  
  19377.    All three program elements──the calling program, the called subroutine,
  19378.    and the interface──must accomplish the following in order to work together
  19379.    successfully:
  19380.  
  19381.    The program must be able to find its way to the subroutine. In the
  19382.    8086-based system of the standard PC family, a subroutine is called
  19383.    through a CALL instruction. There are two kinds of CALL instruction:
  19384.  
  19385.    ■  The near CALL locates a subroutine within the current 64 KB code
  19386.       segment (CS) and does not require the CS register to be changed.
  19387.  
  19388.    ■  The far CALL locates a subroutine outside the current CS using a
  19389.       complete segmented address in the CALL instruction (which changes the
  19390.       CS setting). Because it needs to access only one executable code
  19391.       segment, a small-model or compact-model program uses near CALLs to call
  19392.       subroutines. A medium-model or large-model program uses far CALLs so
  19393.       that it can change CS and access multiple code segments.
  19394.  
  19395.    The subroutine must know what to do when finished. A subroutine typically
  19396.    returns to the calling program with an instruction that corresponds to the
  19397.    way it was called (that is, with a near or far RET instruction).
  19398.    Occasionally, however, a subroutine does something unusual──for example,
  19399.    you may want to terminate a program and return to DOS from a subroutine.
  19400.  
  19401.    The subroutine must know what supporting framework is provided by the
  19402.    caller. A typical supporting framework describes how the segment registers
  19403.    are set and whether a stack is available for use. In general, the segment
  19404.    registers are exactly as they should be: CS has the right code segment, DS
  19405.    points to the location of the calling program's data, and SS and SP are
  19406.    set up with the caller's stack.
  19407.  
  19408.    The called subroutine usually can continue to use the caller's stack, but
  19409.    there is no practical way to know how much working space is available. If
  19410.    the subroutine's needs are reasonable──say, fewer than 64 bytes──the
  19411.    caller's stack space should be adequate. However, if the subroutine should
  19412.    need more working space, it can set up its own stack space in memory.
  19413.  
  19414.    If the program needs to pass information (parameters) to the subroutine,
  19415.    both the program and the subroutine must know how many parameters exist,
  19416.    where they are, and what they are. Programs and subroutines typically work
  19417.    with a fixed number of parameters, although some languages, including C,
  19418.    can handle a variable number of parameters. The parameters are usually
  19419.    passed to the subroutine through the stack, either directly or indirectly.
  19420.    The direct method, known as pass-by-value, passes the actual value of the
  19421.    parameter through the stack; the indirect method, known as
  19422.    pass-by-reference, passes the parameter's address through the stack.
  19423.  
  19424.    The parameter-passing method used depends primarily on the language; some
  19425.    languages place only addresses──never parameter values──on the stack. With
  19426.    languages that can handle both addresses and values, you have a lot more
  19427.    freedom to decide which method to use, and the method you use lets you
  19428.    control how the parameters are dealt with as they are passed from one
  19429.    program to another.
  19430.  
  19431.    For example, if you want to protect a caller's parameter from being
  19432.    changed by the called subroutine, you'll use the pass-by-value method to
  19433.    pass a copy of the parameter's value on the stack. But if you want the
  19434.    parameter's value to be changed by the called subroutine, you must use the
  19435.    pass-by-reference method so that the subroutine can change the parameter's
  19436.    value by modifying the contents of memory at the specified address.
  19437.  
  19438.    Parameter passing is the most complicated part of the subroutine
  19439.    interface, made even more complicated by the different ways programming
  19440.    languages deal with data and stack information. Because of its complexity
  19441.    and variability from one language to another, parameter passing is the
  19442.    main issue we'll discuss in our language comparisons in the next chapter.
  19443.  
  19444.    The subroutine must preserve certain information. Although requirements
  19445.    may vary in different situations, a few ground rules govern what
  19446.    information should be preserved, and what can and cannot be done when
  19447.    calling a subroutine.
  19448.  
  19449.    ■  Interrupts can be suspended briefly when segment registers are changed;
  19450.       they must be turned back on before returning. (See page 52.)
  19451.  
  19452.    ■  The contents of any CPU registers used by the calling program as well
  19453.       as the subroutine are preserved by being pushed on the stack.
  19454.  
  19455.    ■  The BP and DS registers should usually be saved and restored if they
  19456.       are changed within a subroutine.
  19457.  
  19458.    Register usage varies: One compiler may rely on the contents of ES being
  19459.    constant, and another might require you to preserve SI and DI if you use
  19460.    them in a subroutine. See your compiler manual for specific information.
  19461.  
  19462.    The stack must be cleaned up after the subroutine is finished. Four things
  19463.    might clutter the stack when a subroutine is finished: some parameters,
  19464.    the return address from the CALL instruction, register values saved from
  19465.    before the CALL, and some working storage from the subroutine.
  19466.  
  19467.    Three of these leftovers are not problems: Subroutines are expected to
  19468.    remove their own working storage from the stack, saved registers are
  19469.    removed by POP instructions, and the return address is removed by the RET
  19470.    instruction. The parameters, however, usually complicate the clean-up
  19471.    process, because the method of removal varies in different languages. Some
  19472.    languages expect the subroutine to remove the parameters by specifying in
  19473.    the RET instruction the number of bytes to remove from the stack. Other
  19474.    languages expect the caller to remove them. We'll point out these
  19475.    differences as we discuss some languages in detail in Chapter 20.
  19476.  
  19477.    With all these program design elements in mind, let's step back a bit
  19478.    farther and see how the whole process works──from creating a program or
  19479.    subroutine to combining it with others.
  19480.  
  19481.  
  19482.  Combining Program Modules
  19483.  
  19484.    In this section, we're going to describe the general process of putting a
  19485.    program together from two or more program modules. Programming languages──
  19486.    and programmers──vary in the way they perform this process, but in
  19487.    general, the tools you use and the sequence of operations you carry out
  19488.    are the same for most language translators. (See Figure 19-3.)
  19489.  
  19490.    ┌────────────────────────────┐
  19491.    │       Source code          │
  19492.    │                            │
  19493.    └─────────────┬──────────────┘
  19494.                  │   Language translator
  19495.    ┌───────────────────────────┐  Library manager  ┌────────────────┐
  19496.    │     Object code (.OBJ)     │─────────────────│ Object library │
  19497.    │(or other intermediate code)│                   │     (.LIB)     │
  19498.    └─────────────┬──────────────┘                   └────────────────┘
  19499.                  │   Linker
  19500.    ┌───────────────────────────┐
  19501.    │    Executable program      │
  19502.    │          (.EXE)            │
  19503.    └─────────────┬──────────────┘
  19504.                  │   EXE2BIN
  19505.    ┌───────────────────────────┐
  19506.    │    Executable program      │
  19507.    │          (.COM)            │
  19508.    └────────────────────────────┘
  19509.  
  19510.    Figure 19-3.  Building an executable program. By convention, object
  19511.    filenames use the .OBJ extension; object libraries use .LIB; executable
  19512.    files use .EXE or .COM.
  19513.  
  19514.  Step 1: Writing the Source Code
  19515.  
  19516.    To begin with, you have to write your program using the commands and
  19517.    syntax of your programming language. This form of the program is known as
  19518.    the source code. For programming languages that use the standard DOS
  19519.    conventions, the source code must be in the form of an ASCII text file.
  19520.    (See Appendix C.) Interpreted BASIC does not normally use the ASCII text
  19521.    file format for its source files, but it can. (To create ASCII text files
  19522.    with the BASIC interpreter, use the A option of the SAVE command.)
  19523.  
  19524.    By convention, source-code files have a filename extension that reflects
  19525.    the name of t