PC System Programming PDF
PC System Programming PDF
19
[il~ II.
[-1[111
~11 1111
~ mI)~
System 1I1 ~
Programming
for developers ~
Michael Tischer
Published by
AbacuslliliiiiiUiil
This book is copyrighted. No part of this book may be reproduced, stored in a retrieval
system, or transmitted in any form or by any means, electronic, mechanical, photocopying,
recording or otherwise, without the prior written permission of Abacus or Data Becker,
GmbH.
Every effort has been made to ensure complete and accurate information concerning the
material presented in this book. However, Abacus can neither guarantee nor be held legally
responsible for any mistakes in printing or faulty instructions contained in this book. The
authors always appreciate receiving notice of any errors or misprints.
This book contains trade names and trademarks of many companies and products. Any
mention of these names or trademarks in this book are not intended to either convey
endorsement or other associations with this book.
PC-DOS, IBM PC, XT, AT, PS/2, OS/2 and PC-BASIC are trademarks or registered
trademarks of International Business Machines Corporation. Ventura Publisher is a
trademark or registered trademark of Xerox Corporation. GEM and CP/M are trademarks or
registered trademarks of Digital Research Corporation. Microsoft Works, Microsoft Quick
C, Microsoft Windows, MS-DOS, XENIX and GW-BASIC are trademarks or registered
trademarks of Microsoft Corporation. Lotus 1-2-3 is a trademark or registered trademark of
Lotus Development Corporation. dBASE is a registered trademark of Ashton-Tate, Inc.
Sidekick, Turbo C and Turbo Pascal are trademarks or registered trademarks of Borland
International. UNIX is a registered trademark of Bell Laboratories. Mickey Mouse is a
registered trademark of Walt Disney Corporation.
Library of congress Cataloging-in-publication Oata
Tischer, Michael, 1953
PC system programming for d'evelopers I Michael Tischer.
p. ClI.
"A Data Becker book ,'I
1. System programming (computer science) 2. Microcomputers-programming. I. Title
QA76.66.T57 1989 DDS.26S--dc20 85-183S0
ii
Table of Contents
1. Introduction ............................................................................................ 1
iii
Table of Contents PC System Programming
7.8 Accessing the Hard Disk from the BIOS .................................................... 323
7.9 Accessing the Serial Port from the BIOS ................................................... 330
7.11 Accessing the Keyboard from the BIOS ............................. ~ ....................... 358
iv
Abacus Table of Contents
7.13 Reading the Date and Time from the BIOS ................................................. 395
10.7 Accessing Video RAM from High Level Languages .................................... 554
H. Glossary of Terms.................................................................................903
v
Chapter 1
Introduction
A few years ago, my computer was a small home computer. When I became
interested in the IBM PC, I had to learn a lot of new things. I learned about MS
DOS and became familiar with 8088 assembly language. I soon reached a point
where I started developing commercial PC programs in partnership with my friend
Axel Sellemerten. All of this happened some time ago, but I still clearly
remember sitting at my desk, looking through dozens of PC books and technical
manuals, trying to find a critical piece of information.
These books and manuals were expensive and hard to find. Besides, none of them
covered all aspects of the PC. Some books tell you about PC hardware m: the
BIOS QI DOS. I could never find a book that dealt with the PC as a total system.
No single book was able to provide me with a complete system overview.
This book is the result of my experience with all of these references. The three
main areas of the PC (hardware, the BIOS and DOS) are combined in this book
from a software developer's point of view. This book was written to serve as an
instruction book as well as a reference manual. It is not, and was never intended to
be, a book for the beginner. The book assumes that you're familiar with MS-DOS
and are able to program in one of the four most popular PC programming
languages (machine language, BASIC, Pascal or C).
Organization
The book is divided into five parts. Part 1 (Chapters 1-5) gives an introduction to
the PC's internal components. Part 2 (Chapter 6) describes the Disk Operating
System (DOS) and Part 3 (Chapter 7) describes the Basic Input Output System
(BIOS). PC hardware that is not part of the central processor is discussed in Part 4
(Chapters 8-18). Part 5 (Chapter 19) describes the interaction between these
components and the keyboard. The book concludes with a large reference section
(Appendices) containing all functions of DOS and the BIOS, among other things.
To understand the content of this book, you must first know something about the
different number systems used in computers. Readers unfamiliar with the binary
1
1. Introduction PC System Programming
BASIC, Pascal and C programmers should read Chapters 2 and 3 and should work
through the subsections in Chapter 4 devoted to your preferred language. Chapter 5
is devoted exclusively to assembly language programming and may be skipped.
2
Chapter 2
While working with the PC, many users have wondered about its ability to solve
complex problems. Users often attribute these abilities to the software or operating
system. The fact is, hardware is as important as the software.
Microprocessor
The microprocessor is the brain of the PC. It understands a limited number of
machine language instructions and processes or executes programs in this machine
language. These instructions are very simple and can't be compared to commands
in high level languages such as BASIC, Pascal or C. Commands in these
languages must be translated into a large number of machine language instructions
that the PC's microprocessor can then execute. For example, displaying text with
the BASIC PRINT statement requires the equivalent of several hundred machine
language instructions.
The PC has its own family of microprocessor chips, all designed by the Intel
Corporation. The figure on the next page describes the Intel 80xx family tree.
Your PC may contain an 8086, an 8088 (used in the PClXn, an 80186, an 80286
(used in the An or even an 80386 microprocessor. The first generation of this
group (the 8086) was developed in 1978. The successors of the 8086 were different
from the original chip. The 8088 is actually a step backward since it has the same
internal structure and instructions of the 8086, but is slower than the 8086. The
reason is that the 8086 transfers 16 bits (2 bytes) between memory and the
microprocessor at one time. The 8088 is slower since it transfers only 8 bits (1
byte) at one time.
3
2. The PC's Brain PC System Programming
Multiprocessing
The three other microprocessors of this family are improved versions of the 8086.
The 80186 offers auxiliary functions. The 80286 has additional registers and
extended addressing capabilities. The 80286's biggest advantages over its
predecessors are its multiprocessing and virtual memory capabilities.
Multiprocessing allows several programs to execute at the same time, such as
compiling a program while using a word processor. This capability, which is
based on the fast switching between the individual programs, can also be
implemented through software (e.g., Microsoft Windows®), but working directly
through the processor is more efficient.
Virtual memory
Virtual memory means that a program appears to use much more memory than is
available in the computer's RAM. Portions of the programs or data which don't fit
into memory are temporarily stored on the mass storage device (floppy or hard
disk). The computer loads these sections into RAM as needed. The CPU and the
operating system share the task of virtual memory management. Earlier versions
of MS-DOS don't support the multiprocessing or virtual memory capabilities of
the 80286, so most AT computers aren't working to their full potential.
80486
8028~
6 8~?A •
t
Relative
power
74 75 76 77 78 79 80 81 8283 84 85 86 8788 89 90
Year
4
Abacus 2. The PC's Brain
The 80386 represents current state of the art technology. It has a more extensive
instruction set than the 80286, and offers additional memory protection features.
These processors are all upwardly compatible with software. This means that
machine language programs developed for the 8086 can be executed on the other
processors of this series. On the other hand, a program written for the 80386 may
not run correctly on the 80286 or the 8088, because instructions available on the
80386 may not be available in the earlier processors.
Throughout this book the PC processor is designated as the 8088, even though
your PC may use a different processor.
5
2. The PC's Brain PC System Programming
BH I Bt
CODE SEGMENT
CS
Cif9~LC( COUNT
SS STACK SEGMENT
Dif~~LD( DATA
01 DESTINATION INDEX
Program Counter
SI SOURCE INDEX
\ INSTRUCTION
IP POINTER
SP STACK POINTER \
BP BASER POINTER
Flag Register
_OIDIIITlslz~
15 11 10 9 8 7 6 4 2 0
8088 registers
All registers are 16 bits (2 bytes) in size. If all 16 bits of a register contain a I,
this is the largest number that can be represented within 16 bits. This number is
the decimal number 65535. Therefore, a register can contain any value from 0 to
65535.
Register groupings
As shown in the above figure, registers are divided into four groups: common
registers, segment registers, the program counter and the flag register. The different
register assignments are designed to duplicate the way in which a program
processes data-which is the basic task of a microprocessor.
The disk operating system and the routines stored in ROM use the common
registers a great deal, especially the AX, BX, ex and DX registers. The contents
of these registers tell DOS what tasks it should perfonn and which data to use for
execution.
6
Abacus 2.1 8088 Registers
These registers are affected mainly by mathematical (addition, subtraction, etc.) and
input/output instructions. They are assigned a special position within the registers
of the 8088 because they can be separated into two 8-bit (I-byte) registers. Each
common register may be thought to consist of three registers: a single 16-bit
register, or two smaller 8-bit registers.
AL
bit 15 bit 0
AX register
The registers have designators of H (high) and L (low). Thus the 16-bit AX
register may be divided into an 8-bit AH and an 8-bit AL register. The H and the L
register designators occur in such a way that the L register contains the lower 8
bits (bit 0 through 7) of the X register, and the H register the higher 8 bits (bits 8
through 15) of the X register. The AH register consists of bits 8-15 and the AL
register of bits 0-7 of the AX register. However, the three registers cannot be
considered independent of each other. For example, if bit 3 of the AH register is
changed, then the value of bit 11 of the AX register also changes automatically.
The values change in both the AH and the AX registers. The value of the AL
register remains constant since it is made of bits 0-7 of the AX register (bit 11 of
the AX register does not belong to it). This connection between the AX, the AH
and the AL register is also valid for all other common registers and can be
expressed mathematically.
You can determine the value of the X register from the values of the H and the L
registers, and vice versa. To calculate the value of the X register, multiply the
value of the H register by 256 and add the value of the L register.
Example: The value of the CH register is 10, the value of the CL register is
118. The value of the CX register results from CH*256+CL, which
is 10*256+ 118 = 2678.
Specifying register CH or CL, you can read or write an 8-bit data item from or to
any memory location. Specifying register CX, you can read or write a 16-bit data
item from or to a memory location.
7
2. The PC's Brain PC System Programming
Address register
The number of memory locations which a processor can access depends on the
width of the address register. Since every memory location is accessed by
specifying a unique number or address, the maximum value contained in the
address register determines the address space. Earlier microprocessors used a 16-bit
address register enabling access to addresses from 0 to 65535. This corresponds to
the 64K memory capacity of these processors.
To address one megabyte of memory the address register must be at least 20 bits
wide. At the time the 8088 was developed, it was impossible to use a 20-bit
address register, so the designers used an alternate way to achieve the 20-bit width:
the contents of two different 16-bit numbers are used to form the 20-bit address.
Segment register
One of the numbers is contained in a segment register. The 8088 has four segment
registers. The second number is contained in another register or in a memory
location. To form a 2O-bit number, the contents of the segment register are shifted
left by 4 bits (thereby multiplying the value by 16) and the second number is added
to the first
8
Abacus 22 Segment and Offset Addressing
Logical
address
1514 13 ... •.. 210 0ff
(16 bits
I I I I I I I I I I I I I I I I Iadd~:~s
Physical 191817 •..
- BIT
. .. 2 1 0
Combining the segment and offset addresses requires special notation to indicate a
memory location's address. This notation consists of the segment address in four
digit hexadecimal format, followed by a colon, and the offset address in four-digit
hexadecimal format. For example, a memory location with a segment address of
2000H and an offset address of AF3H would appear in this notation as 2000:0AF3.
Because of this notation, you can omit the H suffIx from hexadecimal numbers.
9
2. The PC's Brajn PC System Programming
::J
...
n
CI)
= 1104H
-
CI)
::J
CI)
Q.
Segment 3
CI)
3
Offset ...
o
'<
II)
Q.
...
Q.
CI)
til
Segment til
CI)
address = 1600H til
The 8088 has four segment registers, which have special roles in the execution of
an assembly language program. There are four registers to accommodate the basic
structure of any program. A program consists of a set of instructions (code). There
are also variables and data items that are processed by the program. A structured
program keeps the code and data separate from each other while they reside in
memory. Assigning code and data their own segments conveniently separates
them.
Each needs a segment address and a segment register. The CS (Code Segment)
register uses the IP (Instruction Pointer) register as the offset address. The CS then
determines the address at which the next assembly language instruction is located.
The IP is also called the Program Counter. When the processor executes the
current instruction, the IP register is automatically incremented to point to the
next assembly language instruction. This ensures the execution of instructions in
the correct order.
Like the CS register, the DS (Data Segment) register contains the segment address
of the data which the program accesses (writing or reading data to or from
10
Abacus 22 Segment and Offset Addressing
memory). The offset address is added to the content of the DS register and may be
contained in another register or may be contained as part of the current instruction.
The SS (Stack Segment) register specifies the starting address of the stack. The
stack acts as temporary storage space by some assembly language programs. It
allows fast storage and retrieval of data for various instructions. For example,
when the CALL instruction is executed, the processor places the return address on
the stack. The SS register and either the SP or BP registers form the address that is
pushed onto the stack.
The last segment register is the ES (Extra Segment) register. It is used by some
assembly language instructions to address more than 64K of data or to transfer data
between two different segments of memory.
CS:OOOO
SS:FFFF
SS:FFFF
SS:OOOO DS:FFFF
DS:FFFF SS:oooo
DS:OOOO
DS:OOOO
Non-overlapplng Overlapping
segments segments
As the figure above shows, two segment registers can specify areas of memory
which overlap, or are completely different from one another. In many cases, a
program doesn't require a full 64K segment for storing code or data. You can
conserve memory by overlapping the segments. For example, you can store data
immediately following the program code by setting the DS and CS registers
accordingly.
11
2. The PC's Brain PC System Programming
The flag register is of special importance. Various bits in this register indicate or
signal the special conditions which may occur during execution of an assembly
language instruction. For example, if an arithmetic operation results in a negative
number, the processor sets the S (sign) flag to 1 to indicate this change.
The C (carry) flag is set to 1 if the sum of two 8-bit numbers cannot be
represented as an 8-bit number.
As the figure above shows, the processor doesn't use all 16 bits of this register.
The unused bits normally contain the value O.
This ends our short trip into the PC's brain. If you didn't quite follow some of
these concepts, the sample application programs in the sections on the BIOS and
DOS functions should help you understand.
12
Abacus 2.3 The CPU Support Chips
These support chips communicate with and control external peripherals such as a
disk drive or the screen display.
Some of these support chips can be programmed using the assembly language
instructions IN and OUT. Since the programming of most support chips is very
complex, we recommend that you leave this up to DOS, unless you have a
complete understanding of the structure and operation of these chips.
The following sections define the most important support chips in the PC.
This chip gets its name from the acronym DMA which stands for Direct Memory
Access. This chip can directly write data to or read data from RAM. The DMA
controller performs disk input/output operations, moving data from RAM to disk
or from disk to RAM. This relieves the processor of this task and accelerates
program execution.
Interrupts are signals from individual components of the system to get the CPU's
attention and to initiate certain tasks. Several interrupts or requests for services
from different system components can be outstanding at one time. These requests
are initially handled by the interrupt controller, which passes them on to the CPU.
It assigns priority to every interrupt request according to its source and passes the
request with the highest priority to the CPU. The interrupt controller in the
PC/XT can process up to 8 interrupt requests at the same time. ATs require more
power, so they use two interconnected interrupt controllers which can process up
to 15 interrupt requests simultaneously.
This chip provides a link between the CPU and the peripherals such as the
keyboard or an audio speaker. However, it only operates as a mediator, addressed by
the CPU for unit access and transmission of certain signals. You cannot bypass
the PPI for direct communication between the CPU and peripherals.
13
2. The PC's Brain PC System Programming
2 .3 . 4 The Clock
If the microprocessor is the brain of the computer, then the clock could be
considered the heart of the computer. This heart beats several million times a
second (about 14.3 megaHertz) and paces the microprocessor and the other chips in
the system. Since almost none of the chips operate at such high frequencies, each
support chip modifies the clock frequency to its own requirements.
The timer chip can be used as a counter and timekeeper. This chip transmits
constant electrical pulses from one of its output pins. The frequency of these
pulses can be programmed as needed, and each output pin can have its own
frequency. Each output pin leads to another component. One line goes to the audio
speaker and another to the interrupt controller. The line to the interrupt controller
triggers interrupt 8 at every pulse, which advances the timer count.
Unlike the chips discussed up until now, the CRT (Cathode Ray Tube) controller
is separate from the main circuit board of the PC. You'll find this chip on the
video board which is mounted in one of the computer's expansion slots. Even
though there are many boards that differ widely in their capabilities (monochrome
display, color display, etc.), all video boards are based on the 6845 CRT controller.
It produces a display on the monitor connected to the computer. The controller has
several internal registers which control the output of the display.
The 8088, 80286 and the 80386 are not capable of performing floating point
arithmetic operations directly. There is a socket on the main circuit board of the
PC for adding a special math coprocessor. The PC/XT uses the 8087, the AT the
80287 and the new 80386 uses the 80387 coprocessor.
While floating point arithmetic can be performed using software routines, a math
coprocessor is up to 100 times faster. The 8087 and the 80287 can perform basic
14
Abacus 23 The CPU Support Chips
15
2. The PC's Brain PC System Programming
The support chips communicate with memory using a bus or path over which the
electronic signals travel.
Address bus
The address bus carries the number of the memory location to be accessed. The
signals on the bus represent a binary number whose value indicates the memory
location for access. Since only those memory locations represented on the address
bus can be accessed, the number which make up the bus lines determine the
number of addressable memory locations .
. The PC/XT has a 20-bit address bus and can address a maximum of 2'}J) (about 1
million) different memory locations. The AT has a 24-bit address bus and can
address more than 16 million memory locations.
Data bus
Once the bus knows the address of the memory location to be accessed, data can be
transferred between the individual chips and the memory location over the data bus.
The number of lines in this circuit determine how many bits are transferred to or
from memory simultaneously.
The PC/XT has 8 lines so it can transfer one byte at a time. However, since the
8088 is a 16-bit processor, 16-bit data must often be transferred. There aren't
enough lines to transfer 16-bit data, so the system divides a 16-bit data item into
two 8-bit numbers. These two 8-bit data bytes are transferred one after the other
along the bus.
The 8086 and 80286 processors can transfer 16 bits simultaneously over their 16
bit-wide data buses. This is one reason why the AT executes programs faster than
the 8088 processor. The 80386 processor can transfer 32 bits at a time.
Word storage
All members of the Intel 80xx processor family share the same method of storing
words (16-bit data) in memory. The lower numbered memory location contains
bits 0-7 (the low byte) and the higher numbered memory location contains bits 8
15 (the high byte). For example, if you store the word 3F87H starting at address
0000:0400, memory location 0000:0400 accepts the low byte 87H and memory
location 0000:0401 accepts the high byte 3FH.
16
1.) The processor doesn't care if a memory address is located in a RAM chip
or a ROM chip. The main difference between RAM and ROM lies in the
fact that you can't write or store new data into ROM (hence its name:
Read Only Memory).
J- RC ca.:r LC:tq~
RC cartr Ldoe
ac Lt~ona H JS RUM
I,; .eo RAM
1: : itio:lal ieo RAM
uo :0
1-: uo :0
,-' UO
110
0
:0
,-!
,-I
,-:
UO
UO
'n
:0
uo :0
,-; 110 :0
un :0
Memory allocation
The first 10 memory segments are reserved for the main RAM memory, limiting
maximum RAM to 640K. A computer's memory size may differ from one PC
manufacturer to another but has at least 64K installed in segment O. If you install
additional RAM, its first memory address must immediately follow the last
existing memory address, since no gaps may exist between individual RAM
memory segments. Memory segment 0 has a special role since it contains
important data and operating system routines.
Memory segment A follows the RAM memory. In this case, an EGA (Extended
Graphics Adapter) is installed. This board uses the memory for the screen display
in different graphic modes.
17
2. The PC's Brain PC System Programming
Segment F contains the actual BIOS routines, the system loader and the ROM
BASIC available on many computers.
18
Chapter 3
Introduction to Interrupts
This chapter presents a view of interrupts, which are vitally important to the
operation of the 8088 processor. An interrupt is a signal from a peripheral device
or a request from a program to perform a specific service. When an interrupt
occurs, the currently executing program is temporarily suspended and an interrupt
routine begins execution to handle the condition that caused the interrupt
Program interrupt
When a program is suspended, the processor saves the contents of the CS and IP
registers on the stack, and begins the interrupt routine. After the interrupt routine
has completed its task, it issues the IRET (Interrupt RETurn) instruction which
restores the contents of the CS and IP registers from the stack, thus resuming the
program.
The interrupt routine saves and restores contents of the other registers before
returning to the interrupted program.
19
3. Introduction to Interrupts PC System Programing
Each interrupt has an associated interrupt routine to handle the particular condition.
To organize the 256 interrupts, the starting address of the corresponding interrupt
routines are arranged in the interrupt vector table.
When an interrupt occurs, the processor automatically retrieves the starting address
of the interrupt routine from the interrupt vector table.
The starting address of each interrupt routine is specified in the table in terms of
the offset address and segment address. Both addresses are 16 bits (2 bytes) wide.
Therefore each table entry occupies 4 bytes. The tota1length of the table is 256*4
or 1024 bytes (IK).
Interrupt Purpose
0000:003FE
,...---
cs
... number:
Free
255
0000:003FC IP
~
OOOO:OOOE CS
OOOO:OOOC 3 Breakpoint
IP
OOOO:OOOA CS
0000:0008 IP
2 NMI
0000:0006 CS
1 Single-step
0000:0004 IP
0000:0002 CS
IP
o Division by 0
0000:0000
15 o
The table itself is located in memory from OH to 3FFH. Since the interrupt's
number is the same as the table entry for the corresponding interrupt routine, the
interrupt routine address for interrupt 0 is the zero table entry in locations OH-3H.
20
Abacus 3.1 The Structure of the Interrupt Vector Table
Memory locations 4H-7H contain the address for the interrupt routine for
interrupt I, etc. The last interrupt, interrupt 255, occupies the end of the table at
locations 3FCH-3FFH.
Advantages
An advantage of using the interrupt vector table is that it's easy to change an entry
in the table to the starting address of a user-written interrupt routine. This makes a
new interrupt routine available to any program which can invoke the routine
simply by executing the corresponding interrupt instruction.
The next section explains the different types of interrupts and how they are used in
the system.
21
3. Introduction to Interrupts PC System Programming
Interrupt types
Software interrupts make it possible to use many of the basic operating system
services from either the assembler (or machine language) level or from many of the
higher level languages which support interrupt processing.
A hardware device such as a disk drive or keyboard can trigger a hardware interrupt.
This is a simple and efficient mechanism for handling events which require
attention.
One example is the keyboard. When you press or release a key, interrupt 9 (the
keyboard interrupt) is signalled. The standard DOS interrupt routine responds by
placing the character value corresponding to the key that was pressed into the
22
Abacus 3.2 Interrupt Types
keyboard buffer following any value which may have been previously there. If the
keyboard buffer is full, the routine generates a short beep. As in any other
interrupt, the original program continues after the completion of the interrupt
routine.
Maskable interrupts
Non-maskable interrupts
In contrast, a non-maskable interrupt cannot be disabled by the STI instruction.
One example is interrupt 2. This interrupt indicates an error in the PC's memory.
It displays a message on the screen that one or more of the RAM chips is defective
and should be replaced.
The last interrupt type to be described is the internal hardware interrupt. The
processors on the main circuit board of the PC trigger this interrupt. One example
is interrupt 8 which is designated as a timer interrupt. The timer triggers this
interrupt at a rate of 12.8 times per second. It also disables the disk drive motor if
no disk access is in progress.
23
3. Introduction to Interrupts PC System Programming
24
Abacus 3.3 Interrupts at a Glance
General overview--interrupts
25
Chapter 4
A BASIC programmer can call an interrupt using a short assembly language pro
gram. You'll find an example of this in Section 4.1.
This chapter provides information on calling interrupts from Pascal, BASIC and
C. Each describes how interrupts can be called in the particular language and the
rules the programmer must observe. Each section concludes with a short
demonstration program.
Read through the section devoted to the language with which you feel most
comfortable. A comparison of the three sample programs could be interesting for
those of you who wish to compare the similarities and differences in the three
languages.
The programs are only examples. Experiment as much as you want-you won't
damage your computer if you change them a little.
27
4. Using Interrupts from High Level Languages PC System Programming
GW-BASIC does not have a function for calling interrupts. However, the CALL
command can be used to execute a machine language program. You can also use
the CALL command to pass certain parameters to the called program. The called
machine language program must be located in the 64K used by GW-BASIC for
program statements and variable storage. Because of this, the interpreter must be
told to reserve part of program memory for the machine language routine.
Otherwise the program or variables may overwrite the machine language routine,
causing a system crash. You can reserve memory directly when you call BASIC
from the operating system. Enter the name GWBASIC followed by the 1M:
parameter. After the colon, enter the highest memory location you want used by
BASIC. For example, since the sample program starts at memory location 60000,
start the GW-BASIC interpreter as follows:
gwbasic /m:60000
This reserves the required memory space. Now you can place the machine language
routine into memory by making it part of the current BASIC program and loading
it into memory using a suitable subroutine. The current BASIC program must
contain the following commands:
60000
60010
60020
•• initialize the routine for the interrupt call .
.***************.****************** •• *******.******.*.**********1
'
,* ____________________________________________________----_____ *1
60030 '. Input: none
60040 '. Output: IA is the Start address of the Interrupt routine *,
60050 1.********************************.*.*.******.****.*************'
60060 '
60070 IA=60000! 'Start address of the routine in the BASIC segment
60080 DEF SEG 'set BASIC segment
60090 RESTORE 60130
60100 FOR 1% = 0 TO 160 : READ X% : POKE IA+I%,X% : NEXT 'poke Routine
60110 RETURN 'back to caller
60120 '
60130 DATA B5, 139, 236, 30, 6,139, llB, 30,139, 4,232,140, 0,139, llB
60140 DATA 12,139, 60,139,118, 8,139, 4, 61,255,255,117, 2,140,216
60150 DATA 142,192,139,118, 28,138, 36,139,118, 26,138, 4,139,118, 24
60160 DATA 138, 60,139,118, 22,138, 28,139,118, 20,138, 44,139,118, 18
60170 DATA 138, 12,139,118, 16,138, 52,139,118, 14,138, 20,139,118, 10
60180 DATA 139, 52, 85,205, 33, 93, 86,156,139,118, 12,137, 60,139,118
60190 DATA 28,136, 36,139,118, 26,136, 4,139,118, 24,136, 60,139,118
60200 DATA 22,136, 28,139,118, 20,136, 44,139,118, 18,136, 12,139,118
60210 DATA 16,136, 52,139,118, 14,136, 20,139,118, 8,140,192,137, 4
60220 DATA 88,139,118, 6,137, 4, 88,139,118, 10,137, 4, 7, 31, 93
60230 DATA 202, 26, 0, 91, 46,136, 71, 66,233,108,255
The DATA statements contain the machine language routine which performs the
interrupt call. The routine is READ and then POKEd into memory. To start this
routine at another memory location, change the value in line 60070. Remember
28
Abacus 4.1 Inlerrupt Calls from BASIC
that the parameters used to start GW-BASIC must also be changed so that the
routine cannot be overwritten by the variables of the program.
To use the machine language routine to call an interrupt, this subroutine must of
course be called frrst. The frrst line of the user program should therefore be:
100 GOSUB 60000
The actual program which calls the interrupt function during its execution can be
stored between line numbers 100 and 60000. The following program line
demonstrates how this can be done:
200 CALL IA(INTNRt,AHt,ALt,BHt,BLt,CH',CL\,DH\,DLt,Dlt,SI\,ES\,FLAGSt)
The variables within parentheses are the variables passed to the assembly language
program. All variables must pass true integer variables and not constants. The
variable names mentioned above may be changed but their order must remain
unchanged. Within your program they can have other names.
The frrst variable in this example, called INTNR%, is the number of the interrupt
you want to call. Be careful to specify the exact interrupt number. Also, avoid
passing a variable which has not been initialized. Otherwise, you may call the
wrong interrupt, which could lead to a system crash. The variables following
INTNR % are copied into the processor registers of the same names. If a register is
not used by an interrupt routine, you can pass any integer variable in the
corresponding register variable. The value of the ES register is treated differently. If
the value of ES% is -1, the contents of the DS register is copied to the ES
register.
Following the completion of the interrupt call, the values are returned in the
designated register variables.
This technique works only with half registers (AH, AL, BH ... ). It may be
necessary to transform these half registers into a whole register. This can be done
as follows:
300 AX' - AH' * 256 + AL\
On the other hand, a whole register can be split into two half registers with the
following commands:
410 AHt - INT (AXt / 256)
420 AL\ - AX' AND 255
After calling interrupt functions, the carry flag in the flag register indicates if the
called functions were executed correctly. In a BASIC program, it may be necessary
to test the carry or zero flags. Since the content of the flag register is in the
variable FLAGS% after the interrupt call, the status of individual flags can be
inspected through this variable. This is possible with the following program
statements:
29
4. Using Interrupts from High Level Languages PC System Programming
Another problem with interrupt calling is passing variable addresses (e.g., character
string output). BASIC stores this set of characters as a string. To determine the
offset address of such a string (the segment address of all variables is constant), use
the VARPTR function. The LO and ill byte of the offset address can be determined
with the following two program lines:
300 LO=PEEK (VARPTR (STRING NAME) +1) 'LQ-Byte of the Offset address
310 HI=PEEK(VARPTR(STRING=NAME) +2) 'HI-Byte of the Offset address
Garbage collection
Remember to include an end marker ("$" or a CHR$(O» at the end of the string
(BIOS and DOS functions expect one of these).
Note: Before copying this subroutine and trying it, we have a small
suggestion. During your first attempts something will probably go
wrong. This is perfectly normal, and you can even expect the
computer to crash a couple of times. Save programs
frequently...especially ~ running the program. This way, you
won't have to type in the program again from the beginning.
Here is a short sample program which uses the subroutine described above to
display text on the screen with function 9 of interrupt 21H.
100 ,**** ••• **********.***********************************************,
110 '. I N T DOS B
120 '*---------------------------------------------------------------*,
130 '. Assignment outputs as an example of an Interrupt
140 '. a String through a DOS function on
.
150 the display screen
160 Author MICHAEL TISCHER
170 '. developed 07/30/87 ,
180 last Update 04/08/89
190 •••••••••••••••••••••••••••••••••••••••••••••••••••••• ************'
200 '
210 CLS : KEY OFF
220 PRINT"NOTE: This program can only be started if the GWBASIC was "
230 PRINT"started from the DOS level with the command"
235 PRINT"<GWBASIC /m:60000>."
240 PRINT: PRINT"If this is not the case, please input <s> for Stop."
250 PRINT"otherwise press any key ... ";
260 A$ - INKEY$ : IF A$ = "s" THEN END
270 IF A$ = "" THEN 260
280 PRINT
290 GOSUB 60000 'install function for interrupt call
30
Abacus 4.1 In.terrupt Calls from BASIC
How it works
The program is composed of separate parts. Lines 210-290 call the subroutine to
initialize the machine language function for the interrupt call. Then the individual
variables for the interrupt call are loaded. T$ accepts the string to be output.
CHR$(13) and CHR$(lO) print a blank line before the output of the actual text
This text ends with the "$" character because the 005 function which outputs the
string expects this character as an end marker (it will not display this character).
INR% and FKT% contain the interrupt number and the function number to be
called. Besides these two variables, the variables OFSLO% and OFSHI% contain
the offset address of 1'$.
The CALL command (line 350) calls the interrupt. The first variable passed is
INR% with the number of the interrupt to be called. Then follows FKT%, which
transfers to the AH register before the interrupt call and informs interrupt 21H of
the function number to be called. Several Z% variables follow. These act as
dummy variables for all registers which have no special significance to the
function which is called. The content of Z% is unimportant. The content of the
register into which it is copied is irrelevant for the called function. After the Z%
variables, which determine the contents of the AL, BH, BL, CH and CL registers,
follow the variables OFSHI% and OFSLO%, which set the offset address of the
string in the DX register. The remaining register contents are unimportant for the
function call and are fIlled with Z%.
31
4. Using Interrupts from High Level Languages PC System Programming
To permit the DOS function which is called to output the text, its offset and
segment address must be known. This address is expected in the DS register and
wHI be set automatically by GW-BASIC.
To conclude this section, here is the listing of the assembler program that we just
used to call an interrupt.
:***********************************************************************
;* BASINT.ASM: This routine offers the capability of
;* calling any interrupt from BASICA or
;* GWBASIC
;*
;**-------------------------------------------------------------------**
:* Call: *
;* CALL ADR(INTNR%,AH%,AL%,BH%, BL%,CH%,CLl,OH%,OL%,OI%, SI%,ES%,FLAGS%) *
:**-------------------------------------------------------------------**
;* On passing control to the machine language program BASIC
;* deposits the variables on the following positions of the stack
;* INTNR% SP+30 AH% SP+28 ALl SP+26 BH% SP+24
;* BLl SP+22 CH% SP+20 CLl - SP+l8 OH% SP+l6
;* OLl SP+l4 OH SP+l2 SH SP+lO ES% SP+8
;* FLAGS% SP+6
i**-------------------------------------------------------------------**
;* for ES the value -1 is passed, then ES is set to OS
i***************************************************** *************** •• !
code segment
assume cs:code,ds:code,es:code,ss:code
32
Abacus 4.1 Interrupt Calls from BASIC
push si ;Store SI
basint endp
i---------------------------------------------------------------------
set intnr proc near ;stores the interrupt number
pop bx
jmp ad 1 -
;---------------------------------------------------------------------
code ends
end
33
4. Using Interrupts from High Level Languages PC System Programmi.ng
Some brief notes on this program follow for those not familiar with the calling
and linking of assembly language programs in GW-BASIC: The program ftrst
pushes the base pointer on the stack since it will be reset by the next instruction.
During re-entry into GW-BASIC, the base pointer must have the value it had
during the call of the routine. Then the base pointer is set to the value of the stack
pointer for access to data on the stack. This is necessary for GW-BASIC to pass
the BASIC variables named in the CALL command to the stack. In the next step,
the DS and the ES registers are stored on the stack, because their content may
change during execution of the routine and must be preserved for return to GW
BASIC.
Now the routine can read in the variables and set the various processor registers. It
is important to note that the stack does not contain variable contents, but their
addresses relative to the DS register. Because of this, the address of the variable
must be loaded fIrst and then the relative value of this address.
Which addresses contain the addresses of the individual variables stored on the stack
can be determined from the header of the assembly language routine. First you
must determine the number of the interrupt to be called. This value must be treated
in a different manner than the other variables on the stack because it isn't passed in
one of the processor registers, but is a part of the INT instruction which calls the
interrupt. It is indicated as a byte following the code of the !NT instruction (CDH).
To set the interrupt number, the number to be passed must be stored following the
CDH code of the !NT instruction. This creates a small problem since this routine
can be POKEd by the BASIC program into any memory location. Because of this,
the address of the INT instruction depends on the current starting address of the
routine instead of remaining constant. The routine doesn't know where the !NT
instruction is located.
A small trick can be used to help here. The routine does not know where it is
stored, but the processor knows the location of the !NT instruction (it has to
know, otherwise it couldn't execute the routine). The subroutine SET_INTR is
called after the interrupt number is loaded into the AX. register. The processor, as
in any CALL instruction, stores the address where the program execution is to
continue on the stack, before calling any subroutine. This is the instruction which
precedes the label AD_I.
Subroutine SET_INTR gets the address of AD_I from the stack. While the address
of the INT instruction is still not known, the distance between AD_I and the !NT
instruction remain constant, the address of the INT instruction can be calculated
and the interrupt number can be stored following the instruction. The task ends and
the routine returns to the main program (to the label AD_I).
The rest of the routine consists of repeating instructions which determine the
contents of the different variables and pass them to the corresponding processor
34
Abacus 4.1 1111errupt Calls from BASIC
registers. The value for the ES register is given a special test: if it is equal to -I,
the value of the DS register is copied to the ES register.
After all registers are loaded, the interrupt is called and the contents of the
processor registers are transferred back to the corresponding BASIC variables. The
last step is to restore the contents of all registers which had been saved on the
stack. Finally control returns to GW-BASIC.
3S
INTR
Turbo Pascal uses the INTR procedure. Since this parameter can accept any value
between 0 and 255, all available interrupts can be called.
MSDOS
The InterruptNumber parameter needed by Turbo Pascal Version 3.0 isn't required
in this procedure since it always calls interrupt 21H, through which almost all
operating system functions can be called.
In both procedures, the parameter register is a record type which holds the contents
of the registers to be passed. These are copied into the registers before the interrupt
call.
The DOS unit contains the parameters for the type called Registers:
type Registers = record
case integer of
o : (AX, BX, CX, DX, BP, sr, D1, DS, ES, Flags: word);
1 : (AL, All, BL, BH, CL, CH, DL, DH : byte);
end;
Once the DOS unit has been included in a Turbo Pascal source code, the var
statement can be used to define the register variables under the name Regs:
var Regs : Registers;
Now Turbo Pascal can easily communicate with the following processor registers:
Regs.ax,
Regs.bx,
Regs .ex,
Regs.ah, etc.
You then pass the values to the registers through standard assignments. For
example:
Register.ax := 254;
36
Abacus 4.2 Interrupt Calls from Turbo Pascal
Unfortunately, the contents of the half registers AH, AL, BL, etc. can't be defined
this way. In this case, a trick can be used by defining the half registers as normal
integer or byte variables and then merging them together into a whole register.
In this statement, the AX register is assigned value composed of the sum of the
AH register multiplied by 256 (shifting a variable left by 8 places is equivalent to
multiplying it by 256) and the AL register.
begin
WholeRegister :- 10 + Hi shl 8;
end;
Before calling the interrupt, you must first specify the interrupt value in the
register. The contents of all other registers are unimportant here. If the called
interrupt returns values to the calling program through registers, they can be
examined by looking at the individual components of the variable register.
Sometimes individual flags pass information from the interrupt to the calling
program. In most cases, the Carry flag serves this purpose. If an error occurs
during the execution of an interrupt, the flag is set.
To test for a set flag, the following Pascal statements are used. They return lRUE
or FALSE as a result depending on whether the corresponding flag was set or not.
carry flag: (register. flags and 1)
zero flag: (register. flags and 64)
sign flag: (register. flags and 128)
Turbo Pascal uses a different format than DOS and BIOS for string storage,
especially for text buffers (mostly variables of type string).
37
4. Using Interrupts from High Level Languages PC Systtfm Programming
TURBO PASCAL
1 DOS
"$"
To convert a Turbo Pascal string into DOS or BIOS format, an end character
(ASCII code 0) or the dollar sign "$" (ASCII code 36) is appended. Which of these
two characters you should use for indicating the end of the string is described
during the discussions of individual interrupts. Regardless of which format you
use, the characters appear as in either of the following commands:
string := string+iO;
string := string+i36;
The address returned by the Ofs function ~ 1 must be passed to the interrupt,
otherwise the byte which indicates the length of the string is accepted by the
interrupt as its ftrst character.
Here is the sample program. Just like the example in Section 4.1, it displays text
on the screen using function 9 of interrupt 21H:
{******.**********************.****************************************}
{* INTDOS *1
{*-----------------------------~--------------------------------------*1
{*----------------------------------,----------------------------------* 1
{* developed : 07/30/87 *1
program INTDOSP;
38
Abacus 42 Interrupt Calls from Turbo Pascal
Uses Dos;
begin
The variable TEXT contains the text to be displayed. The sequence "#13#10"
places the ASCII code 13, followed by ASCII code 10, at the beginning and the
end of the text, creating a blank line before and after the text. The last character is
the "$" character which indicates the last character of text to DOS.
The number of the function being called (9) is copied to the AH register. Since
Turbo Pascal doesn't allow access to the AH register alone, the entire AX register
must be addressed. The value 0 is loaded into the AL register, but any other value
could be entered into this register since its content has no significance to the called
function. As a last step, before calling interrupt 21H using the MSDOS procedure,
the segment address of the string is placed in the DS register and the offset address
in the DX register.
39
4. Using Interrupts from High Level LangUQges PC System Programming
The C language is the language of choice for most developers. Since it was
originally designed for operating system development, C has provisions to include
machine language routines, which is a benefit within the scope of this book.
The standard libraries of both the Microsoft C and Borland Turbo C compilers have
a number of functions for calling interrupts.
int86x
intdos
intdosx
seqread
All functions and applicable data structures are declared in the OOS.R library me.
A program which wants to access one of these functions must therefore link the
me to the current program using the #include preprocessor command
The BYTEREGS and the WOROREGS structures are joined in the union REGS
which lets the programmer work selectively with either half or whole registers.
Using a variable of the type REGS (called register here for simplicity's sake) gives
us the following:
union REGS register;
AH: register.h.ah
AL: register.h.al
The carry flag is represented by the variable register.x.cflag. If this variable is equal
to 0, the carry flag remains unset. Any other value sets the carry flag.
40
Abacus 43 Interrupt Calls from C
The functions starting with the characters int all serve to call interrupts. The
SEGREAD function reads the current contents of the segment register.
The functions that call interrupts use different register variables for input to the
interrupt routine, and output from the interrupt routine. There is an advantage to
this method over returning information to the same register variable in that the
input information is not overwritten.
Since the individual functions pass only the address of the variable representing the
register and not the variable itself, it is possible to combine the input and output
registers into a single variable. In this case, the address of one variable is provided
for the variable representing the input and the output registers (this method is used
in the sample program at the end of this section).
Before calling the interrupt, the contents of the input variable are copied to the
corresponding processor registers. Following the interrupt call their contents
become the output variables.
All interrupt functions return the content of the AX register as a result code after
the interrupt call.
int86
int86x
The int86x function differs from the int86 function in that it requires an additional
argument of the SREGS type. Its contents are copied into the segment register
before calling the interrupt, but are not copied back following the call to the
interrupt routine.
41
4. Using Interrupts from High Level Languages PC System Programming
The intdos and the intdosx functions differ from the two functions described above,
in that the number of the interrupt to the call is not passed. As the names suggest,
they call DOS interrupt 21H through which most DOS functions can be accessed.
intdos
Only the addresses of the input and the output variables representing the processor
registers are passed to the intdos function:
intdos(InRegister, OutRegister);
intdosx
The intdosx function, like the int86x function, has an additional parameter for the
segment register. The function call is as follows:
intdosx(InRegister, OutRegister, SegRegister);
So far you've seen how to call an interrupt from C and how to set the registers.
You also have to determine the address of a variable.
In C, you can easily determine the address of a variable. To do this, use the address
operator &, which returns the offset address of any desired variable. Use the
SEGREAD function mentioned above to determine the segment address of a
variable. The address of a variable of the SREG type is passed to the function
(using the address operator &) into which the content of the segment register can
be copied.
If, for example, the address of the variable SegRegister is passed to the function
and the variable was previously defined by the command:
union SREG SegRegister;
Then the variable SegRegister.ds contains the segment address of the variable
SegRegister, after calling the SEGREAD function.
While C supports interrupt calls with numerous functions, the library of the
Microsoft C compiler library does not have a function to return the contents of a
memory location. Since such a function could be very valuable in some programs,
the assembler program below contains the PEEKB and POKEB functions for
inclusion in programs created with the Microsoft C compiler. PEEK returns the
contents of a memory location (one byte), while the POKE function writes a one
byte value into a memory location.
Note: If you use the Borland Turbo C compiler, you won't need to use this
program since the Turbo C library already contains the PEEK,
PEEKB, POKE and POKEB functions. Because of this, linking the
assembler program into the C example programs of this book is
42
Abacus 43 Interrupt Calis from C
If you are using the Microsoft C compiler, enter the following program with a text
editor and save it under the name PEPO.ASM. It can then be assembled with:
masm pepo;
BSS segment word public 'sss' ;this segment accepts all non
BSS ends ;initialized static variables
PeekB endp
43
4. Using Interrllpts from High Level LanglUlges PC System Programming
_PokeB endp
i---------------------------------------------------------------------
text ends ;End of the program segment
The example program below uses the two functions described above. This next
program examines the model identification number or code of the PC and displays
PC type on the screen using a ooS function:
/*******.***** ••• *****.************************.***********************/
1* I N T DOS *I
1*--------------------------------------------------------------------*/
1* Task an example of an interrupt call, outputs *1
1* a string through a DOS function on *I
1* the display screen *I
1*--------------------------------------------------------------------*1
1* Author MICHAEL TISCHER *I
1* developed : 08/30/87 *1
1* last update : 04/08/89 */
/*--------------------------------------------------------------------*/
1* (MICROSOFT C) */
1* Creation MSC INTDOSC *1
/* LINK INTDOSC PEPO; *1
1* Call INTDOSC *1
1*--------------------------------------------------------------------*1
1* (BCRIJ\ND TURBC C v2.0) *1
1* Creation through the RUN cO!lVTland in the menu •.. or... *1
1* tcc -K intdosc *1
1* Call intdosc *1
/.**** •• ******************** ••• ******************* ••• ************.*****/
void main()
44
Abacus 43 Interrupt Calls from C
I
intdos(&Register, &Register); /* Call DOS interrupt 21H */
I
The main function defines three CHAR pointers which point to the text for each
PC type. Each of them starts and ends with an "'n" character. This creates a blank
line before and after the text itself.
In the first instruction of the main program the AH register is loaded with the
DOS function number for string output on the screen. Then the model
identification byte is read from memory location FOOO:FFFE using the PEEKB
function. Depending on the value read, the offset address of the accompanying text
is transferred to the OX register where it is expected by the interrupt 21H function.
In addition to this offset address, the function also requires the segment address of
the text in the OS register. Since the compiler automatically sets this register, you
don't have to be concerned with the segment address. The last instruction of the
program calls the INTDOS function which in turn calls interrupt 21H with the
registers which were dermed earlier.
The file header states how it can be executed: If you are using the Microsoft C
computer, then it is important that you link the file with the previously assembled
PEPO program so that the new program contains the PEEKB and POKEB
functions. These can then be called from the C program.
45
Chapter 5
Unlike programmers using any of the higher level languages, the assembly
language programmer doesn't have to rely on complicated functions or procedures
to call an interrupt. The MOV instruction loads the input parameters into the
registers provided, and the !NT instruction calls the interrupt.
Certain interrupts, or the functions hidden behind these interrupts, are called
frequently in many programs. An example of this is interrupt 21H function 9,
which displays text on the screen. You call it by placing function number 9 in the
AH register and the offset address of the text you want displayed in the DX
register. This process looks like this in assembly language:
mov ah,9 ;load function number 9
mov dx,offset Text ;load offset address of text
int 21h ;call DOS interrupt 21h
Even if you call the function very frequently, it doesn't pay to write a subroutine
for it since the address of the text to be displayed must be passed. All that remains
is to load the value 9 into the AH register and to call the interrupt. You'll fmd the
three program lines described above included for every function call in a program in
this chapter.
47
5. Using Interrupts from Assembly Language PC System Programming
The first line declares the macro name (PRINT). In this case, the macro also has
one parameter (string). The assembly language instructions follow in successive
lines until the ENDM instruction terminates the macro.
int 21h
48
Abacus 5.2 A Sample Mocro
Data segment
Text db CR, LF, "This is how MACROS are used", CR, LF, TEND
Data ends
dw 64 dup (7)
stack ends
rnov ds,ax
49
5. Using Inlerrupts from Assembly Language PC System Programming
Program ends
end Start ;beqin with START
After you enter the source program, it can be assembled, linked and executed as
indicated in the header.
Most of the lines in this listing have nothing to do with the actual program but
are definitions and declarations for the assembler.
The macro and constants are defmed in the fIrst part of the program, which helps to
make the listing more understandable to the reader. The definition of the data
segment follows, where the string to be displayed is stored as a character string. It
is preceded and followed by a carriage return and a linefeed to display a blank line
before and after the actual text. The text ends with the character "$" (the DOS
function used for text display always looks for this as the last character in a
string).
Following the data segment is the stack segment, which controls the stack during
program execution. Since the program is not very large, the stack can be fairly
small. The last segment is the code segment which contains the program
instructions. It consists of only fIve commands: The first two instructions
initialize the program. They load the segment address of the data segment into the
DS register to provide access to the text in this segment Then the macro PRINT
is called, and the text is passed to it.
Note: You may fmd it useful to group together certain macros into a me or
library. When one of these macros will be used in a program, the
library may be linked or included with the assembly language code.
50
Chapter 6
The following chapter discusses the PC's operating system, which the PC loads
from floppy diskette or hard disk. It is commonly referred to as PC-DOS, MS
DOS or just DOS.
What is DOS?
Most users only know the user interface of DOS, with which you run programs,
format disks, etc. In the following sections, however, you'll view DOS from an
angle you may not have known existed.
Beneath the surface of DOS many processes takes place. DOS uses a large number
of different routines (called/unctions) to accomplish its tasks. These functions are
available to the user as well as to DOS. The main focus is on how these functions
can be used in practical applications.
The data structures which act as the connecting link between the different DOS
functions will also be examined in this chapter. These data structures make mass
storage devices such as floppy disks and a hard disk possible.
Finally, this chapter discusses each DOS function in detail, and includes a brief
look at DOS Version 4.0.
51
6. The Disk Operating System PC System Programming
In April 1980 the CP/M-86 operating system announced by Digital Research for
use on the 8086 processor was unavailable. A programmer named Tim Paterson
began developing a new operating system. This system is the ancestor of the
current MS-DOS.
At this time a lot of software was available for CP/M-80 systems. The
development of new software for an 8086 operating system would have required
enormous expenses and effort. Paterson's goal was to allow easy conversion of
existing software from CP/M-80 to the new operating system. He tried to include
the functions and the most important data structures of the CP/M-80 operating
system, while removing the weak points of CP/M-80. The fmished product was an
operating system that required only 6K of memory. Programs developed for CP/M
80 could also be converted with little effort to the 8086. The new system was
named 86-DOS.
Many changes have been made to DOS since 1981. Because these changes are of
great significance to the DOS programmer, this chapter contains a segment for
each major version of DOS. Each segment lists changes from preceding versions
with explanations. Many components of DOS are explained here, which will give
you some idea of the complexity of an operating system.
Version 1.0
This version represented a compromise for Microsoft They had relied heavily on
CP/M-80 and needed to transfer existing programs quickly and easily. This can be
seen in the fact that the file names (eight-character filename, three-character
extension) was identical with CP/M-80. Also, the designation of the disk drives
and the internal structure had many similarities to the successful 8-bit operating
system.
52
Abacus 6.1 A Short History of DOS
During this time many improvements and enhancements of the hardware occurred,
such as more RAM and faster disk drives. Microsoft decided to make DOS more
hardware independent by removing the association between physical file length and
logical file length.
In CP/M-80 every disk was divided into 128-byte units which could only be
accessed as a whole. This is why you couldn't access individual bytes on the disk
(this created a programming problem that shouldn't have existed in the frrst place).
DOS solved this problem by making the logical and physical data length
independent of one another. In addition, functions were implemented to permit
reading or writing of more than one data set of a file on a disk. Treating the input
and output devices like files achieved hardware independence. These input and
output devices were assigned their own names:
If you used one of these three names instead of a filename to access a file with a
DOS routine, then the computer addressed the corresponding device and not the
disk drive. This also permitted redirecting input and output from the keyboard or
screen to a file or other device.
Before this time, DOS only supported program files which loaded and executed
from a fixed location in memory. This proved to be impractical, and so Version
1.0 introduced a new program file type. This new file type had a file extension of
.EXE instead of .COM. An .EXE file could be stored and executed from almost
any memory location.
Two changes were made to the command processor, the part of the operating
system which accepts commands from the user and controls the execution of these
commands. The first change was to store the command processor in a separate file
named COMMAND.COM. This allowed programmers to develop a customized
command processor and link it to the system.
The second change was to divide the command processor into a resident and a
transient portion. This approach was taken because early PC systems contained
only a small amount of memory. The resident portion was written to be as small
as possible. Many DOS commands were stored on disk and loaded and run only
when required, hence the name transient. Examples of transient commands are
DISKCOPY and FORMAT.
A major innovation that took MS-DOS Version 1.0 beyond CP/M-80 was the
introduction of the FAT (file allocation table) on disk. Every entry in this table
corresponds to a data area of 512 bytes (called a sector) on the disk. The FAT
indicates whether the sector is allocated to a file or is still available.
S3
6. The Disk Operating System PC System Programming
The FAT has special significance in connection with the directory entry which
exists for every file type. Besides the filename and other information, it also
indicates the number of an entry in the FAT which corresponds with the fIrst
sector of a file on the disk. This FAT entry points to another FAT entry which
indicates the next sector which was allocated to the file. The other FAT entries on
a disk perform the same task.
The introduction of batch processing offers the user the option of placing several
DOS commands into one file. When you "run" this file (which has a fIle extension
of .BA1'), DOS executes the individual commands from this fIle as if you had
entered the commands from the keyboard, thus saving the user time in entering
frequently used groups of commands repeatedly.
The current date and time follows every filename. DOS includes this data to help
the user determine the last time a file was modified.
When IBM introduced a new PC in 1982 which used both sides of a disk for data
storage, Microsoft released DOS Version 1.1.
Version 2.0
IBM announced a new personal computer in March of 1983, called the PC XT,
which in addition to the floppy disk drive also had a hard disk (also called afued
disk). The enormous capacity of this hard disk (10 megabytes) allowed the user to
store several hundred files on one unit, but created some problems for the operating
system. The largest problem was that DOS could only handle one directory for
each storage unit. It would be nearly impossible for the hard disk user to maintain
hundreds of fIles in a single directory. Microsoft had two options to solve this
problem: They could either borrow an idea from the CP/M-SO operating system, or
from the UNIX operating system.
CP/M views a hard disk as several individual disk drives which share the total
storage on the hard disk, each with only one directory.
UNIX uses a hierarchical file system, in which every storage unit has a root
directory which can contain subdirectories as well as files. Every one of these
subdirectories can have subdirectories within them. This creates a directory tree
whose trunk is the root directory and whose branches are represented by the
individual subdirectories.
Microsoft chose the hierarchical file system, which has since become a popular
component of DOS. This· was another step away from CP/M-80 toward an
efficient 16-bit operating system. With the introduction of an hierarchical fIle
system some major changes had to be made in the area of fIle control by DOS.
Before this time, fIle access was conducted through afile control block or FCB.
54
Abacus 6.1 A Short History of DOS
This file control block had been introduced for compatibility with CP/M-80. The
FCB contained important information about the name, size and location of a file
on disk. This CP/M would not allow access to a file in another directory.
The DOS developers standardized file access through DOS functions. The access to
a file occurs exclusively through the file handles. A handle is a numerical value
passed to the program as soon as it opens a file through a DOS function. The
FCBs were not eliminated, but the programmer no longer came in contact with
them since DOS took over the control block manipulation.
Version 2.0 added the option of formatting the individual tracks of a disk with nine
sectors instead of eight. This increased the storage capacity of a single-sided disk
from 160K to 180K, and the capacity of a double-sided disk from 320K to 360K.
Version 3.0
Version 3.0, like Version 2.0, was developed for a new PC, the IBM PC AT. It
was released in August of 1984 and supported the 20 megabyte hard disk of the
ATs as well as the high capacity 1.2 megabyte floppy disk drive. Many changes
occurred in DOS's internal routines. They contributed to faster execution of certain
operations, but are transparent to the programmer.
Version 4.0
DOS 4.0 appeared on the market in August 1988. Before this, Microsoft released a
new multiprocessing operating system called OS/2. Before OS/2, multiprocessing
was unknown to MS-DOS.
The user can easily seethe changes to DOS 4.0 over earlier versions of DOS. In
place of the line-Oriented command line interpreter used by DOS versions 3.3 and
earlier, DOS 4.0 has a Shell allowing user-defined menus, easy selection of
applications, files and directories from both mouse and keyboard.
Most important are the unseen changes made to DOS, particularly in adapting the
operating system to the new hardware standards on the market. As the operating
system has grown in power, it has also grown in complexity and memory use. For
example, earlier versions of DOS were limited to "only" 640K of RAM and a 32
megabyte hard disk. However, DOS 4.0 handles the Expanded Memory System
(EMS) following the LIM standard, normal RAM capacity of up to 8 megabytes,
and hard disks up to 2 gigabytes (2048 megabytes) capacity.
55
6. The Disk Operating System PC System Programming
DOS-BIOS
Do not confuse the device drivers in this module with the installable device drivers.
The DOS-BIOS device drivers cannot be changed by the user.
DOS kernel
Command processor
Unlike the two modules described above, the command processor is contained in
the file named COMMAND. COM. It displays the "A">" or "C>" prompt on the
screen, accepts user input and controls input execution. Many users wrongly think
that the command processor is actually the operating system. In reality it is only a
special program which executes under DOS control.
S6
Abacus 6.2 Internal Structure of DOS
The transient portion contains code for displaying the (A» prompt, reading user
input from the keyboard and executing the input. The name of this module is
derived from the fact that the RAM memory where it is located is unprotected, and
can be overwritten under certain circumstances. When a program ends, control
returns to the resident portion of the command processor. It executes a checksum
program to determine whether the transient portion was overwritten by the applica
tion program. If so, the resident portion reloads the transient portion.
The initialization portion loads during the booting process and initializes DOS.
This part of the command processor will be examined in detail in the next chapter.
When its job ends, it is no longer needed and the RAM memory it occupies can be
overwritten by another program. The commands accepted by the transient portion
of the command processor can be divided into three groups: internal commands,
external commands and batch files.
Internal commands lie in the resident portion of the command processor. COPY,
RENAME and DIR are internal commands.
External commands must be loaded into memory from diskette or hard disk as
needed. FORMAT and CHKDSK are external commands.
After execution the command processor releases the memory used by these
programs. This memory can then be used for other purposes.
Batch files
A batch file is a text file containing a series of DOS commands. When a batch file
is started, a special interpreter in the transient portion of the command processor
executes the batch file commands. Execution of batch file commands is the same
as if the user entered them from the keyboard. An important batch file is the
AUTOEXEC.BAT file which executes immediately after DOS is flfSt loaded.
Like all commands of a batch file, these commands are checked for internal
commands, external commands or calls to other batch files. If the ftrst is true, the
57
6. The Disk Operating System PC System Programming
command executes immediately, since the code is already in memory (in the
transient part of the command processor). If it is an external command or another
batch file, the system searches the current directory for the command. If such a file
doesn't exist in this directory, all directories specified in the PATII command are
searched in sequence. During the search, only files with the .COM•.EXE or .BAT
extensions are examined.
Since the command processor cannot search for all three extensions at the same
time, it first searches for files with .COM extensions, then for .EXE files and
finally for .BAT files. If the search is unsuccessful, the screen displays an error
message and the system waits for new input.
58
Abacus 63 Booting DOS
First the PC checks for a disk in the floppy disk drive. If a disk exists in the
floppy disk drive, the PC checks the disk for the boot sector. If a disk is not in the
drive, the PC searches for a hard disk from which to boot DOS. If no hard disk
exists, the PC displays an error message asking the user to insert a system disk.
The ftrst sector on a bootable floppy disk or hard disk is called the boot sector. The
program in the boot sector is read into memory and executes. First it checks for
the presence of two files: IBMBIO.COM (sometimes called IO.SYS) and
IBMDOS.COM (sometimes called MSooS.SYS). A bootable floppy disk or hard
disk must contain these two files or an error message is displayed. Next these
program fIles are loaded into memory.
The program file IBMBIO.COM consists of two modules. The ftrst contains the
basic device drivers-keyboard, display and disk. The second contains the
initialization sequence for DOS. When the IBMBIO.COM program executes it
continues to initialize the system by moving the DOS kemal (loaded in the
IBMooS.COM program fIle) to the last available memory location.
The DOS kemal builds several important tables and data areas, and performs
initialization procedures for individual device drivers which were loaded with the
IBMBIO.COM program fIle.
Next, DOS searches the boot disk for a file named CONFIG.SYS. If found, the
commands contained in the me are executed. These commands add device drivers to
DOS, allocate disk buffers and file control blocks for DOS and initialize the
standard input and output devices.
Lastly the command processor COMMAND.COM (or other shell specifted in the
CONFIG.SYS fIle) is loaded and control is passed to it. The booting process ends
and the initialization routines remain as "garbage" data in memory until
overwritten by another program.
S9
This section describes the structure and functions of these last two program types.
One difference between COM and EXE program files is in the size limitation for
each type of program. A COM program cannot exceed 64K in size. An EXE
program can be as large as the memory capacity available to DOS.
In a COM program, the program code, data and stack are stored in one 64K
partition. All of the segment registers are set at the start of the program and remain
fixed for the duration of the program execution. They point to the start of the 64K
memory segment. The contents of the ES register may be changed however, since
it has no direct effect on program execution.
In an EXE program, the code, data and stack may be stored in different segments,
and depending on program size, may be distributed over severnl segments.
While a COM program file is stored on disk as an image copy of RAM memory,
an EXE program file is stored in a special format that will be described shortly.
EXEC
Both program types can be loaded and started using the DOS EXEC function. Any
user can access this, but the command processor uses it for executing external
commands. Before the EXEC function loads the program into memory, it reserves
the RAM memory to hold the program. At the beginning of this memory the
EXEC function stores a PSP (program segment prefIX) data structure. The program
is then loaded immediately following the PSP. The segment registers and the stack
are initialized and the program is given control. Later, when the program ends, the
memory is released based on the contents of the PSP.
60
Abacus 6.4 COM and EXE Programs
+OEH
+ 12H
Copy of interrupt
vector 23H
Copy of interrupt
vector 24H
(2 words)
(2 words)
1
+ 16H reserved (22 bytes)
+ 2CH Segment address of (1 word)
environment block
in command line
The PSP itself is always 256 bytes long and contains information important for
DOS and the program to be executed.
Memory location OOH of the PSP contains a DOS function call to terminate a
program. This function releases program memory and returns control to the
command processor or the calling program. Memory location OSH of the PSP
contains a DOS function call to interrupt 21H. Neither of these are used by DOS,
but are leftovers from the CP/M system.
Memory location 02H of the PSP contains the segment address to the end of the
program. Memory location OAH contains the previous contents of the program
termination interrupt vector. Memory location OEH contains the previous contents
of the <Ctrl><C> or <Ctrl><Break> interrupt vector. Memory location 12H
contains the previous contents of the critical error interrupt vector. For each of
these memory locations, the program changes one of the corresponding vectors
during execution; DOS can use the original vector in the event that it detects an
error.
Location 2CH contains the segment address of the environment block. The
environment block contains information such as the current search path and the
directory in which the COMMAND.COM command processor is located on disk.
61
6. The Disk Operating System PC System Programming
Memory locations 5CH through 6CH contain a file control block. This FCB is
not often used by DOS since it does not support hierarchical files (paths) and is
also left over from CP/M.
The string of parameters that are entered on the command line following the
program name is called the command tail. The command tail is copied to the
parameter buffer in the PSP beginning at memory location 81H and its length is
stored at memory location 80H. Any redirection parameters are eliminated from the
command tail as it is copied to the parameter buffer. The program can examine the
parameters in the parameter buffer to direct its execution.
The parameter buffer is also used by DOS as a disk transfer area (DTA) for
transmitting data between the disk drive and memory. Most OOS programs do not
use the DTA contained in the PSP because it is another leftover from CP/M.
SS:OOOO
DS:OOOO ES:OOOO
ES:OOOO DS:OOOO
PSP (256 BYTES) PSP (256 BYTES)
cs:oooo
CS:IP
Code
Code, data
and stack in (Address defined
one 64K segment by the END
CS:IP ...... command in an
assembler
SS:SP - Stack adjusts
to the direction
program)
COM program files are stored on disk as an image copy of memory. Because of
this, no further processing is required during loading. Therefore COM programs
load faster and start execution faster than EXE programs.
A COM program loads immediately following the PSP. Execution then begins at
the ftrst memory location following the PSP at offset lOOH. For this reason, a
COM program must begin with an executable instruction, even it if is only a
jump instruction to the actual start of the program.
62
Abacus 6.4 COM and EXE Programs
When control is turned over to the COM program, all segment registers point to
the beginning of the PSP. Because of this, the beginning of the COM program
(relative to the beginning of the PSP) is always at address lOOH. The stack pointer
points to the end of the 64K memory segment containing the COM program
(usually FFFEH). During every subroutine call within the COM program, the
stack is adjusted by 2 bytes in the direction towards the end of the program. The
programmer is responsible for preventing the stack from growing and overwriting
the program, which would cause it to crash.
There are several ways to end a COM program and return control to DOS or the
calling program:
If the program runs under DOS Version 1.0, it can be terminated by calling
interrupt 2lH function 0, or by calling interrupt 20H. It can also be terminated by
using the RET (RETurn) assembler instruction. When this instruction executes,
the program continues at the address which is at the top of the stack. Since the
EXEC function stored the value 0 at this location before turning control over to
the COM program, program execution continues at location CS:O (the start of the
PSP). Recall that this location contains the call for interrupt 20H which
terminates the program.
Programs that run on versions later than DOS Version 1.0, are terminated using
interrupt 2lH function 4CH. The terminating program can pass a numeric return
code to the calling program. For example, a value of 0 may indicate that the
program executed successfully, while a non-zero value indicates an error during
execution.
Next we'll talk about a few of the details that the assembly language programmer
will have to take care of in developing a COM program. Note that the high level
language programmer is usually insulated from these details by the compiler or
interpreter, so you may want to skip ahead.
A COM program is limited to a 64K size. The code and data for the program must
be contained within a single segment and addressed through NEAR procedures.
Therefore an assembly language program that is to become a COM program may
not contain any FAR procedures.
63
6. The Disk Operating System PC System Programming
Before calling a COM program, DOS reserves all available memory for the
program even though it normally uses only one 64K segment and indicates this by
setting memory location 2 in the PSP. Usually the program terminates and the
memory is made available to DOS again.
In other circumstances you may want to execute another program from this COM
program using the EXEC function. Again, since DOS thinks that memory is
unavailable, it won't allow the new program to run.
There are two approaches in doing this: release only the memory outside of the
64K COM segment or release memory outside of the 64K COM segment plus any
unused memory within the 64K COM segment. This creates more memory for
other programs, but relocates the stack outside the protected COM segment
memory, leaving it open to be overwritten by other programs. Because of this, the
stack must be relocated to the end of the code segment before releasing the
memory. The stack must have a certain limit in size (in most cases 512 bytes will
be more than enough).
The following sample program can serve as an example for developing a COM
program. A small (init) routine relocates the stack to the end of the code segment
after the start of the program and releases all remaining memory. Even when this
program loads another program, itremains resident. This routine can be useful to
applications, and can be part of any COM program.
itestcorn.asrn
code segment para 'CODE' ;Definition of CODE-segments
64
Abacus 6.4 COM and EXE Programs
First you must assemble the source program using the assembler. In the following
example, we are using the Microsoft assembler. Following assembly, you then
link the object code using the LINK program. When you execute the LINK
program, the following message appears:
Warning: no stack segment
You can disregard this message. If the program contains no errors, the LINK
program creates an EXE file. Since you want a COM program and not an EXE
program developed, you must run the EXE2BIN program as the last step. This
converts EXE programs into COM programs. Here are the steps for preparing an
assembly language program using the Microsoft assembler. The program to
assemble is named TESTCOM.ASM.
masrn testcom:
link testcom;
If all steps were carried out correctly, the program TESTCOM.COM can be
executed from DOS by simply typing TESTCOM.
6S
6. The Disk Operating System PC System Programming
EXE programs have an advantage over COM programs because they are not
limited to a maximum length of 64K for code, data and stack. The disadvantage of
this is the greater complexity of these files. This means that in addition to the
program itself, other information must be stored in an EXE file.
EXE programs contain separate segments for code, data and stack which can be
organized in any sequence. Unlike a COM program, an EXE program loads into
memory from disk and undergoes processing by the EXEC function and then
finally begins execution. This is necessary because of the limitations already
described for COM programs.
EXE programs aren't limited to loading at a fixed memory location, but to any
desired location in memory that's a multiple of 16. Since an EXE program can
have several segments, this requires the use of FAR machine language
instructions. For example, a main program can be in one segment and call a
subroutine in another segment. The segment address must be provided for this
FAR instruction in addition to the offset for the routine to be called. The problem
is that the segment address may be different for every execution of the program.
COM files avoid this problem since the program size is limited to 64K, which
makes the use of FAR commands unnecessary. EXE programs solve this problem
in a more complex way: the LINK program places a data structure at the beginning
of every EXE file which contains the addresses of all segments, among other
things. It contains the addresses of all memory locations in which the segment
address of a certain segment is stored during program execution.
If the EXEC function loads the EXE program, it knows the addresses where the
various segments should be loaded. It can therefore enter these values into the
memory locations at the beginning of the EXE file. Because of this, more time
elapses between the initial program call and when the program actually begins
execution than for a COM program. The EXE program also occupies more
memory than a COM program. The following illustration shows the structure of
the header for an EXE file.
66
Abacus 6.4 COM and EXE Programs
After the segment references within the EXE program have been resolved to the
current addresses, the EXEC function sets the DS and the ES segment register to
the beginning of the PSP which also precedes all EXE programs in memory.
Because of this, the EXE program can access the information contained in the
PSP, such as the address of the environment block and the parameters contained in
the command line (command tail). The stack address and the contents of the stack
pointer are stored in the EXE file header and accessed from there. This also applies
to the code segment address containing the first instructions of the program, and
the program counter. After the values have been assigned, the program execution
starts.
Of course, memory must be available for the EXE program. The EXE loader
determines the total program size based on the size of the individual segments of
the EXE program. Then it can allocate this amount of memory and some
additional memory immediately following the EXE program. The first two fields
of the EXE program file header contain the minimum and maximum size of
memory required in paragraphs (1-6 bytes).
First, the EXE loader tries to reserve the maximum number of paragraphs. If this
is not possible the loader tries to reserve the remaining memory which may be no
smaller than the minimum number of paragraphs. These fields are determined by
the compiler or assembler, llil1 the linker. The minimum is 0 and the maximum
67
6. The Disk Operating System PC System Programming
allowed is FFFFH. This last number is unrealistic in most cases (it adds up to 1
megabyte) but reserves the entire memory for the EXE program.
This brings us back to the same problem as in COM programs. EXE files make
poor resident programs, but an EXE program may need to call another program
during execution. This is possible only by fIrst releasing the additional reserved
memory. The following program below contains a routine which reduces the
reserved memory to a minimum.
The program uses separate code, data and stack segments. It can serve as a model
for other EXE programs that you can write.
; testexe.asm
i== stack ============================================_ac============-
68
Abacus 6.4 COM and EKE Programs
Here are the individual steps for preparing an EXE program from the assembly
language source named 1ES1EXE.ASM.
masm testexe;
link testexe;
If all these steps were executed correctly, the program TESTEXE.EXE can be
started from the DOS level by typing TESTEXE.
69
6. The Disk Operating System PC System Programming
The functions can be divided into two types: those carried over from the CP/M
operating system and those borrowed from the UNIX operating system. While the
two types of functions can be intermixed, we recommend that you use one type of
function throughout a program for the sake of consistency.
The handle functions perform file access as well as character input to or output
from a device. DOS recognizes the difference by examining the name assigned by
the handle. If the handle is a device name, it addresses the device; otherwise it
assumes that file access should occur. The device names are as follows:
Output and input go to and from the AUX, PRN and NUL devices. For the device
CON, output is sent to the screen and input is read from the keyboard.
When DOS passes control to a program, five handles are available for access to
individual devices. These handles have values from 0 to 4 and represent the
following devices:
70
Abacus 65 Character Input and Output from DOS
Before discussing these devices, here are some functions used to access any device.
Function 40H of interrupt 21H sends data to a device. The function number (40H)
is passed in the AH register and the handle is passed in the BX register. For
example, to display an error message, the value 2 indicates the handle for
displaying the error message (this device cannot be redirected, so handle 2 always
addresses the console). The number of characters to be in the error message is
passed in the ex register. The characters making up the message are stored
sequentially in memory whose segment address is stored in the DS register and
offset address in the DX register.
Following the call to the function, the carry flag signals any error. If there was no
error, the carry flag is reset and the AX register contains the number of characters
that were displayed. If the AX register contains the value 0, then there was no
more space available on the storage medium for the message. If the carry flag is
set, the error message was not sent and an error code is indicated in the AX
register. An error code of 5 indicates that the device was not available. An error
code of 6 indicates that the handle was not opened.
Function 3FH of interrupt 21H reads character data from a device and has many
similarities to the previous function. Both functions have identical register usage.
The function number is passed in the AX register and the handle in the BX
register. The number of characters read is passed in the ex register and the
memory address of the characters transferred are passed in the DS:DX register pair.
Following the call to the function, the carry flag also signals any error. Again, any
error code is passed in the AX register. Error codes 5 and 6 have the same meaning
as when using function 40H. If the carry flag is reset, then the function executed
successfully. The AX register then contains the number of characters read into the
buffer. A value of 0 in the AX register means that the data to be read should have
come from a file, but that this file contains no more data.
71
6. The Disk Operating System PC System Programming
The function number 3DH is passed in the AH registel'. The AL register contains 0
to enable reading from the device, 1 to enable writing to the device and 2 for both
reading and writing to the device. The name of the device is placed in memory
whose address is passed in the DS:DX register pair. So that the DOS can properly
identify the device name, the names must be specified in uppercase characters. The
last character of the string must be an end character (ASCII value 0).
Following the function calls the status is indicated by the carry flag. A reset flag
means that the device was opened successfully and the handle number is passed
back in the AX register. A set flag indicates an error and the AX register contains
any error code.
The handle is closed using function 3EH of interrupt 21H. The function number is
passed in the AH register and the handle number is passed in the BX register. The
carry flag again indicates the status of the function call. A set carry flag indicates
an error.
You can also close the predefined handles 0 through 4 using this function. But if
you close handle 0 (the standard input device) you'll no longer be able to accept
input from the keyboard
Keyboard
The keyboard can perform only read operations. The results of the read operations
depend on the mode in which the device was addressed. Here DOS differentiates
between raw and cooked. In the cooked mode OOS checks every character sent to a
device or received from a device to see if it is a special control character. If DOS
finds a special control character, it performs a certain action in response to the
character. In raw mode the individual characters are passed through unchecked and
unmanipulated. DOS normally operates the device in cooked mode for character
input and output. However, you can switch to raw mode within a program (see
below).
The difference between cooked and raw mode can be best explained by an example
of reading the keyboard. Assume that 30 characters are read from the keyboard in
cooked mode. As you enter the characters DOS allows you to edit the input using
several of the control keys. For example <Ctrl><C> and <Ctrl><Break> abort the
input. <Ctrl><S> temporarily halts the program until another key is pressed.
<Ctrl><P> directs subsequent data from the screen to the printer (until <Ctrl><P>
is pressed again). <Backspace> removes the last character from the DOS buffer. If
the <Enter> key is pressed, the first 30 characters (or all characters input up to
now if there are less than 30) are copied from the DOS buffer into the input buffer
of the program without the control characters.
In raw mode all characters entered (including control characters) are passed to the
calling program without requiring the user to press the <Enter> key. Mter exactly
72
Abacus 6.5 Character Input and Output from DOS
30 characters, control passes to the calling program, even if you pressed the
<Enter> key as the second character of the input.
Screen
To display characters on the screen, handle 1 is usually addressed as the standard
output device. Since this device can be redirected, output through this handle can
pass to devices other than the screen. On the other hand, you cannot redirect the
standard error output device (handle 2), so error messages that pass through this
handle always appears on the screen. This handle is recommended for character
display on the screen ~.
Printer
Unlike the keyboard and screen, printer output cannot be redirected-at least not
from the user level. An exception to this rule is redirecting output from a parallel
printer to a serial printer. Characters ready to print can be sent to a buffer before
they are sent to the printer. Handle 4 is used to address the standard printer. There
are three standard printer devices LPTl, LPT2 and LPT3. Device PRN is
synonymous with LPTI. When this handle is opened the device name is specified
as one of the three: LPTl, LPT2 or LPTI.
Serial interface
Much of the information that applies to the printer also applies to the serial
interface. For example, serial input and output cannot be redirected to another
device (e.g., from a serial printer to a parallel printer). The programmer can use the
predefined handle 3 for serial access, through which you can address the standard
serial interface (AUX).
Handle 3 is used to address the standard serial device. The two are names COMl
and COM2. A PC can have multiple serial interfaces. Only the first two (COMl
and COM2) are supported by DOS. Since the system doesn't know exactly which
interface to access during AUX device access, you should open a new handle for
access to the specific device.
Errors during read operations in DOS mode are returned to the serial interface in
cooked mode. The number returned to the AX register will not match the number
of characters actually read. We recommend that you operate the serial interface in
the raw mode, even if this mode ignores control characters such as <Ctrl><C> and
EOF (end-of-fIle).
73
6. The Disk OperaJing System PC System Programming
The DOS functions for input and output aren't based on the handle oriented
functions. If you use these functions you won't need to specify a handle, since
each function pertains to a specific device.
Below are the various input and output devices and the way in which these
functions work with them.
Keyboard
There are seven DOS functions for addressing the keyboard but they differ in many
ways. For example, they respond differently to the <Ctrl> <Break> key. Some
functions echo the characters on the screen; others don't.
You can use DOS functions OIH, 06H, 07H and OSH to read a single keyboard
character. The function number is passed in the AH register. Following the call,
the character is returned in the AL register.
For DOS function OIH, DOS waits for a keypress if the keyboard buffer is empty.
When this happens, the character is echoed on the screen. If the keyboard buffer is
not empty, a new character is fetched and returned to the calling program. DOS
function 06H can be used for both character input and output. To input a character
a value of FFH is loaded into the DL register. This function doesn't wait for a
character to be input but returns immediately to the calling program. If the zero
flag is set, a character was not read. If the zero flag is reset, a character was read and
returned in the AL register. The character is not echoed on the screen.
DOS functions 07H and 08H are used to read the keyboard similar to function 1.
Both either fetch a character from the keyboard buffer or wait for a character to be
entered at the keyboard. Neither echo the character to the screen. They differ in that
function OSH responds to <Ctrl><C> and function 07H does not.
By using function OBH, a program can determine whether one or more characters
are in the keyboard buffer before calling any functions that read characters. After
calling this function, the AL register contains 0 if the keyboard buffer is empty,
and FFH if the keyboard buffer is not empty.
DOS function OCH is used to clear the keyboard buffer. After it is cleared, the
function whose number was passed to function OCH in the AL registered is
automatically called.
DOS function OAH is used to read a string of characters. Again this function
number is passed in the AH register. In addition, the memory address of a buffer
for the character string is passed in the DS:DX register pair. This buffer is used to
hold the character string. The first byte of the buffer indicates the maximum
number of characters that may be contained in the buffer.
74
Abacus 65 Chmacter Inplll tmd Outplll from DOS
When this function is called, OOS reads up to the maximum number of characters
and stores them in the buffer starting at the third byte. It reads until either the
maximum number of characters is entered or the <Enter> key is pressed. The
actual number of characters is stored in the second byte of the buffer. Extended key
codes which occupy two bytes each in the buffer may be entered. The fIrst byte of
the pair (ASCII value 0) signifies that an extended key code follows. This means,
for example, that for a maximum buffer size of 10 bytes, only five extended
characters may be entered.
The following table illustrates how the various functions respond to <CtrlxC>
or <Ctrb<Break>, and provides a quick overview of the individual functions for
character input
Pet. Task <Ctrl><C> Echo
01H Character input yes I yes
06H direct character input ro ro
07H Character in~ut ro ro
OBH Character input yes ro
OAll Character string input Yf!s ro
OBH Read input-status yes no
OCH Reset input-buffer then input varies varies
Screen output
DOS function 02H outputs a single character to the screen or standard output
device. The character is passed to the DL register.
DOS function 09H is used for string output. Again, the function number is passed
in the AH register. The address of the string is passed in the DS:DX register pair.
The last character of the string is a dollar sign. In addition, the following control
codes are recognized.
Code Operation
7 "Bell", rinqs the bell on the PC
B "Backspace", erases the preceding character and moves the cursor
back by one character
10 ULine Feed 11 , (LF) moves the cursor one line down
13 "Carriage Return", (CR) moves the cursor to the beginning of the
current line
75
6. The Disk Operating System PC System Programming
Printer
DOS function 05H is used to output a single character to the printer. If the printer
is busy, this function waits until it is ready before returning control to the calling
program. During this time, it will respond to the <Ctrl><C> and <Ctrl><Break>
keys.
Serial interface
There are two DOS functions for communicating using serial interface-one for
input and one for output. Both functions respond to <Ctrl><C> and
<Ctrl><Break>, but they don't return the status of the serial interface, nor do they
recognize transmission errors.
DOS function 03H is used to input data from the serial interface. The character is
returned in the AL register. Since the data is not buffered, the data can overrun the
interface if the interface receives data faster than this function can handle it
DOS function 04H is used to output data over the serial interface. The character to
output is passed in the DL register. If the serial interface is not ready to accept the
data, this function waits until it is free.
Again, most programmers prefer to use the BIOS equivalent functions (see Section
7.9) to perform serial data transmission because of their more complete data
handling capabilities.
Demonstration programs
Earlier we mentioned that it was possible to switch a device from cooked mode to
raw mode and back. The BASIC, Pascal and C programs that follow show you
how to do this. They use the IOCTL functions which permit access to the DOS
device drivers (see Section 6.11.7 for details on this routine). These are routines
which serve as interfaces between the DOS input/output functions and the
hardware. The IOCTL functions in these programs tell the CON device driver
(responsible for the keyboard and the display) whether it should operate in the
cooked mode or in the raw mode.
To demonstrate how differently characters respond in the two modes, the programs
switch the CON driver into raw mode fIrst. Then this driver displays a sample
string several times. Unlike cooked mode, pressing <Ctrl><C> or <Ctrl><S> in
raw mode has no effect on stopping program execution or text display.
76
Abacus 65 Character Input and Output from DOS
After the program finishes displaying the sample string, the driver switches to the
cooked mode. The sample string is displayed again several times. When you press
<Ctrl><C> the program stops (Turbo Pascal version). For the BASIC and C
versions, you can press <Ctrl><C> to stop the program, or press <Ctrl><S> to
pause or continue the display.
Switching between the raw and the cooked mode does not take place directly
through a function. First the device attribute of the driver is determined. This
attribute contains certain information which identifies the driver and describes its
method of operation. One bit in this word indicates if the driver operates in raw or
cooked mode. The programs set or reset this bit, depending on the mode you want
running the driver.
200 '
220 PRINT"WARNING: This program can only be started if the GWBASIC was"
240 PRINT : PRINT"If this is not the case, please input <s> for Stop.·
340 PRINT"Because of this not even <CTRL> + <S> can stop the "
400 CLS
425 PRINT"input/output."
77
6. The Disk Operating System PC System Programming
51060 '
51070 GOSUB 53000 'Get device attribute of driver
51080 ATTRIB% = ATTRIB% AND 223 'Find COOKED-Bit
51090 GOSUB 54000 'Set device attribute of driver
51100 RETURN 'back to caller
51110 '
52000 .******* •• ****************** •• ***** •••• *****.*.*******.****.***.
52010 ,* change device driver to RAW mode
52020 ,*-------------------------------------------------------------.'
52030 ,* Input: HANDLE% ~ handle connected to the driver
78
Abacus 6.5 Character Input and Output from DOS
53070 '.
determined
53080 ,****** •• ******.***************** •• ****.******.****.*.**********,
53090 '
53100 FCT%-&H44 'Function number for IOCTL
53110 FCTl%-O 'Read Function number for IOCTL: Read device attribute
53120 INR%=&H21 'Call DOS-Interrupt 21H
53130 HANDHH = INT(HANDLE%/256) 'HI-byte of the handle
53140 HANDLO% - HANDLE% AND 255 'LO-byte of the handle
53150 CALL IA(INR%,FCT%,FCT1%,HANDHI%,HANDLO%,Z%,Z%,Z%,ATTRIB%,Z%,Z%,Z%,Z%)
53160 RETURN 'back to caller
53170 '
54000 1*********.*****************************************************,
54010 '1*. _____________________________________________________________
Set device attribute of a driver *'
54020
..'
54030 ' . Input : HANDLE% - handle connected to a driver *,
54040 ,* ATTRIB% - the attribute of the driver
54050 Output: none
54060 Info Z% used as Dummy-Variable ,
54070 1**************************************************.*.*.********,
54080
54090 FCT%=&H44 'Function number for IOCTL
54100 FCT1%-1 'Set function number for IOCTL: device attribute
54110 INR%-&H21 'Call DOS-Interrupt 21(h)
54120 HANDHI% - INT(HANDLE%/256) 'HI-byte of the handle
54130 HANDLO% - HANDLE% AND 255 'LO-byte of the handle
54140 ATHH - INT (ATTRIB%/256) 'HI-byte of the Attribute
54150 ATLO% - ATTRIB% AND 255 'LO-byte of the Attribute
54160 CALL IA(INR%,FCT%,FCTl%,HANDHI%,HANDLO%,Z%,Z%,ATHI%,ATLO%,Z%,Z%,Z%,Z%)
54170 RETURN 'back to caller
54180
60000 ,*******************************.*******************************,
60010 '. Initialize the Routine for Interrupt call *,
.*____________________________________________________----_____ *1
.'.'
60020
60030 '* Input : none
60040 '* Output: IA is the Start address of the Interrupt-Routine
60050 1******** •• ******************* •• * •••• *****.*****.* •••• **********'
60060
60070 IA-60000! 'Start address of the routine in the BASIC-Segment
60080 DEF SEG 'Set BASIC-Segment
60090 RESTORE 60130
60100 FOR 1% - 0 TO 160 READ X% POKE IA+I%,X% NEXT 'Poke Routine
60110 RETURN 'back to caller
60120 '
60130 DATA 85,139,236, 30, 6,139,118, 30,139, 4,232,140, 0,139,118
60140 DATA 12,139, 60,139,118, 8,139, 4, 61,255,255,117, 2,140,216
60150 DATA 142,192,139,118, 28,138, 36,139,118, 26,138, 4,139,118, 24
60160 DATA 138, 60,139,118, 22,138, 28,139,118, 20,138, 44,139,118, 18
60170 DATA 138, 12,139,118, 16,138, 52,139,118, 14,138, 20,139,118, 10
60180 DATA 139, 52, 85,205, 33, 93, 86,156,139,118, 12,137, 60,139,118
60190 DATA 28,136, 36,139,118, 26,136, 4,139,118, 24,136, 60,139,118
60200 DATA 22,136, 28,139,118, 20,136, 44,139,118, 18,136, 12,139,118
60210 DATA 16,136, 52,139,118, 14,136, 20,139,118, 8,140,192,137, 4
60220 DATA 88,139,118, 6,137, 4, 88,139,118, 10,137, 4, 7, 31, 93
60230 DATA 202, 26, 0, 91, 46,136, 71, 66,233,108,255
79
6. The Disk Operating System PC System Programming
program RAWCooKP;
begin
Regs .ah : ~ $44; ( Function number for IOCTL: Get Mode
Regs.bx := Handle;
MsDos ( Regs ); Call DOS-Interrupt 21H
GetMode Regs.dx ( Pass device attribute
end;
begin
Regs.ax $4401; ( Function number for IOCTL: Set Mode
Regs.bx Handle;
Regs.dx GetMode(Handle) and 255 or 32; ( new device attribute
MsDos ( Regs ); Call DOS-Interrupt 21H
end;
(*********************************************************************}
(* SETCOOKED Change a character driver into the COOKED-Mode *)
(* Input the handle passed must be connected with the *J
{* device addressed *1
(* Output none *)
{*********************************************************************}
80
Abacus 65 Character Input and Output from DOS
begin
Regs.ax .= $4401; 1 Function number for IOCTL: Set Mode
Regs.bx := Handle;
Regs.dx .= GetModelHandle) and 223; new device attribute
MsDosl Regs ); Call DOS-Interrupt 21H
end;
procedure TestOutput;
begin
Test := ·Test ..... ':
Regs.bx .- STANDARDOUT; { output on the Standard output device
begin
end:
writeln;
end:
{************************************* •• ******************************}
{* MAIN PROGRAM *}
{************************************.*************.*.********* •• *****}
begin
ClrScr; { Clear screen }
writeln('RAWCOOK (c) 1987 by Michael Tischer"13flO);
writeln('The Console driver is now in RAW-Mode. Control keys such as <Ctrl><C>');
writeln('are not recognized during output. Press a key to display a text on
'113110) ;
writeln{'the screen, and try stopping the display by pressing <Ctrl><C>');
Keys : = ReadKey; ( wait for key )
SetRaw(STANDARDIN); { Console driver in RAW mode }
TestOutput; Output Test-String 1000 times }
ClrScr; ( Clear Screen )
while KeyPressed do
Keys := ReadKey; ( Empty keyboard buffer
writeln{'The Console driver is now in COOKED mode. Control keys such as');
SetCooked(STANDARDIN);
end.
81
6. The Disk Operating System PC System Programming
C listing: RAWCOOK.C
/***************************.**********************.*.******** •••••• **/
1* RAW COO K *1
1*-------------------------------------------------------------------*1
1* Task provides two functions for *1
1* switching a character device driver into the RAW *1
1* or into the COOKED mode *1
1*-------------------------------------------------------------------*1
1* Author MICHAEL TISCHER *1
1* developed on : 08/16/87 *1
1* last Update : 04/08/89 *I
1*-------------------------------------------------------------------*1
1* (MICROSOFT C) *1
1* Creation MSC RAWCOOKC; *1
1* LINK RAWCOOKC; *1
1* Call RAWCOOKC *1
1*-------------------------------------------------------------------*1
1* (BORLAND TURBO C) *1
1* Creation : through command RUN in the menu *1
'*._----------_._._---._._--_._._---_._.... _-._._.-._-****************/
'include <dos.h> 1* include Header files *1
'include <stdio.h>
'include <conio.h>
int GetMode(Hand1e)
int SetRaw(Handle)
82
Abacus 65 Character Input and Olllput from DOS
int SetCooked(Handle)
Register.x.bx - Handle;
I
/**********************.*** ••• *****.***** •• ********.*.**********.*****/
/* TESTOUTPUT: outputs a Test-String 1000 times on the Standard */
/* output device */
/* Input none */
/* Output none */
/******** ••• ************************************* ••• **.*.* ••• *** ••• ***/
void TestOutput()
printf ("\n");
for (i - 0; i < 1000; i++) /* output 1000 times */
fputs(Test, stdout); /* Output String on the Standard output. */
printf ("\n");
I
/*******************.*.*.*.*******************.**********.************/
/** MAIN PROGRAM **/
/******** •••• *.*************** •• **** ••• ********* ••• *******************/
void main ()
(
printf("\nRAWCOOK (c) 1987 by Michael Tischer\n\n");
printf ("RAW Mode. \nDuring the following output control characters, \n");
printf("Try it.\n\n");
TestOutput () ;
83
6. The Disk Operating System PC System Programming
Operating systems such as DOS provide the programmer with functions for file
management. For example, DOS provides functions which return special file
information or functions to rename a file. One peculiarity of DOS is that these
functions exist in two forms because of the combined CP/M & UNIX
compatibility. For every UNIX compatible file function, there is also a CP/M
compatible file function.
FeB functions
The CP/M compatible functions are designated as FCB functions since they are
based on a data structure called the FCB (File Control Block). OOS uses this data
structure for information storage during file manipulation. The user must reserve
space for the FCB within this program. The FCB permits access to the FCB
functions which open, close, read from and write to files.
Since the FCB functions were developed for compatibility with CP/M's functions,
and since CP/M has no hierarchical file system, FCB functions do not support
paths. As a result, FCB functions can only access files which are in the current
directory.
It is easier for the programmer to access a file using the handle functions than to
access a file using the FCB functions. The handle functions do not require a
programmer to use a data structure for file access like the FCB functions do. In a
manner similar to the functions of the UNIX operating system, file access is
performed using a filename. The filename is passed as an ASCII string when the
file is opened or fIrst created. This must be performed before the fIrst write or read
operation to the file. In addition to the filename, it may contain a device
designator, a pathname and a file extension. The ASCII string ends with the end
84
Abacus 6.6 File Management in DOS
character (ASCII code 0). After the file is opened, a numeric value called the handle
is returned. Any further operations to this file are performed using this 16-bit
handle. For a subsequent read or write operation, the handle and not the filename is
passed to the appropriate function.
For each open file, DOS saves certain information pertaining to that file. If the
FCB functions are used, DOS saves the information in the FCB table within the
program's memory block. When the handle functions are used, the information is
stored in an area outside of the program's memory block in a table that is
maintained by the DOS. The number of open files is therefore limited by the
amount of available table space. The amount of table space set aside by DOS is
specified by the FILES parameter of the CONFIG.SYS file:
FILES = x
In DOS Version 3.0, this maximum is 255. If you change the maximum number
of files in the CONFIG.SYS file, the change will not go into effect until the next
time that DOS is booted.
FILES
While the FILES parameter specifies the maximum number of open files for the
entire operating system, DOS limits the number of open files to 20 per program.
Since five handles are assigned to standard devices such as the keyboard, monitor
and line printer, only 15 handles are available for the program. For example, if a
program opens three files, DOS assigns three available handles and reduces the
number of additional handles available by three. If this program calls another
program, the three files opened by the original program remain open. If the new
program opens additional files, the remaining number of handles available is
reduced even further.
In addition to the standard read and write functions, there is also a file positioning
function. This lets you specify an exact location within the file for the next data
access. Knowing both a record number and the length of each data record allows
you to specify the position to access a particular data record:
This function is not used during sequential file access since DOS sets the file
pointer during opening or creation of a file to the first byte within the file. Each
subsequent read or write operation moves the file pointer by the number of bytes
read towards the end of the me so that the next me access starts where the previous
onecnded.
The following table summarizes the handle functions. For a more detailed
description of these functions, see Appendix C.
85
6. The Disk Operating System PC System Programming
Here are a few general rules to follow when using these functionsl
Function 59H of DOS interrupt 21H returns very detailed infonnation concerning
errors which occur during disk operations. This function is available only in DOS
Versions 3.0 and higher.
As discussed earlier, DOS uses an FeB data structure for managing a file. The
programmer can use this data structure to obtain information about a fIle or change
infonnation about a file. For this reason we shall examine the structure of an FeB
before discussing the individual FeB functions.
The FeB is a 37-byte data structure which can be subdivided into different data
fields. The following figure illustrates these fields.
86
Abacus 6.6 File MQNJgement in DOS
RAM
1\ 0000(00
+ OOH Device name (1 byte)
+ 01H Filename (S bvtesl
+ 09H File mode (3 bytes)
+ OCH Current block number (1 word)
+ OEH Data record size (1 word)
+ 10H File size (2 words)
+ 14H Modification date (1 word)
+ 16H Modification time (1 word)
+ ISH Reserved (8 bytes)
+ 20H Current data record number(l byte)
+ 21H Data record number for (2 words)
random access
~otice that the name of the file is found beginning at offsets om through OBH of
the FCB. The byte at offset 0 is the device indicator, 0 is the current drive, I drive
A, 2 drive B, etc.
The filename which begins at offset I is an ASCII string. It may not contain a
pathname since it's limited to 8 characters. For this reason, the FCB functions can
access only files in the current directory. Filenames shorter than eight characters
are padded with spaces (ASCII code 32). The file extension, if any, occupies the
next three bytes of the FCB.
At offset OCH of the FCB is the current number of the block for sequential file
access. The two bytes at offset OEH are the record size. The four bytes at offset
lOH are the length of the file.
The date and time of the last modifications to the file are stored beginning at offset
14H of the FCB in encoded form.
87
6. The Disk Operating System PC System Programming
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 bit
I~~1~1~1~1~1~1~1~1~1~lrrl~ITI~I~1~I
~' ____ ~Ir- _____A'______ ~I ______-,A'____ ~I ______'
Hour Minute Seconds in
2-second
Increments (e.g.,
13 means 26)
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 obit
I I I I I I I I II II II I I I
\. A .A. J
I I I
Year (relative to 1980) Month Day of month
An eight· byte data area follows and is reserved for DOS (no user modifications
allowed). The use of this area varies from one version of DOS to another.
Following this reserved data area is the current record number which is used in
connection with the current block number to simulate CP/M operations.
Random files
The last data field of the FCB is used for a type of access in which the data within
the file may be retrieved or written in a non-sequential order. This field is four
bytes long. If a record is equal to or larger than 64 bytes, only the first three bytes
are used for indicating the current record number. All four bytes of this field are
used for records smaller than 64 bytes.
Extended FCB
Besides a standard FCB, DOS also supports the extended FCB. Unlike normal
FCBs, extended FCBs access files with special attributes, such as hidden files or
system files. Furthermore, they permit access to volume names and subdirectories
(this doesn't mean that you can access files in other directories besides the current
directory).
An extended FCB is similar to a standard FCB, but it's seven bytes larger. These
seven bytes are located at the beginning of the data structure. All subsequent fields
are therefore displaced by seven bytes.
88
Abacus 6.6 File Management in DOS
RAM
+ OOH FF (1 byte)
1\ OOT OO
+ 01H Reserved(O) (5 bytes)
+ 06H File attribute n byte)
+ 07H Device name (1 byte)
+ 08H Filename (8 bytes)
+ 10H File extension (3 bytes)
+ 13H Current block number (1 word)
+ ISH File record size (1 word)
+ 17H File size (2 words)
+ 1BH Modifications-date (1 word)
+ 1DH Modifications-time (1 word)
+ 1FH Reserved (8 bytes)
+ 27H Current data record number (1 byte)
+ 28H Data record number (2 words)
The ftrst byte of an extended FCB always contains the value 255 and identifies this
as an extended FCB. Since this address contains the device number in a normal
FCB and can therefore not contain the value 255, OOS can tell the difference
between a normal and an extended FCB. The next five bytes are reserved
exclusively for the use by OOS. They should not be changed. The seventh byte is
a fIle attribute byte. See Section 6.1.2 for the details of the file attribute byte.
Now that you're familiar with the FCB structures, the next section focuses on
using FCBs for accessing fIles.
Before accessing a fIle, an FCB must be built in the program's memory area. The
area can be reserved within the data segment of the program or by allocating
additional memory using another DOS function (see Section 6.9).
Although it is possible to write the data directly into the FCB, it is better to use
one of the appropriate OOS functions to do this.
For example, to set the filename in the FCB you can use OOS function 29H. The
function number is passed in the AH register. The address of the FCB is passed in
the ES:DI register pair. The address of the fIlename is passed in the DS:SI register
pair. The fIlename is an ASCII string terminated by the end character (ASCII code
0). The AL register contains flags for converting the fIlename and are discussed in
more detail in Appendix C.
Open FCB
After the FCB is properly formatted the fIle can be opened or created using a OOS
function. When this happens DOS stores information about that fIle in the PCB
89
6. The Disk Operating System PC System Programming
such as the file size, date and time of file creation, etc. At this point the FCB is
considered opened.
By default, the record length is set to 128 bytes when the FCB is opened. To
override this record length, store the desired record length at offset OEH of the FCB
after it is opened. Otherwise the default length will be used.
DTA
For record lengths greater than 128 bytes, the record buffer also known as the
DTA, or Disk Transfer Area must be moved to accommodate the longer record
size. Normally, DOS builds the DTA in the PSP (Program Segment Prefix).
Accessing the file using the default DTA for a record length greater than 128 bytes
would overwrite some of the other fields in the PSP.
The most convenient way to select a new DT A is to reserve the space in the
program's data segment. To change the address of the DTA use DOS function
lAH. The address of the new DTA is passed in the DS:DX register pair. DOS
assumes that you have set aside an area large enough to accommodate your largest
record length so you don't have to specify the new length.
File access
For sequential file access, processing begins at the first record in the file. DOS
maintains a record pointer in the FCB to keep track of the current record within the
file. Each time the file is accessed, DOS advances the pointer so that the second,
third, fourth, etc record is processed in order.
For random file access, the records can be processed in any order. The position of
each record relative to the beginning of the file determines its record number. This
record number is then passed to DOS to access a specific record. The last field of
the FCB is used to specify the record number to DOS.
It's also possible to change from sequential access mode to random access mode
and vice versa since processing depends on a specific DOS function to access the
file. In effect. there are two sets of independent functions. one for sequential access
and one for random functions.
Following is a list of all of the FCB functions of DOS interrupt 21H. A more
detailed description of the functions is found in Appendix C.
90
Abacus 6.6 File ManlJgemenl in DOS
Using the FCB functions, you can access several files, each with their own unique
FCB. To tell OOS which file is to be accessed, pass the address of the file's FCB
in the DS:DX register pair.
Most of the functions return an error code in the AL register or the value zero if
the function was successfully completed. For functions which open, close, create
or delete a file, a code of 255 is returned if an error occurs. The other functions
return specific error codes. More detailed information about these errors can be
determined by calling OOS function 59H but is available only in versions of DOS
V3.0 or later.
After the two groups of functions made available by OOS have been presented, the
advantages and disadvantages of the individual functions should be discussed
briefly. For those who want to convert a program from the CP/M or UNIX
operating systems into DOS, the choice will be easy, but for those who want to
develop a new program under OOS, this discussion can help in your deciding on
which set of functions to use.
Handles
There are two main advantages to using handle functions. The first is the
capability to access a file in any subdirectory of the disk. The second is that the
handle functions are not limited to the number of FCBs which can be stored in a
program's memory space.
There are a number of additional considerations. You can access the name of a disk
drive only by using an FCB. When the FCB is opened, you can easily determine
its file size and the date of the last modification. The handle functions
automatically provide an area large enough to accommodate the records in the file.
As you can see there are arguments for and against using either the FCB functions
or the handle functions. For future versions of DOS, the handle functions will play
a more important role and the importance of the FCB functions will diminish.
This is reason enough to use the handle functions for your new program
development
91
6. The Disk Operating System PC System Programming
There are two groups of DOS functions for working with directories. The first
group is used to manipulate the subdirectories and the second to search for mes on
the mass storage devices.
With DOS Version 2.0 came the introduction of subdirectories. A mass storage
device could be logically divided into smaller subdirectories which could in turn be
further subdivided. In effect this organization created a directory tree.
Main directory
START.BAT
= Directory, subdirectory
= File
Directory tree
In this directory tree, the names and numbers of subdirectories are not static.
Therefore there must be a way to add, change and delete entries on the tree. Other
functions must be available to set the current directory so that a complete
pathname is not required for all me accesses.
At the user level the MD, RD and CD commands can be used to make a directory,
remove a directory and change a current directory. Internally, these commands are
performed with functions 39H, 3AH and 3BH of DOS interrupt 21H.
The function number is passed in the AH register. The address of the path is passed
in the DS:DX register pair. The path is a string and may be a complete path
designation including a preceding drive letter followed by a colon (a device name)
and terminated by ASCII code O. If the device name is omitted, the current device
is the default.
92
Abacus 6.7 Accessing the DOS Directory
Following execution, the carry flag indicates the return code. If the carry flag is
reset (0), then execution was successful. If the carry flag is set, then an error
occurred and the error code is passed back in the AX register.
Function 39H creates or makes a new directory (Make Directory). The name for the
new directory is specified as the last element in the path. An error will be returned
by the functions if one or more of the directories specified in the path do not exist,
if the new directory name already exists or if the maximum number of ftles in the
root directory is exceeded.
Function OEH sets the default disk drive. Besides the function number in the AH
register, only the device code of the new current device must be passed in the DL
register. Code 0 stands for the device A, 1 for B, 2 for C, etc.
Directory specification
Before specifying the current directory using function 3BH, it is sometimes
necessary to find the current directory. DOS makes function 47H available to the
programmer for this purpose. Since it can return the path of the current directory
for any device, the device number must be passed to the function. If this is the
current device, the value 0 must be passed in the DL register. For all other devices,
the value 1 must be passed for drive A, 2 for B, 3 for C, etc.
Besides the device code, the function must also have the address of a 64-byte buffer
within the user program. The DS register contains the segment and the SI register
holds the offset address of this buffer. After the function call this buffer contains
the path designation of the current directory, terminated with the end character
(ASCII code 0). The path designation cannot be preceded by the device name or the
\ character. If the current directory is the root directory, the buffer contains only the
end character. If a device code unknown to DOS was passed during the function
call, the carry flag is set and the AX register contains the error code OFH.
Let's consider the functions for searching for one or more files in the current
directory on the current device. Again the parallel between handle and FCB
functions appears. Two function groups exist to search for files. The group of
FCB functions has the disadvantage that they limit the search to ftles in the current
directory of a certain device, while handle functions allow searching for files in any
directories of any devices. The term "handle" functions doesn't really fit these
functions since they are not addressed with a handle. This designation originated
with the introduction of subdirectories (and therefore the handle functions) in DOS
Version 2.0. Version 1.0 offered only the FCB functions.
93
6. The Disk Operating System PC System Programming
This method of file search uses functions llH and 12H. Using them you can
search for files with a fixed name or flIes with a mename extension. Function IlH
finds the first flIe in the current directory. Function 12H finds all other additional
files. The FCBs play a significant role since they mediate between the calling
program and the two functions. Let's see how we can search for mes in a directory:
First the program must reserve space for two FCBs. This is done either by
reserving memory in the data area of the program, or by requesting memory from
DOS using function 48H. The programmer can use either normal or extended
FCBs. Extended FCBs offer the advantage of being able to search for mes with
special attributes (system or hidden), volume names and subdirectories. The
flIename for which the search will be made is specified in one of the FCBs. DOS
places the name of the flIe(s) that it finds in the other FCB. To differentiate
between the two FCBs, they are designated with the names Search FCB and Found
FCB.
The address of the Found FCB must be passed to DOS using function lAH. The
Found FCB becomes the new data transmission area (DTA) when this function call
occurs. This area is important for these two functions as well as all other functions
which transfer data between computer and disks. For this reason function 2FH
should determine the address of the current DTA before activating the new DTA.
When the file search ends, the DTA can be restored to its original state using
function lAH.
After the DTA is set to the Found FCB, the next step is to place the name of the
file you are looking for into the'Search FCB. For a more general search, the
wildcards * and ? may be used. You can transfer the flIename directly or transfer it
using function 29H. If you want to search through all mes, use the filename *.*.
If an extended FCB is used, you may insert an additional value into the attribute
field of the Search FCB to limit the search to mes with certain attributes only (see
Section 6.12 for more information on the various attributes).
This concludes the preliminary work. The file search can begin with the current
directory. For this purpose, function IlH is called with the function number in the
AH register, the segment address of the Search FCB in DS and the offset address in
the DX register. If the system finds a flIe with the indicated name, the AL register
contains the value 0 after the function call. If the flIename wasn't found, the AL
register contains a value of 255. The found flIename and its attributes (if extended
FCBs are used) can be read from the Found FCB. For additional searches, function
12H (not function I1H) is called. Function 12H's register contents during call and
return are similar to function IlH. If it returns the value 255 in the AL register
during one of the calls, the Search has ended.
94
Abacus 6.7 Accessing the DOS Directory
Working with handle functions is easier than working with the FCB functions.
There are functions for searching for the first file (the 4EH function) and
subsequent files (the 4FH function). Both functions return the information to the
DTA. For this reason the DTA should be moved into an area accessible to the
current program before calling either of these functions. This area must have at
least 43 bytes available. As mentioned in connection with the FCB functions, the
DTA should be restored to its original address after the search ends.
During the call of the 4EH function, the function number is passed in the AH
register, the attribute in the CX register and the address of the file to be found in
the DS:DX register pair. The filename is a series of ASCII characters, terminated
with an end character (ASCII code 0). In addition to a device name, you may add a
complete path designation and the wildcard characters * and ? If a path is not
specified, DOS assumes that the search should be made in the current directory of
the indicated device. If a device is not specified, the search proceeds on the current
device. Mter the function call, the carry flag indicates whether a file was found. If
the file couldn't be found, the carry flag is set, and the AX register contains an
error code. An error code of 2H is returned if the indicated path does not exist If no
file could be found, an error code of 12H is returned. If the carry flag is reset, the
DTA contains the information about the file found. It has the following structure:
Address Contents Type
+OOH reserved for DOS 21 bytes
+15H Attribute of file found 1 byte
+16H Time of last modification 1 word
+18H Date of last modification 1 word
+1AH low word of file size 1 word
+lEH high word of file size 12 bytes
Function 4FH executes any further searches. The function number is passed in the
AH register, and no other parameters are required. The carry flag indicates if there
are additional fIles in the current directory to which the search may be applicable.
95
6. The Disk Operaling System PC System Programming
Demonstration programs
The three programs below read directory entries and display them on the screen
using one of the handle functions. You'll find the display more user friendly than
the DOS DIR command: the files appear in a window, and the filename display
stops as soon as the window is fIlled with filenames. This permits easy reading of
filenames. By pressing any key, the program displays any additional pages of
fIlenames.
All three programs are designed on the same basic principle: first the main
program determines the search path. It contains the names of the directories in
which the search should be made for the files, the names of the files and the device
where the directory is located. This name can contain wildcards (* and 7) to search
for several files at the same time. If the user does not indicate a search path, the
program defaults to the search path n*.*n. This displays all fIles in the current
directory of the current device, as well as the hidden attribute fIles.
After the program determines the search path, a routine coordinates the loading and
display of individual directory entries. First a routine creates the display window on
the screen for individual entry output. Then a search proceeds for the first entry
using DOS function 4EH. If an entry is found, the screen displays the entry.
Function 4FH searches for all subsequent entries and displays them in the window.
The bottom line of the display window moves up one line with each new line
displayed. Once the entire window fills with data. any further display of entries
stops until the user presses a key. After all entries in the selected directory have
been displayed, the number of fIles is displayed and the program ends.
220 PRINT"WARNING: This program can be run only if GWBASIC was started"
240 PRINT"If this is not the case, please enter <s> for Stop."
290 CLS
310 PRINT
330 PRINT"Example: If all files with the extension .BAT in the Root"
96
Abacus 6.7 Accessing the DOS Directory
97
6. The Disk Operating System PC System Programming
50620 '
51000 ,****.*************************************** ••••• **************'
51010 ,* Search for first entry in a Directory *,
51020 ,*-------------------------------------------------------------*,
51030 '* Input: DIR$ - Search path
51080 Z\ is a Dummy-Variable *,
52070 ,*
52090 ,**********************************************.****************'
52100 '
52110 FCT\ = &H4F 'Find function number for next entry
52120 INR\ = &H21 'Call DOS-Interrupt 21H
52130 CALL IA(INR\,FCT\,Z\,Z\,Z\,Z\,Z\,Z\,Z\,Z\,Z\,Z\,FLAGS\)
52140 FOUNDIT' = «FLAGS\ AND 1) - 0) 'test Carry-Flag
52150 RETURN 'back to calling program
52160 '
53000 ,******* ••• *****************************************************1
53010 ,* Output a Directory entry from the DTA to the display
53020 '* ____________________________________________________ ---------*1
53030 Input: OFFSET% first line of the Directory window *,
53040 ENTRY \ Number of entries in the Directory window
53050 DTAOFS\ Offset address of the DTA
53060 MONTH$ = contains the names of months
53070 Output: none *'
53080 ,***************************************************************1
53090 '
53100 DEF FNDTA(X) = PEEK(DTAOFS% + X)
53110 DEF SEG = DTASEG\ 'Set Segment address of the DTA
53120 LOCATE OFFSET'+ENTRY%+2,15 'Output in the last line of the window
53130 H = 30 'Offset address in DTA for file names
53140 WHILE FNDTA(I\) <> 0 'the END character terminates the name
53150 PRINT CHR$(FNDTA(I\)); 'output a character of the file name
53160 I\ = 1\ + 1 'next character
53170 WEND 'End of Loop
53180 LOCATE OFFSET'+ENTRY\+2,28 'Set Cursor to column 28
53190 PRINT USING ".If .. U"; FNDTA(26) + FNDTA(27) * 256! + FNDTA(28) *
4096! + FNDTA(29) * 65536!;
53200 DATE = FNDTA(24) + FNDTA(25) * 256 'Get Date
53210 LOCATE OFFSET%+ENTRY\+2,36 'Set Cursor to Column 36
53220 PRINT MONTH$[(INT(DATE / 32) AND 15) - 1]; 'Output name of month
53230 PRINT"/";:PRINT USING • .. ·;DATE AND 31; 'Output day of month
53240 PRINT USING "/ffU";INT(DATE / 512) + 1980; 'OUtput year
53250 LOCATE OFFSET'+ENTRY%+2,49 'Set Cursor to column 49
53260 FTIME = FNDTA(22) + FNDTA(23) * 256 'Get time
53270 PRINT USING "ff";INT(FTIME / 2048); 'Output hour
53280 PRINT " ..
....
,
98
AbaclU 6.7 Accessing the DOS Directory
54190 '
One problem in the BASIC version of the directory listing occurs during the
directory output. Functions 4EH and 4FH read the entry into the DTA. It would
make more sense to move the DTA to a variable within the program (an integer
array would be best) to make it easier for the routine which outputs the entry to
access the data. BASIC's garbage collection feature makes this difficult. The
integer array containing the DTA moves periodically in storage and the address of
the DTA, stored internally in DOS, no longer cOrresponds with the address of this
integer array.
For this reason, the DOS function 2FH determines the DTA address. As the entries
are displayed, this address accesses the DTA to determine the me information.
99
6. The Disk Operating System PC System Programming
program DIRP;
(! Turbo 4.0 owners should use the Registers type from the DOS unit.)
end;
Attribut byte;
Ztime integer;
Zdate integer;
Datgrlo integer;
Datgrhi integer;
end;
{*********************************************************************}
{* GETFIRST: read in the first Directory entry *1
{* Input none *J
{* Output true or false, depending if an entry was found */
(* *)
{* Info the entry is stored in Variable DIRBUF *1
{*********************************************************************}
begin
DateiName := DateiName + fO; { terminate filename with NUL
Register.ax := $4E shl 8; Function number for search of first
Register.cx := Attribute; ( Attribute, for which search is performed
Register.ds seg{DateiName); ( Segment address of filename
Register.dx := succ{ofs(DateiName»; (Offset address of filename
msdos (Dos. Registers (Register»; { Call DOS Interrupt 21H {Turbo 4.0/1
{NOTE:Turbo 3.0 users should change previous line to read msdos{Register);1
( defined in DOS unit.)
if (Register. flags and 11 = 0 { Test Carry-Flag 1
100
Abacus 6.7 Accessi"g the DOS Directory
begin
Register.ax :- S4F shl B; Function number for next search }
msdos{Dos.Registers{Register}}; { Call DOS Interrupt 21H V 4.0}
{NOTE: Turbo 3.0 users should change the previous}
{line to read msdos(Register};}
if (Register. flags and 1) - 0 ( Test Carry-Flag )
then Get Next '. true Equal to 0 : File found }
else GetNext :- false; otherwise no file found }
end;
(*** •• ***************.*.*******.************************************)
(* PRINTDATA: Output information on an entry *)
{* Input none *}
(* Output none *)
(* Info the information about the entry are taken by this *)
{* procedures from Variable DIRBUF *}
{*************** •• ******************************.*.***.******* ••• ***)
procedure PrintData;
DataLenght2 := DirBuf.Datgrlo;
gotoxy(21, ENTRY};
write (' ) , );
1 write ('Jan');
2 write ('Feb');
3 write ('Marl) ;
4 write ('Apr') ;
5 write ('May') ;
6 write ('Jun') ;
7 write ('Jul' );
8 write ('Aug') ;
9 write ('Sep') ;
10 write ('Oct') ;
11 write ('Nov') ;
12 write ('Dec')
101
6. The Disk Operating System PC System Programming
end:
write('/',DirBuf.Zdate and 31:2, 'j'); { determine day
write(DirBuf.Zdate shr 9 + 1980:4); ( determine year
gotoxy(34, ENTRY);
write('I', DirBuf.Ztime shr 11:2, ':'); determine hour
write(DirBuf.Ztime shr 5 and 63:3); determine minutes
gotoxy(44, ENTRY); evaluate file attribute
write (' I ') ; separator to preceding field
if (DirBuf.Attribut and 1)<>0 then write('X') ( Read-only?
else write(' ');
i f (DirBuf .Attribut and 2)<>0 then write('X') hidden?
else write(' ');
i f (DirBuf.Attribut and 4)<>0 then write('X') system?
else write (' ');
i f (DirBuf.Attribut and 8) <>0 then write('X') Volume-Label?
else write (' ');
i f (DirBuf.Attribut and 16)<>0 then write ('X') { Directory?
else write(' 'I;
write (' I'); ( right border of window frame )
end;
{****************************************************.****************}
1* SETDTA *'
1* Input
{* Output
set Address of DTA
: see above
: none *}
*'
(***********************•• ******************************** •• **********)
begin
Register.ax := $lA shl 8; { Set Function number for DTA
Register.ds := Segment; { Segment address into DS register
Register.dx := Offset; ( Offset address into DX register
msdos(Dos.Registers(Register»; ( Call DOS-Interrupt 21H )
INOTE: Turbo 3.0 users should change the previous}
Iline to read msdosIRegister);)
end:
{*********************************************************************}
{* BUILDSCREENDISPLAY: prepares the display for output of the *}
(* Directory *}
{* Input : none *}
(* Output : none *}
{**** •• ***************************************************************}
procedure BuildScreenDisplay;
begin
clrscr: 1 clear display
window (14, (20-ENTRY) shr 1+1,64, (20-ENTRY) shr 1 +5+ENTRY);
gotoxy(l,l); Cursor to left upper corner of window
write ('r T T TTl');
writel'l Filename I Size I Date Time IRHSVDI');
write('I------------lf------~-------------~-------+-----I');
for Counter .= 1 to ENTRY do
end:
{*********************************************************************}
{* DIR: controls the input and output of Directories *1
{* Input : none *)
102
Abacus 6.7 Accessing the DOS Directory
(* output : none *)
{*********.******* ••••• ***.*** ••• ****.********** •• ***.****************}
procedure Dir;
begin ( Yes
end:
PrintData; ( output data of entry
write (' I) ;
case NurnEntries of
end:
window (1, 1, 80, 25); set whole display as window I
end;
begin
Dir; { Load Directory and display }
103
6. The Disk Operating System PC System Programming
end.
In the above Pascal program and in the following C program, accessing the DTA
is much easier than in the BASIC version of the same program. RECORD or
STRUCT defines the structure of the directory entry into the DTA, and the
programs implement a variable of this type. OOS function lAH then transfers the
DTA to this variable. All the information in a directory entry can be easily
accessed. With Turbo Pascal, the display design is particularly easy. Turbo Pascal
also has a procedure to define any display area as a window. However, the C
language program uses the scroll function of the BIOS interrupt lOH to scroll the
directory window one line upward.
C listing: DIRC.C
/***************************************************** ****************j
1* D I R C *1
1*-------------------------------------------------------------------*1
1* Task : Displays all files in any Directory, *1
1* including Sub-Directories and volume names *1
1* on the screen. *1
1*-------------------------------------------------------------------*1
1* Author MICHAEL TISCHER *1
1* developed on : 08/15/87 *1
1* last Update : 04/08/89 *I
1*----------------_·_--------------------------------- ----------------* I
1* (MICROSOFT C) *1
1* Creation : MSC DIRC; *1
1* LINK DIRC; *1
1* Call : DIRC *I
1*-------------------------------------------------------------------*1
1* (BORLAND TURBO C) *1
1* Creation With the RUN command in the command line *1
1* Info Arguments can be passed to the program with *1
1* the OPTION/ARGS command in the command line *1
1* of TURBO C *1
1* or *1
1* *1
1* Creation : TCC DIRC *1
1* Call : DIRC *1
/*********************************************************************/
finclude <io.h>
'include <string.h>
104
Abacus 6.7 Accessing the DOS Directory
byte GETPAGEO
/****************** •• *************************************************/
1* SCROLLUP: moves a displa¥ area one or more lines *1
1* upward or erases it *1
1* Input see above *1
1* Output none *1
1* Info if 0 is passed as number, the display area *1
1* is filled with blanks *1
/*****************************************************.***************/
105
6. The Disk Operating System PC System Programming
/********** •• ****************************************************.****/
1* GETPOS Get the position of the Cursor in current display page *1
1* Input : none */
1* Output : see below *I
/*******************+.**************************** •• ** ****************1
/***********************************.*********************************/
/* WRITECHAR: writes a character with an attribute to the current */
/* cursor position on the current display page */
/* Input see below */
/* Output none */
j******************************************** •• ******* ****************/
/*********************************************************************/
/* WT writes a character string with constant color starting */
1* at a specified position on the current display page. */
/* Input see below */
/* Output none */
/* Info Text is a Pointer to a character Vector, which contains */
/* the text to be output and is terminated with a '\0' *1
/* character. *1
/*********************************************************************/
106
Abacus 6.7 Accessing the DOS Directory
void CIs ()
/** ••• ****** •••••• ******.*.*.* •• ****.* •••••• ** ••• ********* •• **** •• **.*,
1* BUILDSCREENDISPLAY: prepares the display for the output of the *1
1* Directory. *1
1* Input none *I
1* Output none *1
/ •• **.*** •••• ***** •••• ****** ••••••••••••• *** •• **** •••• *** ••• *** ••••• *./
void BuildScreenDisplay()
{
byte i; 1* Loop Counter *1
Cls(); 1* Clear Screen *1
WT (14, EZ, 'f-------r r ---"'lTr------"1Tr- ----4'"--10, NOF) ;
WT(14,EZ+l,"1 Filename I Size I Date I Time IRHSVD I ",NOF);
WT(14,i,"1 I I I I",NOF)·
WT (14, EZ+ENTRY+3, "L.-----.L---.L-----.. L-----.L--J·,
NOF);
107
6. The Disk Operating System PC System Programming
1-··_·---_··_··------------------_·_--_·_·_·_·_-_·_---.-.-._.-.---_._./
1* GETFIRST read the first Directory entry */
/* Input none */
f* Output TRUE, if entry was found, otherwise FALSE */
/* Info Entry is read into the DTA */
1-*------_·_·····_---------------_·_------*----------- -*_. __ .-._._._--/
byte GetFirst (Sname, Attribute)
j._--------*-----------------------_._------_._-_._._-----------_._._-/
/* SETDTA sets the DTA to a Variable in the Data Segment *f
/* Input : see below *f
/* Output : none */
1---·--·_--_·_-_·_------·_-_·_·_·· __ ·_·_---_····-·-·_· w.www.wwWWWWW_K_/
void SetDTA(Offset)
/*********************************************************************/
f* DIR controls the input and output of Directories *f
f* Input : see below *f
/* Output : none *f
/** •• **************************************************.*.************/
108
Abacus 6.7 Accessing the DOS Directory
(
int NumEntries, /* Total number of entries found */
Numwind; /* Number of entries 1n display */
struct DirStruct DirEntry; /* a Directory entry */
/* no entry found */
do
(
PrintData(&DirEntry, EZ+ENTRY+2); /* output entry */
if (++Numwind == ENTRY ) /* Window full 2 */
(
Nurnwind - 0; /* fill a window */
WT(14, EZ+4+ENTRY,
" Please press a key H, INV);
qetch (); /* wait for key */
WT(14, EZ+4+ENTRY,
",NRM) ;
switch (NurnEntries)
(
case 0 printf("no files found tt, ;
break:
break;
109
6. Tlu! Disk Operating System PC System Programming
Parent/child
The EXEC function is one of the many DOS functions which can be called with
interrupt 21H (function 4BH). Generally speaking, this function lets a parent
program (main program) call a child program (secondary program). The child
program is loaded from a mass storage device into memory and then executes. If
this child program doesn't become resident, the memory occupied by the child is
released following program execution. The child program can also call another
program which works with the parent program. This creates a type of program
chaining limited only by the amount of available RAM.
One example of the EXEC function is the command processor. Using the EXEC
function, the command processor executes user-specified programs and becomes the
parent program. Some programs (such as Microsoft Word®) permit the user to
execute DOS commands from the main program using this function.
The parent program can pass parameters to the child program in the command line
and can also pass parameters using the environment block. It can also transfer
information to the child program within the PSP. Since the child program, like all
executable programs, has a PSP preceding it, information can be entered into the
two FCBs within this PSP and made accessible to the child program.
Child program
After transferring control to the child program, it can access all files and devices
previously opened by the parent program (or one of the parent programs) with a
handle function. This allows the child program to read information from a file or
write information to a file whose handle is known (the child program doesn't need
to know the filename). This is only possible if the handle was passed by the parent
program in one of the three methods described, or if the child program refers to one
of the five handles which are always open. These file accesses affect the file
pointer. Since values are not reset, these file accesses become "visible" to the
parent program when control returns to the parent program.
After execution of the child program, control returns to the parent program and
execution continues. To pass information (e.g., an error that occurred during the
execution of the child program), the child program can pass a numeric value at the
end of its execution. This can be done using DOS function 4CH, which terminates
a program and returns a code to the parent program.
The communication between parent and child program functions only if both
programs agree on this return value. After control returns to the parent program, it
110
Abacus 6.8 Th£ EXEC Function
can detemline the code using function 4DH of interrupt 21H. To use function 4DH
only the function number is passed in the AH register. The code passed by the
child program is returned to the calling (parent) program in the AL register.
As mentioned previously, the EXEC function can only load the child program if
enough memory is available. While DOS can estimate the memory needed for
EXE programs fairly accurately, it cannot do the same for COM programs. For
COM programs DOS reserves all unused memory. Because of this, a COM
program cannot call another program with the EXEC function, since DOS reserves
no extra memory. The same is true for many EXE programs. If a call to a child
program is necessary, the required memory space must be released from the calling
program before calling the EXEC function (see Sections 6.4.1 and 6.4.2 for
explanations on how this is done).
EXEC
If the EXEC function is called, the various parameters are loaded into the registers
before calling interrupt 21H. Function number 4BH is passed in the AH register.
A value of 0 or 3 is passed in the AI.. register. A value of 0 indicates that the
EXEC function is to load and execute the program while a value of 3 indicates that
the program is loaded as an overlay (without executing it). The address of the name
of the program to be loaded or executed is passed in the DS:DX register pair. And
the address of the parameter block is passed in the ES:BX register pair.
The program name is specified as an ASCII string and ended with a null character
(ASCII code 0). The program name can include the device name and a complete
path description. Its last element is the program name which, besides the name
itself, must have the extension .COM or .EXE. If the device name or path
designation are omitted, the system searches for the program in the current
directory of the current device. Since the EXEC function cannot execute a batch
fIle directly, the program name passed cannot contain the extension .BAT.
Batch child
111
6. The Disk Operating System PC System Programming
processor with the Ic parameter offers the option of calling any other program, and
even internal DOS commands such as DIR.
Besides calling a program directly, it's possible to specify program names without
file extensions during a command processor call. The command processor searches
for an EXE file; then a COM file; and finally a BAT file. If none of these files
exist in the current directory, it searches all directories specified in the PATH
command. This chain of events is not followed during a direct program call
without the addition of the command processor.
The directory which contains the command processor should be specified. If not
specified, it will be loaded from the path indicated by the COMSPEC environment
string of the SET command.
Parameter blocks
Parameters can be passed to the command processor in the parameter block
following the program name. These parameters are identical to the parameters
entered from the keyboard when the program is called. How these parameters affect
the EXEC function will be seen shortly, but fmt take a look at the parameter
block's structure when the AL register contains the value O. This block's address is
passed to the EXEC function in the register pair ES:BX.
Field 1 indicates the segment address of the child program's environment block.
This block doesn't require an offset address since it always starts at a location
divisible by 16, and therefore its offset address is always to O.
Environment block
The command processor and other programs obtain information from the
environment block. The environment block is a series of ASCII character strings.
This infonnation can include paths for file searches. Each string has the following
syntax, tenninated by a null character (ASCII code 0):
Name - Parameter
The individual strings follow each other sequentially (i.e., the null character of one
string is immediately followed by the beginning character of the next string). The
environment block ends with a null character. Any environment block has a
maximum length of 32K.
112
Abacus 6.8 The EXEC FlU'lCtion
The environment block can be changed or modified by the user using the DOS
SET and PATH commands. Programs which remain resident after execution are
unaffected by any changes made to the environment block through these two DOS
commands once made resident
If the parent program wants to pass infonnation to the child program using the
environment block, it can either construct a new environment block or supplement
its own environment block with this infonnation. In the first case, the segment
address of the new environment block is specified in the fllSt field of the parameter
block. If the child program should have access to the environment block of the
parent program, specify a value of 0 in this field. Before blming over control to
the child program, the EXEC function stores the segment address of the
environment block in the memory location at address 2CH of the child program's
PSP.
If the child program is to use a new environment block, it should contain at least 3
strings which are normally part of the environment block of the parent program,
and are important to the command processor:
COMSPEC = Parameter
PATH - Parameter
PROMPT = Parameter
Fields 2 and 3 indicate the command parameters' address which is passed to the
PSP of the program starting at address 80H. They must have the same strucwre in
memory as expected by DOS in the PSP. The first byte indicates the number of
command characters minus 1, then follows the command characters as nonnal
ASCII codes. The command parameters terminate with a carriage return (ASCII
code 13) which is not included in the character count. The fllSt character in the
string should be a space for compatibility with COMMAND.COM.
To call a batch program (called DO.BAT) using the command processor, the
following command parameters must be specified as a string in memory:
DB 10," Ie OO.BAT",13
The EXEC function copies the command parameters in a controlled fashion into
the PSP of the program to be executed. It removes all parameters which would
redirect the input or output, since a redirection of the standard input/output can
only be performed by the parent program. The child program can still use
input/output redirection if the standard input/output handles have been redirected by
the parent program (see Section 6.10 for more detailed information and an example
of this process).
113
6. The Disk Operating System PC System Programming
Fields 6, 7, 10 and 11 indicate two FCBs installed in the PSP at address 5CH or
6CH. If this is not required, specify -1 (FFFFH) in these two fields. If program
execution requires it, enter the first two command parameters in the two FCBs
with DOS function 29H. Before passing control to the child program, the EXEC
function copies these two FCBs into the PSP of the child program.
Even though all registers and the parameter block now have the required values, the
EXEC function cannot be called yet. Since it destroys the contents of all registers
up to the CS and IP registers during execution,the contents of all registers must
be placed on the stack before it is invoked. Then the contents of the SS and SP
registers must be stored within the code segment. Only then can interrupt 21H
function 4BH be called to activate the EXEC function. After the EXEC function
ends, the carry flag signals if the function executed normally. Before program
execution can continue, the value of the SS and SP registers must be restored,
from the code segment. Then the contents of the other register can be restored
again from the stack.
The EXEC function serves a different purpose when a value of 3 appears in the AL
register. In this case, it loads a COM program or an EXE program into memory
without executing. After the target program is loaded, control immediately returns
to the calling program. In contrast with sub-function 0, the program loads to a
memory address indicated by the calling program instead of loading to any non
specific location. Since no parameters are passed to the loaded program, the
parameter block has a different structure during the call of sub-function 3 than
during the call of sub-function 0:
Field Byte Purpose
1 0-1 Segment address where overlay is loaded
2 2-3 Relocation factor
Before the function is called, the segment address to which the program should be
loaded is specified in the frrst field of the parameter block. If the calling program
doesn't have enough memory available for loading the external program, it should
request additional memory with one of the DOS memory management functions.
The loaded program loads directly to the segment address indicated with the offset
address 0 since no PSP precedes the program.
Relocation
The relocation factor adjusts the segment address of the called program. Since this
factor applies only to EXE programs (COM programs cannot have specific
segment assignments), the relocation factor for COM programs should always be
equal to O. The relocation factor for EXE programs should indicate the segment
address where the program will be loaded to confmn to the program's segment
assignments.
After the program is loaded, its routines are ready to be accessed. The routines of
the loaded program should always be treated as subroutines; and therefore, called
114
Abacus 6.8 TM EXEC FlUlCtion
with the machine language CALL instruction. It must always be a FAR type
instruction even though the loaded program may be located immediately following
the calling program, but can never have the same segment address. The offset
address for CALL is always l00H for a COM program, since execution always
starts immediately following the PSP at address l00H. This creates a problem.
Sub-function 3 prevents the PSP from loading. Therefore the code segment of the
COM program starts at address 0, not at the offset address l00H (relative to the
load segment). Since all jump instructions and accesses to data within the COM
program are relative to address l00H and not address 0, you cannot execute a FAR
CALL instruction with the address of the load segment as the segment address, and
address 0 as the offset address. The segment address for the FAR CALL must
indicate the address of the load segment minus 10H and the address l00H as the
offset address.
If the COM program specifically acts as an overlay for another program, entry
addresses other than address l00H are possible. In such a case, only the offset
address for the FAR CALL instruction changes. The segment address must remain
10H smaller than the address of the load segment.
The problem is different for EXE programs. If they are loaded for execution using
sub-function 0, the EXEC function sets the code segment and the instruction
pointer to the instruction which was declared as the first instruction in the
assembler source. This address, however, is unknown to the program which loaded
the EXE program as an overlay. This can easily be remedied by placing the frrst
executable instruction in the EXE program at the beginning of the EXE program.
This makes its offset address O. The EXE program source must not be in the
normal sequence with the stack frrst. In this case, the code segment must be the
frrst segment in the source to ensure that it begins the EXE program.
The FAR CALL uses the address of the load segment as the segment address, and
address 0 as the offset ad,dress.
While BASIC, Pascal and C have commands or procedures to call a program from
another program, assembly language routines must use DOS function 4BH. To
help you further understand this function, here is an example program.
The framework of the EXE program listed in Section 6.4.2 acts as the basis for
this program. The EXEPRG procedure performs the actual dirty work in this
program. It calls the new program using function 4BH. Two strings which contain
the name of the program to' be called and the necessary parameters are passed to it.
Both strings end with the null character (ASCII code 0). All variables required by
EXEPRG for execution can be found in the code segment. This offers the
advantage that the lines from the code segment only must be copied into one of the
application programs to use this routine. After calling EXEPRG, the carry flag
signals if an error occurred If true (carry flag=I), the AX register contains the error
115
6. The Disk Operating System PC System Programming
code as returned by the EXEC function of DOS. If the called program executed
correctly, the carry flag is reset (0) and the tennination code of the called progmm,
as returned by DOS function 4DH, is returned by the AX register.
Within this program, EXEPRG displays the current directory using the command
processor. The command processor defaults to the current directory of the current
device.
; •• ** ••• **.** •••••• ******.*** •••• ** ••••• ** •••••••••••• ··········**····i
;* EXEC *;
i*-------------------------------------------------------------------*;
;* Task Calls a program with the help of the *;
;* EXEC function of DOS. In this example *;
;* program the content of the current *;
;* Directory of the current device is displayed. *;
;*-------------------------------------------------------------------*;
116
Abacus 6.8 The EXEC Fu.nction
117
6. The Disk Operating System PC System Programming
pop si
pop di
pop dx
pop cx
pop bx
exeprg endp
118
Abacus 6.9 Memory Allocation from DOS
The second area is designated as the TPA (Transient Program Area). It contains
programs and their environment blocks for execution. The TPA starts after the end
of the operating system area. Depending on the memory requirements of the
individual programs, DOS assigns them different amounts of memory administered
through a special data block preceding every memory range and connected with the
data block of the next memory range. This also applies to memory not assigned to
a program.
This data block, called a memory control block (or MCB) is a 16-byte block
containing a variety of information. An MCB begins at one of the addresses
divisible by 16, and controls memory allocation. DOS looks for the segment
address of the allocated memory range, and is helped in this task through the MCB.
The following table shows the structure of an MCB in memory:
Address Contents Type
+OOH ID ("Z"-last MCB, "M"-another MCB follows) 1 byte
+OlH Segment address of correspondinq PSP 1 word
+03H Number of paragraphs in allocated range 1 word
+05H unused 11 bytes
+lOH Allocated memory ranqe x paragraphs
As the table above illustrates, the MCB contains three ftelds. The ftrst fteld
indicates whether any MCBs follow the current MCB under analysis. The letters
"M" (more MCBs to follow) and "Z" (last MCB) are the initials of one of the
creators of MS-DOS, Mark Zbikowski.
The second fteld speciftes the segment address of the corresponding program's PSP.
This only applies when memory allocation becomes a part of the environment of
the program being handled. in which case the PSP is indicated by the contents of
this field. In most cases, this fteld simply points to the memory range needed by
the program.
The third fteld of the MCB speciftes the size of the corresponding memory range in
paragraphs. Next follows the memory range itself. then any further MCBs after
that (provided that the frrst fteld contains an "M" ID letter). MCBs can be linked
together to create a group, as shown in the ftgure below:
119
6. The Dis/c Operating System PC System Programming
Memory allocation
If the DOS EXEC loader loads and executes a program, this function immediately
requests two data areas through another DOS function. The fU'St of these two areas
stores the environment block, while the second accepts the current program and the
program's PSP. The size of the area made available to a program is difficult to
estimate from the EXEC loader. This is even more difficult for COM programs
than for EXE programs since COM programs are copies of memory contents and
have no information preceding them. DOS therefore defaults to the maximum and
reserves the total available memory for a COM program.
This method worked well in the early days of DOS, but has created other
problems. While only one program could exist in memory at a time in the early
days of DOS, now it's common for one program to load and run a second program,
or even make one of the programs pennanently resident in memory. This can't be
done if no memory exists, as would be the case after loading a COM program.
This is why a COM program should always release the memory it no longer needs
after it starts (see Section 6.4.1 for details on how this happens).
A COM program can only load when a memory range large enough to
accommodate the COM program exists (Plus 256 bytes for the PSP and at least 2
bytes for the stack). The COM program ensures that enough memory is available.
Under the minimum conditions presented above, the program probably won't run
without errors, since few programs can operate with only a 2-byte stack.
EXE program fil~s have a set of information created by the linker. The EXEC
loader can determine the amount of memory required for code segment, data and
stack from this infonnation. The start of the EXE program itself contains
additional information about the amount of memory needed for the program. This
amount defines an upper and lower limit of the additional memory, rather than a
specific number of bytes. The EXEC loader tries to reserve the upper limit of
l20
Abacus 6.9 Memory Allocation from DOS
memory if it can. If this is not possible, the EXEC loader uses the lower limit or
reserves the remainder of memory. If the lower limit of memory cannot be
allocated, the loading process aborts and control returns to the program which
called the EXEC loader (in most cases, the command processor).
The same occurs after program execution when the EXEC loader releases the
reserved memory space for further use, unless prevented by function 31H of
interrupt 21H, called from the program.
Now that you know some of the theoretical aspects of DOS memory management,
here are descriptions of the most important of these DOS functions. Functions
48H, 49H and 4AH are all called through interrupt 21H. The function number is
passed in the AH register.
Function 48H allocates memory. The function number is passed in the AH register
and the number of paragraphs to be reserved (16 bytes per paragraph) is passed in
the BX register. If the requested number of paragraphs can be reserved, the function
returns with the carry flag clear. The AX register indicates the segment address of
the reserved memory. Therefore, it starts at address AX:OOOO. If the program
required more memory than was available, the carry flag is set following the call to
the function and the AX register contains an error code. The BX register contains
the maximum memory available in paragraphs.
Function 49H performs the reverse of function 48H. This function releases
memory previously reserved through function 48H. The segment address of the
memory area to be released is passed in the ES register. This segment address was
originally passed in the AX register when function 48H was called. Normally
function 49H should execute without errors and the carry flag should be reset after
the function call. If this is not the case, it could be caused by either a destroyed
data block (placed ahead of a memory area by DOS), or a segment address passed in
the ES register which doesn't match a reserved memory area.
A third function changes the size of memory area which had been previously
reserved. The memory area can be either enlarged or reduced by using function
4AH. The segment address of the area to be modified is passed in the ES register.
The BX register reserves the number of paragraphs (16-byte units) which the
memory area should contain. The register contents following the call to the
function are identical to those of function 48H.
121
6. TM Disk Operaling System PC System Programming
The assignment of this program is to go through the memory from MCB to MCB
and examine the allocated storage areas. In order to move to the next MCB each
time, it uses the third field within an MCB, which helps it point to the next
MCB. This sets up a loop which will run until the last MCB is discovered, which
will have the letter "z.. in its ID field.
But in order to move through the chain of MCBs, the address of the first link, that
is the first MCB, must be known. DOS lists this within an internal structure
called DIB (DOS Information Block), which is not normally accessible to
application programs, i.e. this represents an undocumented DOS feature (see also
Section 6.15). However, we can find out the address of this structure with the help
of function 52H, which will output the address to the ES:BX register pair when
called.
Curiously, this address points to the second field in the MCB rather than the fU'St
But since it's the first field that contains the address of the first MCB, the
information we're looking for is behind the pointer. Since the pointer on the first
MCB consists of an offset address and a segment address, it is four bytes long and
can therefore be found at the address ES:(BX-4). But be careful with the address
statement, because it makes it seem as though all you have to do is subtract 4
from the contents of the BX register in order to get the effective address of the
desired information in the ES:BX register pair. This will only be successful if the
offset address in the BX register is greater than or equal to 4. But if it is less than
4, the consequences are disastrous, because this leaves a negative number. There is
no such thing as a negative memory address. Let's use an example to make this
clear:
If the value 0 is returned to the BX register as the offset address of the DIB, the
subtraction would give the value OFFFCH. With arithmetic operations, this is
interpreted quite correctly as -4. However, during memory access, this will not
point to the address -4, but rather right to OFFFCH, and therefore to the end rather
than the beginning of the accompanying segment Of course, you won't fmd what
you're looking for there.
The program will help you here, first of all by decrementing the delivered segment
address by 1. This reduces the effective address, which you get by appending the
segment address and the offset address, by 16. Finally, by adding 12 to the offset
address, the effective address is reduced by only 4 and points to the desired memory
location. The address of the first MCB can then be taken from this memory
location without any problems.
The loop which runs through all MeBs and analyzes them begins with this
address. First, some status information on the MCB and the memory it controls is
given. This includes:
122
Abacus 6.9 Memory AllocaJ.ionfrom DOS
Next, the contents of the storage area that belongs to it are examined. We get its
address by incrementing the segment address of the MCB by 1. The first thing
we11 determine is whether we're df'.aling with an environment block in this storage
area. We'll know for sure if we find the string COMSPEC= at the beginning of the
area. This string starts every environment block. If this string is found, the
program proceeds as though this were indeed an environment block, and it lists the
individual environment strings. In front of these, it lists the name of the program
the environment block belongs to, which is located at the end of the environment
block for DOS version 3.0 and higher.
If the program also does not run into this, it can't tell if the memory range
contains program code, data, or whatever. In this case, the program will send the
first 80 bytes of the storage area to the screen as a hex and ASCII dump, in order
to give you a chance to figure it out for yourself.
After this, the user is prompted to strike any key. When the keystroke is received,
the next MCB is examined, and the program will finally end when the last MCB
has been handled.
The following programs in Pascal and C produce the MCB dump. A BASIC
version could not be implemented here because this program works its way
through the entire memory, and BASIC offers only the DEF, SEG and PEEK
commands for this purpose. The use of these commands is too awkward in this
case and would detract from the real task of the program.
Since both programs are very similar in terms of the logic, function calls, and
variables used, they are described together in the following section.
Both access memory with FAR pointers, since the storage areas to be addressed are
outside of their data segments. While Turbo Pascal automatically uses FAR
pointers, C requires selection of the appropriate memory configuration through
Compact, Huge, Large or with the help of Cast operations, each of which
explicitly defines the task with a FAR pointer. This program goes the latter way,
so that it may also be compiled in a memory configuration that works with NEAR
pointers by default (Tiny, Small, Medium).
123
6. TIu! Disk Operating System PC System Programming
Converting separately retrieved offset and segment addresses to one FAR pointer
presents a problem in both languages. This can be done in C with a macro, which
is already defined in the Include file DOS.H in Turbo C, but is missing in
Microsoft C. For this reason, the macro is defined within the C program, in case it
hasn't been previously defined. In Pascal, the address conversions happen with the
help of a small inline procedure, that enters both addresses directly into the
memory locations that form the pointer.
Beyond these brief remarks, the listings should be able to speak for themselves,
since they are fully documented.
Pascal listing: MEMP.PAS
1*********************************·******·**********··** •• *************}
{* MEMP *}
{*--------------------------------------------------------------------*}
{* Description : displays the memory blocks allocated by DOS. *}
{*--------------------------------------------------------------------*}
{* Author MICHAEL TISCHER *}
{* developed on : 08/22/1988 *}
{* last update : 08/22/1988 *}
1************·****_·*****************************···*·**********••• *.*.}
program MEMP;
1******************************·******·****··********·*****************}
{* GetDosVer: determines the DOS version *}
{* Input : none *}
{* Output: the DOS version number (30 for DOS 3.0, 33 for 3.3 etc.) *}
{*.**.*** ••• **•••••••••••••••••••• *•• *******••• *.**** •••• ********* •• ***}
begin
Regs.ah :~ $30; ( function no. for "Get Dos Version"
MsDos( Regs ); { call DOS interrupt $21
GetDosVer := Regs.al * 10 + Regs.ah; { get version number
end;
{*••• *** •••• *•• *••••• *••• *•••*.*.**•• ** •••••• *.*****.*** •••• *.***.** ••• }
(* MK_FP: creates a byte pointer out of the segment and offset *)
{* addresses passed. *}
{* Input - Seq - segment to which the point should point *}
{* - Ofs = offset address to which the pointer should point *}
{* Output the pointer *}
124
Abacus 6.9 Memory Allocationfrom DOS
begin
inline $8B / $46 / $08 / mov ax, [bp+8) (get segment address)
end;
begin
CvHStr :- 'xxxx'; { initialize the string
for Counter:-4 downto 1 do ( run through the 4 digits of the string
begin
end;
HexString := CvHStr; ( return the created string
end;
begin
Regs.ah := S52; { ftn. no.: get address of the DOS info block
MsDos ( Regs ); ( call DOS interrupt $21
(*-- ES: (BX-4) points to the first MCB, create pointer -------------*)
FirstMCB :- MCBPtr2( MK_FP( Regs.ES-1, Regs.BX+12 ) )A;
end;
125
6. The Disk Operating System PC System Programming
begin
HexStr[l] := chr( (HByte shr 4) + ord('O') ); first digit
if HexStr[l] > '9' then convert to letters?
HexStr[l] := chr( ord(HexStr[l]) + 7); ( yes
HexStr[2] :- chr( (HByte and 15) + ord('O') ); ( second digit
if HexStr[2] > 'g' then convert to letters?
HexStr[2] .- chr( ord(HexStr[2]) + 7); ( yes
end;
begin
HexStr :== IZ Z '; ( initialize the hex string
writeln;
write('DUMP I 01234567B9ABCDEF 00 01 02 03 04 05 06 07 OB');
writeln(' Og OA DB OC OD DE OF');
write ('-----+--------------------------------------------------------');
writeln('--------------------------');
Offset :- 0; ( start with the first byte in the block
while Num>O do ( run through the loop ANZ times
begin
procedure TraceMCB;
begin
DosVer := GetDosVer; get DOS version
Done :- false;
NrMCB :- 1; { the first MCB is number 1
CurMCB '- FirstMCB; get pointer to the first MCB
repeat { follow the MCB chain
126
Abacus 6.9 Memory Allocation from DOS
127
6. The Disk Operating System PC System Programming
begin
writeln('unidentifiable (program or data) ');
Dump ( MemPtr, 5); { dump the first 5x16 bytes)
end;
end;
{************************************************************.*****.***}
(** MAIN PROGRAM
{*******************••• **** ••• *.*********************** •••• ********•• **}
**'
begin
ClrScr; clear the screen
TraceMCB; run through the MeBs
end.
C listing: MEMC.C
/************* •••***************.***************** ••**********.********/
1* M E M C *1
1*--------------------------------------------------------------------*1
1* Description : Displays the memory blocks allocated by DOS *1
1*--------------------------------------------------------------------*1
1* Author MICHAEL TISCHER *1
1* developed on : 08/23/1988 *I
1* last update : 05/1211989 *1
1*--------------------------------------------------------------------*1
1* (MICROSOFT C, *I
1* creation : CL lAS IZp memc.c *1
1* call : MEMC *I
1*--------------------------------------------------------------------*1
1* (BORLAND TURBO CJ *1
1* creation : via the Compile-Make command *1
1* (no project file) *I
,********* •• ****************** ••• ********************* *****************1
finclude <dos.h>
'include <stdlib.h>
struct MCB {
byte
segadr psp;
'* 'M'
1* describes an MCB in memory *1
=a block follows, 'Z'
1* segment address of the PSP *1
= end */
128
Abacus 6.9 Memory Allocation from DOS
};
typedef struct MCB far *MCBPtr; '* FAR pointer to an MCB *'
MCBPtr first_mcb()
{
union REGS regs; '* stores the processor registers *'
struct SREGS sreqs; '* stores the seqrnent registers *'
regs.h.ah = Ox52; '* ftn. no.: get address of the DOS info block *'
intdosx( 'regs, ®s, &sregs ); '* call DOS interrupt Ox21 *'
}
printf ("\02X ., *lptr++);
printf ("\n"); '* move to the next line *'
/***********************************************************************
* Function : T R ACE MC B
**------------------------------=-------------------------------------**
129
6. The Disk Operating System PC System Programming
( 1* output a string *f
printf (" 00);
for ( ; *lptr ; ) 1* run through the string to a NUL character *1
printf ( "tc", * (lptr++) ); 1* output a character *1
printf ("\n") ; f* move to the next line *f
I
else 1* no envrionrnent *1
{
130
Abacus 6.9 Memory Allocation from DOS
printf("==-=-------===--=-----=======---==--==--");
while ( ! done ); /* repeat until the last MeB has been processed *j
)
/********************.***********************************.*.*.***** •• **/
/** MAIN PROGRAM **/
/*************************************************.******************.*/
void main ()
(
printf ("\nMEMC (c) 1988 by Michael Tischer\n\n");
131
6. The Disk Operating System PC System Programming
If the user calls a program from the OOS level, the < character redirects input and
the> character redirects output. In the following example, the input comes from
the file IN.TXT instead of the keyboard. The output is written to the file
OUT.TXT instead of the screen:
SORT
After the user enters the above command, DOS recognizes that a program named
SORT should be called. Then it encounters the expression <IN.TXT which
redirects the standard input. This occurs by assigning the handle 0 (standard input,
which formerly pointed to the keyboard) to the file IN.TXT. The expression
>OUT.TXT resets handle 1 to the OUT.TXT file instead of the screen. The affected
handle is first closed, and then the redirected file is opened.
132
Abacus 6.10 DOS Filters
Once the command processor finishes with the command line it calls the SORT
program using the EXEC function (DOS function 4BH). Since the program called
with the EXEC function has all the handles of the calling program available, the
SORT program can input/output characters to handles 0 and 1. Where the
characters originate is unimportant to the program.
After the SORT program completes its work, it returns control to the command
processor. The command processor resets the redirection and waits for further input
from the user.
Pipes
The filter principle as supported by DOS becomes especially powerful through
pipes. This expression comes from the idea of a pipeline used for transporting oil
or gas. DOS pipes have a similar function: they carry characters from one program
to another and permit the connection of various programs with each other.
When this happens, characters output from one program to the standard output
device can be read by another program from the standard input device. As in the
redirection of the standard input/output, the two programs do not notice the
pipelines. The difference between the two procedures is that under redirection of the
standard input/output devices, data can be redirected only to one device or file,
while the use of pipes allows data transfer to another program.
Combined filters
Pipes allow the user to connect multiple filters. The pipe character I is inserted
between the programs to be connected. An example should make this more
understandable: A text file named DEMO.TXT is sorted and then displayed on the
screen in page format. Even though this task appears to be very complicated at
first, it can be performed easily using two DOS filters: SORT and MORE. SORT
sorts the file and MORE displays the file on the screen in page format.
The question is, how can you tell the command processor to do these things? First
SORT is used. This filter is told to sort the file DEMO.TXT. The redirection of
standard input can be used as illustrated at the beginning of the chapter:
After the user enters this command, SORT sorts the file DEMO.TXT then
displays the file on the screen. This display would be much easier to read in page
format. Formatted output can be implemented by redirecting the output from
SORT to a file (for example TEMP.TXT) and displaying this fIle using the
MORE command. The following sequence of commands do this:
133
6. TIu! Disk Operating System PC System Programming
You can use a pipe to connect the SORT filter and the MORE filter, saving the
user typing time. The following command line sends the output from SORT
directly to MORE and immediately displays the sorted file in page format:
SORT <DEMO. TXT I MORE
Any number of filters can be connected using pipes. DOS always executes these
pipelined filters from left to right. It sends the output from the first program as
input to the second program, the second program's output as input to the third
program, etc. The last program can again force the redirection of the output with
the > character so that the final result of the whole program or filter chain travels
to a file or other device instead of the screen.
Note: DOS cannot send data from one filter directly to another because it
would have to execute both filters simultaneously, and the current
version of DOS doesn't have multiprocessing capabilities. Instead,
the following method is used. The input calls the first filter and
redirects its output to a pipe file. After the first filter ends its
processing, it calls the second filter but redirects its input to the pipe
file to read in the output from the first filter. This principle applies
to all filters. The pipe file is stored in the current working directory.
The word "dump" is a computer buzzword for a way to display the contents of a
file in ASCII characters and/or hexadecimal numbers. The DUMP programs below
performs this task as a filter. As the contents are displayed in ASCII format,
DUMP differentiates between normal ASCII characters (letters, numbers, etc.) and
control characters such as carriage return, linefeed, etc. These control characters are
displayed in mnemonic form (e.g., <CR> for carriage return and <LF> for
linefeed). This DUMP filter is fairly simple in structure, yet it can be very useful
to quickly examine a file's contents.
The structure of the DUMP program is typical for a filter. Since DUMP displays a
maximum of nine ASCII characters and/or hexadecimal codes per line, it asks for
nine characters by using the read function from the standard input device. If not
enough characters are available, it reads what characters are available. DUMP
places these characters in a buffer, then converts the characters into ASCII
characters and hex codes. This buffer will accept a comple.te line of 78 characters.
When the buffer processing finishes, the filter uses the handle to write to the
standard output device. This process is repeated until no more characters can be read
from the standard input device.
The following programs are written in Pascal, C and assembly language. Note that
there isn't a BASIC version. The reason is that BASIC, as an interpreted language,
is unsuitable for developing a filter which can be called from the DOS level. A
BASIC compiler would be required for this task.
134
Abacus 6.10 DOS Filters
program DUMP;
BS 8; ASCII-Code Backspace
(*-*--------------._._-_._.__.... ------_._.-----------****.**********)
(* SZ writes the name of a control character into a Buffer *)
(* Input see below *)
(* OUtput none *J
(* Info after the call of this procedure the pointer *)
(* which was passed, points behind the last character of *)
{* the control character name in the Dump-Buffer *}
{********************************************************************}
begin
Buffer [Pointer] :- '<'; ( leads control character
for Counter := 1 to length(Text) do ( transfer Text to Buffer
Buffer[Pointer + counter] := Text[Counter];
Buffer[Pointer + Counter + 1] := '>'; ( terminates control char
Pointer := Pointer + Counter + 2; { Pointer to next character
end;
procedure DoDump;
135
6. The Disk Operating System PC System Programming
if not(Endc) then
begin ( NO
for Counter :- 1 to 30 ( Fill buffer with blanks
do DumpBuf [Counter) := , ';
DumpBuf[31) '= '219; Place Separator between Hex and ASCII
NextA :- 32; ASCII-characters follow separator
for Counter 1 to Regs.ax do ( start processing characters
begin ( read in
HexChr :- ord(NewByte[Counter) shr 4 + 48; ( Hex top 4 bits
if (HexChr > 57) then HexChr :- HexChr + 7; ( convert char
DumpBuf[Counter * 3 - 2) := chr(HexChr); ( store in buffer
HexChr :- ord(NewByte[Counter) and 15 + 48; ( Hex bot. 4 bits
if (HexChr > 57) then HexChr := HexChr + 7; ( convert number
DumpBuf[Counter * 3 - 1J := chr(HexChr); ( store in buffer
case ord(NewByte[Counter) of ( test ASCII-Code
NUL SZ(DumpBuf, 'NUL', NextA); ( NUL-character
BEL SZ(DumpBuf, 'BEL', NextA); ( Bell character
BS SZ(DurnpBuf, 'BS' , NextA); ( Backspace
TAB SZ(DumpBuf, 'TAB', NextA); ( Tab
LF SZ(DurnpBuf, 'LF' , NextA); ( Linefeed
CR SZ(DurnpBuf, 'CR' , NextA); Carriage Return
EOF SZ (DurnpBuf, ' EOF', NextA); ( End of File
ESC SZ(DurnpBuf, 'ESC', NextA); ( Escape
else
begin ( normal character
DumpBuf[NextA] := NewByte[Counter); ( Store ASCII-character
NextA '= succ(NextA) ( Set pointer to next character
end
end;
end;
DurnpBuf[NextA] :- '219; ( Set End character
DumpBuf[NextA+1) :- chr(CR); Carriage-Return followed by Line
DumpBuf[NextA+2] :- chr(LF); ( feed to buffer end
Regs.ah '= $40; ( Function number for writing handle
Regs.bx :- 1; ( Standard output device is handle 1
Regs.cx '= NextA+2; ( Number of characters
Regs.ds := seg(DumpBuf); { Segment address of the buffer
Regs.dx '= ofs(DurnpBuf); ( Offset address of the buffer
MsDos ( Regs ); { Call DOS-Interrupt 21H
end;
until Endc; { repeat until no more characters are available
end;
t****************************************···*****··***.********** ••• *}
(* MAIN PROGRAM •)
{********** •• ***** •• ********* •• ***** ••• *.******** •• *********.********j
begin
DoDump; ( Output Dump )
end.
136
Abacus 6.10 DOS Filters
C listing: DUMPC.C
/********.* •• ******.*****.*************.****.***~***** ***************/
1* DUMPC *1
1*------------------------------------------------------------------*1
1* Task a Filter which reads in characters from the *1
1* Standard input and outputs them as *1
1* Hex and ASCII-Dump on *1
1* the Standard output device *1
1*------------------------------------------------------------------*1
1* Author MICHAEL TISCHER *1
1* developed on : 08/14/87 *1
1* last Update : 04/08/89 *1
1*------------------------------------------------------------------*1
1* (MICROSOFT C) *1
1* Creation MSC DUMPC; *1
1* LINK DUMPC; *1
1* Call DUMPC [<Input] [>Output] *1
1*------------------------------------------------------------------*1
1* (BORLAND TURBO C) *1
1* Creation : tcc dumpc *1
1* Call : DUMPC [<Input] [>Output] *1
/***************************************************** ***************j
j***************************************************** ***************/
1* GETSTDIN: reads a certain number of characters from the Standard *1
1* input device into a Buffer *1
1* Input see below *1
1* Output Number of characters read *1
1***************************************************** ***************/
1***************************************************** ***************/
1* STRAP Attach character to string *1
1 * Input : see below *1
1* Output : Pointer behind the last added character *1
/****************************** ••• **.***~*.*****.***** ***************/
137
60 The Disk Operating System PC System Programming
j**.**.****.**** ••• **** •• *******.*** ••• *** •••• *** ••••• ******** ••• ****/
/* DODUMP reads the characters in and outputs them as Dump */
1* Input : none *1
1* Output : none *I
,.**** ••• ************.***** ••• ********* •••• *** •••• **** •• *********** •• /
void DoDurnp ()
/********.*.* ••••••• *.*.*******.**** •• ***** ••• ********* ••• *** ••• *****,
/** MAIN PROGRAM **1
,.****.********.*** •••• ** •• ***** •••• *** ••••• *****.**** ••• *** •• ***** •• j
138
Abacus 6.10 DOS Filters
void main ()
org 100h
139
6. The Disk Operating System PC System Programming
140
Abacus 6.10 DOS Filters
141
6. The Disk Operating System PC System Programming
<Ctrl><Break>
In order to prevent this, DOS calls interrupt 23H. This interrupt is also known as
the <Ctrl><Break> interrupt. When a program is started, this interrupt points to a
routine which brings about the end of the program. But a program is free to select
a routine of its own, thus maintaining control of what occurs when the user
presses <Ctrl><Break>.
However, the interrupt routine doesn't execute immediately. The break flag
controls when the interrupt routine occurs. This flag can be set at the DOS prompt
using the BREAK (ON/OFF) command from DOS, or with the help of DOS
function 33H, sub-function 1. If the break flag is on, every time a function of
DOS interrupt 21H is called, the keyboard buffer will be checked to see if either
<Ctrl><Break> or <Ctrl><C> has been pressed. If the break flag is off, this check
will be made only when calling the DOS functions that access the standard input
and output devices.
If this test fmds the appropriate key combination, the processor registers are loaded
with the values contained in the DOS function to be executed. Only after this is
interrupt 23H called.
If a program directs this interrupt to a routine of its own, there are several ways to
react. For example, the program could open a window on the screen which asks if
the user would like to end the program. It can also decide for itself whether or not
the program should end.
Maintenance
If the program chooses to halt execution, some form of clean-up routine should
follow. A routine of this type closes all open files, resets any changed interrupt
pointers, and releases any allocated memory. After this, function 4CH can end the
program without returning control to the interrupt 23H caller.
142
Abacus 6.11 <Ctrl><.Break> and Critical EmJr Interrupts
Both ways of handling this situation will be demonstrated in an example at the end
of this section.
Critical error interrupt
Unlike the <Ctrl><Break> interrupt, the critical error interrupt call is rarely a
reaction to something the user does intentionally. It is usually a reaction to an
error that occurs when accessing an external device, such as a printer, disk drive, or
hard disk. While the user can correct the error in many cases (e.g., printer not
turned on), other errors can be caused by hardware failures that require repairs (e.g.,
read error while accessing hard disk).
To make allowances for the various kinds of errors, the critical error interrupt
(interrupt 24H) normally points to a DOS routine that displays the following or a
similar message on the screen and waits for input from the user:
(A)bort (R)etry (I)gnore (F)ail
This clears the screen of the program currently under execution. In addition, this
interrupt doesn't provide a "clean" program end. Like <Ctrl><Break>, the program
is in a situation where files are not properly closed, allocated memory is not
released, etc.
Installing an interrupt handler in a program to replace the DOS handler can help
here, too. DOS enlists the help of a processor register to pass this handler various
information when it is called. This helps the interrupt handler locate the source of
the error. Bit 7 in the AH register indicates either a floppy or hard disk access error
(bit 7 ofO, or some other error (bit 7 on). In addition, the BP:SI register pair
points to the head of the device driver that was being called when the error
appeared. A detailed error code is contained in the lower 8 bits of the DI register,
and the contents of the upper 8 bits are undefined. This returns the following error
codes:
143
6. The Disk Operating System PC System Programming
When called, the; critical error handler can respond by opening a window on the
screen that asks the user to decide to ignore the error, retry the access, or abort the
program. The latter option can only instruct the interrupt to call DOS functions
OlH to OCH. This means that the program ends abruptly, similar to pressing
<Ctrl><Break>. While it is true that calling other DOS functions within the
handler causes no errors in itself, the return to DOS causes a system crash. Such
handlers are also not allowed to end a program through the use of DOS function
4CH. Instead the handler must return to its caller with the help of the lRET
command. With that, DOS expects a code in the AL register that will show it how
to react to the error. It interprets the contents of the AL register as follows:
The last output code in the above list represents the most sensible reaction to an
error that can't be fixed by repeating the operation (as in the example where the
printer needs to be turned on). The receipt of this code invokes the normal ending
of the function call in which the error occurred. The function then sets the carry
flag to signal the error. While this makes a "critical" error and a "normal" error
indistinguishable to the program, it's possible to tell them apart by setting a flag
within the critical error handler.
*******.**.********************•••• **********.************************
CE HAN D
*--------------------------------=-----------------------------------*
Description : Forms the basic structure of an assembler
program, in which the DOS Ctrl-Break and *
Critical Error Interrupt are captured
*--------------------------------------------------------------------*
Author : MICHAEL TISCHER
developed on 9/5/1988
last update : 4/8/1989
144
Abacus 6.11 <Crrl> <Break> and Critical E"or Interrupts
;* call CE HAND *;
;* (please leave the disk drive open so that a *;
;* Critical Error occurs.) *;
;.**.***•••••• **••••••• ********** •••••• *****•••••**••• ····**···········i
i-- constants ---===~=-===================----==--==-=--=--=====--=====-
145
6. TIu! Disk Operating System PC System Programming
146
Abacus 6.11 <Ctrl> <Break> and Critical Error 1nterrupts
147
6. The Disk Operating System PC System Programming
In earlier operating systems, device drivers resided in the operating system code.
This meant that changes or upgrades of these routines to match new hardware were
very difficult, if not impossible. DOS Version 2.0 introduced a flexible concept of
device drivers. This makes it possible for the user to adapt even the most exotic
PC clone to DOS.
Custom drivers
Since communication between DOS and a device driver is based on relatively
simple function calls and data structures, the assembly language programmer can
develop a device driver to adapt DOS to any device. Unfortunately, device drivers
cannot be programmed in a higher level language.
When developing the code for a driver, the same rules are observed as for
developing a COM program (no direct segment access). The difference is that a
device driver starts at offset address OH, and not at lOOH. The end of this section
explains the assembly language implementation in detail.
Drivers
During the DOS boot process, the drivers NUL, CON, AUX, PRN and the drivers
for the disk drives and hard drive (if needed) are loaded and installed. They are
arranged sequentially in memory and connected to each other. If the user wants to
install his own driver, he has to inform DOS using the CONFIG.SYS file. This
text file contains the information which DOS requires for configuring the system.
Contents of the CONFIG.SYS file are read and evaluated during the boot process
after linking the standard drivers. If DOS finds the DEVICE= command, it knows
that a new driver should be included. The name of the driver and perhaps a device
and path designation are indicated after the equal sign.
ANSI.SYS
DEVICE=ANSI.SYS
148
Abacus 6.12 DOS Device Drivers
The new driver is added to the chain immediately following the NUL device driver
(the first driver in the chain). The ANSI.SYS driver replaces the default CON
driver. To ensure that all function calls for monitor or keyboard communication
operate through ANSI.SYS, the ANSI.SYS driver is placed first in the device
group, and the CON driver is moved farther down the chain of devices. Since the
operating system moves from link to link during the search, it finds the new CON
driver (ANSI.SYS) first and uses it. Therefore, the system ignores the old CON
driver as seen in the illustration below:
Before adding
new CON
5'
driver Q
CD
I»
en
:r
cc
3
CD
3
o
-<
!.
...CD
Q.
Z
en
Not all drivers can be replaced with new ones. The NUL driver is always the first
driver in the chain. If you add a new NUL driver, the system ignores the new driver
and continues accessing the original NUL driver. This also applies to the drivers
for floppy disk drives and hard drives. The reason for this is that disk drives have
drive specifiers instead of names such as CON (e.g., A:). A new disk drive can be
added to the system, but since DOS may assign it the name D:, it may not be
addressed by all programs which want to access device A:. This problem can be
avoided by redirecting all device accesses using ooS's ASSIGN command. You
can make the ASSIGN command part of the AUTOEXEC.BAT file. It executes
after adding drivers and executing the CONFIG.SYS file. To redirect all accesses
from drive A: (the first disk drive) to device D: (in this case, a new driver for a new
disk drive), the AUTOEXEC.BAT file must contain the following command
sequence:
149
6. The Disk Operating System PC System Programming
ASSIGN A=D
The drivers for mass storage devices and the drivers such as PRN are handled
differently. ooS has two kinds of device drivers:
Character device drivers communicate with the keyboard, screen, printer and other
hardware on a character by character (byte by byte) basis. Block device drivers can
transmit an entire series of characters during each function call (disks, hard disks,
etc.). The two driver groups differ somewhat through the ways each supports
different functions.
Let's start with character device drivers because their structure is simpler than block
device drivers. Character device drivers transmit one byte for every function call.
They communicate with devices such as the keyboard, display, printer and modem.
A device driver can service only one device. Therefore, individual drivers for
keyboard, display, printer, etc., exist in ooS after booting.
In cooked mode, the device driver reads characters from the device and performs a
test for certain control characters. OOS then passes the character to an internal
buffer. DOS also checks to determine whether any <Enter>, <Ctrl><P>,
<Ctrl><S> or <Ctrl><C> characters exist. If the system detects the <Enter>
character, it ignores any further input from the device driver, even if the specified
number of characters has not yet been read. Then the characters read are copied from
the internal buffer to the buffer of the calling program. If characters are output in
cooked mode, DOS tests for <Ctrl><C> or <Ctrl><Break>. If one of these
combinations is detected, the currently running program stops. Pressing
<Ctrl><S> temporarily stops the program until the user presses any other key.
<Ctrl><P> redirects the output from the screen to the printer (PRN). Pressing
<Ctrl><P> a second time redirects the output from the printer back to the screen.
Raw mode
In raw mode, the device driver reads all characters without testing. If a program
wants to read in 10 characters, it reads exactly 10 characters, even if the user
presses the <Enter> key as the second character of the string. Raw mode transmits
the characters direct to the calling program's buffer, instead of using an internal
DOS buffer. During character output, raw mode doesn't test for <Ctrl><C> or
<Ctrl><Break>.
150
Abacus 6.12 DOS Device Drivers
DOS function 44H of interrupt 21H defmes the mode of the character device driver
(see the end of this section for a detailed description of this interrupt).
A block device driver normally communicates with mass storage devices such as
floppy or hard disks, or high speed cassette tapes. For this reason, they
simultaneously transmit a number of characters which are designated as a block. In
some cases, a single call to a function transmits several blocks of data. The sizes
of these blocks can differ from one mass storage device to another, as well as
within one particular mass storage device.
Everyone of these devices must have a flle allocation table (FAn and a root
directory. Block device drivers make no distinction between cooked and raw modes.
They always read and write the exact number of blocks unless an error is detected.
Access
There are several ways to access a device driver. Character device drivers are
accessed using the normal FCB or handle functions by simply indicating the name
of a driver (e.g., CON: instead of a fllename). A block device driver is accessed
using the normal DOS functions (flle, directory, etc.) by using the drive designator
assigned by DOS during the boot process.
Even though the two types of device drivers differ in some important details, they
do have similar structures. Each has a device header, a strategy routine and an
interrupt routine (a different kind of interrupt from the ones you've read about up
until now).
151
6. The Disk Operating System PC System Programming
Device beader
The device header appears at the beginning of each device driver and contains
infonnation needed by OOS for implementing the driver.
The fIrst two fIelds are the link to the next driver (offset and segment address) in
the chain of device drivers. The memory locations required for these link fIelds
must be reserved by the programmer, but OOS fIlls in when the driver is installed
in the system. The next fIeld of the device header is the attribute word. The
attribute word describes the device driver and tells OOS, among other things, if it
is a block or character device driver.
\7000
RAM
OOH nff.... t- "nnr...... "f n .. "j- nriv.. r 11 worn)
+ 02H Seament address of next driver 11 word)
+ 04H Device attribute 11 word)
+ 06H
+ 08H
+OAH
Offset address of strateqv routine (1 word)
Offset address of interrupt routine (1 word)
Driver name from character driver (8 bytes)
or number of devices used by block driver
/F= "
'
152
Abacus 6.12 DOS Device Drivers
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 bit
1=Cl.IT9rlt sIa"ldard
I I I IXI IXIXIXIXIXIXIXI I I I I-+ output delAce
I 1=a.rrent sta1dErd
il>Ut deIAce
... 1=a.rrent
dockdeW:e
. 1=OJrrent
NULdeW:e
. 1=Medum
cha1ge
mcognized
1=OOn-1BM
~ bmat
(I:.b:k diver)
1~lJl1i
i1s1n.Ja3d
L...-. (cf1crac.U <:tiwr)
1=1OCTL
support
. 0=I:lI0ck driI.er
1=Ghaa::U ctiwr
Only bits 11 through 15 are used by a block driver. The IOCTL bit tells DOS if
this driver supports the IOCTL function of DOS. The end of this chapter and the
descriptions of functions 3 and 12 describe this function in greater detail. Bit 11
fIrst appears in DOS Version 3 and should be 0 in earlier versions. A block driver
indicates whether a medium change is recognized on the device supported (e.g., a
floppy disk drive). If the bit is set, the driver must support a few additional
functions.
The next two fields contain the offset address of the strategy routine and interrupt
routine. The last field contains the name of the device driver if it is a character
device driver. If the name is less than eight characters in length, blank spaces
(ASCII code 32) pad the remaining characters. If it is a block device driver, the fIrst
byte of this field contains the number of logical devices supported by the driver.
The remaining seven bytes of this fIeld remain unused and contain the value O.
Strategy routine
DOS calls the strategy routine first to initialize the driver, then repeatedly before
each subsequent I/O request from the driver's interrupt routine. The address of a data
153
6. The Disk Operating System PC System Programming
The request header, whose address is passed to the strategy routine, always contains
at least 13 bytes and contains information which tells the driver how to perfonn
the upcoming operation. Depending on the operations performed, further
information can be added to the end of the request header which differs depending on
the operation.
RAM
+ OOH Data block lenqth in bytes
+ 01H Device number in communication (1 mdl
(1 word) \ 0000:0000
+ 02H Command code (1 word)
+ OSH Reserved (8 bytes)
+ DDH Media descriptor (1 byte)
+ OEH Buffer offset address (1 word)
+
+
+
1DH
12H
14H
Buffer segment address
Number
Starting sector
(1
(1
(8
word)
word)
bytes) / "
DOS calls the interrupt routine immediately after calling the strategy routine. Its
first task is to save the processor registers that will have their contents changed by
the various functions of the driver to the stack. Then it obtains the command code
from field 3 of the request header and calls the appropriate command code routine.
After executing the routine, it fills in the status field of the request header and
restores the processor registers from the stack. As a last step it returns control to
the calling DOS function.
Status field
The value of the status field specifies whether the function executed without error,
or if an error occurred during execution. For this reason, every driver function must
set the DONE bit (bit 8) in the status field. This DONE bit must be set even if the
function is a dummy (non-perfonning) function.
154
Abacus 6.12 DOS Device Drivers
1=error
O=medium write
1=ready 1=unknown device
2=drive not ready
1=busy 3=unknown command
4=read (CRC-) error
5=parameter data block
has a false length
6=search error
7=unknown medium
8=sector not found
9=printer out of paper
10=write error
11 =read error
12=common error
Under DOS Version 2, any installable device driver must support 13 functions,
numbered from 0 to 12, even if their only action consists of setting the DONE
flag in the status word. DOS Versions 3 and 4 include four additional functions
which can be supported, but are not required. Some of these functions concern one
of the two driver types, while others apply to both driver types (e.g.,
initialization). Unused functions must at least set the DONE flag of the status
word. Let's look at the various functions in detail according to their function
numbers.
Request header
Every function described here receives its arguments from the request header (whose
address is passed by DOS to the strategy routine) and stores its "results" in the
request header. For this reason, the offset address to the arguments, relative to the
beginning of the request header, is passed to the specified function. These
arguments are later transferred to variables. Besides this offset address, a flag
indicates whether this information consists of a byte, word or PTR. The PfR data
type represents a pointer to a buffer and consists of two adjacent words. The fIrst
word is the offset address of the buffer. The second word is the segment address of
the buffer.
155
6. The Disk Operating System PC System Programming
OOS calls this function during the system boot procedure to initialize the device
driver. This function can involve hardware initialization, setting various internal
variables to their default values, or the redirection of interrupts. Since the entire
operating system has not been completely initialized at this point, the
initialization routine can only call functions 1 through OCH and 30H of OOS
interrupt 21H. These functions can be used to determine the OOS version number
and to display a driver identification message on the screen. Even if the newly
linked driver is a CON driver, the output to the display occurs through the old
CON driver, because there are no new drivers linked into the system after
completion of the initialization routine.
In this case, the device name is ANSI.SYS, which assigns the standard ANSI
escape sequences for screen control to the PC. The memory address passed to the
initialization routine points to the character following the equal sign (in this case,
the A of ANSI.SYS). This makes it possible to store additional information
following the name of the device driver. This information is ignored by OOS, but
can be read by other routines.
The initialization routine must retlD1l four parameters to the calling OOS function.
The first parameter is the status of the function, i.e., the indication of whether the
function has executed correctly. For a block device driver, the number of logical
devices supported must also be passed. This information could also be obtained
from the device driver's header, but is ignored by OOS.
156
Abacus 6.12 DOS Device Drivers
The next parameter that the device driver must pass to OOS is the highest memory
address which it occupies or uses. This lets DOS know where the next device
driver can be installed.
BPB
If the driver is a block device driver, the last argument passed must be the address
of an array which contains an entry for every logical device. This array contains the
addresses of BIOS parameter blocks (BPBs). The address is passed as two words,
the fIrst word contains the offset, and the second word contains the segment address
of the array. The fIrst two words within this table are the address for the fIrst
logical device supported. The next two words indicate the address for the second
logical device, etc. The BPB, described in detail in Section 6.12, is a data block
containing information which describes a logical device. If all or some of the
logical devices have the same format, all entries in the BPB address table can point
to a single BPB.
157
6. The Disk Operating System PC System Programming
This function is used only with a block device driver. A character device driver
should merely set the DONE flag of the status word and exit. This function is used
by DOS to determine whether the media (diskette) has changed. It is often used
when examining a disk directory. If the disk medium was not changed since the
last access, DOS still has this information in memory, otherwise DOS must reread
the information from the media which delays the execution of the current task.
In some cases, as with floppy disks, the answer to the question is fairly
complicated. For this reason DOS permits function 1 to answer not only with
"yes" and "no", but also with "don't know." In any case, the answer affects further
DOS activity.
If the media is unchanged, access to the media can take place immediately. If the
media was changed, however, DOS closes all internal buffers related to the current
logical device. This causes the loss of all data which should have been transmitted
to the media. Then it calls function 2 of the current device driver, loads the FAT
and the root directory. If the media check function answers with "don't know," the
additional steps taken by DOS depend on the status of the internal buffers related to
the current logical device. If these internal buffers are empty, DOS assumes that
the media was changed and acts as if function 1 answered "yes." If the buffers
contain data which should have been transmitted to the media, DOS assumes that
the media is intact and writes the data. If the media was indeed changed, the data
written to a changed media may damage the new diskette's file structure.
Since subsequent processing depends on the response from the media check
function, the driver should handle the response carefully. Before enabling the
mechanism used by the function to respond, the function examines the parameters
passed to it. If the driver supports several logical devices, the first parameter is the
158
Abacus 6.12 DOS Device Drivers
number of devices. Next is a media descriptor code. This code contains information
about the type of media last used in the current logical device. Only devices which
can handle several different formats can use this task. For example, AT disk drives
which can use both 360K and 1.2 megabyte diskette formats.
If the media check function determines that the medium in a device is non
removable (e.g., a fixed disk), it can always respond "not changed". If, on the other
hand the device media can be changed (e.g., a disk), the correct response can only
be determined by fairly complex procedures. If these procedures are not used, the
response should be "don't know".
For the sake of completeness, here are the three procedures which provide fairly
accurate results.
Since a device with changeable media has an opening and closing mechanism, the
function should check to determine whether the media was removed. However, it
cannot determine if the removed media is identical to the newly inserted medium.
If the media has a name, the function should read this name to determine whether
the media was changed. This procedure only makes sense if every media has a
unique name.
The disk drive procedure used by DOS hinges on the fact that changing medium
takes some time. DOS assumes that even a user that can move fast needs about
two seconds to remove a diskette from a drive and insert a new diskette in the same
drive. If two consecutive diskette accesses occur less than two seconds apart, DOS
assumes that no diskette change occurred.
A byte in the data block is used to indicate changes. The value -1 (FFH) means
"changed", 0 means "don't know" and 1 means "not changed".
If the media was changed, the device driver signals a media change (bit 11 in the
device attribute = 1), the address of a buffer must be passed to DOS Version 3 and
newer, which contains the volume name of the previous media. This name must
be stored there as an ASCII string and terminated with an end character (ASCII
code 0).
159
6. The Disk Operating System PC System Programming
This function is used only by block device drivers. A character device driver should
just set the DONE flag of the status word and exit. DOS calls this function when
the media check function determines that the media was changed. This function
returns a pointer to a new BPB for the media
As you can see by the layout of the calling parameters. the device number media
descriptor and a pointer to a buffer are passed to this function by DOS. If the
device is a standard format (bit 13 of the device attribute =0). then the buffer
contains the first sector of the FAT.
Returned~eters of function 2:
Offset 3Jwor<D J Status word
Offset 18 (pte) I Address of the BPB of addressed device
This function passes control information from the character or block device driver
to the application program. It can only be called through function 44H of interrupt
21H if the IOCTL bit in the device attribute word in the device driver header is set
Different parameters are passed to the function. depending on whether the driver is
a c.JaraCter or a block device driver.
A character device driver is passed the number of characters to be transferred and the
address of a buffer for the transfer of the data
A block device driver is passed the device number, the media descriptor byte, the
address of the buffer to be used for the data transfer, the pointer to the flTSt sector to
be read and the number of sectors to be read.
160
Abacus 6.12 DOS Device Drivers
Function 4: Read
This function reads data from the device to a buffer specified in the calling
parameter. Should an error occur reading the data. the error status must be set.
Additionally the function must report the number of sectors or bytes read
successfully. Simply reporting an error is not good enough.
This function is used by a character device driver to test for unread characters in the
input buffer. A block device should set the DONE flag of the status word and exit.
DOS tests for additional characters using this function. If more characters exist, the
busy bit must be cleared (set to 0) and the next character passed to DOS. The
character that is passed remains in the buffer so that a subsequent call to a read
161
6. The Disk Operating System PC System Programming
function will return this same character. If no additional characters exist, the busy
bit must be set (set to 1).
Function number 5
Returned...Jllll1!!!!eters of function 5:
If a character is waiting to be read from the input buffer, the busy bit is cleared (set
to 0). If a character is not in the input buffer, the busy bit is set (set to 1).
When a character is waiting to be read, the Input Status function (06H) resets the
status word busy bit to 0 and returns the character to DOS. The character is not
removed from the buffer and is therefore non-destructive. This function is
equivalent to a one-character look ahead.
Function number 6
Returned~ameters of function 6:
J
Offset 3 (word) Status word: Characters already in buffer =0; Read request to
l.J?l.!Ysical device = 1
This function clears the internal input buffers of a character device driver. Any
characters read but not yet passed to DOS are lost when this function is used. A
block device driver should set the DONE flag of the status word and exit
Function number 7
162
Abacus 6.12 DOS Device Drivers
Function 8: Write
This function transfers characters from a buffer to the current device. If an error
occurs during transmission, the status word is used to indicate this error. Both
block and character devices use this function.
The parameters used for this function depend on whether the driver is for a character
or block device. Both pass a buffer address from which a certain number of
characters should be transferred. A character device driver is passed the number of
bytes to be transferred in addition to this information.
A block driver is passed the number of sectors to transfer (not the number of
characters), the number of the device to be addressed, its media descriptor and the
address of the first sector on the medium.
Should an error occur writing the data, the error status must be set. Additionally
the function must report the number of sectors or bytes written successfully.
Simply reporting an error is not good enough.
This function is similar to function 8, but with the difference that the characters
written are reread and verified.
163
6. The Disk Operating System PC System Programming
This function indicates whether the last write operation to a character device is
completed or not A block device should set the DONE flag in the status word and
exit.
If the last write operation is complete then the busy bit of the status word is
cleared; otherwise the busy bit is set to 1.
Function number 10
I
Returned ~eter of function 10:
Offset 3 (word) Status word: The busy bit is 1 if the last character output
has not been completed
This function completely clears the output buffer even if it contains characters
waiting for output. A block device should set the DONE flag on the status word
and exit.
Function number 11
164
Abacus 6.12 DOS Device Drivers
This function passes control infonnation from the application program to the
character or block device driver. It can only be called through function 44H of
interrupt 21H provided the IOC1L bit in the device attribute word in the device
driver header is set. Different parameters are passed to the function, depending on
whether the driver is a character or a block device driver.
A character device driver is passed the number of characters to be written and the
address of the buffer from which these characters are transferred.
A block device driver is passed the device number (in case the driver services
logical devices), the media descriptor byte, the address of the buffer from which the
data is to be written, the number of the ftrst sector to be written and the number of
sectors to be written.
A character device driver returns the number of bytes written. A block device driver
returns the number of sectors written.
The following four functions are supported by OOS version 3.0 and higher.
This function can be used only if the OCR (Open/Close/RM) bit in the device
attribute word in the device driver header is set Its task differs, depending whether
it is a character or block driver.
A block driver uses this function every time a ftle is opened. This function
detennines how many open fIles exist on this device. Use this command carefully,
since programs which access FCB function calls tend not to close open ftles. This
problem can be avoided by assuming during every media change that no ftles
us
6. The Disk Operating System PC System Programming
remain open. For devices with non-changeable media (e.g., a hard disk) even this
procedure may not help.
Within a character driver, this function can send an initialization string to the
device before transmitting the data. This is an advantage when used for
communication with the printer. The initialization string should not be included in
the driver, but can be called, for example, with the IOCTL function of interrupt
21H, which calls function 12 of a driver to transmit it from an application
program to the driver. The function can also be useful because it can prevent two
processes (in a network or in multiprocessing) from both accessing the same
device.
For the devices CON, PRN and AUX, this function is not called since they are
always open.
IReturned :r I
Offset 3 (word
eter of function 13:
Status word
This function is the opposite of function 13. This function can only be addressed if
the OCR bit in the device attribute word of the device driver header is set Its task
differs, depending whether it is a character or block driver.
A block driver calls it after closing a file. This can be used to decrement a count of
open files. Once all files on a device are closed the driver should flush the buffers
on removable media devices, because it is likely that the user is about to remove
the media.
A character driver can use this function to send some closing control information
to a device after completing output. For a printer this could be a formfeed. As in
function 13, the string could be transmitted from an application program using the
IOC1L function.
166
Abacus 6.12 DOS Device Drivers
This function indicates if the media in a block device can be changed or not. This
function is used only if the OCR bit in the device attribute word of the device
driver is set. A character device driver should set the DONE flag in the status word
and exit.
If the media can be removed, the busy bit is cleared; otherwise it is set to 1.
I
Returned parameter of function 15:
Offset 3 (word) Status word: If the media can be removed, the busy bit must
contain the value 0
This function transfers data from a buffer to an output device until the device is
busy (i.e., can no longer accept more characters). As this function is supported by
character devices, a block device driver should set the DONE flag on the status
word and exit.
This function works particularly well with print spoolers, through which files can
be sent to a printer as a background activity while a program executes in the
foreground. It is possible that not all of the characters in the transfer request will
be sent to a device during this function call. This is usually not an error, it could
be the result of the device becoming busy. The function is passed the number of
characters to be transmitted as well as the buffer address. If the output device
indicates during transmission that it can no longer accept additional characters, it
indicates the number of characters successfully transferred and returns control to the
device driver.
167
6. The Disk Operating System PC System Programming
The clock driver is a character device driver whose only function is to pass the date
and time from DOS to an application. The clock driver can also have a different
name, since DOS identifies it by the fact that bit 2 in the device attribute word of
the device driver header is set to I, instead of by name. Bit 15 must also be set
since the clock driver is a character device driver. Functions 2AR to 2DH of DOS
interrupt 21H read the date and time and call the driver. A clock driver must
support only functions 4, 8 and 0 (initialization). During the call of function 4
(reading), the date and time pass from the driver to DOS. DOS can set a new date
and time with function 8. Both functions have the time and date passed in a buffer
of 6 bytes in length.
+ OSH
Hundredths of seconds
Seconds
(1 byte)
(1 byte) V r
The date format is unusual. Instead of passing the month, day and year separately,
DOS passes the number of days elapsed since January I, 1980 as a 16-bit number.
A fairly complex formula converts this number into normal date format, taking
leap years into account. The clock driver normally uses function 0 and 1 of the
BIOS interrupt IAH to read and set the time.
Clocks on AT models
AT and AT-compatible computers have a battery powered realtime clock.
Functions 0 and 1 of interrupt lAR use a software controlled time counter and not
the battery powered realtime clock. When the computer is rebooted, the date and
time previously set with driver function 8 is cleared. You can use the clock driver
to access the realtime clock using functions 2 and 5 of interrupt lAH instead of
function 0 and 1.
168
Abacus 6.12 DOS Device Drivers
Now that you have some familiarity with the functions of the different device
drivers, you can look toward developing your own personal device driver. Here are
the steps which take place before and after calling a device driver function.
A chain of events begins when a DOS function which handles input and output is
called using interrupt 21H. Calling one of these functions can in turn call a series
of other functions and corresponding read and write operations.
Open
One example of this is when the Open function 3DH is called to open a file in a
subdirectory. First of all, before it can be opened, DOS must find the file. This
may require the searching of a set of directories instead of just reading in the FAT.
During each access of interrupt 21H, DOS determines which of the available device
drivers should be used to read or write characters. When this happens, DOS sets
aside an area in memory to store the information required by the device driver.
For files, DOS must convert the number of records to be processed into logical
sector numbers. DOS then calls the strategy routine of the device driver, to which
it passes the address of the newly created data block (request header). Then the
interrupt routine of the driver is called, which stores all registers. It isolates the
function code of the requested function from the data block and starts to process the
function.
If the addressed driver is a character device driver, the function only has to send the
characters to the hardware or request the characters to be read.
Block devices
For a block device (e.g., a mass storage device such as a floppy or hard disk) the
logical sector number must be converted into a physical address before a read or
write access. The logical sector number is broken down into a head, track and
physical sector number.
Mter the read or write operation ends, the driver function must place a result code
in the status field of the request header to be returned to the calling DOS function.
Next the contents of all registers are restored and control is returned to the calling
DOS function, which, depending on the result of the driver function, sets or resets
the carry flag and places any error code into the AX register. The interrupt function
then returns control to the routine which called interrupt 21H.
169
6. The Disk Operating System PC System Programming
The IOCTL function itself is one of many functions addressable from DOS
interrupt 21H. Its function number is 44H. Three groups of sub-functions are
accessible:
Device configwation
Data transmission
Driver status
The number of the desired sub-function is passed to the IOCTL function in the AI..
register. After the function call, the carry flag indicates whether the function
executed correctly. A set carry flag indicates the occurrence of an error and the error
code can be found in the AX register.
Sub-functions 6 and 7 can determine the status of a character device driver. Sub
function 6 can determine if the device is able to receive data. Sub-function 7 can
determine if the device can send data. The handle of this device is passed in the BX
register.
If the device is ready, both functions 6 and 7 return the value FFH in the AI..
register.
Sub-function 2 reads control data from the character device driver. The handle is
passed in the BX register and the number of bytes to be read is passed in the CX
register. In addition, the DS:DX register pair contain the address of the buffer into
which the data will be read. If the carry flag is clear, then the function was
successful and the AX register contains the number of characters read. If the carry
flag is set, then there was an error and the AX register contains the error code.
170
Abacus 6.12 DOS Device Drivers
The return codes are the same as for sub-function 2. These two sub-functions are
used to pass information between the application program and the device driver.
Block device driver status
Sub-functions 4 and 5 have the same task as sub-functions 2 and 3. However, they
are used for block devices and not character devices. Instead of passing the handle in
register BX, you pass the drive code (O=A, I=B, etc.) in the BL register.
Sub-function 0 is used to get device information for a specified handle. The sub
function nwnber is passed in the AL register and the handle in the BX register. The
function returns the device information word in the DX register.
For block devices:
bit 15 = reserved
1 if raw mode
bit 4 reserved
Two final interrupts are sometimes used by block device drivers. These two
interrupts, 25H and 26H are used to read from and write to the disk drive. You can
use these interrupts, for example, to process disks that were formatted using a
"foreign" operating system.
171
6. The Disk Operating System PC System Programming
Major headaches in developing a device driver occur because of problems that arise
during the testing phases of a new driver. First, a device driver must load into a
memory location assigned to it by DOS, at an address unknown to the
programmer. Second, a newly developed eON driver can't be tested using the
DEBUG program, since DEBUG uses this driver for character input and output.
We recommend that after you write the actual driver, you write a short test
program that calls the individual functions in the same manner as DOS, but
without having the driver installed as part of DOS. The advantages to this are that
everything executes under user control, and the whole process can be corrected with
a debugger. In any case, a new device driver (especially a block device driver)
should only be linked into the system after it has been tested completely and has
been proven to be error-free.
Note: When working with a hard disk, prepare a floppy system diskette
before test booting the system from the hard disk with the new driver
installed for the first time. If a small bug should exist in the new
driver, and the initialization routine hangs up, the booting process
will not end and DOS will be out of control. In such a case, the only
remedy is to reset the system and boot with a DOS diskette in the
floppy drive. Once DOS loads, you can then access the hard disk and
remove the new driver.
This section contains a sample device driver for each of the three different types of
device drivers, to demonstrate the information you've read about so far.
The first program is a character driver which corresponds exactly to the format of a
normal console driver. The second program is a block device driver which creates a
160K RAM disk. The final program is a DOS clock driver to support an AT
computer realtime clock.
***********************************************.****** ****··*********i
CONDRV *;
*-------------------------------------------------------------------*;
Task : This program represents a nonnal Console *;
Driver (Keyboard and Display Monitor). It should *;
serve as a framework for a driver in the form of *i
an ANSI.SYS driver. *;
172
Abacus 6.12 DOS Device Drivers
i*-------------------------------------------------------------------*i
;* Author MICHAEL TISCHER *;
;* developed on 8.4.87 *;
,. * last Update 9.2l.B7 *.
:*-------------------------------------------------------------------*;
;* assembly MASM CONDRV; *;
,. * LINK CONDRV; *.,
;* EXE2BIN CONDRV CONDRV.SYS *;
;*-------------------------------------------------------------------*:
;* c..ll Copy into Root Directory, copy the comnand *;
;* DEVICE-CONDRV.SYS into the file CONFIG.SYS *;
, and then boot t he System. *;
i···**********************************************···· ****************:
code segment
assume cs:code,ds:code,es:code,ss:cocte
173
6. The Disk Operating System PC System Programming
strat endp
;---------------------------------------------------------------------
intr proc far ;Interrupt routine
intr endp
i---------------------------------------------------------------------
dummy proc near ;This routine does nothing
174
Abacus 6.12 DOS Device Drivers
durmny endp
;---------------------------------------------------------------------
no_sup proc near ;This routine called for all functions
;which should really not be called
mov aX,B003h ;Error: Command not recognized
ret ;back to caller
;---------------------------------------------------------------------
store c endp
;--------_._-----------------------------------------------------------
read proe near :read a certain number of characters
;from the keyboard to a buffer
175
6. The Disk Operating System PC System Programming
read endp
; ----------'-----------------------------------------------------------
read b endp
;---------------------------------------------------------------------
del in b proc near ierase input buffer
-
mov ah,1
;still characters in the buffer?
int 16h
;Call BIOS key board interrupt
je del e
;no character in the buffer --> END
write endp
;---------------------------------------------------------------------
init proc near ;Initialization routine
176
Abacus 6.12 DOS Device Drivers
;=====---===-==-======--=~=============--==---=-----===-==============
code ends
end
The header of this driver describes a character device driver which handles both the
standard input device (keyboard) and the standard output device (monitor). Mter
linking it into the system, setting the two bits in the device attribute calls this
driver on all function calls previously handled by the CON driver. Like any other
driver, this driver has a strategy routine and an interrupt routine. The former stores
the address of the datablock in the variable DB_PI'R.
The interrupt routine saves the contents of all registers which will be changed by it
on the stack and gets the routine number to be called from the data block. It then
checks whether CONDRY supports this function. If not, it jumps directly to the
end of the interrupt routine and sets the proper error code in the status field of the
request header which was passed to the routine. Then it restores the registers which
were saved on the stack and returns control to the calling DOS function.
For any of the functions that are supported by the device driver, the offset address
of a routine to handle a particular function is determined from the table labeled
FK.T_TAB. Notice that the routines named DUMMY and NO_SUP appear several
times. DUMMY is for all functions which apply only to block device drives and
therefore are not used in this driver. The DUMMY routine clears the AX register
and sets the BUSY bit in the status word. The NO_SUP routine handles any
functions which cannot be used since the drive attribute for CONDRY does not
support these functions.
The STORE_C routine can be accessed from the lower level routines in this driver.
Its purpose is to store a character in the internal keyboard buffer of the driver. The
driver really shouldn't have this buffer available since BIOS (whose functions are
used by the driver to read characters from the keyboard) also has such a buffer. The
problem is that the BIOS always returns two characters when pressing a key with
extended codes (cursor keys, function keys etc.). If the higher level functions of
DOS only ask for one character at a time from CONDRY, the second character
must not be lost. It should be stored in a buffer and delivered to DOS by the read
function on the next call. This is STORE_C's task.
Reading characters
The next routine is the READ function. It obtains the number of characters to be
read from the request header passed by DOS. If it is 0, the routine is terminated
immediately. If not, then a loop starts which executes once for every character read
It rrrst tests for characters still stored in the internal keyboard buffer. If so, a
character is passed to the buffer of the calling function. If no additional character
177
6. The Disk Operating System PC System Programming
exists in the keyboard buffer, function 0 of the BIOS keyboard interrupt 16H
inputs a character from the keyboard. This character is also passed to the internal
keyboard buffer. If it's an extended keycode, it is divided into two characters. The
next step removes a character from the internal keyboard buffer and passes the
character to the buffer of the calling function. The process repeats until all
characters requested have been passed to DOS. Then the routine ends.
The higher level DOS functions also call the function named READ_P. It tests
whether a character was entered from the keyboard. If not, it sets the BUSY bit in
the status field of the request header passed by DOS, and returns to the calling
function. If a character was entered without having been read, the driver reads this
character and passes it to the calling DOS function in the request header, and resets
the busy bit. The character remains in the keyboard buffer, and on a subsequent call
of the read function, it is again passed to DOS. To test the availability of a
character, the READ] function uses function 1 of the BIOS keyboard interrupt
16H.
The function DEL_IN_B also gets called by the higher level DOS functions.
DEL_IN_B deletes the contents of the keyboard buffer. It removes characters from
the buffer using function 0 of the BIOS keyboard interrupt until function I
indicates that no more characters are available. This ends the function and it returns
to the calling function after the busy bit is reset
Writing characters
WRITE takes the number of characters from a buffer passed by DOS and displays
the characters on the screen. This routine uses function OEH of the BIOS video
interrupt. Once all characters have been displayed, it sets the BUSY bit in the
status field and ends the function. This function also executes when the higher
level DOS functions call the Write and Verify functions.
Initialization
The last function, the initialization routine, is called first by DOS. Since
CONDRV does not initialize variables and hardware, the routine simply enters the
driver's ending address into the passed request header. The routine returns its own
starting address since it will never be called again, and is the end of the chain of
drivers.
In its current form the driver has little use, since it uses only those functions
already available to the CON driver of DOS. It would be more practical if an
enhanced driver like ANSI.SYS were developed, through which screen design could
be more tightly controlled. For example, it's possible that such a driver would
have complete windowing capability which could be accessed from any program,
in any programming language.
178
Abacus 6.12 DOS Device Drivers
assume cs:code,ds:code,es:code,ss:code
erst b equ this byte ;this is the first byte of the driver
db 1 ;a device is supported
fkt tab dw of fset init ; Funct ion 0: Ini t iali zat ion
dw offset med test ;Funct ion 1 : Media Test
dw offset get=bpb ; [unction 2: created BPS
dw offset read ; function 3: direct reading
dw offset read ;Function 4: Read
dw offset dummy ; Function 5: Read, remain in Buffer
dw offset dummy ;Function 6: Input-Status
dw offset dummy ; Funct ion 7: Erase Input-Buffer
dw offset write ; Funct ion 8: Write
dw offset write ; Function 9: Write & Verifi cation
dw offset dummy ;Function 10: Output -Stat us
dw offset dummy ;Function 11: Erase Output-Buffer
dw offset write ;Function 12: direct Write
dw offset dummy iFunctlon 13: Open (after DOS 3.0)
dw offset dummy ; Funct ion 14 : Close
179
6. The Disk Operating System PC System Programming
:-- the Boot routine not included since a System can not----
be booted from a RAM-Disk
strat endp
:---------------------------------------------------------------------
intr proc far ;Interrupt routine
180
Abacus 6.12 DOS Device Drivers
intr endp
i---------------------------------------------------------------------
init proc near ;Initialization routine
181
6. The Disk Operating System PC System Programming
init endp
:---------------------------------------------------------------------
dummy proc near ;This Routine does nothing
dummy endp
;---------------------------------------------------------------------
med_test proc near ;Media of RAM-Disk
;cannot be changed
:---------------------------------------------------------------------
get_bpb proc near ;Pass address of BPB to DOS
get_bpb endp
i---------------------------------------------------------------------
no_rem proc near ;Media of RAM-Disk cannot be changed
mov ax,20 ; Set busy-bit
ret ;back to caller
182
Abacus 6.12 DOS Device Drivers
no rem endp
;---------------------------------------------------------------------
write endp
j---------------------------------------------------------------------
read proc near
read endp
move endp
183
6. The Disk ()perating System PC System Programming
;---------------------------------------------------------------------
code ends
end
This driver is similar to the CONDRY driver. The biggest difference between the
two lies in the functions which each supports.
Note: The initialization routine INIT here is more comprehensive than the
CONDRY initialization routine, and remains in memory after the end
of execution even though it is no longer needed. You'll see why this
is so in the paragraph below entitled "The INIT routine" .
First, this routine fmds the DOS version number using function 30H. If the
version number equals or is greater than 3, the request header passed by DOS
contains the device designation of the RAM disk. The system reads the
designation, changes it to a character and places the character into the installation
message. DOS function 09H is used to display this message on the screen.
Next, the program computes the ending address of the RAM disk. Since the actual
data area of the RAM disk starts immediately after the last routine of this driver,
160K is added to the program's ending address. Further, the address of a variable
(BPB_P1R) containing the address of the BIOS parameter block is passed to DOS.
This variable describes the RAM disk's format. In this case, it tells DOS that the
RAM disk uses 512 bytes per sector. Each cluster is made up of one sector and
only one reserved sector (the boot sector) exists. In addition, only one FAT exists.
Additional information indicates that a maximum of 64 entries can be made in the
root directory and that the RAM disk has 320 sectors available (160K of memory).
The FAT occupies a single sector, and the media descriptor byte FEH designates a
diskette with one side and 40 tracks of 8 sectors each.
These parameters are then placed into the request header of DOS and the segment
address of the data area of the RAM disk is calculated (which the driver itself
requires, DOS does not need this information).
184
Abacus 6.12 DOS Device Drivers
with these data structures and would crash the system. This is why the
initialization routine is not at the end of the last routine of the driver, which would
place it at the beginning of the RAM disk's data area.
The boot sector occupies the complete first sector of the RAM disk, but only the
fIrst 15 words are copied into it since DOS only needs these. The name "boot
sector" is actually a misnomer here, since it's impossible to boot a system from a
RAM disk.
The second sector of the RAM disk contains the FAT. The fIrst two entries are the
media descriptor byte and 0 in the entries that follow. These zeros indicate
unoccupied clusters (an empty RAM disk).
The last data structure is the root directory. It contains no entries other than the
volume name.
Remaining routines
This concludes the work of the initialization routine and returns the system to the
calling function. The remaining driver routines are examined in order.
The DUMMY routine performs the same task as the routine of the same name in
the CONDRV driver.
The MED_TEST routine is found only in block device drivers. This routine
informs DOS whether or not the medium was changed.
The next routine, GET_BPB, simply passes the addresses of the variables which
contain the address of the BPB of the RAM disk to DOS, as the initialization
routine had already done.
NO_REM allows DOS to sense whether the medium (the RAM disk) can be
changed. You cannot change a RAM disk, so the program sets the BUSY bit in
the status fIeld.
The two most important functions of the driver perform read and write operations.
As in CONDRV, the program calls Write and Verify instead of the normal Write
function, since no data error can occur during RAM access. The routine itself does
very little; it loads the value 0 into the BP register and jumps to the MOVE
routine. The READ routine performs in a similar manner, except that it loads a 1
into the BP register.
MOVE itself is an elementary routine for moving data. The BP register signals
whether data is to move from the RAM disk to DOS or in the opposite direction.
The routine receives all other data (the DOS buffer's address, the number of the
sectors to be transferred and the fIrst sector to be transferred) from the data block
passed by DOS. See the comments in the MOVE routine for details of the
procedure.
185
6. The Disk Operating System PC System Programming
Changes
This RAM disk: can of course be enhanced. If you have enough unused memory,
you can extend the size of the RAM disk: to 360K. AT owners could make the
RAM disk: resident beyond the I megabyte boundary. In this case, the data transfer
between DOS and the RAM disk: would use function 87H of interrupt ISH.
The clock driver
This final sample driver directly accesses the battery powered clock of an AT
computer. It offers the advantage that when the two DOS commands DAlE and
TIME are used, the date and time are passed directly to the battery powered realtime
clock. Reading the date and time reads the information directly from the memory
locations of the realtime clock.
i**************************·*****···*********·***********************·i
;* ATCLK *;
i*-----------------------------------------------------
;* Task
--------------*;
This program is a clock-driver which can be *;
;* used by OOS for functions which access date *;
;* and time on the battery powered clock *;
;* of the AT. *;
i*-------------------------------------------------------------------*i
;* Author MICHAEL TISCHER *;
;* developed on : 8.4.87 *;
.* last Update : 9.21.87 *;
;*-----------------------------------------------------
;* assembly MASK ATCLK;
--------------*i
*;
;* LINK ATCLK; *;
;* EXE2BIN ATCLK ATCLK.SYS *;
; *-----------------------------.-------------------------------------* i
;* Call : Copy into root directory place the command *;
;* DEVICE=ATCLK.SYS in the CONFIG.SYS file *;
;* and then boot the system. *;
i*********************************************************************i
code segment
assume cs:code,ds:code,es:code,ss:code
186
Abacus 6.12 DOS Device Drivers
strat
;---------------------------------------------------------------------
intr proc far ;interrupt routine
intr endp
;----------------------------------------------------------------------
187
6. The Disk Operating System PC System Programming
ck read endp
i----------------------------------------------------------------------
188
Abacus 6.12 DOS Device Drivers
ck_write endp
;-- OFS DATE: Convert number of days since 1.1.1980 into date
;-- Input : AX = Number of days since 1.1.1980
;-- Output CL - Year, DH - Month and DL - Day
;-- Registers : AX, BX, ex, DX, SI and FLAGS are changed
;-- Info : For conversion of Offsets the Array MaN_TAB
:-- is used
189
6. The Disk Operating System PC System Programming
shl al,1
shl al,l
shl al,l
iret urn in AL
190
Abacus 6.12 DOS Device Drivers
shr al,l
xor ah,ah ;Set AH to 0
mov ch,10 ;process in decimal system
mul ch ;multiply AX by 10
mov ch,cl ;transmit CL to CH
and ch,l1l1b ;Set Hi-Nibble in CH to 0
add al,ch ;add AL and CH
ret ;back to caller
;---------------------------------------------------------------------
init proc near ;Initialization routine
init endp
;---------------------------------------------------------------------
code ends
end
The basic structure of this driver differs from the other drivers in that it calls the
individual functions directly, not through a table of their addresses. Since it only
supports functions OOH, 04H and 08H, it can test the function numbers passed by
DOS directly. If any other function occurs, it signals an error. Besides the INIT
routine, which only sets the ending address of the driver like CONDRY, the driver
only has the Read Time and Date and Write Time and Date functions.
Time routine
The TIME routine is fairly simple. For reading the clock, the routine reads the
time from the memory locations of the clock, converts the time from BCD to
binary format and then passes the time to the DOS buffer. For setting the time,
the reverse occurs: The routine reads the time from the DOS buffer, converts the
code from binary to BCD format and writes the BCD code into the memory
locations of the clock.
DOS uses the same format for indicating time as the clock: Hour, minute and
seconds each comprise one byte.
191
6. The Disk Operating System PC System Programming
Date routine
The DATE routine is more complicated. While the clock stores day, month and
year as one byte each, date encoding by DOS is the number of days since January
1, 1980. This number must be converted into a date in the form of day, month and
year as DOS writes the time and date. The reverse is true when you call the Read
function: the clock date must be converted into the number of days. Let's look at
how this is done.
The conversion routine starts with the year 1980. January 1, 1980 (called
NUMDAYS from here on) is equal to the value O. The routine tests whether this
year is less than the current year. If so, it adds the number of days in this year to
NUMDAYS, adding a day to compensate for each ltap year. Then it increments the
year and tests again for a smaller number than the current year. This loop repeats
until it reaches the current year. The routine then computes the number of days in
the current year's month of February, and enters this month into a table which
contains the number of days for each month.
In the next step, for every month less than the current month, the routine adds the
number of days in this month to NUMDAYS. Once it reaches the current month,
only the current days of the month are added to NUMDAYS. The end result is
transferred to the DOS buffer and the routine terminates.
January starts another loop which tests whether the number of days in the current
month is less than or equal to NUMDAYS. If this is the case, the month
increments and the routine subtracts the number of days from NUMDAYS. If the
number of days in a month is larger than NUMDAYS, the loop ends. NUMDAYS
must only be incremented enough to give the day of the month and complete the
date.
The routine then converts the date to BCD format and enters the date in the
memory locations of the clock.
6.12.10 CD-ROMs
Soon after their introduction into the audio world, the compact disk industry began
approaching the PC market. A CD-ROM drive and a PC form an interesting
192
Abacus 6.12 DOS Device Drivers
combination. The compact disk medium itself is read-only, but 660 megabytes of
data can be stored in the form of text, graphics, etc.
Many publications and references are currently available on CD-ROM, such as:
Telephone directories
Books in Print
Why CD-ROM?
The CD-ROM has a clear advantage over the printed medium. Once captured and
digitized, information can be processed by a computer in whatever form the user
needs. The possibilities appear to be limitless, considering how easy it is to read
and compare information.
Another important consideration is the ease of access for many users. Load the
driver software, press a key or two, and the information is on the screen and ready.
You can buy a PC-compatible CD-ROM player for $800 to $1,000 at the time of
this writing. These players are available as either external or internal devices.
Interfacing
The PC's hardware can be easily interfaced to a CD-ROM player. The software
may encounter some problems, however. This is understandable, since DOS was
never intended to support these devices. This subsection shows how a CD-ROM
drive. using the proper drivers and utility programs, can be accessed like a read
only floppy disk drive. This information may not be of immediate use to you.
However, this data will give you a closer look into the world of the device driver
and operating system organization.
This book mentioned earlier that the device drivers act as mediators between the
disk operating system and the external devices such as monitor, printer, disk drives
and hard disks. DOS differentiates between block device drivers and character device
drivers. As a mass storage device capable of reading information in a block mode, a
CD-ROM drive would normally be added to the rest of the system through a block
driver. Here's where the problem begins: OOS makes a number of assumptions
about block devices, and a CD-ROM drive cannot meet the criteria of these
assumptions.
193
6. The Disk Operating System PC System Programming
Memory limitations
A character driver works better for implementing a CD-ROM driver, since DOS
makes no assumptions about the structure of the devices connected through
character drivers. Even character drivers are poorly suited for communication with a
CD-ROM drive, since they transmit characters one at a time instead of in groups
of characters. Another disadvantage is the need for a name (e.g., CON) instead of a
device designation. DOS must first see the CD-ROM driver as a character driver to
DOS to prevent read accesses to a non-existent FAT. The CONFIG.SYS file
supplies the name of the device during the system booting process.
The manufacturer usually includes CD-ROM driver software with the CD-ROM
drive package. A driver of this type usually has a name such as SONY .SYS or
HITACHI.SYS, depending on the manufacturer.
The CONFIG.SYS sequence which installs this driver can look something like
this:
DEVICE=HITACHI.SYS /D:CDRl
The device driver selects the name CDR! as the name of the CD-ROM drive.
Mter executing the initialization routine from DOS, the CD-ROM is treated as a
block driver which has been enhanced with a few special functions supporting CD
ROMs. However, DOS still views the CD-ROM player as a character driver: DOS
cannot view the CD-ROM's directory, nor can it directly access the files on the
CD-ROM.
MSCDEX /D:CDRl
194
Abacus 6.12 DOS Device Drivers
MSCDEX first opens this driver through the DOS OPEN function and provides it
a device designation. DOS assumes that MSCDEX is a device on a remote
network, as supported by DOS in Version 3.1.
MSCDEX brings us closer to the solution, since DOS handles network devices as
files containing more than 32 megabytes. These devices are accessed through
redirection, rather than direct access from DOS. The resident portion of MSCDEX
interfaces to the redirector, and intercepts all calls to the redirector. If MSCDEX
receives a call addressed to the CD-ROM drive, it adapts each instruction to a call
applicable to the CD-ROM driver. This makes a perfect connection between DOS
and the CD-ROM drive, while still allowing access to subdirectories and files at
any time.
CD-KJM ecce••
Keyboard
CD-KIM dr i ve
195
6. The Disk Operating System PC System Programming
From the user's viewpoint, DOS addresses mass storage devices as volumes where
each individual volume has been assigned a letter. Floppy disk drives are identified
by the letters A and B, while the letters C or D usually identify a hard disk. A
mass storage device can have several volumes. This division into several volumes
or partitions is very practical for hard disks. Partitions on a floppy diskette don't
work as well due to the limited amount of storage space. A hard disk may be
divided into additional partitions if UNIX (or XENIX) is used in addition to DOS.
Each of the two operating systems then has its own volume which is also
designated by its own letter.
Volume names
Each volume can be assigned a volume name when created, but this volume name
is not a requirement. The DIR command lists volume names when they are
available. Each volume has its own root directory, which can contain multiple
subdirectories and files. These subdirectories and files can be maintained and
manipulated by using one or more of the interrupt 21H functions.
Sectors
DOS subdivides each volume into a series of sectors. These sectors are organized
sequentially. Each sector contains a specific number of bytes (usually 512) and is
assigned a consecutive number beginning with sector O. Since function calls with
interrupt 21H are directed to files rather than individual sectors, DOS converts
these file accesses into sector accesses. To do this, DOS uses directories and a data
structure known as the FAT (file allocation table), which you read about earlier in
this book. Mter the desired sector number has been determined, control is passed to
the device driver which translates this sector number into a physical address. Mass
storage devices such as floppy and hard disks are divided into individual tracks
which contain a certain number of sectors. In addition to the physical sector
number, the driver must also detennine the number of the track and the number of
the read head.
196
Abacus 6.13 DOS Mass Storage
The name boot sector comes from the fact that OOS boots (i.e., starts) from it.
DOS is loaded and started from disk-it is not usually stored in permanent PC
memory (ROM). After you turn the computer on, the BIOS takes over the system
initialization and loads logical sector 0 of the floppy or hard disk into memory.
Once it completes its work the BIOS starts execution at address O.
197
6. The Disk Operaling System PC System Programming
Bootstrap
Next comes the bootstrap routine to which the jump instruction branches at the
beginning of this boot sector. It handles the loading and starting of DOS through
the individual system components (see Section 6.3).
Several reserved sectors may follow the boot sector. These reserved sectors can
contain additional bootstrap code. The numbers of these sectors are recorded in the
BPB in the field starting at address OEH. It terminates the boot sector and a 1 in
this field indicates that no additional reserved sectors follow the boot sector (this is
the case for most PCs).
In order for OOS to add new files or enlarge existing files, it must know which
sectors of the media are still available. This information is contained in a data
structure called the FAT (file allocation table) which is immediately adjacent to the
media's reserved area. Each entry in the FAT corresponds with a certain number of
logically contiguous sectors, called clusters, on the media. Location ODH of the
boot sector specifies the number of sectors per cluster as part of the BIOS
parameter table. Only multiples of 2 are legal values. On an XT hard disk this
location contains the value 8 (8 consecutive sectors form a cluster). As the
following table demonstrates, the number of sectors comprising a cluster depends
on the stomge medium.
The reason for joining several sectors into a cluster is derived from the logic used
by OOS to write files to a media. It disassembles the file to fit the pieces into the
198
Abacus 6.13 DOS Mass Storage
sectors which are still available, instead of selecting adjoining sectors for file
storage. This process slows file access since the read/write head must be
repositioned after almost every read function. To avoid an excessive disassembly of
the file, DOS gathers several sequential sectors on the media into a cluster. This
ensures that at least the sectors of a cluster contain a portion of a file. If DOS
didn't use clusters, a file of 24 sectors could be stored in many separate sectors,
which would require the read/write head to be positioned a maximum of 24 times
to read the entire file. The cluster principle saves a lot of time, since the file is
stored in 6 clusters and the read/write head only has to be repositioned 6 times.
There is a problem however. Since a file is assigned at least one cluster, some
storage space is wasted. Consider AUTOEXEC.BAT which is usually no longer
than 150 bytes. Normally, a single sector could contain this file (and still waste
almost 400 bytes), but AUTOEXEC.BAT occupies a cluster of 2048 bytes on an
AT, which wastes more than 1.5K of hard disk space.
The size of individual entries in the FAT under DOS Versions 1 and 2 is 12 bits.
For DOS Version 3 and later, the size of an entry in the FAT depends on the
number of clusters: if a volume has more than 4,096 clusters, then each FAT entry
is 16 bits; otherwise each FAT entry is 12 bits. The number of bits per FAT entry
must be determined before file access. The information in the BIOS parameter
block is used for this purpose. The total number of sectors in the volume can be
found starting at location 13H. Divide this number by the number of sectors per
cluster to obtain the number of clusters in the volume.
The fIrst two entries of the FAT are reserved and have nothing to do with the
cluster assignmenl Depending on the sizes of the individual entries, 24 bits (3
bytes) or 32 bits (4 bytes) can be available. The first byte contains the media
descriptor, while the value 255 ftIl in the other bytes. The media descriptor, which
is also stored in address ·15H of the BPB, indicates the device which the media uses
(for example a diskette). The following codes are possible:
Code Device
F8H Hard disk
F9H 5.25" disk drive (AT only)
2 sides, 80 tracks, 15 sectors
FCH 5.25" disk drive
1 side, 40 tracks, 9 sectors
FDR 5.25" disk drive
2 sides, 40 tracks 9 sectors
FER 5.25" disk drive
1 side, 40 tracks, 8 sectors
FFH 5.25" disk drive
2 sides, 40 tracks 8 sectors
This shows the various diskette fonnats which DOS supports in 5.25" diskettes.
199
6. Tire Disk Operating System PC System Programming
You may have wondered why the individual entries of the FAT are 12 or 16 bits
wide if all they do is indicate whether a cluster is occupied or not. This could have
been done with one bit: The bit could contain 1 when the cluster is occupied and 0
if the cluster is available. The reason is that the entries in the FAT help mark the
available clusters and identify the individual clusters containing a specific ftle. The
directory entry of a file tells OOS which cluster holds the fIrst data of a file. The
number of this cluster corresponds to the number of the FAT entry belonging to
it. In this entry is the number of the cluster containing the next sector of ftle data.
As the following illustration shows, a chain fonns in which the individual clusters
assigned to a ftle can be located in the proper sequence.
200
Abacus 6.13 DOS Mass Storage
Media descriptor
entry number FAT
(12 bit)
O.
1.
00
F 0 R M
2.
3.
04 A T 32 32
4.
5.
E X E
6.
7.
8.
9.
A.
B.
C.
D. 74
E. IC
F. 16
The FAT entry which corresponds to the last cluster of a file must contain a
special code which tells DOS that the file ends here. The following table shows
the meanings of the various FAT entries.
Code Meaning
(O)OOOH Cluster is available
(F) FFOH - (F) FF6H reserved cluster
(F) FF7H Cluster damaged, not used
(F) FF8H - (F)FFFH Last file cluster
(x)xxxH Next file cluster
DOS is designed so that several identical copies of the FAT on the media may be
kept. This offers the advantage that in case of damage to one FAT, it can be
replaced with another, preventing data loss.
The DOS CHKDSK command tests the various FATs to see if they are identical.
201
6. The Disk Operating System PC System Programming
Directory structure
Now let's look at the structure of a directory.
The root directory of a volume immediately follows the last copy of the FAT.
This root directory (like all subdirectories) consists of 32-byte entries in which
information can be stored about individual files, subdirectories and volume names.
The maximum number of entries in the root directory, and therefore its size, is
stored in the BPB starting at address HH. The FORMAT command specifies both
the size number and the BPB. Before considering individual fields of this data
structure, here's a graphic overview of a directory entry:
The first 8 bytes normally contain the name of the current file. If the filename is
shorter than 8 characters, DOS fills the remaining characters with spaces (ASCII
code 32). If the directory entry does not contain information on a file, but the file
is used in another manner, the first byte of the filename (therefore the first byte of
the directory entry) is identified by special code:
Code Meaning
OOH Last directory entry
OSH First character of filename
has ASCII code ESH
2EH File applies to current
directory
ESH File deleted
The second field contains the three character filename extension. If the extension is
less than three characters in length, DOS fills in the extra characters with blank
spaces (ASCII code 32). The period between filename and extension is displayed by
the DOS command DIR but is not kept in the directory; DIR displays it just to
make the names between easier to read.
Next follows the one-byte attribute field. As shown in the following figure the
individual bits of this field define certain attributes. The various attributes can be
combined so that a file (as in the IBMBIOS.COM file) can have the attributes
READ_ONLY, SYSlEM and HIDDEN.
202
Abacus 6.13 DOS Mass Storage
7 6 5 4 3 2 1 o bi t
I I l l I I I 1_ p=read/write
~ =wrlte-protected
enabled
L I
I ~=hldden file
(Invisible to DIR)
=system file
=volume name
=subdlrectory
arChive bit
reserved
While the significance of bits 0 to 4 is easy to see, the significance of bit 5 needs
additional explanation. The name archive bit comes from its use in making backup
copies. Every time a file is created or modified, this bit is set to 1. If a program is
used to backup this file, (for example the DOS BACKUP command), the archive
bit is reset to O. The next time the BACKUP command is used, it can detennine
from the archive bit whether this file has been modified since the last backup. If it
still contains the value 0, the file doesn't have to be backed up again. If the archive
bit contains a I, the file was modified and should be backed up again.
The attributes volume name and subdirectory will be discussed in more detail
below.
A reserved field which DOS requires for internal operations follows the attribute
field
The time and date fields indicate when the file was last created or modified. Both
are stored as words (2 bytes), but have special and different fonnats.
203
6. The Disk Operating System PC System Programming
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 bit
~I~I~I~I~I~I~I~I~I~I~I~I~I~I~I~I
I I
. I
Hour Minute Seconds In
2-second
Increments (e.g.,)t
(13 means 26)
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 o bit
IIIIIIIII III II I I
I I I
Year (relative to 1980) Month Day of month
The file size in bytes is stored in 2 words with the lower word stored frrst. Using a
small formula and the two words, the ftle size can be calculated as follows:
File size = wordl + word2 * 65,536
Both subdirectory and volume name deserve special consideration. The volume
name can only exist in the root directory and is indicated by bit 3 of the current
directory entry's attribute field. The ftlename in a volume entry acts as the volume
name; the DOS commands DIR, VOL and TREE can be used to display the
volume name.
If bit 4 of the current directory's attribute field is set, then this entry is for a
subdirectory. If in addition bit 1 in this field is set, the subdirectory can be
addressed, but will not be displayed when you execute the DIR command. For
these entries, the ftlename and extension field contain the subdirectory name; the
date and time field contain the time of its creation. The file length field is always
O. The field which normally indicates the frrst cluster of the me now indicates the
cluster which contains the directory entries of this subdirectory. They have the
same 32-byte structure as the entries in the root directory. As in a normal file, the
entry in the FAT, which corresponds with the subdirectory cluster, points to the
next cluster of the subdirectory, as long as one cluster is enough for the directory
of the subdirectory. This is not true of the root directory which extends through
several sectors or clusters, which follow each other logically. Furthermore the
204
Abacus 6.13 DOS Mass Storage
individual clusters of the root directory cannot be connected through the FAT,
because it only refers to the data area of the volume. This is the area which accepts
mes and subdirectories, but not the root directory.
The process described above reveals that DOS separates the individual mes in a
storage unit according to their directories. It doesn't store the files of one directory
in one area, but scatters the files across the storage medium.
When a subdirectory is created, two files are created with the names '.' and '..'
which can only be erased when you remove the entire subdirectory. The frrst of
these two mes points to the current subdirectory. and its cluster field contains the
number of the first cluster of the current subdirectory. The second entry points to
the parent directory. which in the directory tree is located ahead of the current
directory. If the parent directory is the root directory, the cluster field contains the
value O. The path to the root directory can be traced back through this entry. since
as every subdirectory searches for its parent directory it comes closer to the root
directory.
Now back to our discussion of mass storage device structures. The file area follows
the root directory just described. It occupies the remaining storage area of the mass
storage device. It accepts the individual files and various subdirectories. For every
cluster in this area there is an entry in the FAT corresponding to this cluster. If a
file is enlarged, DOS reserves a cluster which is still available to store the
additional data of the file. The FAT entry of the last cluster which formerly
indicated the end of me is changed to point to the new cluster which in tum
contains the new end character. In DOS Versions 1.0 and 2.0, unused clusters are
searched for from the beginning. In DOS Versions 3.0 and up, a more
sophisticated search is used to try to select an unused cluster in the vicinity of
other clusters comprising the file. This reduces the access time to the me as much
as possible. Conversely, when reducing file size or deleting a file, the FAT is
updated to indicate that the unused clusters are again available. They can be used
again when a new file is created or expanded.
20S
6.14 T
ips on Compatibility between Computers
This book discusses three methods of accessing PC hardware. On the one hand,
you can access available DOS or BIOS functions. On the other hand, you have the
option of developing new functions and routines for direct hardware control. While
this offers no advantage in mass storage device and keyboard access, special
routines for screen display are often much faster and more efficient than BIOS and
DOS routines used to do the same job.
For compatibility, however, DOS functions win hands down. Those of you who
want to develop programs which can run, without problems, on virtually any DOS
computer, must observe some rules for DOS function calls. These rules also apply
to future compatibility. To develop programs under the current DOS versions
which should execute without problems under future versions of DOS, you should
follow the suggestions made below.
Use only DOS functions for screen and hardware access. Do not use BIOS
or other hardware dependent functions.
Display error messages on the standard error device (handle 2).
Use Version 2 UNIX-compatible handle functions for file access. This
ensures compatibility with future versions of DOS.
If you use the old FCB functions for file or directory access (e.g., for
special attributes), make sure no FCBs are opened which are already open,
and no FCBs are closed which are already closed. This could cause
problems in a network.
Check the DOS version number at the beginning of the program and end
the program with an error message if it cannot be executed under this
version.
Store as many constants as needed for program execution (e.g., the paths
of programs and files to be loaded) within the environment block. Access
these values from the environment block within the program.
Release all memory not required by the program using the DOS functions
(this is especially important when working with COM programs).
If you need additional memory, request it by using the proper DOS
functions.
Use the available DOS functions for interrupt vectors; do not access
interrupt vectors directly.
• To change the contents of various interrupt vectors within a program,
flfSt save the old contents and restore them before the end of the program.
206
Abacus 6.14 Tips on Compatibility between Computers
Call one of the DOS functions (31 H or 4CH) before the end of the
program to pass a value to the calling program to signal whether the
program was executed correctly. Avoid using the other functions for
ending a program (interrupt 20H and function 0 of interrupt 21H).
Use function 59H of interrupt 21H (available in DOS Versions 3.0 and
higher) to localize error sources.
In conclusion, here is an overview of the older DOS functions to avoid. and the
new equivalent functions that can replace them.
Old New
OOH End proqram 4CH End Process
OFH Open file 3DH Open Handle
IOH Close file 3EH Close handle
llH Find first entry 4EH Find first entry
12H Find next entr~ 4FH Find next entry
13H Erase file 4lH Erase directory entry
14H Sequential read 3FH Read (through handle)
ISH Sequential write 40H Write (through handle)
16H Created file 3CH Created handle or
5AH Created temporary file or
5BH Created new file
17H Rename file 56H Rename directory entry
2lH Random access read 3FH Read (throuqh handle)
22H Random access write 40H Write (throuqh handle)
23H Sense file size 42H Move file pointer
24H Set data set number 42H Move file pointer
26H Create new PSP 4BH Load and execute from file
27H Random access read 3FH Read (through handle)
28H Random access write 40H Write (through handle)
If you follow all these suggestions, your programs will execute on other
computers and under future DOS versions with little or no modifications.
207
6. The Disk Operating System PC System Programming
The many structures which DOS keeps in mass storage (boot sector, File
Allocation Table [FA11, root directory, etc.)
Floppy disk and hard disk management utilities make intensive use of the
undocumented structures. If you examine the Norton Utilities® using a debugging
application, you'd see how much this program accesses these structures.
A minor change in these structures took place between DOS Version 3.3 and
Version 4.0, but this is the fIrst change since the introduction of ooS Version 2.0
in 1983. Therefore, the chances are almost nil of fInding altered coding in the
undocumented structures of subsequent OOS versions.
Knowing about these structures can be practical data for programming some
applications. This section lists our fIndings from viewing the Norton Utilities®.
The DOS Info Block (DIB) is the key to accessing the most important DOS
• structures. This block holds pointers to several ooS structures and to other
information as well. The knowledge of its existence and construction is useful to a
program only if its address in memory is known. This address is not in a fIxed
memory location, nor can it be obtained with any of the documented functions of
DOS interrupt 21H. However, the undocumented function 52H can offer us some
208
Abacus 6.15 Undocumented DOS Structures
assistance in finding that address. Calling function 52H returns the address of the
DOS Info Block to the ES:BX register pair.
As opposed to all other DOS functions that fetch pointers to a structure or data
area, the contents of the ES:BX register pair point not to the fust. but rather to the
second field within the DIB after the function call.
The first field in the DIB contains a pointer to the Memory Control Block (MCB)
of the fust allocated memory area. You will find detailed information on this
structure and what it does in Section 6.9 (Memory Allocation from DOS). The
pointer in the second field of the DIB gives access to a wealth of information that
could not be had in any other way. It points to the first Drive Parameter Block
(DPB), a structure which DOS lays out for all mass storage devices (floppy disks,
hard disks, tape drives, etc.).
209
6. The Disk Operating System PC System Programming
The fIrst fIeld of the OPB tells us to which device the block belongs. 0 stands for
drive A, 1 for B, 2 for C, etc. The second field specifIes the number of the subunit
To understand the meaning of this field, remember that access to the individual
devices occurs through the device driver. DOS doesn't perform direct access to a
disk drive or hard disk. This keeps DOS from having to deal with the physical
characteristics of a mass storage device. Instead, DOS calls a device driver for this
purpose, which acts as mediator between DOS and hardware.
Of course, not every device has a separate device driver, since one device driver can
support many single devices. For example, the device driver built into DOS
manages the floppy disk drives and the fust available hard disk. DOS confIgures a
OPB for each device, so a hard disk system would automatically have 3 OPBs
available (a OPB is always configured for floppy drive B, even if only one floppy
drive is actually available). Each device receives a number between 0 and the total
number of devices minus 1, to help each driver to identify the devices it manages.
This number is the one found in the subunit field.
The next field lists the number of bytes per sector. Under DOS this is almost
always 512. After this comes the interleave factor, which gives the number of
logical sectors displaced by physical sectors when the medium is formatted (more
on this in Chapter 7). This value can be 1 for floppy disk drives, 6 for the XT hard
disk and 3 for the AT hard disk. For floppy disk drives, this fIeld can also have the
value FER if no access has been attempted to the disk in the drive. The value FER
means that the interleave factor is currently unknown.
There are a number of other fields related to these two which have already been
named in connection with the management of mass storage devices through DOS
(see Section 6.13). Among other things, they describe the status and the size of the
structures DOS created to manage mass storage devices. A pointer to the header of
the device driver lies within these fields. DOS uses this pointer when accessing the
device. More information can be obtained with this pointer since, for example, the
driver attribute is listed in the header of the device driver.
Following this field is the media descriptor to which the Used flag is connected.
As long as no access to the device has occurred, this flag contains the value OFFH.
After the frrst access it changes to 0 and remains unchanged until a system reset.
The OPB ends with a pointer that establishes communication with the next OPB.
Since every OPB defines its end with such a pointer, a kind of chain is created,
through which all OPBs can be reached. To signal the end of the chain, the offset
address of this pointer in the last OPB contains the value OFFFFR., When a
program needs the information within the DOS, there are many ways to find the
address of the desired OPB. One method is to follow the chain described above by
fust finding out the address of the DIB. This gives you the pointer to the fust
OPB, from which you can follow the chain until you reach the OPB you want.
210
Abacus 6.15 Undocumented DOS Structures
There's a better way, which isn't as susceptible to changes within the DIB, through
two undocumented DOS functions. This involves the IFH and 32H functions,
which have been part of the DOS function repertoire since Version 2.0, although
not documented by Microsoft. When called, both return a pointer to a DPB to the
DS:BX register pair. While function IFH always delivers a pointer to the DPB of
the current disk drive, the address delivered by function 32H refers to the device
whose number is passed to the function in the DL register at the time it's called. (0
represents the current drive, 1 is drive A, 2 drive B etc.). It's much more flexible
than function IFH.
Access to the various DPBs with the IFH and 32H functions offers a further
advantage, because it forces DOS to retrieve other information such as the
interleave factor and the media descriptor byte, which is ascertained for the disk
drive only after the fIrst access. If you get to the DPB through the pointer in the
DIB block, the various fIelds may not have been initialized, and could contain the
wrong values.
Besides the pointer to the frrst DPB, the DIB contains the pointer to the frrst DOS
buffer at address 12H. These DOS buffers store individual sectors, so that the
sectors don't have to be repeatedly loaded from disk. The DOS buffers can be most
effective when used for storing disk sectors that are frequently needed by the
currently running program. Besides the FAT, these include the root directory and
its subdirectories. The number of buffers can be defIned by the user in the
CONFIG.SYS fIle. If this number exceeds those needed for the FAT, root directory
and subdirectories, normal sectors can also be temporarily stored here, in the hope
that they are called to be loaded again in the near future, and can be taken directly
from the buffer.
So that DOS can quickly check each buffer for the desired sector with every read
operation, the individual sectors are linked together.
As with DPBs, this happens with the help of a pointer which appears at the start
of every buffer. Also, the last buffer is reached when the offset address of the
pointer contains the value OFFFFH. After the fIeld linking one buffer to the next
comes the number of the drive where the buffered sector originates. The value
would be 0 for drive A, 1 for B, 2 for C, etc. Besides the drive number, the
identification of a sector requires a sector number. This is located beginning at
position 06H in the DOS buffer. The last fIeld in the buffer header stores a pointer
211
6. The Disk Operating System PC System Progranuning
to the corresponding DPB, so that DOS can get information on the device which
loaded the buffered sector. Although this is the last field in the header of the DOS
buffer, the buffered sector does not end immediately after this field. There are two
more bytes which follow. The reason for this is that the DOS code is written in
machine language, and when it comes to working with memory blocks, it is most
efficient to have the buffered sector begin with an address that is divisible by 16.
The header of the DOS buffer is not the last place we run across the DPB. It turns
up again in the path table, which starts at address 16H in the DIB. This contains
the current path for each drive as well as a pointer to its DPB.
o 1 2 3 4 5 678 9 ABC DEI
0000: 41 3A 5C 43 41 43 48 45-00 00 00 00 00 00 00 00 A:\CACHE ........
0010: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00
0020: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00
0030: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00
0040: 00 00 00 00 40 20 74 80-02 27 03 FF FF FF FF 02 .... @ t .. • .... ..
0050: 00 42 3A 5C 00 00 00 00-00 00 00 00 00 00 00 00 .B:\ .......... ..
0060: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00
0070: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00
0080: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00
0090: 00 00 00 00 00 40 40 74-80 02 00 00 FF FF FF FF ••••• @@t . . . . . . . .
OOAO: 02 00 43 3A 5C 54 43 5C-42 41 55 53 5C 41 53 4D •• C:\TC\BAUS\ASM
OOBO: 5C 48 45 52 43 4D 4F 4E-4F 00 00 00 00 00 00 00 \HERCMONO •••••••
OOCO: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00
OODO: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00
OOEO: 00 00 00 00 00 00 40 60-74 80 02 65 05 FF FF FF . . . . . . @'t .. e •..•
OOFO: FF 02 00 44 3A 5C 4D 53-43 5C 42 49 4E 00 00 00 ••• D:\MSC\BIN •••
0100: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00
0110: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00
0120: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00
0130: 00 00 00 00 00 00 00 40-00 00 80 OD 17 00 FF FF . . . . . . . @. . . . . . . .
0140: FF FF 02 00
212
Abacus 6.16 DOS 4.0
Graphic user interfaces for directory display, file selection and running
progmms
Hard disk partition (volume) support and support for device capacity larger
than 32 megabytes
The introduction of these features mean changes in the opemting system code.
Although most of these changes will not affect most application programs, they
may cause problems in programs that lie within the system, as well as programs
developed without following rules of compatibility (see Section 6.14).
Compatibility problems
First of all, the support of hard disk partitions and files larger than 32 megabytes
implies definite changes to the DOS file system. These changes don't affect
programs that manipulate files only through the DOS interrupt 21H functions.
However, many block device drivers and progmms that access the DOS structures
of the file system directly will have to be adapted to the new file system. This
includes programs like the Norton Utilities®. PC Tools® and all the other
utilities which perform tasks such as optimizing hard disks and restoring lost files.
All of these will be of little or no use under DOS Version 4.0.
To give you a chance to adapt programs affected by these changes to DOS 4.0, the
following pages give a description of changes to the file system (see Section 6.13
for a comprehensive look at the DOS file system).
In order to best visualize the changes to the file system, let's begin with a picture
of its fundamental structure. which remains valid under Version 4.0. This
fundamental structure can be divided into three layers, one on top of the other.
These range from the logical partitioning of a mass storage device on the top layer
to a purely physical system on the bottom layer. The top layer forms the function
interface to u~r programs. This interface calls individual functions through
interrupt 21H. No changes are allowed on this level in the switch to DOS 4.0 to
213
6. The Disk Operating System PC System Programming
ensure that all applications that use these functions will continue to run normally.
File accesses from the first level are converted to device driver function calls on the
second level. In order to locate each file (i.e., retrieve the sectors which must be
accessed) this level uses various data structures which are kept in the storage
medium. These include:
These functions cannot be changed as well, since one of the most important
demands placed on the new DOS version is the ability to work with partitions that
were created and formatted under previous versions. This is possible only if the
structures listed above are not changed. This does not leave many ways to increase
the capacity of a volume. Since the size of the FAT entry is limited to 16 bits, a
volume can use no more than 65519 clusters. Therefore, an increase is possible
only by using more sectors in a cluster.
When DOS 4.0 sets up new partitions, it assigns the following cluster sizes:
While this procedure minimizes the changes on the second level of the file system,
it also has a disadvantage: The bigger the partition, the more memory it wastes.
Since the memory in a partition can only be allocated in clusters, some memory is
always wasted when a cluster is not completely ftlled. This is true of ftles that are
smaller than the cluster size. Memory space is also wasted in the last cluster of a
larger file. since the size of a ftle is rarely an integral multiple of the cluster size.
The changes become most noticeable on the third level of the file system, called
the device driver level. While character drivers remain unaffected by changes in the
partition size, these changes have a great impact on block drivers that support
partitions of more than 32 megabytes.
It's true that changes on this level could be kept to a minimum by increasing the
sector size from 512 bytes, but this could lead to compatibility problems with
partitions that were configured under previous versions of DOS. The only
alternative was to increase the number of sectors per partition. But when a
partition exceeds the 32-megabyte limit, the 16 bits. which up until now were
used to store the logical sector number, are no longer enough. For this reason,
DOS 4.0 has introduced a new type of block driver that supports partitions larger
214
Abacus 6.16 DOS 4.0
than 32 megabytes, and works with 32-bit sector numbers. DOS recognizes these
drivers with the help of bit 1 in the device attribute. This bit carried a value of 0 in
previous versions of DOS.
Starting with Version 4.0, DOS knows that it is dealing with a 32 bit driver if
this bit is turned on. Increasing the sector number also changed the structure of the
parameter data block, with which DOS passes information on the functions and
parameters being called, to the device driver. Since a 16-bit field is no longer large
enough for the sector number, DOS 4.0 adds a 32-bit field to the end of the block.
This stores the sector number for a 32-bit driver as a dword (double word). As
usual, the word with the smaller value is stored before that with the larger value.
To indicate that the new field is in use, DOS also loads the value -1 (FFFFH) into
the old field.
The following driver functions are affected by the change to 32-bit sector numbers:
0 initialize driver
2 setBPB
3 direct read
4 real
8 write
12 direct write
The structure of the BIOS parameter block (BPB), which the initialize driver
function must pass to DOS, has also changed. This structure is also part of the
boot sector of a DOS volume. It has been supplemented by two fields compared to
the old BPB, and now looks like this:
215
6. The Disk Operating System PC System Programming
The two new fields in this extended BPB refer to the total number of sectors in the
volume and the number of sectors between the first sector on the storage medium
and the first sector of the volume. Even though these fields were already present in
the old BPB, they were there only as 16-bit values, and had to be appended as 32
bit fields. To guarantee maximum compatibility with the drivers of previous DOS
versions, DOS only needs to use the new BPB when the sector numbers cannot be
represented as 16-bit values. This happens if the distance from the first sector on
the storage medium to the first sector in the volume is greater than 32 megabytes.
The new BPB is installed while formatting a volume, but the old 16 bit fields are
used to store the number of sectors and the distance from the first sector when the
conditions mentioned above don't apply. Otherwise, the corresponding values are
entered in the 32 bit fields and the 16 bit fields are assigned a value of O.
Extending the logical sector number to 32 bits also caused a change in the way the
25H and 26H interrupt functions work. These functions represent the only way for
an end-user program to directly access the individual sectors of a volume via DOS.
If the number of the first sector to be processed was passed to the DX register of
these interrupts by an earlier DOS version, direct sector access is only possible
undt:r Version 4.0 if the volume to be accessed is smaller than 32 megabytes. To
access larger volumes in Version 4.0 and higher, the DS:BX register pair of these
interrupts must receive a pointer to the data block pictured on the next page:
216
Abacus 6.16 DOS 4.0
Since neither the 8088 nor the 80286 processors can perform dword operations, the
SHR eX,1 and the DB 66H instructions are simply replaced with NOP
instructions when installing the module, if the PC is equipped with a processor
other than an 80386.
217
Chapter 7
The BIOS
BIOS is the abbreviation for Basic Input!Output System. The name indicates that
the BIOS provides basic input and output routines for communicating between
software and the hardware peripherals such as keyboard, screen and disk drive.
Since these routine calls are standardized, this saves the programmer the trouble of
fitting programs to one particular PC hardware configuration. This means you can
develop a program on one PC or compatible, and run it on another compatible PC
without errors, even though neither the hardware nor the individual BIOS routines
are completely compatible. This hardware independent concept contributed much to
the popularity of the PC. It offers the computer manufacturers the ability to
develop PCs which aren't quite identical to a true IBM PC, yet can run popular
software.
BIOS functions occur through the individual routines contained in the BIOS
interrupts IOH to 17H and lAR. The processor registers, whose usage is also
standardized, transfer data from the calling program to the interrupt and from the
interrupt to the calling program.
Number Meaning
lOH BIOS display function call
llH Testing the configuration
12H Testing RAM
13H BIOS disk functions
14H Functions for asynchronous communication
ISH Cassette functions
16H Reading the keyboard
219
7. TheBlOS PC System Programming
BIOS architecture
The BIOS itself is located in PC ROM, making it resident even after the computer
has been turned off. It is stored very high in the processor's address space
beginning at address FOOO:EOOO. It extends to address FOOO:FFFF, the last
location addressable on the Intel 8088 microprocessor. The BIOS routines must
create, store and modify variables, much like any other routine. Since this is
impossible in the BIOS area itself, BIOS stores these variables in the lower part of
memory starting at address 0040:0000.
220
Abacl4S 7.1 Booting the System
Initialization
Program execution in a computer based on the Intel 8088 (or one of its successors)
starts after the computer is turned on at memory location FOOO:FFFO. This
memory location is part of the ROM-BIOS and contains a jump command to a
BIOS routine which takes over system initialization. The location of this routine
may differ from one computer to another (actually from BIOS to BIOS) because
the BIOS changes internally with each manufacturer. The task this routine
performs remains identical for nearly all PCs, however.
System check
First the BIOS tests individual functions of the processor, its registers and some
instructions. If an error occurs during this test, the system stops without
displaying an error message (this is impossible with a defective processor). If the
CPU passes the test, a checksum is computed from each of the ROM's contents
and compared with the various ROMs to determine whether a defect exists there.
Each chip on the main circuit board (such as the 8259 interrupt, the 8237 DMA
controller, and the RAM chips) goes through tests and initialization.
Peripheral testing
After determining the functionality of the main circuit board, the computer tests
the peripherals (keyboard, disk drive, etc.). In addition to these hardware related
tasks, the BIOS variables and the interrupt vector table must be initialized.
Note that no mention has been made of the operating system so far. It hasn't been
loaded into the computer from diskette or hard disk yet. Interrupt 19H, known as
the bootstrap loader, performs this task on startup or on system reset (when you
press the <AlI><Ctrl><Delete> key combination). This routine tries to load some
form of the basic operating system from a predetermined place on the diskette.
There is a disk in the drive, but the disk isn't bootable (the DOS mes are
not available on the diskette). If this occurs, the bootstrap routine
221
7. TheBJOS PC System Programming
attempts to fmd the routine on the other disk drives connected to the pc,
or on a predetermined location on an existing hard disk.
If the system still cannot find the bootable system disk, there are two other reasons
that may be causing a problem:
222
Abacus 7.2 Determining BIOS Version
You can examine the contents of these memory locations to determine which
BIOS version your PC uses. Call the DEBUG program from the DOS prompt
debug
Enter the following line to display the bytes at the end of the ROM-BIOS:
d fOOO:fffO 1 10
The next line displays the contents of this memory location as a hexadecimal
number; the characters to the right of the hex display are the corresponding ASCn
codes. Day, month and year appear as two digits separated by "f' characters.
C>debug
-d fOOO:fffO 1 10
FOOO:FFFO EA 5B EO 00 FO 30 32 2F-30 36 2F 38 36 00 FC 00 [ ••• 02/06/86 •••
-q
C>
223
7. TheBIOS PC System Programming
A program which calls these functions must first ensure that the computer in use
is in fact an AT, and that the functions addressed are available. The programmer
can use the model identification byte located in the last memory location of the
ROM-BIOS at address FOOO:FFFE. This byte can contain the following codes:
252 or FCR: AT
255 or FFR: PC
org Offfeh
PeID db (?)
IDSeg ends
224
Abacus 73 Determining the PC Type
je IatAT
;Device is a PC/XT
Higher level languages can also find the identification byte. The following BASIC
program uses the PEEK statement for reading the model identificatioo.
10 def seg - &hFOOO
Turbo Pascal uses the mem array to read the model identification:
begin
if mem[SFOOO : SFFFEJ - 252 then writeln('AT')
else writeln('PC/XT');
end;
225
7. TheBlOS PC System ProgrfJllUtling
Under DOS versions 1.0 and 1.1, these BIOS routines were the only options for
cursor positioning and color choice. DOS Versions 2.0 and up make these
functions available under DOS as well.
More about compatibility
The BIOS routines execute faster than their corresponding DOS routines. Those
concerned about compatibility and output device redirection may be better off using
DOS routines. In any case, the application itself should dictate which routines will
be used.
The BIOS routines, like the DOS routines, offer the programmer the advantage of
independence from a particular video card (IBM monochrome, IBM color, Hercules,
etc.), since they can be adapted to various cards. Because these cards have different
features supported by BIOS, let's look at the capabilities of these cards before
examining the routines of interrupt 10H. Programs demonstrating the function
calls are listed in BASIC, Turbo Pascal, C and assembly language later in this
chapter.
226
Abacus 7.4 BIOS Screen Output Functions
ROWS COLUMNS
76 77 78 19
22
2) t-+--+---it-+--+--I
Each of the 2000 (80*25) positions on the screen is represented by a character from
a set of 256 characters (ffiM PC standard character set) and an attribute character.
also called an attribute byte. Both characters require one byte apiece. so 2000*2
(4000 bytes) of video RAM must be available to display the entire screen. This
video RAM exists on the video display card. Since video RAM is not part of the
normal RAM. the starting address remains constant at address BOOO:OOOO for the
monochrome card.
While the PC systems have standard character sets for all the video cards described
here. the attribute bytes change from card to card.
As the figure below shows. bits 0 to 2 and 4 to 6 of the attribute byte defines the
foreground and background color of the displayed character.
227
7. TheBIOS PC System Programming
7 6 5 4 3 2 1 0 b'~t
I I I I I
"""""'r
r Character color
Character Intensity
=
o normal,1 high =
Background color
Blinking
=
o off,1 on=
Attribute byte color structure--monochrome display adapter
Bit 3 of the attribute byte indicates the intensity of the foreground color. If it
contains a 1, the character appears in high intensity. Bit 8 indicates whether the
character on the screen should blink (a 1 in this bit causes the character to blink).
While these bits can be set in any manner, only bit combinations which "look
good" should be used for foreground and background color.
Normal characters
(white on black)
Inverse characters
(black on white)
This card offers text display of the IBM PC standard character set and various
graphic modes. Text mode works with a resolution of either 8Ox25 or 4Ox25
characters. 40x25 resolution displays characters in double width. This mode allows
the management of up to eight different video pages (8Ox25 mode allows up to
228
Abacus 7.4 BIOS Screen Output Functions
four different pages). The line and column number assignment is similar to the
monochrome display card
The attribute byte used on this card mainly selects foreground and background
colors of the characters. A total of 16 colors is available. The first eight of these
may be used as background colors.
OOOl(b) 1 Blue
As the figure below shows, bits 0 to 3 of the attribute bytes represent the
foreground color, while bits 4 to 6 indicate the background color. Bit 7 means the
same as in the monochrome display card: it decides whether the character should
blink.
7 6 5 4 3 2 1 0 bit
I I I JJ I
..........,
Y Character color
Background color
Blinking
=
o off,1 on =
Attribute byte structure---color graphic adapter
This card can emulate a monochrome display card (see above) in which the
attribute character has the same meaning as in the monochrome card, with the
exception that no underlined characters can be produced.
229
7. The BIOS PC System Programming
Graphic modes can have either a resolution of 64Ox200 dots with 2 colors or
32Ox200 dots with 4 colors. In both modes the upper left comer of the screen has
the coordinates 0/0.
No attribute byte exists in this mode since every dot on the display is either
illuminated with a color or not, and not composed of standard characters from a
character set. To display characters from the standard character set in this mode,
they must be drawn on the screen with pixels (dots).
The video RAM of this card starts at location B800:oooo (unlike the monochrome
display card which starts at BOOO:oooo). This ensures that the video RAMs of the
two cards do not overlap. They can be used in parallel with each displaying data on
its own monitor.
The Hercules graphic card has the same text mode as the mM monochrome display
adapter, and can display two video pages of text at a time. A Hercules card also
offers a graphic mode in which two video pages can be displayed with a resolution
of nOx348 pixels. Unfortunately, the BIOS cannot access either the two video
pages or the graphic mode. BIOS treats this card like a normal monochrome card,
which can only display one text page of 80x25 characters.
Now that you have some general knowledge of graphic adapters, here are the
functions called from interrupt lOH:
230
Abacus 7.4 BIOS Screen Output Functions
As always, the processor registers pass the function arguments. Some common
rules define which registers accept which arguments:
The AH register indicates the number of the function to be called with interrupt
IOH. If character should be displayed, or a dot placed on the screen in graphic
mode, its value passes to the AL register.
Hercules functions
If the function expects display coordinates for text mode, the X-coordinate
(column) must be loaded into the DL and the Y-coordinate (line) into the DH
register. In graphic mode the ex register accepts the X-coordinate and the DX
register the Y -coordinate. The number of the display page (if required) should be
contained in the BH register.
It is important for assembler programmers that the contents of the BX, ex, DX
and the contents of the segment registers remain the same before and after the
interrupt call. The contents of all other registers may change.
Before sending output to the screen, the video mode must be selected. The current
video mode in use might not be the one you desire. Function 0 of interrupt IOH
performs this task and also selects the active video card in case the PC has several
video cards connected. For a call to this function through interrupt lOH, the AH
register must contain function number 0 and the AL register must contain the
number of the video mode to be activated. Of course only those video modes that
are supported by the video card in the PC can be activated. The following numbers
correspond to the various video modes (the video card supporting the mode is in
parentheses):
The mode makes no difference on a monochrome card, since only one mode exists
(80x25); this mode is constantly active. It uses the internal designation number of
7.
231
7. TheBIOS PC System Programming
The opposite of this function is function OFH. which determines the current video
mode. A value of OFH in the AH register during a call to interrupt lOH executes
this function. It returns the value of the video mode (refer to the table above) in the
AL register. As mentioned above, a monochrome card always returns the value 7.
Besides the video mode, the number of columns per display line in this mode (40
or SO) returns in the AH register and the current display page number in the BH
register.
After the video mode initialization, screen output can begin. Function 2 defines the
cursor position. Calling this function places Jhe blinking cursor in the desired
location on the screen. This sets the starting position of character display. Prior to
calling this function the AH register should be loaded with the function number
(2), the DH register with the line location of the cursor, and the DL register with
the column location of the cursor. The BH register holds the display page onto·
which the cursor should be positioned. Remember that every display page has its
own cursor for positioning the text output, but only one active or blinking display
cursor exists. This active cursor always appears on the currently displayed page.
Function 2 moves the active cursor if the value in the BH register corresponds to
the current screen page.
The counterpart of this function is function 03H. It reads the current cursor
position of a selected display page and returns the position to the calling program.
At the call of this function the AL register must contain the function number (3)
and the BH register the number of the display page whose cursor position is being
read.
Monochrome display cards return a value of 0, since the card can only display one
page (numbered 0). After the call of interrupt lOH the DH register contains the
cursor position's line and the DL register the cursor position's column. In addition,
two values are returned to the CH and CL registers which have special
significance. They indicate the starting and ending raster scan (pixel) lines of the
cursor. These lines are independent of the displayed page.
232
Abacus 7.4 BIOS Screen Output FlUlCtions
These values must of course remain within the legal values of the individual video
cards (i.e., 0 to 7 for a color card and 0 to 13 for a monochrome card), otherwise
the blinking text cursor may disappear from the screen.
While these values are read with the help of function 3, function 1 is used to set
these values. The AH register loads with a I, the CH register with the starting line
of the cursor, and the CL register with the ending line of the cursor, before calling
interrupt lOH. The starting line must be smaller than or equal to the ending line,
or the cursor becomes invisible.
This book has frequently mentioned the current display page without telling how
to activate this page. Function 05H of interrupt 10H performs this task. Place a
value of 5 in the AH register and the number of the page you want activated
(displayed on the monitor) in the AL register. The number of the page to activate
depends on how many pages are available in the current video card and video mode.
Since the monochrome video card offers only one display page, using this function
with a monochrome card makes no sense at all. The following values are allowed
for the color card's different video modes:
o to 7 (40*25 character text display [Color-card])
o to 3 (80*25 character text display [Color-Card])
After selecting the video mode and moving the cursor to the desired location on the
screen, one or more characters are output on the screen in most ~s. BIOS makes
various functions available which have different abilities in providing character
display on the screen. One difference between these functions is that they process
control codes in various ways. These control codes are the ASCII codes 7, 8, 10
and 13. They represent the following:
7 Bell Iproduces a sound
8 Backspace erases preceding character & moves
cursor back one character position
10 Linefeed moves cursor one line down
13 Carriage return moves cursor to start of current line
Some functions view these codes as normal ASCII characters and execute them
accordingly. Other functions see them as control codes. For example, code 7
produces a sound with some functions. The choice of which function to use
depends on which control code processing is desired.
Text display in graphic mode
Text display functions can be used in both text and graphic modes. Text output in
graphic mode creates different characters since the characters must be drawn on the
233
7. TheBlOS PC System ProgrtlnlnUng
screen from pixels. The PC uses ASCII codes to set the graphic pixels. While the
character samples for the ASCII codes 0 to 127 are already stored in the ROM, the
character patterns for the codes 128 to 255 must be read from a table in RAM.
This table installs itself in RAM when you execute the DOS GRAFfABL
command.
BIOS obtains the address of this table from the memory locations OOOO:OO7C to
OOOO:OO7F, where the table's offset address lies in the lower two bytes and the
table's segment address in the upper two bytes. These memory locations are inside
the interrupt vector table but can be used for this purpose since interrupt IFH
(whose address normally appears there) remains unused.
Having this table stored in RAM makes it possible to define your own table, so
that special characters which are not contained in the standard character set can be
displayed on the screen. Since every character is comprised of 8 bytes, the first 8
bytes of the table are reserved for ASCII code 128, the next 8 for the code 129, etc.
Each byte contains the bit pattern for one of the 8 lines which compose a
character. Bit 0 represents the dot on the right border of the character matrix, bit 7
the dot on the left border. If you set a bit to 1, this illuminates the corresponding
pixel on the screen.
Functions 09H and OAH are available for character output. Function OAH displays
the character in the color determinedoy the attribute corresponding to that
particular screen position. Function 09H sets the color (attribute) of the character
to be displayed. Neither function moves the cursor to the next screen position after
character display. Character output resumes at the same location on the next
function call. Function 02H must be called to move the cursor to the next screen
position for displaying readable text
234
Abacus 7.4 BIOS Screen Output Functions
A serious disadvantage of these two functions is that the cursor's position does not
advance after the function call. Function OEH cures this problem. It acts like a
terminal, hence its nam~the TIY (feletype output) routine. The cursor advances
to the next screen position after a character is displayed. If the cursor reaches the
end of the screen line, it moves to the beginning of the following line. If the
cursor is in the last display screen position (line 24, column 79), the entire screen
is scrolled one line upward and the top line of the screen disappears from the
display area. In addition, the function clears line 24 and the cursor moves to the
beginning of the line.
Prior to the function call, the AH register must be loaded with function number
OEH, the AL register loaded with the code of the character to be displayed and the
BH register with the display page intended for character display.
While functions 09H, OAH and OEH display characters on the screen, function OSH
makes it possible to read characters from the screen, i.e., to sense the character and
attribute displayed. Before the call, the value 08 must be loaded into the AH
register and the number of the display page from which the character should be
loaded into the BH register. The display position from which the character should
be read is the current cursor position in the display page indicated by the BH
register.
In text mode the character code can be read directly from video RAM. However,
graphic mode requires a comparison between the bit pattern at the current cursor
position and every character's bit pattern in the character set
After the function call, the AH register contains the attribute (color) and the AL
register contains the ASCII code of the character read.
Function 06H scrolls the screen up one or more lines, or clears sections of the
screen by displaying spaces (ASCII code 32). These operations can only be
performed on the current display page. To call this function, you must load the AH
register with the function number (6). The AL register is loaded with the number
235
7. TheBIOS PC System Programming
of lines the display should be moved up. A 0 in this register instructs the function
to fill the screen area with spaces instead of scrolling the screen. The BH register
contains the color (attribute) for the blank line. The CH, CL, DH and DL registers
define the display page window to be scrolled or cleared. The C register represents
the upper left comer of the window, while the D register defines the lower right
comer of the window. The following list illustrates the meaning of each register:
Reg Meaning
CR Line of the upper left corner of the window
CL Column of the upper left corner of the.window
DR Line of the lower right corner of the window
DL Column of the lower right corner of the window
Function 07H scrolls the screen down one or more lines, or clears sections of the
screen by displaying spaces (ASCII code 32). These operations can only be
performed on the current display page. To call this function, you must load the AH
register with the function number (7). The AL register is loaded with the number
of lines the display should be moved down. A 0 in this register instructs the func
tion to fill the screen area with spaces instead of scrolling the screen. The BH
register contains the color (attribute) for the blank line. The CH, CL, DH and DL
registers define the display page window to be scrolled or cleared. The C register
represents the upper left comer of the window, while the D register defines the
lower right comer of the window. The following list illustrates the meaning of
each register:
Reg Meaning
CR Line of the upper left corner of the window
CL Column of the upper left corner of the window
DR Line of the lower right corner of the window
DL Column of the lower right corner of the window
236
Abacus 7.4 BIOS Screen Olllput FlU'lClions
Graphic functions
The following are descriptions of the functions used in the different graphic modes.
They can be used in connection with video cards capable of producing graphics.
Function OOH switches on one of the available graphic modes. The border color (or
color palette) should then be selected for the 320x200 (or text) mode by loading
function number OAH in the AH register. The BH register dictates the use of the
border color or the color palette. If during the function call the BH register contains
a 0, the value in the BL register becomes the background and border color for the
graphic mode. All 16 colors are available, so the BL register can contain a value
between 0 and 15. This function remains valid for the text mode. However, only
the border color can be set. The background color for each character is set
individually by the top 4 bits of the color attribute, and therefore cannot be set for
everything.
Once the graphic mode initializes and the colors are selected, graphic drawing can
begin. Function OBH writes graphic pixels at specified locations of the screen. The
pixel coordinates to be addressed are passed in the ex and DX registers. The values
in these registers depend on the graphic resolution of the current graphic mode. The
ex register contains the X-coordinate (column coordinate) of the pixel, and the DX
register the Y-coordinate (line coordinate) of the pixel. The function call must have
the function number (OBH) passed in the AH register. The color value of the pixel
to be manipulated is passed in the AL register. The Hercules card and the 64Ox200
mode of the color card permit the values 0 and 1 only. In the 320x200 mode of the
color card, the values 0 to 3 are allowed for the 4 possible colors. The significance
of these values depends on the active color palette. If a program enables palette 0,
the values have the following significance:
0 Color selected for background with function OBH
1 Green
2 Red
3 Yellow
237
7. TheBIOS PC System Programming
3
White
Function ODH is the equivalent of this function, which detennines the color value
of a pixel. Before the call, the value ODH must be passed in the AH register, the
X-coordinates of the pixel must be loaded into the ex register, and the Y
coordinates into the DX register. The pixel color is returned as a result in the AL
register. This value corresponds to the rules described in function OBH.
The AL register's contents define one of the four possible modes in which the
character string can be displayed. The string fonnat in modes 0 and 1 differ from
string fonnat in modes 2 and 3. Modes 2 and 3 place attribute bytes after every
character in the string. In modes 0 and 1, the individual characters of the string
follow one another in sequence. The attribute byte for all characters depends on the
contents of the BL register. In modes 2 and 3, 2 bytes are stored in the string for
every character displayed. For example, a character string of 4 characters requires 8
bytes of memory. The number of characters to be displayed (4 characters in this
example) must be indicated in the ex register. Another difference between modes 0
and 2 and modes 1 and 3 is in display fonnat. Mter the string display in modes 1
and 3, the cursor appears following the last character of the string. The next
character displayed with one of the BIOS functions then appears at this position on
the screen. The cursor position does not get updated in modes 0 and 2.
238
Abacus 7.4 BIOS Screen Output Functions
Demonstration programs
The following programs demonstrate the use of BIOS video interrupt functions
available from higher level languages. In Pascal and C, you'll find that using BIOS
display functions works much faster than the standard procedures and functions
provided in these languages, which use the slower DOS functions. BASIC's use of
BIOS screen functions is minimal, since these functions are even slower than the
BASIC PRINT statement
Advantage
Accessing BIOS video interrupt functions has an advantage over the use of onboard
graphic commands in higher level languages: the BIOS functions can be accessed
at any time.
Disadvantage
There is a serious disadvantage to using BIOS functions for screen output. The
higher level language display commands can accept numerical variables, which are
then converted to ASCII characters. These higher level commands can fonnat the
variables according to decimal places or a certain degree of precision, then display
these variables. However, if numerical variables are to be displayed using the BIOS
functions, they must first be converted into a character string which you must
transfer to the BIOS output function. This procedure takes time.
All three programs are identical in function. Each fills the screen with continuous
characters from the PC character set, then opens two windows in which two arrows
move up and down. How this was done, and how it will actually appear on the
screen, should become clear after you take a closer look at the program codes. The
programs limit their access to one video page, due to incompatibility problems
that could occur between monochrome and color cards. They also do not present
subroutines, functions or procedures for calling the BIOS graphic functions.
Once you understand this section you should be able to easily add the missing
functions and even write a short demo program of your own. Using BIOS video
interrupt assures that the computer will not crash and that nothing major can go
wrong.
BASIC listing: VIDEOB.BAS
100 .**************.* •• ********.***********************.*.************'
110 • * V IDE 0 B BAS *,
120 ,*---------------------------------------------------------------*.
130 Task : Makes some Subroutines available for access *,
140 to the Display using the BIOS-Video-Interrupt *'
150 ,*
160 Author : MICHAEL TISCHER *,
170 developed on : 07/18/87
180 last Update : 05/14/89 *,
190 ,***••• ***••••• ********.*.*.*.*.*.**.*.*.*.******* •••• *.**********,
200 '
210 CLS : KEY OFF
220 PRINT "WARNING: This Program should only be started if GWBASIC was •
239
7. The BIOS PC System Programming
280 CLS
240
Abacus 7.4 BIOS Screen Output Functions
51130
52180 '
53000 1***************************************************************1
53010 ,* Read Cursor Position and Beginning and End Row
53020 ,* of the blinking Text-Cursor
53030 1*----------------------------------------------------_________ *1
53040 Input: PAGE% - is the Number of the Display page
53050 Output: DISPCOL% - Column of the Cursor in the Display page
53060 DISPROW% Row of the Cursor in the Display page
53070 BEGLIN% = beginning Line of the Text-Cursor
53080 ENDU is the End Line of the Text-Cursor
53090 Info the Variable Z% is used as Dummy
53100 1*****************************************.*********************1
53110 FKT%=3 'Read Function number for Cursor position
53120 INR%-&H10 'Call BIOS-Video-Interrupt 16(h)
53130 CALL IA(INR%,FKT%,Z%,PAGE%,Z%,BEGLIN%,ENDL%,DISPROW%, DISPCOL%,Z%,Z%,Z%,Z%)
53140 RETURN 'back to caller
53150
54000 1********.***********************.******************.***********1
54010 '* Set the current display page on the
54020 I * screen
54030 1* _____----------------------------------------------- _________ *1
54040 Input : PAGE% = is the Number of the Display page
54050 I * Output: none
54060 '* Info : the Variable Z% is used as Dummy
54070 '***************************************************************1
54080 FKT%-5 'Set Function number for Display page
54090 INR%-&H10 'Call BIOS-Video-Interrupt 16 (h)
54100 CALL IA(INR%,FKT%,PAGE%,Z%,Z%,Z%,Z%,Z%,Z%,Z%,Z%,Z%,Z%)
54110 RETURN 'back to caller
54120
55000 1***************************************************************'
55010 ,* Scroll current Display page up or erase
55020 1*-------------------------------------------------------------*1
241
7. The BIOS PC System Programming
,.
.'.'.'
55030 InputVALUE' = how many Lines to scroll
55040 ULC% = Column upper left
55050
55060
55070
55080
'. ULR%
LRC%
LLR%
- RoW upper left
~ Column lower right
Row lower right
COLRR% = COLRR of erased Lines
.'.'
55090 Output: none
55100 Info If VALUE% 0 is indicated, the
55110 Display area is erased
55120 the Variable Z% is used as Dummy
55130 ,.****_. ___ *. ___._**.***_*_. ___
.* ___ *_***_*** __ * ___ • __ **********'
55140 '
55190 '
57180 '
58000 1***************************************************************'
58010 '* Output a String starting at a certain Position within a
58030 ,*-------------------------------------------------------------*,
58040 Input : T$ the String for output
58070
58080
58090
58100 Info
DISPCOL% Column - start of String
Output: none
.'
58110 1***************************************************************'
58120
58130 GOSUB 52000 'Set Cursor position for Output
242
Abacus 7.4 BIOS Screen Output Functions
The program can be divided into three parts. Lines 100 to 700 represent the
demonstration program proper, which uses the subroutines in lines 50000 to
58220. These subroutines call a special function of the BIOS video interrupt and
access the routine for interrupt calls as described earlier. The program DATA
begins on line 60000.
See the header of each subroutine for the variables of each subroutine and what
each variable does.
It should be noted that all subroutines receive and return numerical values as
integer variables. Do not forget the percentage character after a variable. In certain
cases a real variable of the same name can be initialized, but the subroutine
expected an integer variable and the wrong parameters will be passed to the BIOS
function.
243
7. TheB/OS PC System Programming
program VIDEOP;
begin
Regs.ah := $OF; { Function number
intr ($10, Regs); { Call BIOS-Video-Interrupt
VideoMode := Regs.al; Number of Video mode )
Number := Regs.ah; { Number of characters per line /
Page .= Reqs.bh; Number of the current display page /
end;
244
Abacus 7.4 BIOS Screen Output Functions
begin
Regs.ah 1; Function number
Regs.ch .- Beginline; { Beginning and
Regs.cl := Endl; { End line
intr($10, Regs); { Call BIOS-Video-Interrupt
end;
begin
Regs.ah := 2; { Function number
Regs.bh Page; { display page
Regs.dh . Line; Display coordinates
Regs.dl := Column;
intr($10, Regs); Call BIOS-Video-Interrupt
end;
begin
Regs.ah :- 3; { Function number
Regs.bh := Page; { Display page
intr($10, Regs); Call BIOS-Video-Interrupt
Column := Regs.dl; { Result of the Function
Line := Regs.dh; { read from the Register
Beginline := Regs.ch; { and store in proper
Endl Regs.cl; { Variables
end;
{*******************.*******************************************.*****}
(* SETDISPLAYPAGE: set the display page *)
{* for output on the monitor *)
1* Input see below *)
1* Output none *)
{*********************************************************************}
245
7. The BIOS PC System Programming
begin
Regs.ah :~ 5; Function number and display page
Regs.al :~ Page; ( Screen page
intr($10, Regs); ( Call BIOS-Video-Interrupt
end;
{*********************************************************************}
{* SCROLLUP: scrolls a display area by one or more *1
{* lines up or erases i t *1
{* Input see below *1
{* Output none *1
{* Info If Number 0 is passed, the display area *1
{* is filled with blanks *1
{*********************************************************************}
begin
Regs.ah :~ 6; Function number and number
Regs.al .- Number;
Regs.bh := COLOR; ( Color of empty line(s)
Regs.ch := LineUL; { Upper left
Regs.cl ColumnUL; { coordinates
Regs.dh LineLR; { Lower right
Regs.dl :~ ColumnLR; { coordinates
Intr ($10, Regs); { Call BIOS-Video-Interrupt
end;
{*********************************************************************}
{* SCROLLDOWN: Scrolls a display area by one or more *1
{* lines down or erases it *1
{* Input see below *1
(* Output none *)
(* Info If Number 0 is passed, the display area *)
{* is filled with blanks *1
{*********************************************************************}
begin
Regs.ah := 7; Function number and number
Regs.al := Number;
Regs.bh := COLOR; ( Color of blank line(s)
Regs.ch := LineUL; { upper left
Regs.cl := ColumnUL; { coordinates
Regs.dh := LineLR; { Lower right
Regs.dl ColumnLR; { coordinates
Intr ($10, Regs) ; { Call BIOS-Video-Interrupt
end;
{*********************************************************************}
{* GETCHAR: Read a character including Attribute from an indicated *1
(* position in a display page *)
(* Input see below *)
(* Output see below *)
{*********************************************************************}
246
Abacus 7.4 BIOS Screen Output Functions
begin
GetVideoMode(Dummy, Dummy, CurPage); {sense current display page
GetCursorPos(CurPage, CurColumn, CurLine, ( Get cursor position
Dummy, Dummy); ( in the current display page
end;
{*********************************************************************}
(* WRITECHAR: Writes a character with indicated color to the *)
(* current cursor position in the display page *)
'* indicated *)
(* Input see below *)
'*
(* Output
(*
Info
none
during the Output of characters, the control codes
such as carriage-Return are treated as ASCII codes *)
*)
*)
{*********************.***********************************************}
begin
Regs.ah :~ 9;
Regs.al ord (Character) ; { Function number and character code
Regs.bh '= Page; { Display page
Regs.bl := COLOR; { Display color
Regs.ex :- 1; { output character only once
Intr ($10, Regs) ; { call BIOS-Video-Interrupt
end;
{******************************************** •• ***********************}
(* WRITETEXT: Writes a String starting at an indicated position in *)
(* a display page. *)
{*********************************************************************}
247
7. TheBIOS PC System Programming
begin
SetCursorPos(Page, Column, Line); Set cursor
begin ( in sequence
begin
clrscr; { Erase display
for i :- 1 to 24 do Perform lrne 1 to 24
for j :=
begin
°
to 79 do { do all Columns
end:
ScroIIDown(O, NORMAL,S, 8, 19, 22); Erase Window 1
WriteText(O, 24, 12, INVERS or BLINK, • »> PC SYSTEM PROGRAMMING «< ');
while j <= 15 do
begin
k := 0;
while k < j do ( create a line of the Arrow
begin
SetCursorPos(O, 12-(j shr 1)+k, 9); Arrow Window 1
WriteChar(O, '*', BOLD);
SetCursorPos(O, 67-(j shr 1)+k, 16); Arrow Window 2
WriteChar(O, '*', BOLD);
k :- succ (k);
end;
ScrollDown (1, NORMAL,S, 9, 19, 22); scroll Window 1
ScroIIUp(l, NORMAL, 60, 3, 74, 16); scroll Window 2
for I := °
to 8000 do ( Wait Loop
j := j+2;
end;
end:
clrscr; ( Erase display )
end.
248
Abacus 7.4 BIOS Screen Output Functions
C listing: VIDEOC.C
1**------_·_·_---_··*--·-··-·_---_·-·_*----------_·_·-... xwxwxxxxxxxx./
1* v IDE 0 C *1
1*-------------------------------------------------------------------*1
1* Task makes functions available which are not *1
1* available from the Library of MICROSOFT and *1
1* the TURBO C-Compilers *1
1*-------------------------------------------------------------------*1
1* Author MICHAEL TISCHER *1
1* developed on : 08/13/87 *I
1* last Update : 05/14/89 *1
1*-------------------------------------------------------------------*1
I* (MICROSOFT C) *I
1* Creation MSC VIDEOC; *1
1* LINK VIDEOC; *1
1* Call VIDEOC *1
1*-------------------------------------------------------------------*1
1* (BORLAND TURBO C)
Ixxxxx*ww*xx
1* ________ • _____
Creation *_*_* the
: through _______________
RUN command *_** ._*_________
____ menu bar
on the
*I
*___*1/
249
7. TheB/oS PC System Programming
void SetDisplayPage(Page)
250
Abacus 7.4 BIOS Screen Output Functions
Register.h.dl ColumnLR;
/*************.***************************.********************.******/
/* SCROLLDOWN: Scroll a display area by one or more */
/* lines down or erase it */
/* Input see below */
/* Output none */
/* Info
/*
If ° is passed as number, the display
area is filled with blanks
*/
*/
/********* •• *********** •• ***************************************** •• **/
void ScrollDown(Number, Color, ColumnUL, LineUL, ColumnLR, LineLR)
int Number; /* Number of lines to be scrolled */
int Color; /* Color or Attrib.ute for the blank lines */
int ColumnUL; /* Column in upper left corner of the display area */
int LineUL; /* Line in upper left corner of the display area */
int ColumnLR; /* Column in lower right corner of the display area */
int LineLR; /* Line in lower right corner of the display area */
Register.h.dl = ColumnLR;
251
7. The BIOS PC System Programming
/*********************************************************************/
1* WRITECHAR: writes a character with an Attribute *1
1* at the current cursor position in the page indicated *1
1* Input see below *1
1* Output none *1
1***************************************************** ****************/
void WriteChar(Page, Character, Color)
1***************************************************** ****************/
1* WRITETEXT: Writes a character string with constant cJlor */
1* starting at a designated position within a display page*1
1* Input see below */
1* Output none */
1* Info Text is a pointer to a character vector which contains *1
1* the text to be output and is terminated *1
1* with a '\0' character */
1***************************************************** ****************/
void WriteText(Page, Column, Line, Color, Text)
int Page; 1* the Text is output in this display page *1
int Column; 1* display Column for Output *1
int Line; 1* display line for Output *1
int Color; 1* Color/Attribute of the Text *1
char *Text; 1* Text for output *1
252
Abacus 7.4 BIOS Screen Output Functions
1--*-·--------·_---------_·--_·_·_·_··_--------------- **************.*/
f* CLEARSCREEN: erase the 80*25 character Text display and set *f
f* cursor into the upper left display corner *f
f* Input none */
f* Output none */
/*************************************************** •• -**-*-----------/
void ClearScreen()
1·-·----------*----_·_·-·_---------_·_-------_.-·_----*************r**/
f** MAIN PROGRAM '**f
1-*---··_--_·_·_-_·_--------·_·_-----------_·_.. _·_*-- ****************/
void mainO
WriteText(O, 24, 12, INVERS I BLINK, " »> PC SYSTEM PROGRAMMING «< ");
draw 50 Arrows *f
)
ScrollDown(l, NORMAL, 5, 9, 19, 22), f* Scroll Window 1 down */
ScrollUp(1, NORMAL, 60, 3, 74, 16); f* Scroll Window 2 up *f
for (1 - 0; 1 < 4000 ; 1++) f* Wait Loop *f
)
}
253
7. TheB/OS PC System Programming
The BIOS functions for screen output have been part of ROM-BIOS since the early
days of the PC. Although they have proven themselves in thousands of
applications, they don't work with the newer types of graphic cards. EGA and
VGA cards are becoming more and more common in the PC market.
Incompatibilities arise between hardware and software, because these cards have
little in common with the eGA and MDA cards for which the original BIOS
functions were intended.
To make EGA and VGA cards compatible with programs that use BIOS functions
to do their screen output, the BIOS functions must first be adapted to the new
hardware standards. The frrst option would be to replace the ROM-BIOS on the PC
motherboard with new ROMs. This solution can create other problems, because no
set standard currently exists for EGA or VGA. Unlike the eGA and MDA cards,
where the mM standard took over simply because there were no other alternatives,
EGA and VGA manufacturers have yet to define a universal standard. Such a
standard would have to apply to hardware, options and capabilities as offered by
each manufacturer.
EGA/VGA ROM-BIOS
Since trying to adapt the ROM-BIOS included with the computer to every graphic
card on the market is impractical, the manufacturers of these systems use the
opposite approach. They package an independent ROM-BIOS with their video
cards. There is a small ROM on the video card itself which contains the necessary
screen output functions. When the system is booted, the BIOS detects this ROM
expansion and allows it to redirect the BIOS video interrupt 16H to its own
routines, replacing the old functions.
By using these routines, all of the programs which use BIOS functions for output
can be executed without problems, but the enhanced capabilities of these video
cards are not used. Since the ROM-BIOS on the motherboard is intended to work
only with eGA and MDA cards, it supports only the capabilities of these cards.
So the graphic card manufacturers extend the BIOS in these video cards by
including new functions or upgrading old functions, so that the enhanced video
capabilities can be used.
This section is dedicated to these functions. No real standard exists for these BIOS
extensions, as mentioned previously. We could use this section to describe the
video functions of the more important EGA and VGA cards (many different cards),
but even with this information you still wouldn't be able to write programs which
would be compatible with all of the video cards on the market. Writing a program
for a specific video card makes sense only when you want the program to run with
that card only.
254
Abacus 7.4 BIOS Screen Output Functions
Instead. let's look at the lowest common denominator. the video modes and
functions supported by virtually all EGA/VGA cards. If you stick to this "low
level" standard. you can be fairly sure that your programs will run properly with
all EGA/VGA cards. The basis of this standard is the set of video modes supported
by the original EGA card, introduced by IBM in 1985. or the original VGA card,
introduced by IBM in 1987. All of the manufacturers of compatible cards have
included similar functions in their own cards, and added their own features.
All EGA and VGA cards have flexibility in common, which allows them to
emulate other video cards, as well as perfonn other tasks. The type of emulation
depends on the monitor connected, since unlike other cards, EGA/VGA cards can
by used with different types of monitors.
In addition, to support the new graphic modes with higher resolutions, EGA cards
offer a palette of 16 colors chosen from the 64 available colors. In text mode it is
also possible to set the heights of individual characters, so that up to 43 lines can
be displayed on the screen at once, instead of the nonnal 25 lines.
VGA features
The VGA card is even more powerful. In text mode, the VGA card can display 25
lines, 43 lines and even 50 lines of text. In addition, the VGA has even more
colors available (262,144 colors, as opposed to the EGA's 64-color spectrum). Of
course, these colors are only effective when displayed on a monitor that has a high
enough resolution.
255
7. TheBlOS PC System Programming
The rest of this section shows how these extended features can be used and how the
original BIOS functions have changed. '
As with the normal BIOS, all of the video modes in the EGA/VGA BIOS are set
with the help of function OOH of the BIOS video interrupt. This function has not
been changed since the old BIOS, but it has been extended. The number of the
video mode to be set is passed in the AL register. The following codes are allowed:
• •
06H 640x200 graphic pixels, 2 colors
07H 80x25 characters, monochrome
ODH
OEH
320x200 graphic pixels,
640x200 graphic pixels,
16 colors
16 colors
••
OFH 640x350 graphic pixels, monochrome
• •
.*.*.*
lOR 640x350 ~raphic pixels,16 colors**
llR 640x480 graphic pixels 2 colors
* VGA only
** EGA cards with 64K of added RAM can only display 4 colors
EGA and VGA cards can suppress clearing the video RAM when switching to a
new video mode. If you want to to do this, bit 7 of the AL register must be set in
addition to video mode number when the function is called.
The codes listed above are also valid for the function OFH, which is used to
determine the current video mode.
Nothing much has changed in functions OlH to OEH. Slight changes have been
made to functions OIH and 03H, which defme and read the design of the cursor. We
will discuss these changes later. You can also get exact descriptions of these
functions from the appendices, where all of the functions of the EGA/VGA BIOS
are described.
Extended functions
After function OFH, which also appeared in the old ROM-BIOS, we have three
new EGA/VGA functions numbered lOH, IlH, and 12H. These new functions are
dedicated to a specific task and have a number of sub-functions.
256
Abacus 7.4 BIOS Screen Output Functions
Function 10H
Function lOR comprises all of the sub-functions for using the color capabilities of
the EGA/VGA cards. Before we describe these functions, we should first look at
the way in which the EGA and VGA cards create colors.
Unlike the MDA and eGA cards, the two nibbles of the attribute byte of a
character in text mode do not directly specify the color or attributes of the character
in the EGA. They comprise an index to one of the 16 palette registers of the EGA
card, which then contains the actual color. This makes it possible to set the desired
colors individually, and allows color changes simply by changing the contents of
the palette registers. The interpretation of the palette register contents, and the
number of displayable colors, depend on the type of monitor used. The EGA card
itself can generate 64 colors, but these can be displayed only on EGA or multisync
monitors, since these monitors have the six color lines required (26 = 64). There
are two lines available for each fundamental color (red, green, and blue), where the
two lines control the intensity level of the color. These six lines correspond
directly to the lower six bits of a palette register, as the following figure shows.
7 6 5 4 3 2 1 0 bit
Ix:xlrlglblRIGIBI
I ......
Blue(Intense)
......
Green (Intense)
......
Red (Intense)
..
• Blue (less Intense)
... Green (less Intense)
....
... Red (less Intense)
EGA palette registers when connected to EGA or multisync monitor
This color scheme is not available when a normal color monitor is connected. It
has only four lines for the color representation, three of which are assigned the
fundamental colors red, green, and blue. The fourth line simply allows the
resulting color to be displayed at higher intensity. These limited possibilities affect
the structure of the palette register, which clearly differs from the six-bit structure
used when an EGA or multisync monitor is connected. A total of only 16 colors
can be displayed in this mode.
257
7. TheB/OS PC System ProgrDnlllling
Blue
Green
Red
Intensity
The bits of a palette register take on a completely different meaning when the card
is connected to a monochrome monitor. In this case the monitor cannot display
different colors, and can only display bright, inverse, and underlined characters.
When connected to such a monitor, the meanings of the individual bits correspond
to those of the attribute byte of an MDA card, which we examined earlier in this
chapter.
The VGA card also uses the most significant and least significant nibbles of the
attribute byte as an index, pointing to one of 16 palette registers. Unlike the EGA
card, which only contains the color code, this byte contains a value between 0 and
255. This number acts as a reference to the DAC (digital analog converter) color
table. This table allows the VGA card to convert a digitally notated color code into
an analog video signal. The DAC color table sees each color code as three six-bit
values, with each value representing the degree of red, green and blue intensity in
the color.
As the following figure shows, the color code layout in some registers plays a role
which also involves the BIOS. Bit 7 of each value controls the grouping of the
different registers in the DAC color table, thus controlling the mode control
register of the video controller. If this bit contains a 0, the index in the DAC color
table bases its palette register on the contents of bits 0 to 5, and the color select
register on bits 2 and 3. The consequence is that the DAC color table is divided
into four groups of 64 consecutive registers. The value in the palette register
represents the index in this group, whereby the active group itself selects the color
based on the contents of bits 2 and 3 of the color select register.
When bit 7 of the mode control register contains a 1, the DAC color table divides
into 16 groups of 16 consecutive registers. The index of this table is based on bits
0-3 of the corresponding palette register, and bits 0-3 of the color select register.
258
Abacl4S 7.4 BIOS Screen OUlpIll FlUlCtions
These registers select the active color group from within the DAC color table, and
the contents of the palette registers represent the index of this group.
You can use this form of coding for creating fast and easy color changes when
characters on the screen must be changed rapidly. This involves storing different
groups in the DAC color table which specify brighter or darker colors, and quicldy
incrementing the active color grouping through the col<r select register.
7 6 7 6
I~o~I~~__~____~I:f:~~f
Mode-Control-Register
To perfectly emulate a eGA or an MDA card, the EGANGA BIOS sets the
individual palette registers (or in the case of the YGA card, the DAC color
registers) to the same color scheme used by a CGA or an MDA card when the
corresponding mode is initialized In the case of CGA emulation (EGA/VGA card
and a eGA monitor),this means that palette register 0 contains the value 0,
palette register 1 the value 1, etc. At the same time, the color select register of the
YGA card must be set to the frrst of 16 palettes whose color codes correspond to
those of a CGA card. This also applies to CGA modes 4 and 5 (320x200 pixels,
four colors), which work with one of two color palettes which can be selected via
function OBH, sub-function 1. The EGA BIOS simply loads the corresponding
colors into the lower three palette registers, depending on the palette selected.
There is normally no need to change the contents of the palette registers in this
case, since no new colors can be displayed on the screen. Individual colors can
easily be exchanged with each other.
259
7. TheBIOS PC System Programming
mode is initialized, but this does not exhaust the color options of the EGA card.
To make full use of these options, sub-function OOH of function lOH can be used
to load one of the 16 palette registers. In addition to the function number in the
AH register and the sub-function number in AL, this function must also be passed
the number of the palette (0 to 15) in BH and the new color value for this palette
in the BL register. Since this function does not check the number of the register, it
can also be used to change the contents of a 17th palette register (screen border and
background color in the graphics mode), although it is better to use sub-function
01H of function lOH for this. Besides, it doesn't make much sense to set a
background color in the text modes, because the text display takes up almost the
entire screen with only two or three raster lines left over for the output of a border
color. The contents of this palette register are ignored when a monochrome
monitor is connected.
To call the function for accessing this palette register, the AH register must fIrSt
be loaded with the function number lOH and the AL register with the sub-function
number 01H. The BH register holds the border color, which is then loaded into
palette register 16 when the function is called.
Sub-function 02H of function lOH is used when you want to load all of the palette
registers at the same time, including the register for the border color. In addition to
the function and sub-function numbers in AH and AL, respectively, the address of
a table must be passed in the ES:DX register pair. This table contains the values
for the 17 palette registers. When this function is executed, the contents of this
table will be copied into the 17 palette registers and will cause all of the colors on
the screen to change at once.
The last sub-function of function lOH (for EGA only) defines the meaning of a bit
in the text modes. As with the CGA and MDA cards, this bit can also be used on
the EGA card to emphasize a character by either displaying it on a bright
background color or flashing it, if the bit is set. While the meaning of this bit can
be changed only by directly programming the video hardware with CGA or MDA
cards, the EGNVGA BIOS can perform the same task using sub-function 03H of
function 10H.
As with calling the other sub-functions, the function and sub-function numbers
must be passed in registers AH and AL. The meaning of bit seven of the attribute
byte is determined by the contents of the BL register. The value of zero in this
register sets the bright background color, while the value one causes all characters
on the screen, with bit seven of their attribute bytes set, to flash on and off.
The VGA card has additional functions available for accessing this table. These
functions are all sub-functions of function lOH, and are only accessible from the
VGAcard.
The contents of a single DAC color register can be modified using sub-function
lOH. Load the AL register with the sub-function number, the BX register with the
260
Abacus 7.4 BIOS Screen Output Functions
number of the corresponding register (0-255) and the CH, CL and DH registers
with the color code. Then call the function. To help correctly interpret the contents
of this register, the DAC color table must be coded as an IS-bit value (6 bits for
red, 6 bits for green and 6 bits for blue). The red components must be loaded into
the DH register, the green components into the CH register, and the blue
components into the DL register.
You must load the number of the register to be updated into the BX register. The
registers receive the number of the DAC register to be updated when you call sub
function ISH.
Any number of DAC color registers can be loaded at a time using sub-function
I2H. The number of the first DAC color register to be loaded is passed to the BX
register, and the number of DAC color registers to be loaded is passed to the CX
register. The new contents of the DAC color registers are loaded into a buffer (the
address of this buffer is contained in the ES:DX register pair). Each DAC color
register receives three consecutive bytes from this buffer. These three bytes specify
the green components, the red components and the blue components of the color
code.
Sub-function 13H allows the organization of the DAC color table and the active
color group, offering two of its own sub-functions. If the BL register contains the
value 0, then the sub-function copies bit 0 of the BH register into bit 7 of the
mode control register of the VGA controller. The organization of the DAC color
table can then be broken down into 4 or 16 groups. However, if the BL register
contains the value I when this sub-function is called, then the sub-function copies
the contents of the BH register into the color select register, then selects the active
color group.
The contents of both registers can be conveyed by calling sub-function lAH. After
calling this function, the content of bit 7 of the mode control register is passed to
the BL register, and the contents of the color select register is passed to the BH
register.
261
7. TheBIOS PC System Programming
Gray scales
Sub-function OBH converts the color codes within the OAC color table into gray
scales. Pass the number of the first register to be converted into the BX register,
and the number of registers to be converted to the CX register. The conversion
results in a color value between 0 (black) and 1 ( white), based on a red intensity of
30%, a green intensity of 59% and a blue intensity of 11%.
Palette registers
The VGA BIOS still has more sub-functions in function 10H for reading the
palette registers. Sub-function 07H reads the contents of any palette register. When
the function is passed and the number of the palette register is passed to the BL
register, the number of the contents is returned in the BH register. This allows read
access to the contents of the overscan register (the color border on palette register
16), but this access requires the use of sub-function 08H. Like sub-function 07H,
the result is loaded into the BH register.
Sub-function 09H loads the contents of the entire palette table (i.e., all 16 palette
registers and the overscan registers) into a 17-byte buffer. The segment address of
this buffer is loaded into the ES register, and the offset address is loaded into the
OX register.
Another feature of the EGA and VGA cards are their ability to work with a number
of different fonts and font sizes. This feature allows the EGA/VGA cards to be used
with different monitors, in different resolutions. Since the screen resolution is
determined by the monitor hardware and cannot be changed, the video card must
adapt to the monitor's resolution. Exceptions to the rule are the more versatile and
expensive multisync monitors, which get their name from the ability to adapt
themselves to different synchronizations (resolutions).
Of the different monitors which can be used in connection with an EGA or a VGA
card, the color monitor, normally used in conjunction with a CGA card, has the
poorest resolution. It only has a resolution of 640 pixels (horizontal direction) by
200 pixels (vertical direction). If you want to display 25 lines of 80 columns each
on the screen, you will have to use a character matrix of 8 by 8 pixels so that all
of the characters fit on the screen.
Even though the monochrome monitor cannot display different colors, it does offer
a resolution of 720 by 350 pixels when used with an MDA or Hercules graphics
card. The individual characters are displayed with a matrix of 9 by 14 pixels.
EGA and multisync monitors also have a vertical resolution of 350 pixels, but can
only display 640 pixels horizontally. The resolution of individual characters is 8 x
14 pixels-only slightly less than that of the monochrome monitors. VGA cards
and multisync monitors usually support a minimum vertical resolution of 480
pixels, but some units even support 600 raster lines. VGA cards often permit
character matrices of 8x16 (text mode) and 9x16 pixels.
262
Abacus 7.4 BIOS Screen Output F/UlCtions
Character generators
In order to support the various resolutions, the EGA/VGA cards have their own
character generators which can display characters in any height between one and 32
raster lines. The number of text lines per screen depends on the height of the
displayed characters and the resolution of the monitor. To make the best use of this
feature, the EGA/VGA cards get the bit patterns of the characters from a section of
the video RAM instead of from ROM.
Function 11H
Normally the character generator is programmed automatically and the appropriate
character set is loaded when a video mode is initialized, but it is possible for a
program to control these features with function IIH. You might want to use this
to display more than the usual 25 text lines on a monochrome, EGA, or multisync
monitor. But even if you do want to use 25 lines, these functions offer the ability
to redefine individual characters of the character set or to install an entirely new
character set. This can be done with sub-function OOH. Like all of the sub
functions of function IIH, the value IIH must be passed in the AH register and
the sub-function number must be passed in the AL register. A number of other
parameters must also be passed in the other processor registers. The BH register
stores the height of the individual characters. Since this function is intended for
modifying individual characters of the current character set, you must load the
height of these characters here. As mentioned above, the height of characters on
monochrome, EGA, or multisync monitors is normally 14 lines (or with the VGA
card, 16 lines on a VGA or multisync monitor), while on color monitors it is 8
lines. The BL register stores the number of the character table in which the
character will be loaded. Theoretically a number 0 through 3 can be given here for
one of the four different character tables, but you should restrict yourself to
modifying character table 0, because it is the only table guaranteed to be accessible
by EGA cards with less than 256K RAM. This character table is also the one into
which the EGA BIOS loads the character definitions when the video mode is
initialized with function OOH. Since you may not want to redefine the entire
character set, the CX register holds the number of characters to be defined
(maximum of 256). The number of the first character to be defined is placed in the
DX register and may not exceed the value 255.
The character definitions themselves are stored in a buffer whose address is passed
in the ES:BP register pair. The bit patterns of the individual characters are placed
in this buffer such that the height of each character (BH register) also specifies the
number of bytes per character in the buffer.
The individual characters are stored sequentially, so the total size of the buffer is
the number of characters multiplied by the height of the characters. The eight bits
of each byte reflect the status of the individual pixels in each raster line. If a bit is
set, the pixel will appear at the corresponding position in the foreground color. If
the bit is cleared, the pixel will appear in the background color. Note that the
263
7. The BIOS PC System Programming
character matrix is actually eight pixels wide, even through the characters are
displayed with a width of nine pixels on a monochrome screen. In this case the
ninth bit is not taken from the character definition, the last bit on each line is
simply duplicated.
Bit
ES:BP
Line 1
7 6 5 4 3 2 1 0
.. First character
00111000b
2 OOl11000b
3 OOOlOOOOb
4 11111110b
5 OOOlOOOOb
6 OOlOlOOOb
..
7 OlOOOlOOb
8 OOOOOOOOb
Second character
Line 1
As long as characters with the appropriate ASCII codes are displayed on the screen,
the changes will be noticeable immediately after this function is called.
While sub-function DOH can be used to load user-defined characters into the
character set, sub-functions OlH and 02H are used to load the two ROM character
sets contained on the EGANGA card. Sub-function OlH loads the entire 8x14
character set of the EGANGA card into one of the four character tables. Sub
function 02H loads the 8x8 CGA-compatible character set into one of the four
character tables. In addition to the function and sub-function numbers, both
functions are passed the number of the character table in which the character set is
to be loaded in the BL register. If the character table involved is the one currently
displayed on the screen, then the changes will be visible immediately after the
function is called. Although these two functions load the character sets, they do
not set the character generator to the height of the appropriate character set. For
example,if you load the 8x8 character set into the current character table while the
characters are being displayed in an 8x14 matrix, you will get a rather strange
. display. Raster lines one to eight will have the bit-map of the 8x8 character set
while lines nine to 14 will have the remainder of the 8x14 set.
264
AbaclLf 7.4 BIOS Screen OMlpIll Functions
If you want to work with several character sets in parallel, it is recommended that
you load the individual character sets into their own character tables and then
switch between the tables. Sub-function 03H is used to switch to a new character
table. In addition to the function and sub-function numbers, it must be passed the
number of the character table to be activated in the BL register.
Sub-functions lOH, llH, and 12H are almost identical to sub-functions OOH, om,
and 02H. They are also used for loading character sets, but they program the
character generator at the same time. This has the result that the characters are
displayed with the proper character height after the function is called. The number
of text lines on the screen changes automatically.
Function lOH is used to load and activate user-defined character sets and is called
exactly like function OOH. The number of text lines which are displayed after the
call to the function results from the vertical resolution of the monitor divided by
the height of the individual characters. If this division is not even and there is a
remainder, the remaining lines will be divided equally between the top and bottom
borders of the screen. Partial text lines are not displayed.
Sub-functions llH and 12H load and activate entire character sets. If the 8x14
character set is loaded with sub-function llH and a monochrome, EGA, or
multisync monitor is being used, 25 lines (EGA) or 28 lines (VGA) will be
displayed on the screen. If this is done while a color monitor is connected, which
has a vertical resolution of only 200 lines, only 14 lines will be displayed on the
screen.
These changes must also be taken into account when calling function 12H, which
loads and activates the 8x8 character set The usual 25 lines will be visible on a
color monitor, while on the other monitors the screen will consist of 43 text lines
(EGA) or SO text lines (VGA).
Regardless of the number of text lines which result from calling one of these
functions, the EGA BIOS ensures that the traditional BIOS functions for screen
output (function numbers OOH to OFH) will still work properly. Even if the screen
contains 43 lines, you can call the functions for character output, scrolling the
screen, and access the lines outside of the usua125-line boundary. However, you
should avoid using multiple screen pages and just use page 0, or you may run into
problems withlhe BIOS versions of various manufacturers.
Cursor emulation
Certain EGA cards can have problems with the mechanism called cursor
emulation. This involves converting the starting and ending lines of the cursor
when the height of the character matrix is changed. For example, if the character
265
7. TheBIOS PC System Programming
height decreases from 14 to 8 lines, then the cursor will be invisible if it was in
the range of raster lines from 9 to 14. To prevent this, the BIOS converts the
starting and ending lines to the new matrix height. This mechanism must be
disabled at the beginning of a program. Unfortunately, no function for doing this
exists in the EGA BIOS; the only way to disable it is to clear a flag in one of the
BIOS variables (bit 0 in the byte at address 0040:0087). The programs at the end
of this section demonstrate this in practice. The VGA BIOS ~ possess such a
function, as we'll see shortly.
Function 12H
All of the functions described so far can only be used in conjunction with an EGA
card or a VGA card To detennine if an EGNVGA card is installed, the EGNVGA
BIOS offers function 12H, which is not available in the normal ROM-BIOS. It is
called with the function number in AH and the value IOH in the BL register. If
this value is still in the BL register after the call, you can assume that no
EGNVGA card is available and the normal ROM-BIOS was called, which does not
support this function. A different value shows that an EGA or a VGA card is
available. In this case the BH, BL, and CL registers contain configuration
infonnation about the installed EGNVGA card.
The value in BH specifies the video mode that will be activated after the system is
booted. Since another mode may have been enabled in the meantime, this
information is of little use. The value in the CL register, which tells you what
kind of monitor the card is driving, is much more useful. The following values are
returned for the individual monitor types:
The contents of the BL register are also useful. They specify the amount of RAM
installed in the EGA card. The following codes can appear:
o 64K 1 128K
2 192K 3 256K
This distinction is important if you want to work with multiple character tables or
with the high-resolution graphics modes of the EGNVGA card. For example,
graphics mode number IOH, which offers a resolution of 64Ox350 pixels, can be
used only if the EGANGA card has at least 128K of RAM. The number of
character tables available also depends on the size of the RAM. This can be
detennined by the incrementing by 1 the number returned in the BL register.
266
Abacus 7.4 BIOS Screen Output FlUlCtions
Function 1AH
Function lAH, sub-function OOH informs the user of whether an EGA card or a
VGA card is installed. This function is only available to VGA cards. You must
pass the function number to the AH register and place the value OOH in the AL
register. This determines whether a VGA card is installed. If the value OOH
remains unchanged, there is no VGA card available. while a returned value of lAH
indicates a VGA card. The contents of the BL register indicate the active video
mode:
Code Meaning
OOH No video card
OlH MDA card / monochrome monitor
02H CGA card / color monitor
03H Reserved
04H EGA card / higp-res monitor
OSH EGA card / monochrome monitor
06H Reserved
07H VGA card / analog monochrome monitor
aSH VGA card / analog color monitor
The VGA BIOS includes six other sub-functions of function 12H, exclusively for
control of the VGA card. Sub-function 30H helps determine the number of raster
lines available (not text lines) when a VGA is operating with a VGA or multisync
monitor. In CGA mode this becomes only 200 lines instead of 400. The sub
function number must be loaded into the BL register. The VGA BIOS interprets
the number it finds in the AL register as the number of raster lines. A value of 0
in the AL register indicates 200, the value 1 indicates 350 and the value 2 indicates
400 raster lines.
Working in conjunction with color selection as mentioned above, so that EGA and
VGA cards can load their palettes or DAC registers, the color spectrum of a CGA
card can be emulated. Sub-function 31H enables or disables this emulation in the
VGA card after calling function OOH (video mode selection). Calling this sub
function signaled by the value 0 in the AL register activates green light, while a
value of 1 tells the VGA BIOS to avoid loading the corresponding register.
267
7. TheBIOS PC System Programming
Function 13H
We will mention one last function of the EGA/VGA BIOS. It is not exactly new,
since it was already in the AT ROM-BIOS, but it was not in the PC or XT BIOS.
This is function 13H, which displays a string on the screen. There are four
different output modes available, which differ in how the string is passed to the
BIOS and whether or not the cursor will be placed at the end of the string when the
output is done. Also, the functions differ in whether all the characters in the string
will be given a constant color or provided with individual attributes. In the first
case, the buffer, the address of which is passed in the ES:BP register pair, need
only contain the ASCII codes of the characters to be printed. The color for all of
the characters is taken from the BL register. In the second case, the attribute byte
for each character follows its ASCII code in the buffer.
0= One color for all of the characters. The cursor position does not
change.
1= One color for all of the characters. The cursor will be placed after the
last character of the string.
2= The buffer contains the individual attributes. The cursor position does
not change.
The number of the screen page on which the string is to appear can be specified in
the BH register, but this should always be the current page. Otherwise problems
will arise with printing control characters (carriage return, linefeed, etc.). The CX
register holds the length of the string. This refers to the number of characters to be
printed (attributes must not be counted in modes 2 and 3). The output position is
passed to function 13H in registers DH (line) and DL (column). And, fmally, we
shouldn't forget the function number in the AH register.
268
Abacus 7.4 BIOS Screen Output Functifms
Demonstration programs
Mter so many register assignments, function numbers, and the like, it helps to be
able to see some example programs to put the information into perspective. Many
of the functions we discussed are found in the programs listed below. Not all of
them are called by the actual main program but are included to show you how it's
done.
The programs have two main tasks. First, they show you how to work with and
program the color palettes. Second, and even more important, these programs
show you what possibilities are offered by defining your own character sets. Here
this is used to display a small graphic in text mode. This could be used when you
want to display a personal or company logo on the screen, but the characters
needed are not found in the ASCII character set. In the e~ample program, this is
demonstrated by displaying the text "PC Internals Michael Tischer" on the screen
in large, fancy lettering while in text mode. This message was first drawn with a
graphics program and then converted to a kind of virtual raster. This corresponds in
density to the character matrix <f 8xlipixels in the text mode when an EGA
monitor is connected. With the he1p of this raster we discovered that four rows of
30 characters each, for a total of 120 characters, were required to display this
graphic in text mode. The next step was to convert the bit-map of this graphic so
that it could be loaded into one of the character tables with the help of sub-function
DOH of function llH. Each eight consecutive pixels were combined into a byte and
then 14 of these eight-bit units in a column were combined together. The results
are the initialized arrays in the program listing.
Once these data-are created, the most time-consuming part of the whole procedure
is done, since all we have to do is call the appropriate function in order to load the
characters into the character table so we are able to display them on the screen.
This proved to be something of a problem in C because none of the functions for
interrupt calls allowed a value to be assigned to the BP register, which is where the
offset address of the character buffer must be passed. We had to write a small
assembly language routine which just loads the parameters passed to it into the
required registers and then calls the BIOS video interrupt
Inside the example program the bit patterns for the graphic are loaded into the
character definitions for the ASCII codes 128 to 248 with the help of this function.
The new characters replace the foreign characters and the border characters, but the
standard ASCII characters like letters and numbers are retained. You can load the
bit patterns in other parts of the character set as well, if you wish.
One r~utine in the program which is not executed is called SetLine and allows the
number of text lines on the screen to be set (25 or 43). If you use this function to
put the screen in 43 line mode, you first make certain arrangements regarding
screen output. Both Pascal and C send their output to the screen using DOS
functions when printf or writeln is called. Turbo Pascal allows direct access to the
video RAM under certain conditions, but this doesn't change the problem. Here it
269
7. TheBIOS PC Synem Programming
To avoid such problems, the two output routines in the example programs offer
the ability to output strings directly to the video RAM and avoid the DOS
functions.
{************************.*********************************************}
{* EGAP *}
{*--------------------------------------------------------------------*}
(* Description : demonstrates the use of the functions of the *)
{* EGAlVGA BIOS. *}
(*--------------------------------------------------------------------*)
{* Author : MICHAEL TISCHER *}
(* developed on : 08/30/1988 *)
{* last update : 06/07/1989 *}
{********************************.*.***********************************}
program EGAVGAP;
( 0, 0,255, 62, 28, 28, 28, 28, 28, 28, 28, 28, 28, 31), E }
( 0, 0,252, 7, 1, 1, 1, 1, 1, 1, 1, 1, 7,252) , A }
( 0, 0, 0, 0,129,195,195,199,199,206,206,142, 14, 14), C }
( 0, 0, 62,193,128,128, 0, 0, 0, 0, 0, 0, 0, 0), H I
( 0, 0, 16,144,112, 48, 48, 16, 16, 0, 0, 0, 0, 0), }
( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), L I
( 0, 0, 3, 0, . 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), I I
( 0, 0,254,248,112,112,112,112,112,112,112,112,112,112), N I
( 0, 0, 0, 0, 0, 0, 0, 0, 0,252, 61, 30, 30, 28) , E }
( 0, 0, 0, 0, 0, 0, 0, 0, 0,248, 6, 7, 3, 3), I
( 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0,128) , c }
( 0, 0, 32, 96,224,224,224,224,224,254,224,224,224,224), 0 I
( 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 6, 12, 28, 24), N I
( 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 28, 6, 7, 7), T }
( 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 15, 7, 7, 7), A I
270
Abacus 7.4 BIOS Screen OllJpwl FlUJCtions
271
7. TheBIOS PC System Programming
0, 0, 0, 0, 0, 0, 0, 0,128,
0, 96,112, 48, 56), ( B )
0, 0, 0, 0, 0, 0, 0, 0, 3,
0, 12, 24, 56, 48), ( M )
0, 0,
0, 0, 0, 0, 0, 0, 0,224, 56, 12, 14, 14), ( - )
0, 0,
0, 0, 0, 0, 0, 0, 0,126, 30, 14, 15, 15), { p }
Q, Q, 0, 0, 0, 0, 0, 0, Q, 60, 78,142, 14, 0) , ( C )
17, 17, 16, 16, 16, 16, 16, 16, 48,254, 0, 0, 0, 0) ,
(196,196,232,232,232,112,112, 8O, 32, 35, 0, 0, 0, a),
(112,112,112,112,112,112,112,112,248,254, 0, 0, 0, 0) ,
( 28, 28, 28, 28, 28, 28, 28, 28, 62,255, 0, 0, 0, 0),
( 56, 56, 56, 56, 56, 24, 28, 12, 6,129, 0, 0, 0, 0) ,
( 7, 0, 0, 0, 0, 0, 1, 2, 12,240, 0, 0, 0, 0) ,
( 7, 7, 7, 7, 7, -:..7, 7, 7, 15, 63, 0, 0, 0, 0) ,
( 0, 0, 0, 0, 0, 0, 0, 0,129,231, 0, 0, 0, 0) ,
(224,224,224,224,224,225,225,224,240,252, 0, 0, 0, 0) ,
( 0, 3, 60,224,224,192,192,224,225, 62, 0, 0, 0, 0) ,
(112,240,112,112,112,112,112,120,184, 14, 0, 0, 0, 0) ,
(224,255,224,224,224, 96,112, 48, 24, 7, 0, 0, 0, 0) ,
( 28,252, 0, 0, 0, 0, 4, 8, 48,192, 0, 0, 0, 0),
( 28, 28, 28, 28, 28, 28, 28, 28, 62,255, 0, 0, 0, 0) ,
( a, 0, 0, 0, 0, 0, 0, 0, 0,128, 0, 0, 0, 0) ,
( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) ,
( 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0) ,
(112,112,112,112,112,112,112,112,248,254, 0, 0, 0, 0) ,
( I, 1, 1, I, 1, I, I, I, 3, 15, 0, 0, 0, 0) ,
(193,193,192,192,192,194,195,195,227,250, 0, 0, 0, 0),
(240,254,255, IS, 1, 0, 0, 0,129,126, 0, 0, 0, 0) ,
( 14, 14,142,206,206,198, 71,195,129, 0, 0, 0, 0, 0) ,
( I, 0, 0, 0, 0, 0, 0, 0,131,124, 0, 0, 0, 0) ,
(193, 1, 1, 1, 1, 1, 65,129, 3, 15, 0, 0, 0, 0) ,
(192,192,192,192,192,192,192,192,224,249, 0, 0, 0, 0) ,
( 56, 56, 56, 56, 56, 56, 56, 56,124,255, 0, 0, 0, 0) ,
(112,127,112,112,112, 48, 56, 24, 12, 3, 0, 0, 0, 0) ,
( 14,254, 0, 0, 0, Q, 2, 4, 24,224, 0, Q, 0, 0) ,
( 14, 14, 14, 14, 14, 14, 14, 14, 31,127, 0, 0, 0, 0) ,
( 0, 0, 0, 0, 0, 0, 0, 0, 0,192, 0, 0, 0, 0» ;
begin
if DoIt then turn emulation on?
ViolnfoByte :E ViolnfoByte or 1 { yes, set bit 0
else \ { NO
ViolnfoByte .= ViolnfoByte and 254 mask out bit 0
end;
{***--.*-_ •• ----_._--_._--_.*._._._--._.-.-._---------***.-_._.----*..-}
(* GetCS: Returns the current output column. *)
(*Input : none *)
{* Output : the current cursor column *}
{***_._._--*._._--_._---.._._-------------------------***-.---*----_._.}
function GetCS : byte;
begin
GetCS .= VColumn; { get column from global variable }
end;
272
Abacus 7.4 BIOS Screen Output Functions
begin
GetCZ •• VLine; { get line from global variable }
end;
'*
{* CharDef: Defines the bit pattern of an individual character.
{*
Input ASCII
- TABLE
- ASCII code of the first char to be defined
number of the character table ( 0 bis 3 )
*}
*}
*}
{* - MATRIX number of lines in the character matrix *}
{* - NUMBER - number of characters to be defined *}
{* - BUFPTR - pointer to the buffer with the character *}
{* Output none *}
{* ••• ** ••• ***** •••••••• ** •• ** ••• **.** ••••••• *** ••••••• ****** ••• ********}
begin
Regs.ax :- $1100; { ftn. no.: character generator, subftn. 0
Regs.bh :- Matrix; { line height of the matrix
Regs.bl .- Table; { number of the character table
Regs.cx Number; number of the character to be defined
Regs.dx Ascii; { first character to be defined
Regs.bp :- Ofs( BufPtr A }; { offset address of the buffer
Regs.es := Seg{ BufPtr A ); {segment address of the buffer
intr(VIDEO_INT, Regs); { call BIOS video interrupt
end;
begin
Regs.ah :~ $12; ftn. no.: get configuration
Regs.bl :- $10; { subfunction number
intr(VIDEO_INT, Regs); { call BIOS video interrupt
case Regs.cl of CL contains the monitor type}
$OB GetMonTyp :~ MOMO; ( monochrome monitor )
end;
end;
{**************************.*******************************************}
{* SetCur : Sets the blinking cursor and the internal output position *}
{* Input - COLUMN output column (0 79 ) *}
{* - LINE = output line ( 1 •• n ) *)
{* Output none *}
{**********************************************************************}
273
7. TheBIOS PC System Programming
begin
Regs.ah .= $2; { ftn. no.: set cursor position
Regs.bh .= 0; { screen page 0
Regs.dh .= Line; { set coordinate
Regs.dl Column;
intr(VIDEO INT, Regs); { call BIOS video interrupt
VLine := Line; { save coordinates in internal variables
VColumn := Column;
end;
{* •• **************************************.*********.******************}
{* SetCol : Defines the contents of one of the 16 color registers in *j
{* the EGA card. *j
{* Input - REGNR - number of the color register *j
{*
{* Output
- COLOR = color value (0 to 63)
none
{****************************************************.*****************}
*'
*j
begin
Regs.ah .= $10; ftn. no.: set colors/attributes
Regs .al := 0; { subfunction 0
Regs.bl regnr; { set number of the register
Regs.bh :- color and 63; { set color value (mask out bits 6 and 7) ,
intr(VIDEO_INT, Regs); { call BIOS video interrupt ,
end;
{*****************************************************--**--**._.-.--.-}
{* Set Border : Defines the border color.
{* Input : - COLOR = color value (0 to 63)
*'*'
{* Output : none *'
{********************.********************** •• ********.****************}
begin
Regs.ah .= $10; { ftn. no.: set colors attributes
Regs.al := 1; { subfunction 0
Regs.bh := color and 63; { set color value (mask out bits 6 and 7)
intr(VIDEO_INT, Regs); { call BIOS video interrupt
end;
*'*'*'
{************** •• *************************************.****************)
{* SetLines Sets the number of lines.
{* Input Sub-function of function 11H:
{* $11 8x4 character set
{*
{*
{* Output
$12 : 8x8 character set
$14 : 8x16 character set
none
*'
*'
*'
{***************************************************** ••• **************}
begin
Regs.ah := $U; ftn. no.: character generator
Regs.al :- Lines; { sub-function of fnc. Ilh
Regs.bl := o· { use character table 0
intr(VIDEO_INT, Regs); { call BIOS video interrupt
end;
274
Abacus 7.4 BIOS Screen Output F/UlCtions
{*** ••• ********* ••••• ** ••• ** ••••••••••••••••• **** •••••• *.*.****.*.* •••• )
{* IsEga: Determines if an EGA card is installed and handles the *.
{*
{* Input
initialization of the global variables.
: none
*.
*.
{* Output : TRUE, if an EGA card is installed, else FALSE. *.
{* •••••••••••••••• ** ••• ** ••••••• ****.** •••• ** •••••••••• *.******* ••• *.*.}
begin
Regs.ah :- $12; ( ftn. no.: get video configuration
Regs.bl :- $10; ( subfunction number
intr(VIDEO INT, Regs); call BIOS video interrupt
if Regs.bl-<> $10 then is it an EGA or VGA card?
begin { yes
(*- create pointer to VRAM depending on the monitor connected
Mono :- Regs.bh - 1; ( connected to monochrome monitor? ,
-*'
IsEga :- TRUE; { an EGA card was discovered ,
end
else
IsEga •• FALSE; ( no EGA card discovered ,
end;
{••• ** •••••••• ** •••• ** •••••••••••••••••••••••••••••• ** •• ** ••••••••• ** •• )
{* IsVga: Determines whether a VGA card is installed, and initializes *'
{* the global variables. *.
{* Input none *'
{* Output TRUE if a VGA card is installed, otherwise FALSE. *'
(* Info Use this function BEFORE calling the ISEGA in your own *'
(* application, since the TRUE for some EGAs also applies *'
(* to this routine as well. *'
f·················································_···*******••• *** ••• *)
function IsVga : boolean;
begin
Regs.ah := $IA; ( function no.: Determine video system
Regs.al :- $00;
intr(VIDEO INT, Regs); ( Call BIOS video interrupt
if ( Regs.al - $IA ) and « Regs.bl = 7 ) or ( Regs.bl - 8 » then
begin ( VGA card installed and active
Mono :- FALSE;
IsVga := TRUE; { definitely a VGA card on board
end
else
IsVga FALSE; ( no VGA card connected ,
end;
f*···-···············································-***.******..
(* PrintAt: Outputs a string at the give screen position with a
{* certain attribute.
*****}
*'*.
(* Input - COLUMN - output column (0 •• 79 ) *'
{* - LINE - output line (0 •. NUMLINE-l *'
(* - COLOR = attribute for the characters to be printed *'
(*
(*
- OUSTR = the string to be printed
Output : none
f*············_······_···························**********************}
*.
*'
275
7. TheB/OS PC System Programming
begin
Stren :- length( OUtStr ); get length of the string
Index :- Line * 80 + Column; { set index in the array
if Mono then
begin { yes
for i:~1 to Stren do { run through the string
begin
MonoRAM[ Index ] .Character '= OutStr[i]; { set character
MonoRAM[ Index ].Attribute : Color; { set color
inc ( Index ); { increment the index
end;
end
else output to the color screen
begin
for i:=1 to Stren do { run through the string
begin
ColorRAM[ Index ] .Character :- OUtStr[i];{ set character
ColorRAM[ Index ].Attribute :- Color; { set color
inc( Index ); { increment the index
end;
end;
begin
Regs.ah :~ $10; { ftn. no.: set colors/attributes
Regs.al := $3; { subfunction number
i f DoBlink then ( blinking?
Regs.bl '. 1 yes, BL = 1 : blinking
else { no
Regs.bl :~ 0; { yes, BL 0: intense background color
intr(VIDEO_INT, Regs); ( call BIOS video interrupt
end;
procedure CIs;
begin
Regs.ah :- $0; { ftn. no.: set video mode
if Mono then connected to monochrome monitor
Regs.al := 7 { yes, 80x25 text display
else ( no, color monitor
Regs.al -= 3; { yes, 80x25 character text display
intr(VIDEO_INT, Regs); { call BIOS video interrupt
end;
276
Abacus 7.4 BIOS Screen Output Functions
{.*••• * •••• ** ••••• *.* ••• ~ •••• ** ••• *.*.*.* •••••• *•••••• •• **•••••••• * •••• }
{* EgaVga : Demonstrates how to use the functions of the EGA/VGA BIOS."}
{* Input : TRUE if VGA card installed, otherwise FALSE *}
{* Output : none *}
{***** ••••••••••••••••••••••••••••••••••••••••••• **•••••••• * •••• *.*•••• J
begin >
(*-- Add EGA/VGA hardcopy routine *)
Regs.ah := S12; { alternate select function
Regs.bl :- S20; ( sub-function: install rtne
intr(VIDEO_INT,RegS); { call interrupt
{*-- prepare screen layout
SetCur(O,O);
-----------------------------------------*)
CIs; ( clear the screen
Blinking( FALSE ); { light background instead of blinking
Printat (33, 22, 15, • press any key to end the program. .) ;
SetCur(34, 22);
begin
inc( i); (increment the color value for the first register
for j:-l to 14 do { run through registers 1 to 14
277
7. TheBIOS PC System Programming
t··········**·····***····**····················**·····
{.. MAIN PROGRAM
...••.•••. ** ••••***}}
{••••••••••• *** •••• ***** •••••••••••••••••••• *** ••••••••••••••••• ** •••• *}
begin
i f IsVga then { VGA card installed?
EgaVga( true { YES, run demo
else
begin
i f IsEga then { EGA card installed?
begin ( YES
if ( GetMonTyp = EGA I then EGA monitor attached?
EgaVga ( false ) ( YES, run demo
else { NO, wrong monitor
begin
writeln('This program only works with an EGA ');
writeln('card or VGA card, and a monitor ');
writeln('supported by one of these cards. ');
end;
end
else
writeln( 'No EGA or VGA card installed••. ·+
• Program aborted.' );
end;
end.
C listing: EGAVGAC.C
/ ••••••••••••••••• ** •••••••••• **** ••••••••••••••••• ****** ••• *.* ••• *****/
'* EGA V G A C *1
'*--------------------------------------------------------------------*1
'*'* Task *'*'
: Demonstration using the functions available
in the EGA-,VGA-BIOS
'*--------------------------------------------------------------------*'
'*'* Author MICHAEL TISCHER *'*'
'*'*--------------------------------------------------------------------*'*'
Developed on
Last update
: 08'30/1988
: 05'02/1989
'* (MICROSOFT C) *,
1* Creation CL lAS Ic EGAVGAC.C *1
'* LINK EGAVGAC EGAVGACA; *I
1* Call EGAC *I
1*--------------------------------------------------------------------*1
1* (BORLAND TURBO C) *f
1* Creation Make a project file containing the following: *f
1* EGAVGAC *I
1* EGAVGACA.OBJ *f
1* Before compiling, select the Options menu *f
1* and the Compiler option - make sure that the *f
'*
f*
1*
Small model is active *1
Select the Linker option - make sure that the *f
Case-sensitive link is set to Off *1
1* The program will compile with one warning... *f
278
Abacus 7.4 BIOS Screen Ordput Functions
'include <dos.h>
'include <stdlib.h>
'include <string.h>
'include <stdarg.h>
'include <bios.h>
EGA card.
279
7. TheBIOS PC System Programming
1*-- Definition of video info byte at offset address OxS? within ----*1
1*-- the BIOS variable segment --------------------------------------*1
'define VIO_INFO_BYTE «BYTE far *) MK_FP(Ox40, OxS?»
/***********************************************************************
Function : GET M °N
.*--------------------------------------------------------------------**
*
Task Determines the type of monitor connected.
* Input parameters None
* Return values Monitor type
BYTE getmon ()
(
union REGS regs; 1* Processor register for interrupt call *1
regs.h.ah = Ox12; 1* Function number: Determine configuration *1
regs.h.bl = Ox10; 1* Sub-function number *1
intB6(VIDEOINT, ®s, ®s); 1* Call BIOS video interrupt *1
if ( regs.h~cl == OxOB ) 1* Monochrome monitor? *1
ret urn ( MONO ); 1* YES *1
if (regs.h.cl OxOB 1* color monitor? *1
return( COLOR ); 1* YES *1
else 1* NO, must be EGA *1
return ( EGA );
1*--··--------·_·--··_··_·_·_*----_·_·_--*·_·_··------ *****************.
Function :SETCOL
**--------------------------------------------------------------------**
Task Defines the contents of one of the 16 EGA *
* color registers.
280
Abacus 7.4 BIOS Screen Output Functions
/***********************************************************************
Function : SET B 0 R D E R
**--------------------------------------------------------------------**
Task Sets the border color.
Input parameters: - COLOR = Color value (0-15)
Return values : None
****************************************************** *****************1
/************************.**********************************************
Function : SET LIN E S
**--------------------------------------------------------------------**
Task Determines the number of lines.
Input parameters: - Sub-function no. for calling function 11H
Ox11 8*14 character set
Ox12 8*8 character set
Ox14 8*16 character set (VGA only)
Return values None
**********************************************.*********** ••• ******** •• /
BOOL is ega ()
{
union REGS regs; /* Processor register for the interrupt call */
281
7. TheBIOS PC System Programming
1·-*·······-_·····---_·_·-······_··-··_·········_····--..-..............
Function : I S V GA *
•• _-----------------------=-------------------------------------------**
Task Determines whether a VGA card is installed.
BOOL is vga ()
{
union REGS regs; j* Processor register for the interrupt call *j
j_ •• _-----.---._._.-.----- •••• _-----_._._ •••• _._ ••• _-- - •••• _-_. __ ._. __ .
* Function : P R I N TAT
**--------------------------------------------------------------------**
Task Displays a string on the screen.
282
Abacus 7.4 BIOS Screen Output Functions
1-·*-··_·_····_···········_--_··················_···_· .*_.****_._.••._-
Function : P R I N T FAT *
**--------------------------------------------------------------------**
* Task Displays a string on the screen (like PRINTF),
writing the string directly to video RAM.
Input parameters: - COLUMN = Display column. *
- LINE - Display line. *
- CHCOLOR- Character color. *
- STRING = Pointer to the string.
* = Additional arguments as needed.
Return values None *
Information - When the end of the screen is reached, the *
screen will not scroll up. *
string can use the normal format specifier
***._--_•••_-_._._••-••__•••_••••_._._•• _._-----------**..._.._._....--/
group as used with PRINTF.
void print fat (BYTE column, BYTE line, BYTE chcolor, char * string, ••. )
..* _------------------------------------------------------------------_..*
Function
Task
: C L S
void cIs II
{
union REGS regs; /* Processor register for the interrupt call */
283
7. TheBlOS PC System Programming
/***********************************************************************
Function : N a KEY
.*--------------------------------------------------------------------**
Task Tests for a depressed key. *
* Input parameters: none *
Return values TRUE if a key is depressed, otherwise
* FALSE.
********************************************.*.*******.****.***********/
BOOL nokey ()
(
tUdef TURBOC 1* Using TURBO C to compile? *1
returnC-bioskey( 1 ) -=
telse
° ); 1* YES, read keyboard from BIOS
1* Using Microsoft C to compile .••
*1
*1
return( _bios_keybrd( _KEYBRD_READY ) --
fendif
° );1* Read from BIOS *1
}
284
Abacus 7.4 BIOS Screen OWplit Functions
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) , 1* s *1
0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0) , 1* *1
/112,112,112,112,112,112,112,112,248,254, 0, 0, 0, 0), 1* f *1
{ 28, 28, 28, 28, 28, 28, 28, 28, 62,255, 0, 0, 0, 0), 1* o *1
{ 3, 3, 3, 3, 3, 3, 3, 3, 7,159, 0, 0, 0, 0), 1* r *1
{128,128,128,128,128,128,128,128,192,240, 0, 0, 0, a) , 1* *1
{ 7,255,
{ 7,
{ 0,
0, 0, 0, 0, 1, 2, 12,240, 0, 0, 0, D),
7, 7, 7, 7, 7, 7, 7, 15, 63, 0, 0, 0, 0),
0, 0, 0, 0, 0, 0, 0,128,224, 0, 0, 0, 0),
1*
1*
1*
e
*'
*1
e *1
{ 14, 14, 14, 14, 14, 14, 14, 14, 31,127, 0, 0, 0, D), 1* h *1
/ 1, 1, 1, 1, 1, 1, I, 1, 3,207, 0, 0, 0, 0), 1* a *1
{192,192,192,193,193,195,195,193,225,248, 0, 0, 0, 0), 1* r *1
/ 0, 7,120,192,192,128,128,192,195,124, 0, 0, 0, 0), 1* a *1
/224,224,224,224,224,224,224,240,112, 29, 0, 0, 0, a) , 1* e *1
/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, D), 1* s *1
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 1* *1
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 1* n *1
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 1* e *1
( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 1* e *1
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 1* d *1
{ 0, 0,252, 60, 30, 30, 30, 23, 23, 23, 19, 19, 19, 17), 1* e *1
{ 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,130,130,130,196), 1* d *1
{ 0, 0,126,120,240,240,240,112,112,112,112,112,112,112), ,* *1
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,192,192,224), 1* e *1
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 64,224,224,224), 1* *1
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192, 96,112,112), 1* 1 *1
{ 0, 0,252, 60, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28), 1* 0 *1
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), ,* *,
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 1* a
*'
'{ 0, 0, 63, 56, 48, 48, 32, 32, 32, 0, 0, 0, 0, 0), 1* *1t
{ 0, 0,255,112,112,112,112,112,112,112,112,112,112,112), 1* *1
{ 0, 0,225,225, 97, 32, 32, 32, 32, 15, 3, 1, 1, I) , I" t *1
{ 0, 0,192,192,192, 0, 0, 0, 0,192,193,195,195,195), 1* h *1
{ 0, 0, 0, 0, 0, 0, 0, 0, 0,252, 3, 0, 0, 0) , 1* e *1
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 65,195, 71, 70), 1* "I
{ 0, 0, 0, 0, 0, 0, 0, 0, 0,124,131, 0, 1, 1), 1* e *1
{ 0, 0, 15, 3, 1, 1, 1, 1, 1, 1, 1,129,193,193), I" e *1
{ 0, 0,192,192,192,192,192,192,192,207,208,224,224,192), ,* n *1
{ 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 96,112, 48, 56), ,* t *1
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 12, 24, 56, 48), 1* e *1
{ 0, 0, 0, 0, o,. 0, 0, 0, 0,224, 56, 12, 14, 14), 1* r *1
{ 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 30, 14, 15, 15) , 1* *1
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 78,142, 14, D), 1* 0 *1
{ 17, 17, 16, 16, 16, 16, 16, 16, 48,254, 0, 0, 0, 0), 1* f *1
{196,196,232,232,232,112,112, 80, 32, 35, 0, 0, 0, 0), 1* *1
{112,112,112,112,l12,112,112,112,248,254, 0, 0, 0, 0), 1* t *1
{ 28, 28, 28, 28, 28, 28, 28, 28, 62,255, 0, 0, 0, 0), ,* h *'
,* *'*,
{ 56, 56, 56, 56, 56, 24, 28, 12, 6,129, 0, 0, 0, 0), 1* e
{ 7, 0, 0, 0, 0, 0, 1, 2, 12,240, 0, 0, 0, 0),
{ 7, 7, 7, 7, 7, 7, 7, 7, 15, 63, 0, 0, 0, 0), 1* *1
s
{ 0, 0, 0, 0, 0, 0, 0, 0,129,231, 0, 0, 0, D) , 1* *1
e
{224,224,224,224,224,225,225,224,240,252, 0, 0, 0, 0), 1* *1
r
{ 0, 3, 60,224,224,192,192,224,225, 62, 0, 0, 0, 0), 1* *1
e
{112,240,112,112,l12,112,112,120,184, 14, 0, 0, 0, 0) , 1* e
*1
{ 28, 28, 28, 28, 28, 28, 28, 28, 62,255, 0, 0, 0, 0),
{ 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 0, 0, 0, 0),
285
7. TheBIOS PC System Programming
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0),
1112,112,112,112,112,112,112,112,248,254, 0, 0, 0, 0),
I 1, 1, 1, 1, 1, 1, 1, 1, 3, 15, 0, 0, 0, 01,
(193,193,192,192,192,194,195,195,227,250, 0, 0, 0, 0),
( 1, 0, 0, 0, 0, 0, 0, 0,131,124, 0, 0, 0, D) ,
(192,192,192,192,192,192,192,192,224,249, 0, 0, 0, 0) ,
( 0, 0, 0, 0, 0, 0, 0, 0, 0,192, 0, 0, 0, 0)
);
H .) ;
286
Abacus 7.4 BIOS Screen Output Functions
void main ()
{
i f ( is vga () 1* Is there a VGA card installed? *1
egavga ( TRUE ); 1* YES *1
else 1* No VGA installed - go on *1
{
if is_ega(» 1* Is there an EGA card installed? *1
{ 1* YES *1
if ( getmon() EGA _E 1* Is there an EGA monitor connected? *1
egavga ( FALSE ): 1* YES, start demo *1
else
( 1* wrong monitor *1
printf(HThis program functions only with an\n H):
printf ("EGA monitor. \nH) ;
)
287
7. TheB/OS PC System Programming
DATA segment word public 'DATA' ;This segment includes all initialized
·/'----.;global and static variables
DATA ends
public _chardef
;----------------------------------------------------------------------
;-- CHARDEF: Defines the appearance of a character --------------------
;-- Call from C : void chardef( BYTE ascii, BYTE table, BYTE lines,
; -- BYTE amount, BYTE far • but);
;-- Return value: none
_chardef endp
;----------------------------------------------------------------------
ends ;End of code segment
end ;End of program
288
Abacus 7.5 Determining System Configuration using BIOS
The content of individual registers is not important during the call of this
interrupt, since neither the function number nor another argument must be passed.
01 = 32K
10 = 48K
11 = 64K
9 -
11 Number of RS-232 cards attached
13 Unused
While this bit assignment is the same for the PC and the XT, it differs from the
configuration word returned by the AT. To interpret the content of the AX register
correctly, you must know the model of the computer being tested.
289
7. TheBJOS PC System Programming
Bit Meaning
02-03 Unused
00: Unused
01: 40*25 cnaracters - color card
02: 80*25 characters - color card
03: 80*25 characters - mono card
06-07 Indicates number of disk drives in system i f bit 0 is
1
00 = 1 disk drive
01 - 2 disk drives
10 - 3 disk drives
11- 4 disk drives
08 Unused
12-13 Unused
Do not use this function to sense the current video mode, since it only indicates
the video mode switched on during system booting. Function ISH of interrupt
IOH provides the number of the current video mode.
290
Abacus 7.6 Determining Available RAM using the BIOS
Memory limits
This method determines RAM below the 1 megabyte limit only. The 8088's
addressing capability limits memory to 1 megabyte, so the PC and XT can report
on the entire memory available. The AT's 80286 processor can manage up to 16
megabytes of memory. However, interrupt 12H cannot report on any RAM beyond
1 megabyte.
Demonstration programs
The three program listings in this section are practical examples of the interrupts
described in the preceding section. The three programs, which were written in
BASIC, Pascal and C, are identical in their basic design.
To keep the program from becoming too long, the programs limit themselves to
the identical bits of the configuration words in the PC, XT and AT. For example,
291
!
You may want to rewrite this program so that it displays all the infonnation
contained in the cQnfiguration word according to computer type.
The comments in each listing should answer any questions you may have about
program flow.
292
Abacus 7.6 Determining Available RAM using the BIOS
630 END
640 '
60000 ,************************.*************.*.**********************'
60010 ,* Initialize the Routine for interrupt-Call *,
60020
60030
,*-------------------------------------------------------------*,
'* Input: none
60050 '***************************************************************,
60060 '
60070 IA-60000! 'Start address of the Routine in the BASIC-Segment
60080 DEF SEG 'Set BASIC-Segment
60090 RESTORE 60130
60100 FOR It - 0 TO 160 : READ xt : POKE IA+lt,Xt NEXT 'Poke Rout ine
60110 RETURN 'back to Caller
60120 '
60130 DATA 85,139,236, 30, 6,139,118, 30,139, 4,232,140, 0,139,118
60140 DATA 12,139, 60,139,118, 8,139, 4, 61,255,255,117, 2,140,216
60150 DATA 142,192,139,118, 28,138, 36,139,118, 26,138, 4,139,118, 24
60160 DATA 138, 60,139,118, 22,138, 28,139,118, 20,138, 44,139,118, 18
60170 DATA 138, 12,139,118, 16,138, 52,139,118, 14,138, 20,139,118, 10
60180 DATA 139, 52, 85,205, 33, 93, 86,156,139,118, 12,137, 60,139,118
60190 DATA 28,136, 36,139,118, 26,136, 4,139,118, 24,136, 60,139,118
60200 DATA 22,136, 28,139,118, 20,136, 44,139,118, 18,136, 12,139,118
60210 DATA 16,136, 52,139,118, 14,136, 20,139,118, 8,140,192,137, 4
60220 DATA 88,139,118, 6,137, 4, 88,139,118, 10,137, 4, 7, 31, 93
60230 DATA 202, 26, 0, 91, 46,136, 71, "66,233,108,255
program CONFIGP;
{*********************************************************************}
{* PRINTCONFIG: Display PC's configuration *)
{* Input : none *)
{* OUtput: none *)
{* Info : The configuration output depends on the PC type *)
{**********************.**********************************************}
procedure PrintConfig;
begin
clrscr; { Clear screen
if mem[SFOOO:SFFFE) = SFC then AT := true { test i f AT or
else AT := false; {PCorXT
writeln('Configuration of this PC');
wriceln('----------------------------------------------------');
write('PC-Type : ');
ease mem[SFOOO:SFFFEJ of Read PC type again
SFF writeln{'PC'); { SFF is a PC
SFE : writeln{'XT'); { SFE is an XT
SFC : writeln('AT') { SFC is an AT
else writeln {'Unknown') ;
293
7. The BIOS PC System Programming
end;
end;
end;
{********************* •• ******************************.***************}
{* MAIN PROGRAM *)
{*********************************************************************}
begin
PrintConfig; { Display configuration I
end.
C listing: CONFIGC.C
/********************************************** ••••• ******************/
/* CON FIG C */
/*-------------------------------------------------------------------*/
/* Task : Outputs the configuration of the PC on the */
/* Display Screen */
/*-------------------------------------------------------------------*/
/* Author MICHAEL TISCHER */
/* developed on : B.13.87 */
/* last Update : 9.21.87 */
/*-------------------------------------------------------------------*/
/* (MICROSOFT C) */
/* Creation MSC CONFIGC */
/* LINK CONFIGC PEPO; */
/* Call CONFIGC */
/*-------------------------------------------------------------------*/
/* (BORLAND TURBO C) */
/* Creation : With the RUN command in the Command Line */
/.***************************************************•• *****.*********,
1***************************************************** ****************/
/* CLS: Clear Screen and Cursor to upper left corner */
/* Input : none */
/* Output : none */
/*********************************************************************/
void ClsO
294
Abacus 7.6 Determining Available RAM using the BIOS
/************************************************************** •••••• */
/* PRINTCONFIG: Output the PC Configuration */
/* Input : none */
/* Output : none */
/* Info : the configuration output dependent on the PC-Type */
, •••• **** ••••••••• ** •••• ***** •••••••• **.*** •••• ** ••••• ************.***/
void PrintConfig()
{
case 0 printf ("undefined\n");
break;
break;
295
7. The BIOS PC System Programming
break;
case 48 printf("80*25 Character Mono-Card\n");
break;
void mainO
296
Abacu 7.7 Accessing the Floppy Disk from the BIOS
Early disk-based PC systems used only one side of disks for data storage. DOS
Versions 1.1 and later store data on both sides of the disk.
Disk structure
Each side of a disk consists of 40 tracks of 9 sectors each. Each sector has a
capacity of 512 bytes. The tracks are numbered from 0 to 39. Track 0 is located on
the outer edge and track 39 on the inner edge of the disk. The two disk sides have
designations of side 0 (front) and side 1 (back). This disk has a total storage
capacity of 360K.
The disk drives included with AT computers have 80 tracks with 15 sectors instead
of 40 tracks with 9 sectors. An AT floppy drive can store up to 1.2 megabytes of
data per disk. Systems with a 1.2 megabyte drive can read both 1.2 meg disks as
well as 360K disks.
Note: While it's possible to write 360K formatted disks using an AT type
1.2 megabyte drive, the resulting disks are not always readable by a
standard PCIXT 360K drive.
297
7. TheB/OS PC System Programming
Track 1
Track 2
Track 3
Sector 1
Sector 2
This structure is based on DOS specifications. It's possible to program the disk
controller directly or use the various BIOS functions to alter the disk structure.
Some methods of copy protection take advantage of this capability to arrange the
data on the disk in such a way that DOS cannot use the data directly.
The methods of transferring data to or from the disk are identical. First the
read/write head moves to the proper track. Since the disk moves constantly, the
sector to be processed eventually passes by the head, allowing data transfer.
BIOS makes some functions available for disk access at the lowest level. BIOS
thinks of DASD (Direct Access Storage Device) rather than disk drives.
A total of six BIOS disk functions can be accessed by calling interrupt 13H and
passing the function number to the AH register.
Function 0 resets the disk drive. The reset always executes automatically during
system start, but should also occur when an error occurs during the call of one of
these six functions. Before the interrupt call, function number 0 must be loaded
into the AH register. After the execution of the function the error status is returned
in the AH register. A value which indicates the type of error if any, is returned in
the AH register after all 6 functions.
298
Abacus 7.7 Accessing the Floppy Disk from the BIOS
If a program calls the reset function without the disk drive previously reporting an
error, error code 1 (function number not pennitted) may be returned in certain
cases, even though no error occurred. For this reason, the fWlction should be called
only after an error, and not after every disk operation.
Function 1: Status
If one of these errors appear, the disk operation just completed has been repeated
several times following a reset. Most of the time the repeated operation succeeds
without an error. If not, the current program in memory should react to the error
condition in a suitable manner and display an error message.
Working with the functions presented here, a time-out error can occur frequently
after a read operation. It usually occurs because of the speed decrease required to
read the disk: The old speed cannot be resumed immediately after reading.
Function 2: Read
Function 2 reads disk data. The BIOS must know the location from which you
want disk data read. This infonnation is passed in the DL, DH, CL and CH
registers:
DL Drive number (0 to 3)
o = Front side
1 = Back side
CL First sector to be read (1 to 9/1 to 15)
CH Track containing_ sector to be read
299
7. TheBIOS PC System Programming
Up to 9 sectors (PC/XT disk drives) or 15 sectors (AT disk drives) can be read
using one function call. The AL register specifies this number of sectors. Since
disk drives usually store data belonging together in sequential sectors, this enables
fast data access (e.g., 9 x 512 bytes = 4.5K in one disk revolution).
The address of a buffer in memory must be passed in registers ES and BX since the
data transfer area has no fixed location in RAM in which it can reside. The ES
register accepts the segment address of the buffer and the BX register accepts the
offset address.
The function returns the error status to the AH register, and the number of sectors
read in the AL register. In addition to the AH register, a set carry flag (carry flag =
1) signals the occurrence of an error.
Function 3: Write
Function 3 allows write access to the disk. It accepts arguments similar to those
used in function 2 above:
The value in the AL register indicates the number of sectors to be written, while
the ES and BX registers indicate the address of the memory area from which the
data should be read. The function passes the error status in the AH register, and the
number of sectors written in the AL register. The carry flag has the same meaning
as in function 2.
Function 4 tests whether data is transferred properly to and from the disk. The
BIOS bases correct data transmission on a cyclical redundoncy check (CRC) value,
instead of just comparing data in memory with data on disk. Using a CRe
involves summing the value of each individual byte in a sector with a specific
formula. Since most disk drives work well and have exceptional reliability, most
programmers ignore this function. DOS only uses this function to test data that
was transmitted to a disk in response to an active VERIFY ON flag.
300
Abacus 7.7 Accessing the Floppy Disk from the BIOS
The register setup is similar to functions 2 and 3 (see above), with the difference
that the AH register must contain 4. Since the function doesn't need a buffer
address, ~ function does not use the BX and the ES registers.
Function 5: Format
The last function of interrupt 13H allows the user to format part of a disk. Disk
formatting (e.g., with the DOS command FORMAl) is a requirement since disks
used by the PC are soft-sectored. This means that software, not hardware,
determines the positioning of the sectors and tracks on the disk. The operating
system must install the tracks and sectors on the disk using this function. Sectors
don't have to contain 512 bytes. This BIOS function lets you format 128, 256,
512 or 1,024 bytes per sector. However, you must format a complete track.
The function number (5) must be passed in the AH register. The AL register is
loaded with the number of sectors to format the track with. This number cail be
less than the DOS default values of 9 or 15. The number of the track to be
formatted is passed in the CH register. This track number must be a value from
°
to 39 (PC1Xl) or from to 79 (Al). The number of the disk drive is passed in the
°
DL register and the disk's side in the DH register.
Besides this information, the format function also requires a field containing
formatting char~teristics, which is also needed by the functions for reading,
writing and verifying a sector. The address of this field is passed in the ES and BX
registers. The segment address is loaded in the ES register and the offset address in
the BX register.
This table contains an entry consisting of four bytes for every sector to be
formatted:
Byte 1 Track to be formatted
Byte 2 Disk side (always 0 for single sided disks)
o = Front side
1 = Back side
o = 128 bytes
1 = 256 bytes
2 = 512 bytes
3 = 1024 bytes
Even though the function already possesses the number of the track to be formatted
and the disk side, these items appear here again for reasons of safety. The sectors
are placed into this table sequentially, which assigns the first sector the logical
number 1 and the second sector the logical number 7.
301
7. TheBIOS PC System Programming
While the logical and physical numbers of the sectors usually agree in a disk drive.
it makes sense in a hard disk to change the logical number of a sector instead of its
physical number. The hard disk of the XT reduces access time for individual sectors
by displacing the logical sectors by six in relation to the physical sectors.
Also the number of bytes which a sector can accommodate does not have to be
uniform. since each sector may be defined in the table. With this and other
parameters of the table, copy protection can be developed based on formatting.
Format-based copy protection cannot be processed by the operating system.
In addition to information such as the disk drive and sector number passed to the
BIOS functions during a call, the BIOS also requires a series of other items to
enable some disk operations. These parameters are passed in the device parameter
table. Such a table exists in the ROM BIOS. but you can install your own in
RAM. The address of the new device parameter table must be placed into memory
locations 0000:0078 to OOOO:OO7B. These memory locations should contain the
address of interrupt lEH (the PC doesn't use this interrupt).
OOS also offers the option of providing a unique device parameter table which
changes some values of this table from the BIOS default. accelerating access to the
disk drives.
The table itself consists of 11 bytes. The frrst two bytes transfer directly to the
disk controller. They indicate the step time and the DMA mode. The step time is
the maximum time period in which the read/write head of the disk drive can move
from one track to another.
The second byte indicates the time the disk drive motor can continue to run after a
disk operation. It defaults to 2 seconds since it assumes that this is the maximum
amount of time between consecutive disk accesses. Disk access speed is quicker if
the disk motor has already achieved operational speed and does not have to be
brought up to speed again. The value in this memory location is based on the 18
unit per second system clock. so a value of 18 represents running time of about
one second
302
Abacus 7.7 Accessing the Floppy Dislcfrom the BIOS
The value in byte 3 indicates the number of bytes per sector for a write or read
operation. It corresponds to the values for formatting a sector, so it normally
contains the value 3 (512 bytes per sector). If you want to write or read sectors
with other sector sizes, the proper value must be entered into this memory
location.
Byte 4 gives the maximum number of sectors per track. The PCf)IT disk drive
defaults to the value 9 in this location, while the AT defaults to the value 15
decimal.
Byte 5 of the table contains a value that represents the amount of empty space
between the end of a sector and the start of the following sector. This space relates
to the time BIOS must allow to elapse until the next sector appears under the
read/write head (not units of length). The value for this memory location defaults
to 42.
Byte 6 determines the data transfer length, which has no influence on data
transmission in most cases.
Since formatting of a disk occurs through the magnetization of certain areas, the
sizes of the non-magnetic spaces between sectors must be determined. Byte 7
records this, and these spaces must be larger than the space between sectors in byte
5 so that the beginning of a sector can be recognized properly.
Byte 8 accepts the ASCII code of the character which fills a sector during
fonnatting. The BIOS defaults to the division character V (ASCII code 246).
After the read/write head moves from one track to another it requires a rest period
to let the vibrations connected with the movement fade away. Then it can properly
perfonn any disk accesses which follow.
This rest period given in byte 9 of the table defaults to multiples of 1 millisecond.
While the BIOS grants 25 milliseconds of rest, DOS only permits 15
milliseconds.
The last entry of the table in byte 10 gives the time duration during which the disk
motor achieves operating speed. The value in this memory location defaults to
multiples of 1/8 second. Even here DOS requires more from the read/write head
than BIOS. It provides only a 1/4 second waiting period, as opposed to 1/2 second
for BIOS.
303
7. TheBIOS PC System Progrfllllllling
The first of these new functions determines the drive type in use. During the
function call, in addition to function number ISH, the number of the drive (0 or 1,
2 reserved for the hard disk) must be passed in the DL register. The function
returns the type of the drive in the AH register:
AH= 0 no drive available
AH = 3 Hard disk
If the drive detects a disk change it can be sensed with the help of function 16H.
After calling this function by passing the value 16H to the AH register and the
number of the drive (0 or 1), the function returns a number to the AH register
which tells whether the disk was changed since the last disk access. If this register
contains the value 6, the disk was changed. The value 0 indicates that no change
took place.
The last new function, function 17H, must be called before calling the formatting
function (function number 5) on PC/AT or PS(l machines to tell the controller
how it should format the disk. It should format the disk in either the 320/360K or
the 1.2 megabyte format. Besides the function number in the AH register and the
drive number in the DL register, a code must be passed to the AL register
indicating not only the format type, but also the type of disk drive in use. This
code has the following meaning:
1 format to 320/360K on a 320/360K-drive
304 J
Abacus 7.7 Accessing the Floppy Disk from the BIOS
Demonstration programs
The disk monitor in this section combines all the functions you have read about so
far. The monitor versions, written in BASIC, Pascal and C, all have the same
basic structure. Let's examine this structure before looking at the individual
programs.
The beginning of each program initializes variables, configures the screen and
resets the disk drives. Next the input loop executes; this loop is the center point of
the program. It displays the program prompt DISKMON> and then waits for user
input. After the user enters input and presses the <Return> key, the program
ensures that this input calls an executable command. If the input is illegal, the
program displays an error message and returns to the program prompt. Legal input
calls the subroutine, function or procedure requested.
All three programs support the Help, Format, Get, Fill, Constants and End
commands. The Fill command fills a sector with one character. The End command
terminates the program. There is no Write command in the monitor's command
set. This is because the amount of coding required to create a window for editing
the 512 bytes of a sector would have made the program listings too long.
All disk access commands ask for the track and perhaps the sector number of the
disk, but not the disk drive number or the disk side number. The program defaults
to disk drive 0 (drive A:) and disk side O. The Constants command lets you change
these defaults so you can access another disk drive or disk side. This command also
specifies the format parameter needed for an AT (i.e., what disk format should be
used).
Like all other user input, the program transfers this input to the BIOS instead of
the program itself. This disk monitor checks the BIOS's reaction to the input The
BIOS returns an error message in response to illogical or false input. Every disk
monitor command which accesses the disk drive reads the error status of the disk
drive after command execution. An error message then appears on the screen as
needed.
Get This overview includes a Get command which reads and displays a
sector of the disk. An internal buffer stores the contents of this sector
after input and displays the contents on the screen. Certain control
characters such as carriage returns or linefeed are shown as character
strings instead of as ASCII codes. For example, <CR> appears
instead of an actual a carriage return, and <LF> appears instead of a
linefeed. While reading a sector the program assumes that the sector
has the standard format of 512 bytes.
305
7. The BIOS PC System Programming
Reset The Reset command resets the disk drives. It also can be called by
various commands when the disk drive reports an error. If it's called
by the user before an error occurs, this can cause an error message.
Most disk error messages cannot cause damage to the drive.
110 '.
DISKMONB
.'
,..*---------------------------------------------------------------*.
120
130 Task Diskmon is a small Diskette monitor based
.'
140
150
160
170
'.
Author
developed on
last Update
on the BIOS-Interrupt 13 (h)
MICHAEL TISCHER
07124/87
05/20/89
.'.'
0'
180 ._••••••••••••••••••••••• _•••••••- ••••••••••• - •••••••• ** •••••••••••
190 '
200CLS : KEY OFF
210PRINT "WARNING: This Program should only be started if GWBASIC was"
"220PRINT "started from the DOS level with <GHBASIC Im:60000>."
230PRINT: PRINT"If this was not the case, please input <s> for Stop."
240PRINT "Else press any key ••• ";
250A$ - INKEY$ : IF AS = "s" THEN END
260IF A$ - ". THEN 250
270DIM SECTOR%[255] 'Stores Sectors to be read or written
280DIM FD% [29] 'Formatting data (maximum 0-29 - 30 Words)
290GOSUB 60000 'Initialize Interrupt-Routine
300 CLS 'Clear Screen
310 KEY OFF 'Turn off Function key assignment
320COLOR 0,7 'dark characters on light background (invers)
330PRINT" DISKMON (c) 1987 by Michael Tischer ? = Help·
340COLOR 7,0 'light characters on dark background
350 VIEW PRINT 2 TO 24 'Lines 2 to 24 form a window
360 DR% - 0 'access unit 0 (A) first
370 SIDE% - 0 'access the first Diskette side
380 FTYP' - 3 '1.2 MB Diskettes in 1.2 MB drive
390 DEF SEG = &HFOOO 'Set BIOS-Segment
400 IF PEEK(&HFFFE) = &HFC THEN AT' = - 1 ELSE AT' = 0 'test if AT
410 DEF SEG 'Set BIOS-Segment again
420 GOSUB 50000 'Execute Reset
430 GOSUB 51000 'Output Error message if necessary
440 INPUT"DISK-MON>",E$ 'User input prompt
450 IF E$ = ." THEN 440 'no input --> repeat input prompt
460IF E$ = ·1" THEN GOSU8 53000 GOTO 440 'Display Help-Text
470IF E$ = "r" THEN GOTO 420 'Reset
480 IF E$ "s" THEN GOSUB 54000 GOTO 430 'fill a Sector
490 IF E$ "f" THEN GOSUB 55000 GOTO 430 'format a Track
500 IF E$ "g" THEN GOSUB 56000 GOTO 430 'Read Sector and display
510IF E$ - "c" THEN GOSUB 57000 GOTO 440 'Input Constants
520IF E$ = "e" THEN VIEW PRINT 1 TO 24: CLS END 'End Program
530 PRINT"unknown Command!" : GOTO 440
540 '
50000 .****.*.*•• ******.*••• ******•••• *.*••• **********.***•• ********.*.
50010 ' 0 Execute Reset of all Disk drives .'
50020 ,*-------------------------------------------------------------*'
50030 ,. Input: none
50040 OUtput: DST' = the Diskette-Status
50050 ,. Info Z% is a Dummy-Variable ..
306
Abacus 7.7 Accessing the Floppy Disk from the BIOS
50120 '
51000 ,****.**********.*** •••• **.*** ••• *** •••••••• *** ••••••• *.*******.,
51010 ,. Output Error Message based on the Diskette-Status
51020 ,.-------------------------------------------------------------.'
51030 ,. Input : DST% = Status of the last Diskette operation
51040 ,. OUtput: none
51050 .••••• *** ••• ***** •• **** •••• ** •• * •••••••• *** •••••••••••••••••••• *1
51060
51070 IF DST% - 0 THEN RETURN '0 = everything o.k.
51080 PRINT "ERROR: ";
51090 IF DST% - &Hl THEN PRINT"Function number not allowed .. : GOTO 50000
51100 IF DSn &H2 THEN PRINT"Address-Marking not found" : GOTO 50000
51110 IF DSn = &H3 THEN PRINT"Write attempt on protected Disk" : GOTO 50000
51120 IF DST% &H4 THEN PRINT"Sector not found" : GOTO 50000
51130 IF DST\ &H6 THEN PRINT"Diskette changed" : GOTO 50000
51140 IF DST\ &H8 THEN PRINT"DMA Overrun" : GOTO 50000
51150 IF DST'" &H9 THEN PRINT"Data transmission beyond segment border" GOTO 50000
51160 IF DST% = 'HI0 THEN PRINT"Read Error" : GOTO 50000
51170 IF DST% 'H20 THEN PRINT"Error of Disk-Controller" : GOTO 50000
51180 IF DSn ,H40 THEN PRINT"Track not found" : GOTO 50000
51190 IF DST' - 'H80 THEN PRINT"Tirne Out Error" : GOTO 50000
51200 PRINT"Error ";DSn;" unknown" : GOTO 50000
51210 '
53000 ,************** •• ******************* ••• ** ••••••• ****************'
53010 ,. Oisplay Help-Text on the screen
53020
53030
,.-------------------------------------------------------------*,
,. Input: none
53040 ,. Output: none
53050 ,.***********.***************.************************.****.*.*.'
53060
53070 PRINT
53170 PRINT
53190 '
54000 ,***.***********************************************************1
54010 '. Fill a Sector
54020 ,* ____________________________________________________ ---------*1
54030 Input : DR'" the Number of the unit addressed
54040 SIDU the number of the Disk side addressed
54050 Output: DST' the Diskette status
54060 Info Z' is a Dummy-Variable
54070 1.**********************************.****.**********************1
54080
54090 INPUT "Track :", TRACK% 'Track in whiCh the Sector is located
541 00 INPUT .. Sector : ", SECTOR' 'Sector to be filled
54110 INPUT "Character: ",Z$ 'Fill Character
54120 IF Z$ = .... THEN Z$ = CHR$ (0)
54130 FOR I'" - 0 TO 511 : POKE VARPTR(SECTOR'[O])+I"',ASC(Z$) : NEXT
54140 DST'" 3 'Function number for writing
54150 INR% = &H13 'Call BIOS-Diskette-Interrupt 13(h)
54160 NUM' - 1 'Number of Sectors
54170 OFS1O' - 0 OFSHI% = 0 'initialize Variables
54180 SEG' - -1 'Use BASIC DS for ES
54190 NUM' - 1 'Number of Sectors to be read
54200 OFS1O' - VARPTR(SECTOR%[O]) AND 255 '10 , HI-Byte of the Offset
307
7. The BIOS PC System Programming
308
Abacus 7.7 Accessing the Floppy Disk from the BIOS
57010 '. Input Constants (Unit number, Diskette side, etc.) .'
57020 '*-------------------------------------------------------------*.
57080 '
57170 '
60060
60070 IA=60000! 'Start address of the Routine in the BASIC-Segment
60080 DEF SEG 'Set BASIC-Segment
60090 RESTORE 60130
60100 FOR It = 0 TO 160 READ X% POKE IA+I%,X% NEXT 'Poke Routine
60110 RETURN 'back to caller
60120 '
60130 DATA 85,139,236, 30, 6,139,118, 30,139, 4,232,140, 0, :'39, 118
60140 DATA 12,139, 60,139,118, 8,139, 4, 61,255,255,117, 2,140,216
60150 DATA 142,192,139,118, 28,138, 36,139,118, 26,138, 4,139,118, 24
60160 DATA 138, 60,139,118, 22,138, 28,139,118, 20,138, 44,139,118, 18
60170 DATA 138, 12,139,118, 16,138, 52,139,118, 14,138, 20,139,118, 10
60180 DATA 139, 52, 85,205, 33, 93, 86,156,139,118, 12,137, 60,139,118
60190 DATA 28,136, 36,139,118, 26,136, 4,139,118, 24,136, 60,139,118
60200 DATA 22,136, 28,139,118, 20,136, 44,139,118, 18,136, 12,139,118
60210 DATA 16,136, 52,139,118, 14,136, 20,139,118, 8,140,192,137, 4
60220 DATA 88,139,118, 6,137, 4, 88,139,118, 10,137, 4, 7, 31, 93
60230 DATA 202, 26, 0, 91, 46,136, 71, 66,233,108,255
" Structurally this program resembles the other BASIC programs which have been
presented. The main program with the input loop is in lines 300 to 540. Then
follow the individual commands of DISKMON which exist as subroutines between
lines 50000 and 57170. The subroutine for initializing the interrupt call starts at
line 60000 (the program uses this interrupt frequently).
The use of a BASIC variable as a buffer for the reading and wtiting of data is
somewhat complicated in this program. The program dimensions an integer array
with elements from 0 to 255. Since every element in this array requires 2 bytes
(for integer), the program allocates 512 bytes for a buffer. The problem arises from
the BASIC interpreter's garbage c:;ollection routine. When it removes data, which is
no longer needed, from the variable storage area, it also moves the data buffer. The
309
7. The BIOS PC System Programming
address of this buffer which was supposed to be passed to BIOS is no longer valid.
Other data are now stored there.
During a write operation this wouldn't be very bad, since only false data would be
written to the disk. During a read operation this could lead to a crash of the BASIC
interpreter, since variable memory could be destroyed. To prevent this, establish
the address of the buffer variable immediately before the BIOS function call. Also,
make sure that the variables which accept this address are constantly available. For
this reason DISKMON initializes the two variables with 0 before storing the
buffer address in them. This offset address must receive the segment address of the
current BIOS function in the ES register. Since the BASIC data segment contains
the buffer address, the contents of the Data segment register DS must be passed to
ES. This is done by passing the value -1 for ES which causes the interrupt
function to copy the contents of the DS registers to ES.
begin
Regs.ah := 0; 1 Function number for reset is 0 }
310
Abacus 7.7 Accessing the Floppy Disk from the BIOS
begin
Regs.ah := 1; ( Function number for error status is 1 )
intr(s13, Regs); ( Call aIOS disk interrupt )
GetDiskStatus :- Regs.ah; ( Read error status ).
end;
begin
Regs.ah 2; { Function number for reading is 2
Regs.al Number; { Set number of sectors for reading
Regs.dh Side; { Set side number
Regs.dl DriveNum; { Set drive number
Regs.ch Track; I Set track number
Regs.cl Sector; { Set sector number
Regs.es := SegAdr; { Set buffer address
Regs.bx := OfsAdr;
intr($13, Regs); ( Call aIOS disk interrupt
NumRead := Regs.al; ( Number of sectors read
ReadSectors '= Regs.ah; { Read error status
end;
t······················ __ ···········_····_············************... *)
(* WRITESECTORS: Write a certain number of sectors
*}
begin
Regs.ah :- 3; ! runct.ion number for writ.ing is 3 )
311
7. The BIOS PC System Programming
Regs.bx :- OfsAdi;
end:
~
{-*_._._--._.. _._-------**...._----_._. __ ._....-.... _-*-_ ...._---_._._}
(* SETDASD: must be called for an AT before formatting to indicate *)
*'*'
(* i f it should be formatted with 360 KB *)
{* or with 1.2 MB
{* Input: see below
{ ... ... _._. __ .... __ ._ .. _. __ ._._._._ ...... _-._ .... _----_ ......_._._---}
(* Output : none
_
*)
begin
Regs.ah $17; Funct ion number
Regs.al :~ DiskFormat; {' Format
Regs.dl :~ DriveNum; ( Dri ve number
intr ($13, Regs); ( Call BIOS disk interrupt
end:
begin
for LoopCnt :~ 1 to Number do Create sector descriptor
begin
DataField[LoopCnt].Track :- Track; ( Number of the track
DataField[LoopCnt] .Side :- Side; ( Diskette side
DataField[LoopCnt].Sector ' s LoopCnt; { Number of the sector
DataField[LoopCnt].Length :~ Bytes; ( Number of bytes in the sector
end;
Regs.ah '= 5;
Regs.al
Regs.es
'.
Number;
seg(DataField[I]);
( Function number, Number
Address of the data field in
Regs.bx ofs(DataField[I]);
.~
( registers ES and BX
Regs.dh := Side; ( Side number
Regs.dl DriveNum; ( Drive unit
Regs.ch := Track; ( Set track number
intr($13, Regs); ( Call BIOS disk interrupt
Format Track Regs. ah; ( Read error status
end;
312
Abacus 7,7 Accessing the Floppy Disk from the BIOS
begin
case ErrorNumber of
SOO ( 0 means no error
SOl writeln('ERROR: Invalid function number');
S02 writeln('ERROR: Address marking not found');
S03 writeln('ERROR: Write attempt on protected disk');
S04 writeln('ERROR: Sector not found');
S06 writeln('ERROR: Diskette changed');
S08 writeln('ERROR: DMA overrun');
$09 writeln('ERROR: Data transmission beyond segment border');
S10 writeln('ERROR: Read error');
S20 writeln('ERROR: Disk controller error');
S40 writeln('ERROR: Track not found');
S80 writeln('ERROR: Time out error');
else writeln('ERROR: Error ',ErrorNumber,' unknown');
end;
if (ErrorNumber <> 0) then ErrorNumber:~ResetDisk; { Reset performed J
end;
{_ .......... __ ......... _...•••....... _.••............ -.... _.. _._ .. _.. -.
*J
procedure Constants;
begin
write('Unit-Number (0-3) : ');
readln(DriveNum); Read unit number
write ('Diskette side (0 or 1): ');
readln(Side); Read head number
i f AT then { only for AT
begin
writeln('Format-Parameter: ' };
writeln(' 1 ~ 320/360-K8-Diskette 1n 320/360-KB drive');
writeln(' 2 ~ 320/360-KB-Diskette in l,2-MS drive');
write(' 3 = l,2-M8-Diskette in l,2-M8-drive -- Please input: '),
readln (FTyp)
end;
end;
procedure Help;
begin
writeln(.13'IO'C 0 M MAN D 0 V E R V lEW');
writeln('-------------------------------');
writeln('e End');
writeln('g - Get (Read) ');
writeln('s = Sector fill');
writeln('r - Reset');
writeln('f - Format');
writeln('c Constants');
writeln('? ~ Help'.13.10);
end;
313
7. The BIOS PC System Programming
{* Input : none *)
{* Output : none *)
{----_ •• _-_ •••••••••••• _._ •• _••••••• _._ •••• _•• _._. __ .-•••*_•••• _••••• _}
procedure READSEC;
begin
write (' Track ') :
readln(Track); { Read track from keyboard )
write('Sector: ');
readln(Sector); Read sector from the keyboard
Errcode :- ReadSectors(DriveNum, Side, Track, Sector, 1,
seg{DataBuffer), ofs(DataBuffer), Dummy);
begin
write('----------------------------------------'+
'----------------------------------------'}i
for Dummy:=l to 512 do { output the 512 characters }
begin
case DataBuffer[DurnmyJ of
.00 write('<NUL>'); {treat control characters separately)
t07 write('<BEL>');
.08 write (' <BS>') ;
.09 write (' <TAB>');
tlO write('<LF>');
t13 write('<CR>');
t27 write (' <ESC>') ;
else write(DataBuffer[Durnmy»; {output normal character}
end;
end:
write {t13.10'----------------------------------------' +
'----------------------------------------');
end
else WriteError(Errcode); { output error message
end;
(-*-_••••• _.*_.-.-----_._._---_._._._._....--------_.---**._._._._....}
{* FORMATIT: format a certain number of sectors of a *}
{* track with 512 bytes each *}
{* Input : none *)
{* Output : none *}
{-** ••••••• _-_ •• _._._._._-----_.- •• _._._ •••• __ ••••• _-- ••• _._._---_.-._}
procedure Formatlt;
begin
write (' Track ') ;
readln (Track) ; I Read number of tracks from keyboard
write (' Sector: ');
readln (Sector); Read number of sectors from the keyboard }
if AT then SetDasd(FTyp); { if AT then diskette type }
WriteError(ForrnatTrack(DriveNum, Side, Track, Sector, 2»;
end;
{************************************.************** •• *·****·**·******t
{* FILLSECTOR: Fill a sector with a character *)
{* Input : none *}
{* Output : none *}
{****.****************************************************************}
procedure FillSectar;
314
Abacus 7.7 Accessing the Floppy Disk from the BIOS
begin
write (' Track ' );
readln(Track); { Read track from keyboard
write (' Sector ') ;
readln(Sector); Read sector from keyboard
write ('Character: ');
readln(FillChar); \ Read the fill character from the keyboard
for LoopCnt :- 1 to 512 do
DataBuffer[LoopCntI := FillChar; Fill buffer with characters
WriteError(WriteSectors(DriveNum, Side, Track, Sector, 1,
seg(DataBuffer), ofs(DataBuffer), Dummy));
end;
begin
clrscri ( Clear screen
textbackground(7); ( light background
text color (0) ; ( dark characters
writeln(' DISKMON: (c) 1987 by Michael Tischer '+ \ Headline
? = Help ');
window (1, 2, 80, 25); ( only first line does not belong to window
else AT := false; ( PC or XT
repeat
repeat
The DISKMON in Pascal and the following version in C strongly resemble each
other. Both have the input loop inside the main program and the individual
commands placed in procedures or functions outside the main program. Unlike the
BASIC version of DISKMON, a difference exists between the DISKMON
commands and the BIOS function call. They are stored in separate program
sections. This has the advantage that the BIOS function calls can be easily
transferred as stand alone modules to other programs.
Problems with addressing the data buffer don't exist in C or in Pascal as they do in
BASIC. The buffer is a local variable.
315
7. The BIOS PC System Programming
There are two small differences between the C and Pascal versions. They are in the
screen display and the administration of constants for unit number, disk side, etc.
While the Pascal version defines these as global variables, the C version defines
them as local variables within the mainO program area.
C doesn't allow easy window defmition for performing tasks. This is why the C
version of DISKMON doesn't use the flTSt screen line as a status line to output a
copyright notice and cali the Help command.
C listing: DISKMONC.C
1***************************************************** *****************/
1* DIS K M 0 N C *1
1*--------------------------------------------------------------------*1
1* Task : DISKMON is a short disk monitor program, *I
1* using BIOS interrupt 13(h) functions *1
1*--------------------------------------------------------------------*1
1* Author MICHAEL TISCHER *1
1* Developed on : 08/15/1987 *1
1* last update : 06/08/1989 *1
1*--------------------------------------------------------------------*1
1* (MICROSOFT C) *I
1* Creation : CL lAS DISKMONC.C *1
1* Call : DISKMONC *1
1*--------------------------------------------------------------------*1
1* (BORLAND TURBO C) *1
1* Creation Make sure Case-sensitive link is OFF before *1
1* compiling & linking *1
1* Select Compile/Make or RUN (no project file) *1
/******************** •• ****************.****************** ••• **********/
'endif
/*-- The following macros state the offset and segment addresses of --of
/*-- any pointer -----------------------------------------------------*1
316
Abacus 7.7 Accessing the Floppy Disk from the BIOS
fdefine GETSEG (p) «unsigned) « (unsigned long) «void far *) p)) » 16))
'define GETOFS (p) «unsigned) «void far *) p))
I-***k*-----*----**--*-*----*--*-*-***-*-*-*--****-*-* -*---*-*-*-**-*--/
/* RESETDISK: Reset all drives connected to system */
/* Input : none */
/* Output : error status */
I_W*kkWkk __ * _______ *_****_*_*_*** ____ **_***_* ____ *_*_***kk***k*kkkk* ___ /
byte ResetDi sk ()
I_W**kW*k ______ *_* __ * _______ * __ **_** _____ **_** __ *** __ *kk*k**kkkkkk*k ___ /
/* WDS: Display status of the last disk operation */
/* Input : see below */
/* Output : TRUE if no error, otherwise FALSE */
/*-*-*----*----*-**--*********-------*------_ ..._------_._._-----------/
b~e WDS(Status)
(
i f (Status) 1* Error occurred? *1
( /* YES */
break;
break;
break:
breaK;
case Ox06 printf("Disk changed\n");
break;
break;
break;
break;
break;
break;
317
7. TheBIOS PC System Programming
break;
break;
I
ResetDisk (); 1* Execute reset on error *1
I
return (! Status);
I
,*******.*********************************** •• *************************/
1* DREAD: Read specified sector from disk *1
1* Input : see below *1
1* Output : error status *1
/************************** •••• *****************.**********************/
/*****.****************************************.*****.*****************/
1* DWRITE: Write to the specified number of sectors *f
f* Input : see below *f
f* Output : error status *1
/*************** ••• *******************.***************.********* •• *****/
318
Abacus 7.7 Accessing the Floppy Disk from the BIOS
/**********************************************************************/
1* FORMAT: format a track *1
1* Input see below *1
1* Output error status *1
1* Info BYTES parameter gives the number of bytes in the for- *1
1* matted sector. The following codes are allowed: *I
1* 0 = 128 bytes, 1 = 256 bytes *I
1* 2 = 512 bytes, 3 = 1024 bytes *I
1-**··_·_·_·_·_·_·_-*-*_·_-*-*·_--------*-*-----------....*------*--**-/
byte Format (Drive, Side, Track, Number, Bytes)
byte Drive,
Side, 1* Side/head number *1
Track, 1* Track to be formatted *1
Number, 1* Number of sectors in this track *1
Bytes; 1* Number of bytes per sector *1
319
7. The BIOS PC System Programming
/**********.~******.********************.******************************'
1* HELP: Display help screen *1
1* Input : none *1
1* Output : none *1
/**********************************************************.***********/
void Help ()
printf("-------------------------------\n");
printf("Track : .. );
(
printf("----------------------------------------"):
printf{"----------------------------------------");
break:
break:
break;
break;
break:
break:
break:
break:
320
Abacus 7.7 Accessing the Floppy Disk from the BIOS
printf("\n----------------------------------------");
printf("----------------------------------------\n");
)
Register.h.al FTyp;
Register.h.dl Drive;
I
WDS(Format(Drive, Side, Track, Number, 2, AT, FTyp»;
)
j****************************************************. *****************/
1* FILL Fill a sector with a character *1
/* Input : see below */
1* Output : none *1
/***************************** •• ********************************** •• ***/
/**********************************************************************/
/*~ MAIN PROGRAM **1
/**********************************************************************/
321
7. TheBlOS PC System Programming
void main()
break;
322
Abacus 7.8 Accessing the Hard Disk from the BIOS
Like the floppy disk, a hard disk consists of magnetized plates, also called disks,
which can store data as magnetic impulses. Unlike the floppy disk, a hard disk
contains several of these disks. The plates in a hard disk can store data on both
sides, and therefore must have a read/write head above and below each disk for
reading and writing data.
Partitions
The hard disk has another division beyond track, sector and cylinder levels:
Partitions allow you to configure parts of a hard disk for different operating
systems. Although you can format a disk according to one operating system and
use that operating system exclusively, hard disks allow you to store several
operating systems at once. You can allocate the number of cylinders needed for
each operating system when formatting a hard disk. The first sector of the hard disk
contains the information about this memory allocation. This information includes
data about the beginning of each partition and its size, as well as which operating
system lies in this partition (e.g., DOS has code 1). It also records which
operating system is active and which operating system should be started during the
system boot
Note: Exercise extreme caution when using the BIOS hard disk access
functions. Unlike a disk drive which you can test out with an unused
disk, you can't do the same with a hard disk. Careless use of the
Write or Formatting function could lead to irretrievable data loss. If
323
7. TheBIOS PC System Programming
you plan to try these functions, back up the entire hard disk ~
you try these functions.
BIOS accesses the hard disk through interrupt 13H-the same interrupt used for
floppy disk access. The individual functions are identical for hard disk and floppy
disk drives, but hard disk control is very different from floppy disk drive control.
BIOS uses different modules for controlling the hard disk and disk drives. When
you call interrupt 13H, it accesses the hard disk routine ftrst. This routine tests
whether the hard disk or floppy disk drive should be addressed, based on the device
number in the DL register. If the hard disk is involved, it calls the proper routine
in the hard disk module. On the other hand, if the floppy disk drive should be
addressed, another module must be called by calling interrupt 40H, which points to
the old disk interrupt 13H.
All hard disk functions share the condition that after the function call they use the
carry flag to signify whether they could perform their task or if an error occurred. If
this is the case, the carry flag sets and an error code passes to the AH register. The
individual codes have the following meanings:
When anyone of these errors occur except error 01, execute a reset and try calling
the function again. Most of the time the error won't recur.
324
Abacus 7.8 Accessing the Hard Dislcfrom the BIOS
The use of processor registers for data transmission becomes another parallel
between the hard disk and floppy disk functions. The function number passes to
the AH register. If the program requires the number of the hard disk to be
addressed, it always passes to the DL register. The value 80H always stands for the
first hard disk, and 81H f<r the second hard disk. The number of the read/write head
(and indirectly of the disk addressed) passes to the DH register. The CH register
accepts the cylinder number. Remember that a 10 megabyte hard disk has more
than 306 cylinders. Since this 8-bit register can only address 256 cylinders at a
time, this register alone isn't enough to indicate the cylinder number.
For this reason bits 6 and 7 of the CL register help indicate the cylinder number.
They form bits 8 and 9 of the cylinder number, permitting an addressable range of
1,024 cylinders (0-1,023). Bits 0 to 5 of the CL register provide the number of the
sector to address (they are numbered from 1 to 17 in each cylinder). If you attempt
to access several sectors at a time, the numbers of these sections pass to the AL
register. During read/write operations a buffer address must be indicated from which
data can be read or to which data can be transferred. In such a case, the ES register
passes the segment address and the BX register the offset address of this buffer.
Function OH resets the controller without the need of any other parameters. After
an error occurs, this function should always be called before the next data access.
The information from the hard disk on which the execution of the reset is based
passes to the DL register.
Function 01 H: Status
Function 01H reads the hard disk drive status (this status is indicated after every
hard disk operation). The number of the drive whose status should be read must be
stored in the DL register.
Function 02H reads one or more sectors. A single call of this function can read up
to 128 sectors. This limitation occurs because the hard disk controller transfers data
directly into RAM through the DMA. The DMA chip can only transfer a
maximum of 64K at a time, in one memory segment at a time. For this reason, it
is important that the complete buffer whose address passes to ES:BX fits into the
64K starting with the segment address in ES. Otherwise the DMA chip may report
an error.
This function initially reads all sectors in numerical order within the cylinder
indicated, using the read/write head indicated. Once the function reads the last sector
of a cylinder, and/additional sectors should be read, reading continues with the first
sector of the same cylinder, but using a different read/write head. After the function
325
7. TheB/OS PC System Programming
accesses the last read/write head and additional sectors still remain, the read process
continues in the first sector of the following cylinder on the fIrst read/write head.
Function 03H writes one or more sectors. A single call of this function can write
data in up to 128 sectors. This limitation is also caused by the DMA (see function
02Habove).
This function initially writes all sectors in numerical order within the cylinder
indicated, using the read/write head indicated. Once the function writes to the last
sector of a cylinder, and additional sectors should be written, writing continues
with the first sector of the same cylinder, but using a different read/write head.
After the function reaches the last read/write head and additional sectors still
remain, the write process continues in the first sector of the following cylinder on
the f1T8t read/write head.
Function 05H formats the hard disk. Before a hard disk can be accessed it must be
formatted. Similar to the function used for formatting a disk, this function must
know the read/write head and cylinder number. In addition, it must pass the address
of the buffer to the register pair ES:BX. This buffer must be 512 bytes long, even
if the function only accesses the first 34 bytes. It contains two bytes for each of
t~e 17 sectors to be formatted. The first byte indicates whether the sector is in
good condition. Assuming that every sector is in good condition, the value 0 is
entered into this byte. The second byte accepts the logical number which should be
assigned to the current sector. BIOS takes information from the first two bytes in
the table about the first physical sector of the cylinder. Bytes 3 and 4 supply
information about the second physical cylinder. Once the physical series has
already been determined, the logical sequence of the sectors can be set through 2
bytes of a sector indication in this table.
The numbers differ between a logical sector and its respective physical sector. This
shift in logical sectors, called sector interleaving, help optimize access time on a
hard disk.
326
Abacus 7.8 Accessing the Hard Disk from the BIOS
The average hard disk rotates at 60 revolutions per second. This means that the
next physical sector appears under the read/write head every thousandth of a second.
The hard disk controller is incapable of transferring the 512 bytes of the sector
previously read into the PC's memory. For this reason, the logical sectors shift in
relation to the physical sectors, so that the next logical sector only appears under
the read/write head after the hard disk controller completes the transmission of the
last sector.
The interleave factor, i.e., the number of sectors by which the logical sectors shift
in relation to the physical sectors, depends on the relationship betw.een the speed at
which the hard disk revolves, and the processing speed of the hard disk controller.
For example, if the interleave factor is 6, this means that for every sector read, a
"jump" of 5 sectors takes place before the next logical sector follows. The closer
this factor comes to 1 (in which case the physical and logical sectors are identical),
the faster the hard disk and the closer the transmission speed comes to the physical
limit.
While XT hard disks operate with an interleave factor of 1:6, AT hard disks are
twice as fast, with an interleave factor of 1:3. The effects of the interleave factor
and the relationship between logical and physical sectors can be seen in the
following table:
4 2 4 10
5 8 5 13
6 14 6 16
7 3 7 2
8 9 8 5
9 15 9 8
10 4 10 11
11 10 11 14
12 16 12 17
13 5 13 3
14 11 14 6
15 17 15 9
16 6 16 12
17 12 17 15
During a function call, BIOS enters a value into the first byte of a sector marker
which tells the calling program whether or not the sector is OK. The value 0
means OK, and the value 128 means a magnetization error occurred. Besides the
327
7. TheBIOS PC System Programming
Function OSH, passing the number of the hard disk: in the DL register, checks hard
disk specifications. This is important for examining hard disks with unusual
fonnats.
Mter the function call the DL register contains the number of attached hard disks.
This number can be 0, 1 or 2. In addition, the DH register contains the number of
read/write heads. Since the read/write head count always staI1$ at 0, a value of 7
means that S heads are available. The CL register (bits 0-7 of the cylinder number)
and the upper two bits of the CH register (bits 8 and 9 of the cylinder number)
indicate the number of cylinders. The counting here also starts at O. The last
information is found in the lower 6 bits of the CH register. It shows the number
of sectors per cylinder, where the counting begins at 1 (an exception to the rule,
since the other counts in this function begin with 0).
When a user interfaces a foreign hard disk to a PC, the BIOS must know the
characteristics of this hard disk to perform correct access. For this reason it uses
interrupt 41H for hard disk: 0 and the interrupt 46H for hard disk: 1 as pointers to a
table. This table has a format prescribed by BIOS and describes the attached hard
disk drive. BIOS stores a whole series of tables so that BIOS can adjust itself
properly during the system boot from the booting hard disk: drive.
Note: If the hard disk: is already in the Pc and functions properly. do not
attempt to access the hard disk description table, since the hard disk:
could be damaged.
A table must be constructed in RAM for foreign hard disk: interfacing, and interrupt
vectors 41H or 46H must point to this table. In addition, function 9 must
configure BIOS to use this table. The number 9 declares the function. The number
of the drive (80H or 81H) is loaded into the DL register. You may never have to
use this complicated function: Most hard disk manufacturers include a
configuration program which performs the same task. Check the documentation
which came with the hard disk: for the parameters needed for the hard disk
description table.
Functions OAR and OBH are additional read/write functions. They differ from
functions 2 and 3 in that they read and write the four ECC bytes at the end of each
sector in addition to the 512 bytes of data. Because of this, every sector has 516
328
Abacus 7.B Accessing the Hard Diskfrom the BIOS
bytes instead of 512 bytes, and only 127 sectors can be read or written at one time,
instead of 128 as in functions 2 and 3.
Function OBH recalibrates one of two hard disks. It also returns the error status,
passing the error number to the DL register.
Function 10H tests whether or not the hard disk whose number is in the DL
register is currently prepared to execute commands. If the carry flag is set on the
return of this function, the hard disk isn't ready. An error code passes to the AH
register.
Function 14H forces the controller to perform an internal self test. If the controller
is OK, it returns with a reset carry flag.
Function 15H determines the type of drive. The number of the drive (80H or 81H)
passes to the DL register. If the drive is unavailable, it returns the value 0 in the
AH register after the function call. If the AH register contains a value of 1 or 2,
the device indicated is a floppy disk drive. The value 3 indicates a hard disk. If this
is the case, the ex and DX registers contain the number of sectors on this hard
disk. The two registers form a 32-bit number (the ex register contains the upper
16 bits, and the DX register the lower 16 bits).
Avoid hard disk access using BIOS functions unless absolutely necessary. Leave
these tasks to DOS functions as much as possible.
329
7. TheBIOS PC System Programming
This type of card enables data transfer between two computers direct through a
cable or through phone lines. Both the sender and receiver require a modem to
communicate using the latter method. Modems convert computer signals into
acoustical signals which can then be transmitted over telephone lines.
1, 1.5 or 2
stopblts
r - - - - - - - - - , Start bit of
next character
330
Abacus 7.9 Accessing the Serial Port from the BIOS
Word length
As the figure above shows, only the two line states, 0 and 1 (also called high and
low) are important The line remains high if no data transmission takes place. If
the line's state changes to low, the receiver knows that data is being transmitted.
Between 5 and 8 bits transfer over the line, depending on the word length.
Unfortunately the BIOS functions only support a word length of 7 or 8 bits. If the
line is low during data transmission, this means that the bit to be sent is O. High
signals a set bit. The least significant bit is transferred first, and the most
significant bit of the character to be transmitted is transferred last.
Parity
The character can be followed by a parity bit which permits error detection during
data transmission. Parity can be even or odd. For even parity, the parity bit
augments the data word to be transmitted, so that an even number of bits results.
For example, if the data word to be transmitted contains three bits set to 1, the
parity bit becomes 1 so that the number of 1 bits increments to four, making an
even number. If the data word contained an even number of 1 bits, the parity bit
would be zero. For odd parity the parity bit is set in such a manner that the total
number of 1 bits is odd.
Stop bits
The stop bits signal the end of the transmission of data. Data transmission
protocol permits 1, 1.5 and 2 stop bits. Some users are confused about the option
of working with 1.5 stop bits, since some believe that you can't divide a bit. The
explanation for this paradox comes from the data transmission protocol.
Baud rate
Old standards dictate that data transfers at a mte of 300 baud (about 300 bits per
second), and one stop bit The signal for a 1 bit and the signal for a 0 bit are both
events. Binary bits when transmitted in an analog environment such as phone lines
may not be identical with baud mtes. Since stop bits always have the value 1, the
line would be high for 1/300 second. If instead you keep the line high for 1/200
second, 1.5 bits are transmitted. The line remains high until a new chamcter
transfers and sets the line transmitting the start bit to low.
Some interfaces work with negative logic. In such a case the conditions for 0 and 1
in the illustration above must be reversed. This doesn't change the basic principle
of serial transmission.
Protocol settings
Data transmission only works if the sender and receiver both match various
protocol parameters. First the baud rate (the number of bits transmitted per second)
must be set The standard baud mtes for data exchange over voice telephone lines
are 300, 1200 and 2400 baud. These baud mtes depend on the capabilities of the
331
7. TlleBlOS PC System Programming
modem in use. For a dedicated (data only) telephone line or for direct data
transmission through a cable, speeds up to 9600 baud are possible. Up to 80 bytes
per second or 4800 bytes per minute can be transmitted at 9600 baud.
The word length depends on the data being transmitted. If the data consists of
nonnal ASCII characters, a 7-bit word is enough, since the ASCII character set has
only 128 characters. If the data encompasses the complete PC set of 256
characters, 8-bit words are more practical.
Next the necessity of a parity check should be determined, and whether even or odd
parity should be used. In most cases parity checking is recommended, since phone
lines do not always transmit all data correctly. The parity selected is unimportant,
as long as both sender and receiver select the same parity.
The number of stop bits must be defined. One stop bit transmits successive
characters faster than a setting of two stop bits. On the other hand, two stop bits
increase the reliability of transmission.
Sample protocol
The following illustration shows a sample transmission of an "A" character with a
protocol of 8 data bits, odd parity and one stop bit. Positive logic and a 300 baud
transmission rate are assumed. Since the ASCII code of the "A" character is 65
(OI00000I(b» and therefore contains only two 1 bits, the parity bit changes to 1
Jl
to set the number of 1 bits to an odd number.
1
logical 0 nI
logical ;::::_~.~;:=:;::::;::::;~::.I---,U~:"""""":-"Ir-..,........,.....,r-----4~
II~ II ~ ITlmel •
I I
~ ~
1/300 second
8 data bits
(01000001 (b) for
Transmitting A character: 8-bit word length,] stop bit, odd parity and 300 baud
UART
332
AbaclU 7.9 .Accessing the Serial Port from the BIOS
Transfer registers
A character transmitted on a data line passes first to a register designated as a
transfe; holding register. It remains there until processing ends on the character
preceding it Then the character moves to the transfer shift register from where the
UART transmits the character bit by bit over the data line. Depending on the
configuration, parity and stop bits implement the stream of data. When the BIOS
function passes the status of the data lines to the AH register, bits 5 and 6 indicate
whether these two registers are empty.
Receiver registers
The receiver shift register accepts received data, then transmits the data to the
receiver data register where the UART removes the parity and stop bits. If a
previously received character is still in the data register, bit 1 of the line status sets
to 1 to avoid overwriting. Bit 0 indicates that a character was received. If while
processing the character, the UART discovers that a parity error occurred during the
transmission, it sets bit 2 of the line status. If a breakdown occurs in the agreed
upon protocol (number of parity and stop bits), the action sets bit 3. The UART
always sets bit 4 if the data line remains longer in low (0) status than required for
the transmission of a character. Bit 7 signals a time out error. This occurs
occasionally when the communication between the RS-232 card and the modem
isn't working properly. . '
7 6 5 4 3 2 1 0 bit
I I I I, IIIII I
Receive character
Overwrite character
I In data register
Parity error
Protocol not specified
Line Interrrupt
Data register clear
Shift register clear
Time out
Line status
Before data can be transmitted or received, the UART must be informed of the
number of stop bits, etc. Function 0 of interrupt 14H serves this purpose. The
function number (0) enters the AH register, and the protocol passes to the AL
register. The bits of the AL register indicate the various parameters:
333
7. The BIOS PC System Programming
Bits Protocol
bit 0,1 Word length
10 (b) - 7 bits
11 (b) - 8 bits
o - 1 Stop bit
1 - 2 Stop bits
00 (b) - none
01 (b) -odd
10 (b) -even
After initialization the function loads the line status into the AH register.
Function 1 transmits characters. During its call, the AH register must contain 1
and the AL register must contain the character to be transmitted. If the character
was transmitted, bit 7 of the AH register changes to 0 after the function call. A 1
signals that the character could not be transmitted. The remaining bits correspond
to the line status.
Function 2 receives characters. After calling this function the AL register contains
the character received. AH contains the value 0 if no error occurred, otherwise the
value corresponds to the line status.
Function 3 senses and returns the modem status and line status. It returns the line
status in the AH register and the modem status in the AL register:
334
Abacus 7.9 Accessing the Serial Port from the BIOS
335
7. TheB/OS PC System Programming
The four cassette interrupt functions remain part of the PC's ROM-BIOS. The XT
has no cassette recorder interface. In addition, the XTs cassette interrupt consists of
a short routine which sets the carry flag and stores an error code in the AH register
to tell the program that the function called is unavailable.
The AT and the cassette interrupt
The cassette interrupt returned with the introduction of the AT. New functions can
be called which have nothing to do with cassette recorder control. The following
describes these functions, available only on AT models.
Among other things, the interrupt makes two functions available based on the
time measurement of the onboard AT realtime clock. The ftrst of these is function
83H. It is useful in situations where the CPU is engaged in a time consuming task
(e.g., computing a complicated formula), but other duties must be performed at the
same time i e.g., checking the keyboard to determine if the user wants to terminate
the operation).
Function 83H calls the address of a flag (a byte in the user program) in which the
highest level bit is set after a certain time period has elapsed. Within an executing
program this flag can be tested after certain amounts of time. Only two assembly
language instructions are necessary for this, so the testing requires little time.
Function number 83H passes information to the AH register. The segment address
of the flag is loaded into the ES register and the offset address into the BX register.
The time that should elapse until the flag is set is passed to the CX and DX
registers. Both registers form a 32-bit number which indicates the number of
microseconds to wait (1 second = 1,000,000 microseconds).
The CX register represents the upper 16 bits of this number. To calculate the total
time, the contents of the CX register must be multiplied by 65,536 and the DX
register must then be added to the total. If the waiting period is known in
microseconds, the value for the CX and the DX register can be calculated:
ex = int(Waiting period /65,536)
336
AbaclLS' 7.10 The Cassette Inlerrllpt
This function can only be called if the previous call of this function h$ ended (the
time indicated h$ elapsed). If this is not the case, the function returns immediately
with the carry flag set.
The second time function, function 86H, differs from function 83H in that it waits
until the time indicated h$ elapsed. For this reason the function number must pass
to the AH register, and the waiting time to the ex and ox registers during the
function call. To convert the waiting time into two values for the ex and ox
registers, the formula above can be used. This function can only be called if
function 83H was not called previously, and if the time period set during its call
h$ not yet elapsed. In such a case, the function returns immediately with a set
carry flag to the calling program.
Extended memory
The AT accepts more than 640K of memory. This additional memory (called
extended) begins at 1 megabyte and cannot be accessed in real mode, in which the
80286 processor operates as an 8086 processor. Function 88H determines the
availability and size of this memory. Placing a value of 88H in the AH register
returns the size of RAM beyond the 1 megabyte boundary (excluding RAM from 0
to 640K) in lK increments in the AX register.
Function 87H moves blocks of memory within the total memory space. This
means that blocks of memory can be moved from the area below the 1 megabyte
limit to the area above the 1 megabyte limit, and the other way around. The
function should not be used for the latter, since its call is complicated and has
other disadvantages. To access memory beyond the 1 megabyte barrier, the
processor must be switched into protected mode (full 80286 mode). Function 87H
requires very comprehensive information, since the 80286 processor is more
difficult to program in protected mode than in real mode (8086 emulation under
DOS). See the end of this section for a program which demonstrates the use of
function 87H.
The function number 87H must fll'St be passed to the AH register, then the number
of the words to be moved (words only-not byteS) must be passed to the ex
register. A maximum value of 8000H corresponds to a maximum value of 64K.
337
7. TheBIOS PC System Programming
Another protected mode innovation is the access code defined for every segment. It
indicates whether the segment described is a data segment or a code segment (only
code segments can be executed). The access code also contains information on
access priority, and whether access is even permitted. Every segment descriptor
consists of 8 bytes apiece. Function 87H expects during its call that six segment
descriptors have been prepared in the GDT (i.e., memory space reserved for them).
The figure below illustrates which segment descriptors are involved, as well as the
construction of a segment descriptor.
GDT
~
Addr Segment descriptor Addr.
+0 + OH
Segment length DUMMY
+2 + 8R
GDT
Bits 0-15 of segment address +lOR
+4 START
Bits 16-23 of segment address +lSH
DEST.
/
+5
+20H
Access code
BIOS CS
+6
+28R
Reserved (always 8) STACK
+8 +30H
Only the segment descriptors designated as start and destination are of interest here,
since the BIOS functions fill out the other descriptors. The first describes the
segment from which the data are taken. The destination descriptor describes the
segment into which the data are copied. The length of both segments can be
OFFFFH (64K decimal), even if fewer bytes (or words) copy over in the process. If
a lower value is indicated, do not allow the number of bytes (number of words
multiplied by 2) to be copied to exceed this amount. Otherwise the processor
notices an access across a segment boundary during copying, which triggers an
error. The address of the two memory areas must be converted to a (physical) 24
bit address. The lower 16 bits of this address enter the second field of the segment
descriptor and the upper 8 bits enter the third field. As access code 92H can be
used, which signals the processor that the described segment is a data segment with
the highest priority; that the segment exists in memory; and that the segment can
be written. The last field of the descriptor exists for reasons of compatibility with
the 80386 processor, and should always contain the value O.
While the address of the user program's buffer stays fixed, the address beyond the 1
megabyte boundary to which data should be copied can be freely selected (subject
338
Abacws 7.10 The Cassette Interrupt
to RAM avai1ability). The following table shows the addresses of the various lK
blocks beyond the 1 megabyte border as 24-bit addresses.
After the function call the carry flag indicates the success of the function call. If
the carry flag sets, an error occurred. The value in the AH register indicates the
cause of the error:
A disadvantage of this function is that while the processor is in protected mode, all
interrupts must be suppressed. The reason is the fact that during the protected
mode, BIOS interrupts (e.g., timer or keyboard) can be called, but these routines
were developed for operation in real mode only. These interrupts may not work
properly in protected mode. The disadvantage can be clearly seen when you call the
timer. Since its interrupts are suppressed, protected mode performs no time
measurement, and time remains frozen for a moment. If programs call function
87H frequently, the clock may run slow by 20 or 30 seconds in one day. The clock
can be reset easily to the proper time with software, so software can bypass most
of the disadvantages.
Function 89H switches the AT into protected mode. Only someone developing his
own operating system may have any interest in this function. Any system capable
339
7. TIu!BJOS PC System Programming
of multiprocessing must run in protected mode. This function goes far beyond the
scope of this book. See the AT technical manual for more infonnation.
Function 84H reads two joysticks connected to the AT. Two sub-functions operate
within this function: Both return a set carry flag if the adaptor to which the
joysticks should be connected doesn't exist.
The fIrSt sub-function executes by passing the function number to the AH register
and the value 0 to the OX register. It returns the status of the joystick fire buttons
in bits 4 to 7 of the AL register.
The content of the AL register is also important to this user routine because it
indicates whether the user pressed or released the <System RequeSt> key. 0 means
activated, 1 released.
340
Abacus 7.10 T1I4 CasseUe Interrupt
Demonstration programs
Of all the functions made available by this interrupt, the most interesting is
probably function 88H. It permits the owners of ATs with memory beyond the I
meg limit to use memory that is inaccessible to DOS. The programs presented in
this section demonstrate easy calls to function 87H within user programs. To
illustrate the function call, each one of these programs copies the current video
RAM contents directly beyond the I megabyte memory border. It then erases the
video RAM and restores it again. The core of these programs is always the routine
which calls function 88H of interrupt ISH. It constructs a GDT for this, enters the
addresss of the start and destination area, as well as the GDT. First it converts the
two addresses (passed as segment and offset addresses) into a 24-bit-wide address.
This routine must be constructed fIrst in assembly language for the higher level
languages, then integrated into the higher level language programs. You'l see how
this is done in the documentation of the individual listings. To avoid detailed
comparison of the various assembler programs for linking into the move function,
the difference lies almost exclusively in the area of the variable passing. Otherwise
the programs are almost identical.
190 '
220 PRINT'was started from the DOS level with <GWBASIC /m:60000>"
230 PRINT : PRINT'If this is not the case, input an <s> to Stop "
290 PRINT"This Program uses Function 87(h) of Interrupt 15(h) to copy blocks"
300 PRINT· of memory between the 'normal' RAM and the RAM beyond the·
350 PRINT·XT, and they do not have memory the l-MB limit, •
380 PRINT· The Program will first copy the current display immediately beyond the •
390 PRINT·l MB border and thens clear the screen. If you then press a key, •
410 PRINT: PRINT· Please activate a key to start the program ••• ·;
341
7. The BIOS PC System Programming
50110 '
342
Abacus 7.10 The Cassette Interrupt
61120 '
61190 DATA 29,246,197, 2,232, 24, 0,136, 84, 20,137, 68, 18,180,135
The DATA statements integrated the interrupt call routine and the memory
movement routine into BASIC. They contain the machine language command
codes, read and POKEd into the BASIC section starting at address 61000. This
address is also stored in the MOVE variable so that the program can be called from
the CAlL command in line 51160. For those of you who have mastered assembly
language, here is the program listing from which the DATA lines of the MOVE
function were derived.
assume cs:code,ds:code,es:oode,ss:code
i-- MOVE: Copy storage blocks beyond the 1MB limit -------------------
i-- Call from BASIC: CALL ADR(Sourcesegment, StartOffset, Destsegment,
i-- DestOffset, Size, Direction);
;- Info - after the call Variables are in the following
;-- Positions on the Stack:
;-- Startseqment - SP + 16
;-- StartOffset - SP + 14
343
7. TheBlOS PC System Programming
;-- Destsegment = SP + 12
;- DestOffset - SP + 10
;- Size - SP + 8
;- Direction - SP + 6
;-- - for Direction the following Codes are accepted
;- o - from below 1 MB --> to below 1 MB
;-- 1 - from below 1 MB --> to over 1 MB
;-- 2 from above 1 MB --> to below 1 MB
;-- 3 - from above 1 MB --> to above 1 MB
;-- - the number concerns words not
bytes, and can not be larger than 8000 (h)
344
Abacus 7.10 The Cassette Interrupt
Move endp
i-- GET lIDR: returns the Offset address of the GOT -------------
; - Input none
; - OUtput SI - Offset address of the GOT
; - Register : SI is changed
or dl,010h ; is beyond 1 MB
inc dl iyes
;=============-===============================_s========-==============
code ends
end
The INLINE command, not DATA statements, integrate the MOVE routine into
the following Pascal program.
345
7. The BIOS PC System Programming
{* is available
{********* •• ******** ••• ******* •• **********.************* ••• *********.*} *'
program MOVEP;
begin
Regs.ah := 15; { Function number
intr($10, Regs); { Call 8IOS video interrupt
if Regs.al ~ 7 then GetPage :- $8000 { Monochrome card
else GetPage •• $8800; ( Color card
end;
(*
{*
2 = from
3 from
above
above
MB--> to below 1 MB
MB--> to above 1 MB , *' *)
($F+'
procedure HiMove(StartSeg, { Segment address of the start buffer
StartOfs, t offset address of the start buffer
DestSeg, { Segment address of destination buffer
DestOfs, { Offset address of destination buffer
Size, { Number of words to be copied
Direction integer); { Direction in which to copy
begin
inline (
S88/S7E/$10/SS8/S76/$OE/$88/S46/S0C/S8E/SCO/$88/$5E/$0A/
$88/S46/S0S/S88/S4E/S06/$8A/SE9/$55/$ES/$5E/SOO/$00/$00/
$OO/$OO/SOO/$OO/$OO/$OO/SOO/SOO/$OO/$OO/$OO/$OO/$OO/SO0/
$FF/SFF/SOO/SOO/S10/$92/$00/$00/$FF/$FF/$00/SOO/$00/$92/
$OO/$OO/$OO/$OO/SOO/$OO/$OO/SOO/SOO/$OO/SOO/SOO/$OO/$O0/
$00/$00/$00/$00/$50/S8C/SCO/$F6/SC5/$01/$E8/S28/$00/S2E/
$88/$S6/$1C/S2E/$89/$46/S1A/$8B/SC7/$8B/SDE/SF6/$CS/$02/
$E8/$16/$00/S2E/S88/$56/$14/S2E/$89/$46/S12/S84/$87/$0E/
S07/S59/$88/$FS/SCD/S15/$E8/S17/$5D/$E8/SCF/$8A/SD4/$Bl/
S04/$D2/SEA/S7S/$03/S80/$CA/$10/$D3/SEO/$03/$C3/$73/$02/
$FE/SC2/SC3/$SD
);
end;
346
Abacus 7.10 The Cassette Interrupt
end
else
begin
For the Pascal programmers interested in assembly language, the assembler listing
of the MOVE function appears here.
Assembler listing: MOVEPA.ASM
;***** ••• *.*** ••• *******************.*.****.* ••• ****** ***·*·**********i
i* MOVEPA *;
i*-------------------------------------------------------------------*;
;* Task copies Data between the RAM below 1 MB and *;
;* above 1 MB *;
;* CAUTION! This is the Version for linking *;
;* in a Pascal Program with INLINE *;
;* conmands *;
i*---------------------------------------------------- ---------------*;
;* Author MICHAEL TISCHER *;
;* developed on : 6.8.87 *;
;* last Update 6.8.89 * ,•
;*-------------------------------------------------------------------*;
;* assembly MASM MOVEPA; *;
i* LINK MOVEPAi *;
, convert to INLINEs and add to Turbo Pascal *;
i*************************·*********·*·****·****·***** ****************;
;--Call: HiMoves(StartSeg,
347
7. The BIOS PC System Programming
;- KartO~,
;-- DestSeg,
; -- DestOfs,
;-- NumWords,
;-- Direction: word);
bptr dw ? ;Taken by BP
348
Abacus 7.10 The Cassette Interrupt
movepa endp
;-- GETGOT: Get Address of the GOT and jump to MOVE ------------------
;-- Input : none
;-- OUtput : CS:BP = Address of the GOT
i-- Register : only BP is changed
;-- Info: this Routine can only be used in the environment
;-- of this Program
inc dl iyes
349
7. The BIOS PC System Programming
The C program differs from the BASIC and Pascal programs in that the MOVE
function is also present as an assembler routine, but excluded from the C program
listing. First the MOVE assembler program assembles, then the C program is
compiled. You then merge the two programs using the linker. For this reason the
listing of the C program follows with the source listing of the corresponding
assembler function.
C listing: MOVEC.C
/*********************************************************************/
/* M 0 V E C */
/*-------------------------------------------------------------------*/
/* Task: integrates an Assembler-Routine in C, which can */
/* move memory blocks beyond the 1 MB boundary */
/*-------------------------------------------------------------------*/
/* Author MICHAEL TISCHER */
/* developed on : 8.13.87 */
/* last Update : 9.21.87 */
/*-------------------------------------------------------------------*/
/* (MICROSOFT C) */
/* Creation MSC MOVEC; */
/* LINK MOVEC MOVECA PEPO; */
/* call MOVEC */
/*------~------------------------------------------------------------*/
/* (BORLAND TURBO C) */
/* Creation: with Project-File with the following content: */
/* movec */
/* moveca.obj */
/************.******.******.* •••••••• **** •• *********************** •••• ,
.include <conio.h>
350
AbacllS 7.10 The Cassette Interrupt
void CIs ()
void main!)
{
printf("\nMOVE (c) 1987 b¥ Michael Tischer\n\n");
printf("This Program uses the Function 87(h) of Interrupt 15(h)");
printf(" to move memory blocks\nbetween the \"normal\" RAM and the H);
printf("RAM beyond the 1 Mega-Byte storage limit.\n");
if (PeekB(OxFOOO, OxFFFE) !- OxFC) 1* test if AT *1
(
printf("Since this PC is not an AT, but a ");
)
else
(
printf ("After starting the program by pressing a key");
351
7. The BIOS PC System Programming
;* developed on : 8.13.87 *;
;* last Update : 9.21.87 *;
; *--------------~-----------------------------------------------------*;
;* assembly : MASM MOVECA; *.f
;********** •••• *****************.*************.******.***** ••• *****.**;
_DATA ends
352
Abacus 7.10 The Cassette Interrupt
AdMove endp
or dl,010h ;beyond 1 MB
inc dl ;yes
calc_adr endp
i---------------------------------------------------------------------
ends ;End of the Program-segment
end ;End of the Assembler-Source
353
7. TheBIOS PC System Programming
;Device-Codes
354
Abacus 7.10 The Cassette Interrupt
xor si,si
xor bx,bx
mavea endp
355
7. TheBIOS PC System Programming
getvseg endp
356
Abacus 7.10 The Cassette Interrupt
inc dl iyes
357
7. The BIOS PC System Programming
BIOS-proof keys
Some key combinations cannot be read by BIOS as key codes because they execute
commands. Activating the <PrtSc> or <Print> key calls BIOS interrupt SH. This
starts a routine which sends the current screen display to a printer, producing a
hardcopy.
The <Ctrl><Num Lock> keys stop the complete system until the user presses
another key. The keyboard buffer ignores the <Ctri><Num Lock> keys and the
subsequently pressed key, so programs cannot read these keys.
Pressing the <Ctrl><Break> key combination calls interrupt IBH. Normally the
current program stops and returns to DOS. To prevent this, this interrupt can be
directed to a routine within the application program which continues program
execution if the routine consists of an !RET assembly language instruction only.
ATs and a few advanced Penns have the <Sys Req> key. Its activation calls
interrupt ISH by passing the value 8S00H to the AX register. When the user
releases the key, the AX register then receives the value 8S0IH. The value 8SH in
the AH register represents the function number of interrupt ISH. After starting the
system, function 8SH of the BIOS interrupt ISH consists only of an IRET
instruction; pressing the <Sys Req> key has no visible result
Control codes
Most people know that any ASCII code can be entered from the keyboard using the
<All> key and the keys of the numeric keypad. Few users know about character
entry with the help of the <Ctrl> key. When used in connection with other keys,
this key can enter ASCII codes smaller than code number 32. The following figure
shows which keys can be accessed.
358
Abacus 7.11 Accessing the Keyboard from the BIOS
24 Ctrl X
25 ~ Ctrl Y
26
- Ctrl Z
- Ctrl [,
Est,Shlft
Est,Ctrl-
Est
28 L
2' ..
30
32 e Spate,
Shlft
Spite,
Ctr 1- Spate,
Alt-Spate
359
7. TheBIOS PC System Programming
Interrupt 16H normally receives a call when a program expects user input of one or
more characters. If a character was already entered before the function call, the
keyboard buffer empties this character and passes it to the calling program. If there
is no character in the keyboard buffer, function 0 waits until a character has been
input and then returns to the calling program. The caller can determine the
character or activate a key from the contents of the AL and the AH registers.
ASCII
If the AL register contains a value other than 0, it contains the ASCn code of the
character. The AH register contains the scan code of the active key. The code in the
AL register corresponds to the ASCII codes for character output on the screen.
Some differences occur in the control keys:
Code Key(s)
8 <Backspace>
9 <Tab>
10 <Ctrl><Return>
13 <Return>
27 <Esc>
Scan codes
The scan code in the AH register indicates the number of the active key, where the
keys on the keyboard are numbered starting with O. Since PC, XT and AT
keyboards differ, this is unimportant for most programs. Scan codes of the various
keyboards can be found in the Appendices of this book.
Extended key codes
If the AL register contains the value 0 after the call, the AH register indicates an
extended keyboard code. The difference between the AScn code and the extended
keyboard code lies in the fact that certain keys (e.g., the cursor keys) cannot fit
within the PC's 256-character set. The following table provides an overview of
extended. keyboard codes:
Code (s) Key(s)
15 <Shift><Tab>
16-25 <Alt><Q>,<W>,<E>,<R>,<T>,<Y>,<U>,<I>,<O>,<P>
59-68 <F1>-<F10>
71 <Home>
72 <Cursor Up>
73 <Paqe Up>
75 <Cursor Left>
77 <Cursor Right>
360
Abacus 7.11 Accessing the Keyboard from the BIOS
79 <End>
80 <Cursor Down>
81 <Page Down>
82 <Insert>
83 <Delete>
84-93 <Shift><F1>-<F10>
94-103 <Ctrl><F1>-<F10>
104-113 <Alt><F1>-<F10>
117 <Ctrl><End>
119 <Ctrl><Home>
Key combinations not contained in this table cannot be sensed using the BIOS
keyboard functions, since they don't generate keyboard codes.
Function 1 also reads the keyboard. Unlike function 0, function 1 leaves the
preceding character in the keyboard buffer. Repeated calls of function 1 or function
o read the keyboard again. Place the value 1 in the AH register to call function 1.
In contrast to function 0, function 1 immediately informs the calling program with
the zero flag after the function call if a character is available or not. If the zero flag
equals I, no character was available. If the zero flag resets, the AL and the AH
registers contain information about the activated key. As in function 0, the AL
register contains the value 0 if the user activated an extended key, and a value
unequal to 0 if the user pressed a "normal" key. The AH register contains the scan
code of normal keys; extended keys place their codes in the AH register.
Function 2 has a completely different task. It reads the status of certain control
keys and conditions (e.g., <lnsert». Place the number 2 in the AH register to call
the function. The keyboard status can be found in the AL register after the function
call.
361
7. TheBIOS PC System Programming
76 5 43210
Each program begins with a routine which reads the status of the keyboard
functions through function 2 of BIOS keyboard interrupt 16H. Since the program
only uses the <Insert>, <Caps Lock> and <Num Lock> modes, the program only
views the three highest level bits in the keyboard status byte. Based on this status
byte, a flag initializes for every keyboard function, which indicates the status of
one of these functions or modes within the program. It is reversed when compared
with the current mode. For example, if the <Insert> mode is switched off, the flag
applying to it changes to OFF. An explanation of this follows below.
362
Abacus 7.11 Accessing the Keyboard from the BJOS
After initializing the internal flags, the actual routine for keyboard reading can be
called. It also uses function 2 of the BIOS keyboard interrupt to read the keyboard
function status. It then compares the current status of each individual function with
the previous status stored in a flag. During its first call after the initialization
routine, it determines if the status of all three functions has changed since its
previous status. The change in status causes the routine to display the new status
on the screen.
This explains the reason for the flag reversal in the initialization routine. It allows
display of the keyboard function status on the screen during the fIrst call of the
keyboard routine, and not after it changed by pressing a key.
Now the routine can proceed to its actual task and read the keyboard. It uses
function 1 of the BIOS keyboard interrupt to detect whether a key is available in
the keyboard buffer of BIOS. If this is not the case, the program jumps to the
beginning of the routine and reads the keyboard function status again. This creates
a loop which runs until a keypress occurs. This loop ensures that any status
change is documented immediately on the screen.
If a character appears in the BIOS keyboard buffer the loop terminates and BIOS
keyboard interrupt function 2 reads the key. The last step of this routine tests for
an extended key code. If this is the case, the program adds 256 to the code to signal
the calling routine that an extended keyboard code was received. Then control
returns to the calling routine.
This routine reads characters from the keyboard and displays them on the screen.
This process repeats until the user presses a certain key. If the user presses the
<Num Lock>, <Caps Lock> or <Insert> key, the screen immediately displays the
result.
A centralized keyboard routine as presented here can be used in other programs for
additional tasks. For example, with the help of this routine a macro conversion can
change one key into a string of characters. Another application could display help
text on the screen when the user presses a certain key. Lotus 1-2-3® and dBASE®
use this method for displaying help screens.
Note: A small problem occurs with keyboard flag output. Since displaying
keyboard flags on the screen changes the cursor's position,
subsequent screen output from the program occurs at different
locations than expected. These can disturb the screen display. To
prevent this, the keyboard routine must determine the current cursor
position before the keyboard flag display. Then the routine must
restore the cursor position to its old value after displaying keyboard
status. The problem of color is very similar. Here the flag output
363
7. The BIOS PC System Programming
assumes a certain color and the old color must be restored after the
output. The problem is that none of the three languages has a
command to determine the current color. In Pascal programs for
keyboard reading. only a special procedure can set the color by
recording the colors in a variable and setting it with a command.
With these variables the keyboard routine restores the current color
after display of the individual flags.
BASIC listing: KEYB.BAS
100 '*••• _••_.--_._-_ •••• _-. __••••• _--_••••••__•••__ ••• _--._.**._.... ,
110 KEY B
120
130
'*-------------------------------------------------------------_•.
,* Task makes a subroutine available which *'
140 reads a character from the keyboard. The
150 status of the control keys *,
160 '* (INSERT, CAPS, NOM) are displayed *'
170 '* on the screen
180
190
200
210
'*
Author
developed on
last Update
MICHAEL TISCHER
7.22.87
9.21.87
1* _____ -_••• _-----._._-----_._•••• _._----_•••• _._-_._.*******.***,
.
*'
,
220 '
230 CLS : KEY OFF
240 PRINT"WARNING: This Program can only be started if GNBASIC was "
250 PRINT"started from the DOS level with <GWBASIC /m:60000>."
260 PRINT : PRINT"If this is not the case, please input <s> for Stop."
270 PRINT"Else press any key ..• ·;
280 A$ = INKEY$ : IF A$ = "s" THEN END
290 IF A$ - "" THEN 280
300 GOSUB 60000 'install function for Interrupt call
310 CLS 'Clear Screen
320 PRINT"TAST (c) 1987 by Michael Tischer" : PRINT
330 PRINT· You can input some characters and change the status of the NOM,"
340 PRINT"CAPS and INSERT mode, where every change is documented in •
350 PRINT"the upper right corner of the display."
360 PRINT"The input of <RETURN> terminates the Program••• • : PRINT
370 PRINT"Your Input: ";
380 GOSUB 50000 'initialize keyboard-Flags
390 GOSUB 51000 'read a character
400 IF LEN(ZS) = 2 THEN 390 'on extended Code do nothing
410 PRINT Z$; 'output characters
420 IF ASC(ZS) <> 13 THEN 390 'on RETURN terminate
430 PRINT
440 END
450
50000
'
1*._.-....__ ._......_._._.__ ._._.._.._._._._.-.-._....... *••• '
50010 '. initialize keyboard-Flags .,
50020 '*----------------------------------------------------------.,
50030 '. Input: none
50090 '
50170 '
364
Abacus 7.11 Accessing the Keyboard from the BIOS
365
7. The BIOS PC System Programming
program KEYP;
[** BIOS keyboard status bits •• ** •• *** ••• ** •• ** ••• ******** ••• *}
SCRL = 16; ScrollLock bit )
NUMI = 32; [ NumLock bit)
CAPL = 64; { CapsLock bit )
INS = 128; ( Insert bit)
{** Codes of some keys as presented by GETKEY ***************.*}
BEL = 7; { Code for bell character
BS = 8; Code for Backspace character
TAB a 9; { Code for Tab character
LF - 10; [ Code for Linefeed
CR 13; { Code for Return
ESC - 27; [ Code for Escape character
Fl = 315; { Code for F1 key
F2 - 316; { Code for F2 key
F3 = 317; { Code for F3 key
F4 = 318; { Code for F4 key
F5 = 319; { Code for FS key
F6 - 320; { Code for F6 key
F7 - 321; [ Code for F7 key
366
Abacus 7.11 Accessing the Keyboard from the BIOS
begin
if (Flag and (FlagReg - 0)) or { test if status
(notIFlag) and (FlagReg <> 0)) then ( of the Flags has changed
begin ( YES
CUrCline :- WhereY; ( record current Line
cUrColumn :- WhereX; record current Column
gotoxy(Colurnn, Cline); { Cursor to Position for Flag-Name
if FlagReg - 0 then { is Flag reset?
begin ( YES
NegFlag :- false; Result of the function : Flag off
textcolor(O); { Foreground color is black
textbackground (0) ; { Background color is black
end
else
367
7. The BIOS PC System Programming
begin
keyRec :- false; no key received
repeat
Regs.ah :- S2; ( read function number for keyboard status
intr(Sl6, Regs); ( call BIOS keyboard interrupt
begin
Regs.ah := 52; ( Read function number for keyboard status
intr (516, Regs); ( call BIOS keyboard interrupt
if (Regs.al and INS <> 0) then Insert :- false ( INSERT flag
else Insert :- true; { set
if (Regs.al and CAPL <> 0) then Caps :- false ( CAPS flag
else Caps : - true; ( set
if (Regs.al and NUML <> 0) then Num • - false HUM flag
else Num true ( set
end;
{*.****.************************~********************* ----*-*-------.-}
(* SCOLCR: sets foreground and background colors for display *)
(* Input: see below *)
(* Output : none *)
(* Var. the color Is stored in the gJobal variables FORECOLCR *)
(* and BCKCOLCR *)
(* Info this procedure must be called for setting the color *)
(' so that after the output of the keyboard flag status, *)
(* the current text color can be restored *)
(* since in TURBO no functions exist for sensing *)
(* this color *)
{*********************************************************************}
begin
ForeColor :- foreground; Record foreground color
BckColor := Background; Record background color
textcolor(Foreground); ( Set foreground color
textbackground(Background) ( Set background color
end;
368
Abacus 7.11 Accessing the Keyboordfrom the BIOS
{*********************************************************************)
{* MAIN PROGRAM *I
{***************************************** ••••*****.*.*** ••• ******* ••• )
begin
Inikey; Initialize keyboard flags
Scolor (7,0) ; ( Color is white on black
clrscr; ( Clear screen
writeln(.13.10'KEYP (c) 1987 by Michael Tischer');
writeln('13'10'A few characters can be input now and switch ,+
'INSERT-, CAPS- or !ruM-');
writeln('mode on or off. The status of the three ,+
'modes is always displayed in');
writeln('the upper right corner of the screen.');
writeln('Pressing the <RETURN> or the <F1>-key terminates the ,+
'program••• ');
write(.13.10'Your Input: ');
repeat ( Input loop
key :- Getkey; ( Get key
if (key < 256) then write(chr(key» { OUtput (if normal)
until (key - 13) or (key - Fl); Repeat until Fl or CR
writeln;
end.
C listing: KEYC.C
/*********************** ••• ***************************_ •••• _._._ •• _._-/
1* KEY C *1
1*-------------------------------------------------------------------*1
1* Task provides a function for reading a *1
1* character from the keyboard and to output *1
1* the Status of the control keys (INSERT, *1
1* CAPS, NOM) on the display. *1
1*-------------------------------------------------------------------*1
1* Author MICHAEL TISCHER *1
1* developed on : 8/13/87 *I
1* last update : 6/09/89 *1
1*-------------------------------------------------------------------*1
1* (MICROSOFT C) *1
1* Creation MSC TASTC; *1
1* LINK TASTC; *I
1* Call TASTC *1
1*-------------------------------------------------------------------*1
1* (BORLAND TURBO C) *1
1* Creation Make sure that Case-sensitive link is OFF in *1
1* the Options menu/Linker option *1
I * Select RUN menu *I
1-····-·-·_··-·-··· __··· __·· __ ····---_················ .***************/
'include <dos.h> 1* include Header-Files *1
finclude <io.h>
'include <bios.h>
369
7. The BIOS PC System Programming
370
Abacus 7.11 Accessing the Keyboard from the BIOS
1·····················_·········-······_··············...•..•.•....... /
371
7. The BIOS PC System Programming
void ClsO
1-*·······_·-················_----······_·-···········...... -.........,
(
.ifdef TURBOC
- -
strJct REGPACK Register;
Register.r ax = 1 « 8;
intr(Ox16,-&Register);
.else
.endif
I
372
Abacus 7.11 Accessing the Keyboard from the BIOS
do
(
Register.h.ah - 2; 1° read function number for keyboard status *1
Caps - NegFlag (Caps, Register. h.al & CAPL, FS+3, FZ, " CAPS ");
)
whi Ie ( ! KeyReady () );
'*
,*
'*
current status. This makes it possible that their
current Status is output on the next call of the
GETKEY-function.
*'
*'
*1
,******** ••••• ****.*.* •••• ***.*.*** ••• *** ••• ***.*.*.* ••••••••••••••••• /
void Inikey ()
void main ()
printf("You can input some characters and at the same time change H);
Inikey();
do
'0
initialize Keyboard-Flags *'
373
7. TheBIOS PC System Programming
The SHOWCLK program displays the current time on the screen every time the
user presses a certain key after installing it. This occurs until another key is
depressed. The key which causes the time to be displayed must be passed to the
program in the command line during its call. For example, entering the following
at the DOS prompt invokes the program and tells the program to display the time
when the user presses the <FlO> key on the XT, or the <F8> key on the AT
keyboard. When the key is pressed, the time appears on the screen at line 1 starting
at column 40:
The following removes the SHOWCLK program from memory (note the lack of
parameters):
showclk
The only stipUlation is that the actuating key must be one that generates an
extended key code (e.g., a cursor key or function key). The program sets the default
clock position to the upper right corner of the screen. This can be changed by
passing parameters in the command line during the program call. Another facet of
the program is its ability to re-install itself during a new call, if the user desires.
;*************************** •• **************••• *******.*._*_ •••••• - •• -;
;* SHOWCLK *;
;*----------------------------------------------------
;* Task
---------------*i
: Outputs the time on the display after pressing*;
;* a key which generates an extended key code *;
;* stops when another key is pressed *;
i*-------------------------------------------------------------------*i
;* Author : MICHAEL TISCHER *;
;* developed on : 8/1/87 *;
;* last Update : 9/21/87 *;
i*------------------------------------------------------ -------------*;
;* assembly : MASM SHOWCLK *;
;* LINK SHOWCLK *;
;* EXE2BIN SHOWCLK SHOWCLK.COM *;
;*-------------------------------------------------------------------*;
,Call : SHOWCLK [Key-code] [/lLine] [/cColumnj ,
,.*********************************************************************.
. ,
i-- Constants =====--========-=-====-=========-===--=====-=======-=~-=
TAB equ 9
LF equ 10
CR equ 13
374
Abacus 7.11 Accessing 1M Keyboard from 1M BIOS
org 100h
375
7. The BIOS PC System Programming
newint endp
376
Abacus 7.11 Accessing flu! Keyboard from flu! BIOS
prz endp
377
7. The BIOS PC System Programming
;evaluate Parameter
378
Abacus 7.11 Accessing the Keyboard from the BIOS
;-- only the PSP, the new interrupt-Routine and the ---------
;-- Data must remain resident.
ascHbin endp
379
7. The BIOS PC System Programming
parmtest endp
end start
Program now
The file header describes the DOS call of the program. As mentioned above, there
are two basic options for the call: If you call the program without parameters in
the command line, it tries to remove any previously installed SHOWCLK. If you
call the program with parameters, SHOWCLK installs itself. The fIrst parameter
must be the scan code which the user wants to trigger the clock display. The line
and column parameters indicate the clock display area on the screen. If these two
parameters are missing, the clock appears in the upper right hand corner of the
screen.
380
Abacus 7.11 Accessing the Keyboard from the BIOS
The constant definition follows the file header to ease your reading of the listing.
The code segment definition follows, which accepts the program code and the data.
The ORG lOOH instruction, which places the beginning of the program at address
lOOH, indicates that SHOWCLK is a COM program. A COM program is a good
choice for a resident interrupt driver because of the compactness of having data,
code and stack in one segment.
The label START shows the fast executable instruction of the program. It jumps
first to the installation routine of SHOWCLK which has the name SHOWINIT.
This routine loads the address of a table and calls the procedure PARMTEST. It
counts the number of arguments passed in the command line and stores the starting
addresses of the individual parameters into the passed table. After this procedure
ends, SHOWINIT tests whether parameters were passed in the command line. If
this is not the case, it jumps to DEACTIVATE which removes the old
SHOWCLK from memory.
DOS function 35H determines the address of the BIOS keyboard interrupt (the
interrupt pointing to a user routine). It returns the segment address of the interrupt
routine in ES, and the offset address in the BX register. If SHOWCLK was already
installed, an interrupt routine must be located at this address which is conlltructed
exactly like the interrupt routine which is installed, since SHOWCLK always
installs the same interrupt routine.
The routine starts with a 2-byte jump instruction to the routine itself. An
identification code follows, consisting of two ASCII characters, which can be the
initials of the author. In this case the initials are MT. INSTALL tests the address
of the interrupt routine plus 2 for the ASCII codes of the initials MT. The test is
not for MT, but for TM, since the low byte is always stored before the high byte.
If the code exists, SHOWCLK is already installed and the program terminates with
an error message. If INSTALL fmds another bit pattern, it means that no previous
version of SHOWCLK existed. INSTALL can then proceed with installation.
381
7. TheBIOS PC System Programming
Installing SHOWCLK
First INSTALL stores the address of the old interrupt routine in the INTALTOFS
and INTALTSEG variables. Next the interrupt 16H points through DOS function
25H to the NEWINT routine. The new interrupt routine of interrupt 16H is called
if a program wants to call one of the three functions of this interrupt. A message
tells the user that the program is now installed, and the DOS prompt returns. It's
important that DOS not release the memory occupied by SHOWCLK for other
programs. This could result in another program overwriting the new interrupt
routine, and a system crash during the call of interrupt 16H. To prevent this, the
program terminates with a DOS function which makes a portion of this program
resident and prevents overwriting by other programs. Function 3lH must be
informed how many 16-byte paragraphs must be protected, starting from the
beginning of the PSP.
Protecting memory
Once installed, the new interrupt routine must stay protected from changes that
other registers could make to it. At the same time, SHOWCLK's installation
routine must remain unprotected. SHOWCLK places the interrupt routine before
the installation routine. Only the number of bytes between the beginning of the
PSP and the last byte of the interrupt routine, converted into paragraphs, must be
passed to function 32H. The new interrupt routine cannot be overwritten.
This interrupt routine must also contain variables. They are stored between the
program start instruction and the intemlpt routine code proper. This ensures that
the variables remain resident in memory. At the beginning of the interrupt routine
(NEWINT) is a jump instruction followed by the identification code. When a
program calls interrupt 16H, a jump occurs directly to label NEWel. NEWel
tests for whether the function number passed to interrupt 16H in the AH register is
O. This is the only function applicable to this program, since the function reads
characters from the keyboard buffer. If you called one of the two other functions,
the program calls the old interrupt 16H and passes control to the calling program.
If function 0 is called, it reads a character from the keyboard with the old keyboard
interrupt The program then compares this character with the key indicated when
the program call occurred. If this is not the case, control returns to the calling
program. If it was the indicated key, preparations begin to display the time on the
screen.
Stack activity
First the contents of all registers which change during the course of the program
are stored on the stack so they can be restored to the calling program. Then the five
characters of the display in the position where the time appears are read from the
screen and stored. DOS function 2CH reads the time and converts it to an ASCII
string for display. After the time appears on the screen, the old keyboard interrupt
waits for a keypress. When this occurs, the characters formerly located where the
time appears return to their old positions. The registers return from the stack and
382
Abacus 7.11 Accessing tM Keyboard from 1M BIOS
the program jumps to the beginning of the routine to read in a key. display the
time again. or pass the key to the calling program.
Deactivating SHOWCLK
The problem is that the new SHOWCLK, which should remove the SHOWCLK
already in memory, doesn't know the address of the old interrupt routine of
interrupt 16H. It's stored in the old SHOWCLK in the variables INTALTOFS and
INTALTSEG. The two variables are in completely different programs, but there is
a simple method of reading these variables. The old SHOWCLK lies in a different
memory segment from the new SHOWCLK, but the offset addresses of the
variables and routines in both programs are identical. Since you know the segment
address of the old SHOWCLK (the segment address of the interrupt routine), the
contents of the variables INTALTOFS and INTALTSEG can be read from the old
SHOWCLK and the interrupt 16H can again point to the original interrupt routine.
Memory can be released again through the segment address of the old SHOWCLK
routine with the help of DOS function 49H. This concludes the task of
DECACTIVA1E and the program can terminate after displaying a message.
Examine the listing step by step and read the comments carefully. This is
important, because the Program can serve as a basic framework for any resident
interrupt driver. We'll discuss another form of resident program (the TSR
program) in Chapter 8.
383
7. TheBIOS PC System Programming
A time out error occurs when BIOS tries to send data for a certain amount of time
to the printer, but the printer refuses the data and returns a busy message (bit 7
becomes 0). The number of tries BIOS makes before signaling a time out error
depends on the contents of address 0040:0078 in RAM. ROM uses this address for
storing variables. The value 20 which BIOS enters into these memory locations
during the system boot is different from the repeat factor of 20. The value in these
memory locations must be multiplied first by 4, then by 65,536. A value of 20
actually refers to 5 million attempts. This number is relative since the loop which
checks the printer has only a few assembly language instructions processed very
quickly by the CPU. This results in a waiting period of only a few seconds before
the BIOS reports a time out error. If working with the BIOS routine seems to
create more time out errors than usual, try increasing the value in the memory
locations mentioned above so that BIOS makes more attempts. This may help
communication between BIOS and the printer.
Various printer conditions can change a series of bits in the status byte. An ON
LINE (ready to print) printer sets bits 7 and 4. If the printer switches to OFF LINE
(e.g., for page advance) then bit 7 and bit 4 reset and bit 3 sets, indicating a
transmission error.
384
Abacus 7.12 Accessing the Printer from the BIOS
The program must decide whether new data should be sent to the printer, whether
printer output should end or further steps should be taken.
°
Function transmits a character to the printer. Load the function number into the
AH register and the ASCII code of the character you want sent into the AI...
register. After the function call the AH register contains the status byte. If the
character transmission/printing failed, the AH register contains the value 1.
The second function initializes the printer ports. You should always execute this
function before sending data to the printer for the first time. Load the function
number 1 into the AH register; no other arguments are required.
Function 2 loads the status byte into the AH register. As mentioned above, the
status byte tells you the current status of the printer. Load the function number 2
into the AH register; no other arguments are required.
Demonstration programs
The programs listed in this section use the BIOS printer interrupt in the same way
as the programs listed earlier to demonstrate the BIOS keyboard interrupt. The
three higher level language programs li~d here send strings to a printer using the
BIOS printer interrupt The fourth program is an assembly language routine which
adapts the BIOS printer interrupt to its own routine.
The three higher level language programs are similar in organization and are
divided into five sections. One section is the main program. The other four
sections call the various functions of the BIOS printer interrupt. These sections
include a routine for initializing a specific printer interface, a routine for character
or string output and a routine which displays an error message on the screen if
needed. The main program initializes printer interface 0, then prints a test string on
the printer connected to this interface. If an error occurs during one of these two
operations, an error message is displayed on the monitor. This message can be
delayed if no printer is attached to the PC, since BIOS continues addressing the
printer, and gives up after a few attempts. If nothing happens for some time, don't
panic. The program will eventually report its error status.
385
7. The BIOS PC System Programming
50060 ,*******************************.******************••••*.**.****,
50070 '
50140 '
51020 "-------------------------------------------------------------"
51050 Output: the Variable DS' contains the Printer status "
51070
51140 '
386
Abacus 7.12 Accessing the Printer from the BIOS
52020
52030
52040 ••
,*-------------------------------------------------------------.,
Input: Z$ = the Character to be output
PRINTER' = the Number of the Printer
..
52050 .* Output: the Variable OS, contains Printer status (O-o.k.)
52150 '
53000 .*************** •••• **** •••••••• ***** ••••• ******* ••• * ••• *.*.*.**,
53020 ,*-------------------------------------------------------------.,
53030
53040
53050
53060
Input: OS, = the Printer status
'* Output: none
,* Info
1 ••
: if the Printer status is o.k., no output
*,
.'
**** •• *****•••• ******* •••••• **************** ••• **** •••••••••• '
53070 '
53080 IF OS, = 0 THEN RETURN 'everything o.k. --> back to Caller
53090 PRINT"Error on access to Printer: ";
53100 IF (OS" AND 1) <> 0 THEN PRINT"Time-Out-Error" : RETURN
53110 IF (OS, AND 8) <> 0 THEN PRINT"I/O Error" : RETURN
53120 IF (OS, AND 32) <> 0 THEN PRINT"no more paper " : RETURN
53130 PRINT"Error type unknown" : RETURN
53140 •
60000 ,************* •••••••••••• *********.**** •••• ****.**.** •••••••••••
60010 •• initialize the Routine for Interrupt-Call .'
60020 '.-------------------------------------------------------------*,
60030
60040
60050
60060
'. Input: none
'. Output: IA is the Start address of the Interrupt-Routine
'.****** ••• ***** •••••••••••••••••• ***.*** •••••• ** •• ** ••••• *****.'.'
60070 IA=60000! 'Start address of the Routine in the BASIC-Segment
60080 DEF SEG 'set BASIC-Segment
60090 RESTORE 60130
60100 FOR I\ = 0 TO 160 : READ X, : POKE IA+I\,X\ NEXT 'poke Routine
60110 RETURN 'back to Caller
60120
60130 DATA 85;139,236, 30, 6,139,118, 30,139, 4,232,140, 0,139,118
60140 DATA 12,139, 60,139,118, 8,139, 4, 61,255,255,117, 2,140,216
60150 DATA 142,192,139,118, 28,138, 36,139,118, 26,138, 4,139,118, 24
60160 DATA 138, 60,139,118, 22,138, 28,139,118, 20,138, 44,139,118, 18
60170 DATA 138, 12,139,118, 16,138, 52,139,118, 14,138, 20,139,118, 10
60180 DATA 139, 52, 85,205, 33, 93, 86,156,139,118, 12,137, 60,139,118
60190 DATA 28,136, 36,139,118, 26,136, 4,139,118, 24,136, 60,139,118
60200 DATA 22,136, 28,139,118, 20,136, 44,139,118, 18,136, 12,139,118
60210 DATA 16,136, 52,139,118, 14,136, 20,139,118, 8,140,192,137, 4
60220 DATA 88,139,118, 6,137, 4, 88,139,118, 10,137, 4, 7, 31, 93
60230 DATA 202, 26, 0, 91, 46,136, 71, 66,233,108,255
387
7. TheBIOS PC System Programming
(*
(*
(*
Author
developed on
'last Update
MICHAEL TISCHER
7/9/87
6/09/89
*'
*'
*'
{*********************************************************************}
program PRINTPP;
{*********************************************************************}
(* PRINTCHARACTER: sends a character to the printer *'
(* Input : see below *'
{* Output : TRUE if an error occurred, else FALSE *'
{* Info : if an error is discovered, the status of the printer is *'
(* stored in the global variable PRINTERROR *'
{*********************************************************************}
begin
Regs.ah 0;
Regs.al ord(Character); Function number & code of character
Regs.dx :~ Printer; { Printer number
intr ($17, Regs); ( Call BIOS printer interrupt
if (Regs.ah and $21) <> 0 then { Did an error occur?
begin { YES
PrintCharacter := false; ( Display error
PrintError :- Regs.ah; Record error code
end
else PrintCharacter :~ true { No error
end;
{****************************************************.****************}
{* PRINTSTRING: sends a string to the selected printer
{* Input : see below
*'
*'
(* Output : TRUE if no error occurred, else FALSE *'
{***** ••• *********************************************.***************}
begin
Counter := 1; ( begin with the first character in the string
repeat
Ok := PrintCharacter(Text[CounterJ, Printer); (Print a character
Counter := succ(Counter) ( Process next character
until not (Ok) or (Counter> length(Text»); { Terminate on error
Print String :- Ok; { Set result of the function
388
Abacus 7.12 Accessing the Printer from the BIOS
end;
begin
Regs.ah :- $2; { Function number for Init
Regs.dx := Printer; { Printer number
intr($17, Regs}; Call BIOS printer interrupt
if (Regs.ah and $21) <> 0 then { Did an error occur ?
begin { YES
InitPrinter :- false; Display error
PrintError := Regs.ah; Record error code
end
else InitPrinter := true ( No error
end;
procedure PrinterError;
begin
write('Error during printer access: ');
if Print Error and 1 <> 0 Time out error?
then writeln('Time-Out Error') { YES
else if Print Error and 8 <> 0 I/O error?
then writeln (. I/O Error') ( YES
else if PrintError and 32 <> 0 { No more paper ?
then writeln('out of paper') ( YES
else writeln('Error unknown');
end;
{.*** ••• *** •••••• ****.*** ••• ****** ••••••••• **.******************* •••• *}
(* MAIN PROGRAM *1
{*** •••• **.** ••••••• ******** ••••• ****** •••••••••• *********************}
begin
clrscr; ( Clear screen 1
writeln('PRINT (c) 1987 by Michael Tischer');
writeln(113110'If a printer is interfaced to the parallel interface '+
'0 of the PC, ');
'printer: I);
writeln(113110'a test of the printer routines ••• ·,13110);
writeln;
begin
if PrintString('a test of the printer routines ••• ·,13flO, 0)
then writeln('all o.k.')
else PrinterError { display error message
end ( Initialization error
else PrinterError; ( display error message
end.
389
7. TheBIOS PC System Programming
C listing: PRINTC.C
/************ •• ** •••• ****** ••• **** •••••• **.** •••• ** ••••• *_•••••••• _-/
1* P R I N T C *1
1*-----------------------------------------------------------------*1
1* TasK MaKes a function available for sending a *1
1* string to a printer. If any errors occur *1
'*
1* during printing, the program will display
errors on the screen
1*-----------------------------------------------------------------*1
*1
*/
1····_·_-··_·_·_-----_····_--_····_----_··_--_·_·_·_--._.... *.***_**k/
1* PRINTCHARACTER: sends a character to the printer *1
1* Input : see below *I
1* Output : FALSE if no error occurred, else *1
1* error number *1
/******************.**********************************.**************/
390
Abacus 7.12 Accessing the Printer from the BIOS
return (Status);
)
/******************~*****~**************************** ***************/
/* INITPRINTER: initialize the printer interface */
/* Input : see below */
/* Output : FALSE if no error occurred, else */
/* error number */
/********************************************************************/
byte InitPrinter(Printer)
/*******************************************************************/
/** MAIN PROGRAM **/
1***************************************************** **************/
void main ()
{
printf("\nPRINT (c) 1987 by Michael Tischer\n\n");
if (PrintError(InitPrinter(O)))
PrintError (PrintString ("a test of the printer routines ... \r\n"), 0);
391
7. TheBIOS PC System Programming
The assembly language program listed below is a resident interrupt driver. It can
~help the user whose printer runs a character set other than the PC standard. This is
true of some Epson printers, whose foreign characters are different from the PC
ASCII character set The program converts these characters before sending them to
the printer by turning the BIOS printer interrupt to its own routine, which is called
every time the BIOS printer interrupt is called.
If a character should be output, the interrupt looks into a table, with the name
CODETAB, for the character. This table consists of2-byte entries. The ftrst (low)
byte contains the new code of the character to be converted. The second (high) byte
contains the old character code. The table ends with a byte containing the value O.
The routine checks the second byte of a table entry if it is identical to the character
to be printed. If the character cannot be found in the table, it passes unchanged
through the old printer interrupt for output. If the character exists in the table, it is
replaced by the first byte of the current entry, then sent for output using the old
printer interrupt.
This program has a similar structure to the resident keyboard interrupt driver
presented in Section 7.11. The main difference between the two programs lies in
the command line, because PRUM (the program listed here) doesn't pass any
parameters. It tests for an existing pre-installed version of itself when it is called.
If no installed PRUM routine exists, it installs itself. Otherwise the installed
version loads from disk or hard disk.
This program can transmit output to the printer using the BIOS printer interrupt as
well as DOS.
;
;'
.
;*-------------------------------------------------------------------*:
Task Points the BIOS printer interrupt to its own
Routine and makes it possible for example
';
';
;*
.*
;'
to convert IBM-ASCII to EPSON.
The program is deactivated again on the
second call and removed from memory. ··. ';
,
;
Author : MICHAEL TISCHER ·
;*-------------------------------------------------------------------*;
;' ;
;'
;'
developed on
last update
: 8/2/87
: 6/09/89 ·
*;
;
assembly : MASM PRUM; ··
;*-------------------------------------------------------------------*;
;' ;
;'
;'
LINK PRUM;
EXE2BIN PRUM PRUM.COM ·
;
;
i*-------------------------------------------------------------------*i
Call : PRUM ';
;***************************************************** ****************i
392
Abacus 7.12 Accessing the Printer from the BIOS
org 100h
newpri endp
instend equ this byte ;up to this mem location everything must
; remain resident
installm db 13,10, "PRUM (c) 1987 by Michael Tischer", 13, 10, 13, 10
db "PRUM was installed and can be deactivated with", 13, 10
db "a new call ",13,lO,"$"
393
7. TheBIOS PC System Programming
;-- only the PSP, the new interrupt routine and the --------
;-- data pertaining to it must remain resident. ---------
394
Abacus 7.13 Reading the Date and TilMfrom the BIOS
Realtime clock
The enhanced functions included in the AT operate in conjunction with the AT's
battery powered realtime clock (RTC). The realtime clock continues keeping time
even when the AT is switched off. This clock's method of timekeeping is quite
different from PC and XT time. PC and XT models measure time using timer
interrupt 8H, which the system calls about 18.2 times per second. Timer interrupt
8H remains independent of the CPU's clock frequency. The AT ROM-BIOS
maintains control of this interrupt, but only for maintaining software
compatibility with the PC and XT. The AT BIOS receives the current time from
the realtime clock accessing the CPU.
Function number OOH gets the current clock time. You can call this function by
passing the number (0) to the AH register. The function loads the time into the
CX and OX registers. These two registers combine to form a 32-bit counter value
(CX contains the most significant 16 bits, while OX contains the least significant
16 bits). The BIOS timer increments this value by I each time interrupt 8H is
called (18.2 times per second). The total value is the result of multiplying the
contents of CX register by 65.536 and adding the contents of the OX register.
Dividing this value by 18.2 returns the number of seconds elapsed, which can then
be converted into minutes and hours.
The AT interprets time differently from the PC and XT. The PC/XT BIOS sets
this counter to 0 during the system booting process. The value returned is the time
passed since the computer was switched on (not the actual time). To obtain the
time, the current time must be converted to the value corresponding to the counter,
then passed to the BIOS (more on this later). The AT doesn't require this time
value conversion since BIOS reads the actual time from the realtime clock during
the system boot. It converts this time into a suitable timer value and saves it.
Reading the counter with the help of function 0 on the AT thus provides the
current time.
Besides this counter, a value the AL register indicates whether or not 24 hours
have pflSsed since the last reading. If the AL register contains a value other than 0,
24 hours have passed. This value does not indicate how many 24-hour periods have
elapsed since the last reading.
If the conversion of time values into clock time is too complicated, function 2CH
of DOS interrupt 21H can be used. This function simply reads and converts the
395
7. TIu! BIOS PC System Programming
current time using function 0 of interrupt lAH (see Chapter 18 of this book for
more information about function 2CH of DOS interrupt lAH).
Function number 01H sets the current clock time. You can call this function by
loading the number 1 into the AH register, the most significant 16 bits of the
counter into the CX register and the least significant 16 bits into the DX register.
These two registers combine to form a 32-bit time value. If the conversion of the
current time into a timer value is too complicated, function 2DH of DOS interrupt
21H can be used instead (see Chapter 18 of this book for more information about
function 2DH of DOS interrupt 21H).
The next six functions are available only on the AT. If you attempt to call these
functions on a PC or an XT, nothing will happen (use the model identification
program described in Section 7.3 to check for AT hardware).
All six functions use BCD format for time and date indications. In this format,
two characters are coded per byte, where the higher number is coded in the higher
nibble and the lower number in the lower nibble. All six functions use the carry
flag following a return from the function call. If the carry flag is set, this indicates
that the realtime clock is malfunctioning (e.g., dead battery). The called function
could not be executed properly.
Function 02H reads the realtime clock time. You can call the function by loading
the function number (2) into the AH register. The current time is returned with the
hour in the CH register, minutes in the CL register and the seconds in the DH
register.
Function 03H sets the time on the realtime clock. You can call the function by
loading the function number (3) into the AH register, the hour into the CH
register, minutes into the CL register and seconds into the DH register. The DL
register indicates whether the "daylight savings time" option is desired. A 1 in the
DL register selects daylight savings time, while 0 maintains standard time.
Functions 4 and 5 read and set the date stored in the realtime clock. Both functions
use the century, the year, the month and the day as arguments. The day of the week
(also administered by the realtime clock) does not apply to these functions. If you
want to read the day of the week, direct access must be made to the realtime clock
(see Chapter 10 for instructions on direct access).
396
Abacus 7.13 Reading th£ Date and Time from th£ BIOS
Function 04H gets the current date from the realtime clock. You can call this
. function by loading the function number (4) into the AH register. The CH register
contains the fIrst two numbers of the year (the century). The CL register contains
the last two numbers of the year (e.g., 88). The month is returned in the DH
register, and the day of the month in the DL register.
Function 05H sets the current date in the realtime clock. You can call this function
by loading the function number (5) into the AH register, either 19 or 20 into the
CH register, the last two numbers of the year into the CL register (e.g., 89
decimal), the month into the DH register, and the day of the month into the DL
register.
Function 06H allows the user to set an alarm. Since only the hour, minute and
second can be indicated, the alarm time applies only to the current day. When the
clock reaches the alarm time, the realtime clock calls a BIOS routine which in turn
calls interrupt 4AH. A user routine can be installed under this interrupt to simulate
the sound of an alarm clock (you can program the routine to make other sounds).
During the system initialization interrupt 4AH moves to a routine which contains
only the IRET assembly language instruction. The IRET instruction forces the
CPU to terminate the interrupt so that arriving at alarm time doesn't result in any
action visible to the user. You can call this function by loading the function
number (6) into the AH register, the alarm hour into the CH register, the alarm
minute into the CL register and the alarm second into the DH register.
Only one alarm time can be set. If this function is called while another alarm time
is set, or has not yet been reached, the carry flag is set after the function call. A
new alarm time doesn't replace the old alarm time; the old time must be deleted
fIrst. You can call this function by loading the function number (7) into the AH
register; no other parameters are required. This call clears the last alarm time so
that a new alarm time can be programmed.
397
7. TheBIOS PC Synem Programming
The following list describes the individual variables, their purposes and addresses.
The address indicated is the offset address of segment address 0040H. For example,
a variable with the offset address 10H has the address 0040:00 10 or 10H.
OOH-07H
During the booting process, a BIOS routine determines the configuration of its
PC. It determines, among other things, the number of installed serial (RS-232)
interfaces. These interface numbers are stored as four words in memory locations
0040:0000 to 0040:0007. Each one of these words represents one of the four cards
that can be installed for asynchronous data transmission. First the low byte is
stored, followed by the high byte. Since few PCs have four serial cards at their
disposal, the words which represent a missing card contain the value O.
OBH-OFH
During the booting process, a BIOS routine determines the configuration of its
PC. It determines, among other things, the number of installed parallel interfaces.
These card numbers are stored as four words in memory locations 0040:0008 to
OO4O:000F. Each one of these words stands for one of the four cards that can be
installed for parallel data transmission. First the low byte is stored, followed by
the high byte. Since few Pes have four parallel cards at their disposal, the words
which represent a missing card contain the value O.
10H-11H
This word represents the hardware configuration of the PC as called through BIOS
interrupt IlH. Similar to the above two words. this configuration is determined
during the booting process. The purposes of individual bits of this word are
standardized for the PC and the XT, but can differ in some other computers.
398
Abacus 7.14 BIOS Variables
12H
This byte provides stomge for infonnation gathered during the system self-test,
executed during the booting process and after a wann start. BIOS routines also use
this byte for recognizing active keys. It has no practical use for the programmer.
13H-14H
This word indicates the RAM capacity of the system in kilobytes. This
infonnation is also gathered during the booting process, and can be read using
BIOS interrupt 12H.
15H-16H
These two bytes test the hardware during the booting process. They have no further
use after each hardware test
17H
This is called the lceyboard status byte because it contains the status of the
keyboard and different keys. Function 02H of BIOS keyboard interrupt 16H reads
this byte. Accessing this byte allows the user to toggle the <Insert> or <Caps
Lock> key on or off. The upper four bits of this byte may be changed by the user;
the lower four bits must remain undisturbed.
76543210
18H
This byte is similar to byte 17H above, with the difference that this byte indicates
the active status of the <SysReq> and <Break> keys.
399
7. Th£BIOS PC System Programming
7 6 5 4 3 2 1 0
19H
This byte currently serves no purpose; it will be used for status in a proposed
extended keyboard once that keyboard appears OIl the market
1 AH-1 BH
This word contains the address of the next character to be read in the keyboard
buffer (see also lEH-3DH below).
1CH-1DH
This word contains the address of the last character in the keyboard buffer (see also
lEH-3DH below).
1EH-3DH
This area of memory contains the actual keyboard buffer. Since every character
stored in the keyboard buffer requires 2 bytes, its 32-byte capacity offers space for a
maximum of 16 characters. For a normal ASCII character, the buffer stores the
ASCII code and then the character's scan code. The scan code is the number of the
activated key which generated the ASCII character. If the character in the keyboard
buffer uses an extended code (e.g., a cursor key), then the lust byte contains the
value 0 and the second byte contains the extended key code.
The computer constantly reads characters from the keyboard buffer. If the buffer is
not full, characters can be added. The address of the next character to be read from
the keyboard buffer is stored in the word at memory location 0040:001AH. When a
character is read, the character moves by 2 bytes toward the end of the buffer in
400
Abacus 7.14 BIOS Variables
memory. When a character was read from the last memory location of the buffer,
this pointer resets to the beginning of the buffer.
The same is true of the pointer in memory location 0040:001C, which indicates
the end of the keyboard buffer. If you add a new character, it is stored in the
keyboard buffer at the location indicated by this pointer. Then the pointer is
incremented by 2 to move toward the end of the buffer. If a new character is stored
at the last memory location of the buffer, this pointer resets to the beginning of
the buffer.
The relationship between the start and end pointers tells something about the
buffer's status. Two conditions are of special interest. The first is the condition
when both pointers contain the same address (no characters are currently available
in the keyboard buffer). The other condition is when a character should be appended
to the end of the keyboard buffer, but adding 2 to the end pointer would point it to
the start pointer. This means that the keyboard buffer is full, i.e., no additional
characters can be accepted.
1:00 1 2 34 5 6 1 8 9 10 11 l2 13 14 15 ~
~ I I I I I I I I I I I I I ~
~~ l'
0040:003D
L...-_ _ _ _ _ _ 0040:001A
~
Pointer to
next character
in 0040:001A
0040:001E 0040:0024
~----------------}~ILOIHi
I 0024H I
Pointer to
last character
Two byte
in 0040:001C
character
r-------------------------------~
Normal character: ASCII code Scan I
Extended character: OOH I Code I
Keyboard buffer with start and end pointers
401
7. TMBIOS PC System Programming
3EH
The lowest four bits correspond to the number of inSlalled PC disk drives (you are
allowed a maximum of four drives). These bytes also indicate whether the
connected drives must be calibrated. This is mostly the case after an error occurs
during read, write or search access. When an el'lU' occurs, the corresponding bit in
this byte is set to O.
3FH
The four lower bits of this byte indicate whether the current disk drive motor is in
motion. A 1 in the corresponding bit indicates this. In addition, bit 7 is always set
when write access is in progress.
40H
This byte contains a numerical value which indicates the time period until a disk
drive motor switches off. Since BIOS can only access one disk drive at a time, this
value refers to the drive last accessed. Following access to this drive, BIOS places
the value 37 into this register. During every timer interrupt (which occurs about
18.2 times per second), the value in this byte is decremented by 1. When it finally
reaches O. the disk motor is turned off. This takes place after about two seconds.
41H
This byte contains the status of the last disk access. When the byte contains the
value 0, the last disk operation was performed in an orderly manner. Another value
signals that an error code was bansmitted by the disk controller.
42H-48H
These seven bytes indicate the status of the NEC disk controller. They also
indicate hard disk controller status on hard disk systems.
49H
This byte contains the current display mode as reported by the BIOS. This is the
same value indicated when the user activates a display mode through function 0 of
the BIOS video interrup,t IOH.
4AH
This word contains the number of text columns per display line in the current
display mode.
402
Abacus 7.14 BIOS Variables
4CH
This word contains the number of bytes required for the display of a screen page in
the current display mode, as reported by the BIOS. In the 80x25-character text
mode, this is 4,000 bytes.
4EH-4FH
This word contains the address of the current screen page now on the monitor,
relative to the beginning of video card RAM. The video RAM of the color card
starts at B800:0000 for the ftrst screen page, and at B800:1000 for the second
screen page in 80x25-character text mode. This variable usually contains the value
l000H.
50H-5FH
These 16 bytes contain the current cursor position for each screen page. BIOS can
control a maximum of 8 screen pages. BIOS reserves two bytes for each screen
page. The low byte indicates the screen column, which can have values ranging
from 0 to 39 (in 4O-column mode) or from 0 to 79 (in 80-column mode). The high
byte indicates the screen line, which can have values ranging from 0 to 24. If you
change the values in this table, the immediate position of the blinking cursor
remains unchanged, but the change will become noticeable the next time you enter
characters into the corresponding display page.
You can use these bytes for positioning the cursor, but we don't recommend this
method.
60H
This byte contains the starting line of the blinking cursor, which can have values
ranging from 0 to 7 (color graphic card) or from 0 to 14 (monochrome graphic
card). Changing the contents of this byte doesn't change the cursor's appearance,
since it must first be transmitted by BIOS to the video controller.
61H
This byte contains the ending line of the blinking cursor, which can have values
ranging from 0 to 7 (color graphic card) or from 0 to 14 (monochrome graphic
card). Changing the contents of this byte doesn't change the cursor's appearance,
since it must first be transmitted by BIOS to the video controller.
62H
This byte contains the number of the currently displayed screen page.
403
7. TheB/OS PC System Programming
63H-64H
This word contains the video card port. If a PC contains several video cards, the
value stored will be the address of the currently active video card.
65H
The contents of a video controller card's mode selector dictates the current display
mode. The current value is stored in this memory location.
66H
67H-6BH
The early PC BIOS versions could use a cassette recorder for data storage. Those
early versions of BIOS used these five bytes for cassette access when storing data.
XT and AT models, which do not have this interface, use these memory locations
in connection with RAM expansion.
6CH-6FH
These four bytes act as a 32-bit counter for both BIOS and DOS. The counter is
incremented by 1 on each of the 18.2 timer interrupts per second. This permits
time measurement and time display. The value of this counter can be read and set
with BIOS interrupt lAH. If 24 hours have elapsed, it resets to 0 and counts up
from there.
70H
This byte contains a 0 when the timer routine is between 0 and 24 hours. Byte
70H changes to 1 when the time counter routine exceeds its 24-hour limit. For
every subsequent 24-hour count, this byte remains at 1.
If the BIOS timer interrupt lAH is used to set the time, this byte resets to O.
71H
This byte indicates whether or not a keyboard interrupt occurs after the user presses
<Ctrl><C> or <Ctrl><Break>. If bit 7 of this byte contains the value 1, a
keyboard interrupt has occurred.
404
AbacllS 7.14 BIOS Variables
72H-73H
During the booting process, a reset command is sent to the keyboard Controller.
For the duration of this reset, the word at this location assumes the value 1234H.
XT BIOS variables
74H-77H
These four bytes are used only by hard disk systems for hard disk control.
78H-7BH
Each of these four bytes returns the status of one of the four printer ports.
7CH-7FH
Each of these four bytes returns the status of one of the four asynchronous
communication (RS-232) ports.
80H-81 H
This word contains the beginning of the keyboard buffer as the offset address to the
segment address 0040. Since the keyboard buffer normally starts at address
0040:001E, this memory location usually contains the value lEH.
82H-83H
This word contains the end of the keyboard buffer as the offset address to the
segment address 0040. Since the keyboard buffer normally ends at address
0040:003E, this memory location usually contains the value 3EH.
AT BIOS variables
The advanced features of the AT require even more BIOS variables. Here is a list of
the BIOS variables found only on AT models.
88H
This byte contains the last data transmission speed of the disk drive or hard disk.
405
7. TheBIOS PC System Programming
8CH-96H
This memory range contains variables necessary dwiog disk,lhard disk access.
97H
This byte reserves a keyboard flag which shows the status of the AT keyboard's
LED (light-emitting diode).
98H-AOH
This memory range accepts variables from the battery-powered realtime clock.
406
Chapter 8
Since its birth, DOS has been criticized for its inability to handle multitasking
(running more than one program at a time). Even though OS/2 is capable of
multitasking, it runs only on ATs or 80386-based computers. But TSR (Terminate
and Stay Resident) programs can bring some of the advantages of multitasking
into the world of DOS machines. This type of program moves into the
"background" once it is started, and becomes active when the user presses a
particular key combination. The SideKick® program produced by Borland
International made TSR programs very popular.
Running a TSR program isn't multitasking in the true sense of the word, since
only one program is actually running at any given time. However, with the touch
of a key, the user can immediately access such useful tools as a calculator,
calendar, or note pad. In addition to these applications, macro generators, screen
layout utilities and text editors can also be found in TSR form.
Many TSR programs can even interact with the programs that they interrupt, and
transfer data between the TSR and the interrupted program. One example of this
would be a TSR appointment book that inserts a page from its calendar in a file
loaded into a currently running word processor.
This chapter examines these two items, and demonstrates simple implementations
of TSR programs.
407
8. Terminate ond Stay Residelll Programs PC System Programming
Before we begin, we should point out that this involves very complex
programming. Comprehending this material requires a certain level of
understanding about how things work within the system. This is especially true of
TSR programs, since by their very defmition they all but ignore the single-task
nature of DOS, in which one program has access to all of the system resources
(RAM, screen, disk, etc.). A TSR program must contend with many other
elements of the system such as the BIOS, ooS, the interrupted program, and even
other TSR programs. Managing this is a difficult but rewarding task, and can only
be realized in assembly language. Of the available PC languages, only assembly
language offers the ability to work at the lowest system level, the interrupt level.
But although it has this capability, assembly language is as flexible as high level
languages for writing TSR applications such as calculators or note pads. Because
of this well list two assembly language programs in this chapter which will allow
you to "convert" Turbo Pascal, Turbo C, and Microsoft C programs into TSR
programs.
It would be better to use interrupt 09H, which is called by the processor whenever
a key is pressed or released. We can redirect this interrupt to our own routine,
which can check to see if the TSR program should be activated or not Before it
does this, the routine should call the old interrupt 09H handler. There are two
reasons for this. The ftrst has to do with the task of interrupt 09H, which informs
the system that the keyboard needs the system's attention in order to transfer
information about a key event. Therefore, interrupt 09H normally points to a
routine within the ROM BIOS which accepts and evaluates information from the
keyboard. Specifically, it receives the code from the keyboard, converts it to an
ASCII code, and then places this code in the BIOS's keyboard buffer. Since our
TSR program neither wants nor is able to handle this job, we must call the
original routine, or keyboard input will be impossible.
The second reason has to do with the fact that it is possible that other TSR
programs were installed before ours, which have redirected interrupt 09H to their
own routines. Since our program is in front of these programs in the interrupt
handler chain, their interrupt routines will not be called automatically if we do not
call the old interrupt handler. The result would be that we could no longer activate
these TSR programs. The end result is that when a TSR program is called via a
408
Abacus 8. Terminate and Stay Resident Programs
redirected interrupt routine, it should always call the old interrupt handler before or
after its own interrupt processing.
The call must not be made with the !NT assembly language instruction, since this
would just recall our own interrupt handler. This would lead to an infinite loop in
most cases, a stack overflow and an eventual system crash. To avoid this we must
save the address of the old interrupt handler when the TSR program is installed.
We can then call the old interrupt handler with this stored address with the help of
a FAR CALL instruction. To simulate calling this handler through the !NT
instruction, we must first place the contents of the flag register on the stack with
the PUSHF instruction before the CALL.
return to proqram
)10
Last installed
activate. YBS TSR proqram
YBS
activate ....~_ _ Other installed
TSR proqram
After the return from the interrupt handler, we can check to see if the hotkey was
pressed to activate the TSR. The BIOS keyboard flag at address 17H in the BIOS
variable segment (segment address 0040H) indicates the status of the following
keys:
<Ctrl> key
<Alt> key
<Num> key
409
8. Terminate and Stay Resident Programs PC System Programming
<CapsLock> key
If the appropriate keys are pressed, the user is trying to activate the TSR program.
We can only do this if certain conditions are met, all of which come down to the
fact that the DOS is not re-entrant.
DOS
Since the TSR program can be activated from the keyboard at any time, regardless
of the other processes in the system, it could conceivably interrupt a call to a DOS
function. This may not lead to problems as long as the TSR program returns to
the interrupted DOS function properly. The problem occurs when the TSR itself
tries to call DOS functions, which is hard to avoid when programming in a high
level language. Here we see the problem of re-entry. This refers to the ability of a
system to allow multiple programs to call and execute its code at the same time.
DOS is not re-entrant, however, since it is a single-task system and assumes that
DOS functions will be called in sequence, and not in parallel.
Calling a DOS function from within a TSR program while another function is
executing leads to problems because the processor register SS:SP is loaded with
the address of one of three DOS stacks when interrupt 2lH is called. Which of the
three stacks is used depends on the function group to which the DOS function
belongs, and cannot be determined by the caller. While the DOS function is being
executed, it places temporary data on this stack as well as the return address to the
calling program. If the execution of the function is then interrupted by the
activation of a TSR program which then calls a DOS function, OOS will again
load register pair SS:SP with the starting address of an internal stack. If it is the
same stack that the interrupt function was using, each access to the stack will
destroy the data of the other function call. The OOS function called by the TSR
program will be executed properly, but the problem will occur when the TSR
program ends and control returns to the interrupted DOS function. Since the
contents of the stack have been changed in the meantime by other OOS calls, the
OOS function will probably crash the system.
Bypassing re-entry
There are two ways to get around these re-entry problems: Avoid calling OOS
functions, or allow the TSR program to be activated only if no OOS functions are
being executed. We have already ruled out the first option, so we must use the
second. DOS helps us here by providing the INDOS flag, which is normally only
used inside DOS but which is very useful to us as well. It is a counter which
counts the nesting depth of DOS calls. If it contains the value 0, no DOS
functions are currently being executed. The value 1 indicates the current execution
of a OOS function. Under certain conditions this counter can also contain larger
values, such as when one DOS function calls another DOS function, which is
allowed only in special cases.
410
Abacus 8. Terminate and Stay Resident Programs
Since there is no DOS function to read the value of this flag, we have to read the
contents directly from memory. The address does not change after the system is
booted, so we can get the address when the TSR is installed and save it in a
variable. DOS function 34H returns the address of the INDOS flag in register pair
ES:BX.
This flag is read in the interrupt handler for intemlpt 09H since it checks to see if
the hotkey was pressed, and allows the TSR program to be activated only if the
INDOS flag contains the value O. This is not the whole solution to the problem,
however. It coordinates the activation of the TSR program with DOS function
calls of the transient program being executed in the foreground, but it does not
allow the TSR program to be called from the DOS user interface. Since the DOS
command processor (COMMAND.COM) uses some DOS functions for printing
the prompt and accepting input from the user, the INDOS flag always contains the
value 1. In this special case we can interrupt the executing DOS function, but we
must make sure that the INDOS flag contains the value I, because a DOS function
can be called from transient program or from the DOS command processor.
There is a solution for this problem too. It involves the fact that the DOS is in a
kind of a wait state when it is waiting for input from the user in the command
processor. To avoid wasting any valuable processor time, it periodically calls
interrupt 28H, which is responsible for short term activation of background
processes like the print spooler (DOS PRINT command) and other tasks. If this
interrupt is called, it is relatively safe to interrupt DOS and call the TSR program.
To use this procedure, a new handler for interrupt 28H is installed when the TSR
program is installed. It frrst calls the old handler for this interrupt and then checks
to see if the hotkey has been pressed. If this has occurred, the TSR program can be
activated, even if the INDOS flag is not O.
One more restriction must still be added-we cannot allow the TSR program to be
activated, even using the handler for interrupt 09H, if time-critical actions are
being performed in the system.
Time-critical actions
These are actions which, for various reasons, cannot be interrupted because they
must complete execution in a relatively short time. In the PC this includes
accesses to the floppy and hard disk, which at the lowest levels are controlled by
BIOS interrupt 13H. If an access to these devices is not completed by a certain
time it can cause serious system disruptions. A dramatic example is if the TSR
program performs an access to these devices before another access, which is
initiated by the interrupted program, has finished. Even if this doesn't crash the
system, it will lead to loss of data.
We can avoid this by installing a new interrupt handler for BIOS interrupt 13H.
When this handler is called, it sets an internal flag which shows that the BIOS disk
interrupt is currently active. Then it calls the old interrupt handler which performs
411
8. Terminate and Stay Resident Programs PC System Programming
the access to the floppy or hard disk:. When it returns to the TSR handler,the flag
is cleared, signalling the end of BIOS disk: activity.
To prevent this interrupt handler from being interrupted, the other TSR interrupt
handlers all monitor this flag and will activate the TSR program only if the flag
indicates that the BIOS disk interrupt is not active.
Recursion
One last condition placed on the activation of a TSR program is that recursive
activations are prohibited. Since the hotkey can still be pressed after the TSR
program has been activated, we must prevent the TSR program from being
reactivated before it is fmished. We can simply add another flag which is checked
before the TSR is activated. The TSR program sets this flag when it begins and
clears it again just before it ends. If an interrupt handler detennines that this flag is
set, it will simply ignore the hotkey.
Once all of these conditions have been satisfied, we can activate the TSR program.
Context switch
The process of activating a TSR program is called a context switch. The program
context or environment is all the infonnation needed for operating the program.
This includes such things as the contents of the processor registers, important
operating system infonnation, and the memory occupied by the program. We don't
have to worry about the program memory in our context switch, however, since
our TSR program is already marked as resident, meaning that the operating system
will not give the memory it occupies to other programs.
The processor registers, especially the segment registers, must be loaded with the
values which the TSR program expects. These are saved in internal variables when
the TSR program is installed. Since the contents of these and other registers will
be changed by the TSR program, the contents of the registers must be saved
because they belong to the context of the interrupted program and must be restored
when it is resumed.
The same applies for context dependent operating system infonnation, which for
DOS includes just the PSP (Program Segment Prefix) of the program and the
DTA (Disk Transfer Area). The addresses of both structures must be detennined and
saved when the TSR program is installed, SO that they can be reset when context is
changed to the TSR program. Also, we must not forget to save the addresses of the
PSP and DTA of the interrupted program before the context change to the TSR
program. There are DOS functions for setting and reading the address of the DTA
(DOS functions lAH and 2FH), but there are no corresponding documented
functions for the PSP. DOS Version 3.0 includes function 62H, which returns the
address of the current PSP, but has no function for setting the address.
Undocumented functions for doing both exist in DOS 2.0: function SOH (set PSP
412
Abacus 8. Terminate and Stay Ruidml Programs
address) and 51H (get PSP address). Both of these are used in our TSR
demonstration program.
One final· task is required of the TSR code. When the TSR program is activated
using interrupt 28H, an active DOS function is interrupted--one whose stack must
not be disturbed. Generally we should take the top 64 words from the current stack
and place them on the stack of the TSR program. This completes the context
change to the TSR program, which means that the TSR program can now be
started.
At the moment, the TSR program can be viewed as a completely normal program
which can call arbitrary DOS and BIOS functions. The only competitor left in the
system is the foreground program. The TSR must ensure that it leaves both the
foreground program and its screen undisturbed.
Saving the screen context
The tasks were exclusively handled in assembly language. However, the C or
Pascal program comprising the TSR program itself can save the screen context.
This screen context includes the current video mode, the cursor position and the
screen's contents. The contents of the color registers and other registers on the
video card must also be saved, if any of these values are changed by the TSR
program.
As described in Section 7.4, the video mode can easily be determined with function
OOH of BIOS video interrupt l6H. If the screen is in text mode (modes 0, 1,2,3,
and 7), the TSR program must save the first 4000 bytes of video RAM. The video
BIOS can be used for this (see Section 7.4), or you can access the video RAM
directly (see Chapter 10).
Saving the video mode becomes very complicated if a graphics mode is active,
since the video RAM for EGA and VGA cards can be as large as 256K in some
modes. If the TSR program interrupted a transient program, it may not be possible
to allocate a large enough buffer to handle both programs.
This is why many TSR programs will not activate themselves from within
graphics mode, and can only be used in text mode. Since PCs· mostly use text
mode, this doesn't present a big problem. GEM® and Microsoft Windows®,
which operate only in graphics mode, are exceptions. Since these programs usually
support some mechanism for parallel execution of calculators, note pads, etc.,
TSR programs can prove less useful under these systems.
The assembler interrace
We now have enough information to understand the operation of the two assembly
language interfaces. The two programs are based on the principles we have outlined
here; the differences between them reflect the different syntaxes of compiled C and
413
8. Terminate and Stay Resident Programs PC System Programming
Pascal programs. We will first concentrate on the common points of the two
programs.
Both programs assume that the TSR program was installed by the first call from
the DOS level, and will be reinstalled on each new call. It is important to
remember one general rule: a TSR program can be reinstalled only if no other TSR
programs have been installed in the meantime. The LIFO (Last In, First Out)
principle applies here, so the only way a TSR program can be reinstalled is if it
was the last one to be installed, and if the corresponding interrupt vectors point to
its interrupt handlers. If another TSR program was installed following it, the
interrupt vectors point to its handlers.
To support this mechanism, the assembly language interface offers the high-level
program three routines with which install and later reinstall the TSR program. To
decide whether the program should be installed or reinstalled, the first function
should be called to see if the TSR program is already installed. This routine is
passed an identification string, which will play an important role later when the
program is installed. The routine looks for this ID string within the handler for
interrupt 09H. If it finds the string, the TSR program is already installed and can
be reinstalled.
If the ID string is not discovered, the TSR program has not been installed, or
another TSR program redirected the interrupt 09H vector in the meantime. The
TSR program can then be installed with the help of the installation routine. This
routine must receive the ID string used to detect whether the program has already
been installed, the address of the high level routine which will be called when the
TSR program is activated, and the hotkey value. The hotkey value is the bit
pattern in the BIOS keyboard flag which will activate the TSR program and can be
defined within the high level language program with the help of predefined
constants.
The initialization routine first saves the addresses of the interrupt handlers for
interrupts 09H, 13H and 28H. Then the data for the context of the high level
program are read and saved in variables within the code segment, so that they are
available for the interrupt handler and for activation of the TSR program. In the
next step, the new interrupt handlers for interrupts 09H, 13H, and 28H are
installed. Finally, the number of paragraphs after the end of the program which are
to remain resident must be calculated. Here the C and Pascal interfaces differ from
each other. Information about this calculation can be found in the individual
descriptions of the interfaces.
The actual installation is now over and the program is terminated as resident.
Notice that the installation routine does not return to the high level language
program, so all initialization such as memory allocation or variable initialization
must be perfonned before the call to this routine.
414
Abacus 8. Termi1'lllle and Stay Resident Programs
If the test function of the assembly language module determines that the program
is already installed, it can be reinstalled with the help of another function. This
function is passed the address of a routine in the high level language program
which will perform a "cleanup" of the program. This process includes releasing
allocated memory and other tasks. If no such routine is to be called, the assembly
language routine must be passed the value -1. Since the "cleanup" function is in
the TSR program, and not in the program which is performing the reinstallation, a
context switch is necessary. Unlike activation of the TSR program and the
corresponding interruption of the foreground program, this is from the program
which is doing the reinstallation to the already installed TSR program. The
reinstallation returns the redirected interrupt handlers to their old routines and
releases the memory allocated by the TSR program.
In addition to these three functions which are called from the high level language
program, the assembler module contains some routines which may not be called
by high level language programs. These include the interrupt handlers for
interrupts 09H, 13H, and 28H as well as a routine which accomplishes the context
switch to and from the TSR program.
The high level lanpage programs
There are some procedures you should follow when developing TSR programs,
that apply to the special characteristics of these programs. First, the program
should be developed as a completely normal program, compiled and executed from
the DOS user interface, or an interactive environment. To prepare for conversion to
a TSR program, you can write an initialization routine and the actual TSR routine
which will be called when the holkey is pressed. Unlike the TSR version, you can
call these routines in the main procedure/function of the program, allowing
activation independent of any bolkeys. You should completely develop and test the
program in this manner. Once it works correctly, you can convert it to a TSR
program.
415
8. Termi1lllle and Stay Resident Programs PC System Programming
The conversion to a TSR program is relatively simple, and involves linking in the
assembly language module to the program and calling the corresponding functions.
You can see how this is done in detail in the two example programs.
After linking the assembly language routines and converting the program to an
EXE file, it should be started only from DOS. Do not start it from within an
interactive environment like Turbo Pascal or Turbo C.
The C implementation
Since TSR programs should use as little memory as possible, the assembly
language interface was developed to be linked with the smallest C memory model
(the small model). In both Microsoft and Turbo C compilers, the program code and
data are placed in two separate segments, each of which may be no larger than
64K. The data includes global and static data as well as the stack and the heap. As
the following figures show, Turbo C and Microsoft C use different memory
organization, despite their similarities. While in Turbo C the stack is placed
behind the heap and moves from the end of the data segment to the end of the heap,
the stack is between the global data and the heap in Microsoft C.
SS:IP
St.ck
He.p
•+ Be.p
__ 641{
5S: SP
Stack
PIP PS'
Turbo C Microsoft C
The size of this memory area depends on the size of the data (or objects) which
will be allocated on the heap by the functions callocO and mallocO. You must
guess this size and pass it to the initialization routine so that the end of the
required memory in the data segment can be calculated.
This mechanism allows you to use the heap functions normally within the TSR
program. Unfortunately, this applies only to the Turbo C compiler. Microsoft C
uses an allocation algorithm which assumes that all of the memory to the end of
the data segment is available, so allocating heap storage should be avoided within a
416
Abacus 8. Terminate and Stay Resident Programs
TSR program compiled with Microsoft C. You should allocate the buffers and
variables required when the TSR program is initialized or place the required objects
in global variables. The example C program allocates the two buffers it needs in
the mainO function and then places the addresses of the buffers in global variables.
There is something else you should be aware of when using Turbo C. Since the
stack grows from the end of the 64K data segment to the heap, it finds itself
outside the program when parts of the data segment are released again, and this in
an area of memory which DOS may give to other programs. To avoid problems
with this, the assembly language interface places the stack immediately afiel" the
heap, giving it 512 bytes of space. This should suffice for most applications, but
may lead to problems if you use large objects (such as arrays) as local variables or
pass them to other functions via the stack. In this case you should enlarge the
stack by setting the constant TC_STACK in the assembly language interface to a
larger value.
The different treatment of the stack is the reason that the initialization routine in
the assembly language interface must be told what compiler the TSR program will
be compiled with. In practice you don't have to worry about this since it is handled
within the C program with the help of constants defined with conditional
preprocessor statements.
The TSR initialization routine TSR_INIT must be called with the following
parameters (in the specified order):
The initialization routine uses the information about the compiler type and the
number of bytes which must be available on the stack to calculate the number of
paragraphs which must remain resident in memory. The C library function SBRK
is called from the assembly language routine to determine the offset address of the
current end of heap. The number of bytes which must be reserved for the heap is
added to this address. With Turbo C we also add the size of the stack, which is
appended to the heap and must also stay resident. The result of this addition is the
offset address of the last byte in memory relative to the start of the data segment.
417
8. Terminate and Stay Resident PrQgrams PC System Programming
data segment (which is also the ending address of the code segment) and the
segment address of the PSP. Since both Turbo C and Microsoft C store the
segment address of the PSP in a global variable called _PSP, it can be read by the
assembly language routine and included in the subttaction. The program is then
ended by a call to DOS function 3tH, which keeps the specified number of
paragraphs (passed in the DX register) resident The TSR program is installed.
You can get additional information from the following listing. It will make a good
basis for developing your own TSR programs.
C listing: TSRC.C
/ •• *** •••••• *************.*.*.***** •••• *************.* ••••••• *******.*./
1* T S R C *1
1*--------------------------------------------------------------------*1
1* Description : C module which is turned into a TSR program *1
1* with the help of an assembly language routine. *1
1*--------------------------------------------------------------------*1
1* Author : MICHAEL TISCHER *1
1* developed on : 08/15/1988 *1
1* last update : 0811911988 *1
1*--------------------------------------------------------------------*1
1* (MICROSOFT C) *I
1* creation : CL lAS Ic TSRC.C *1
1* LINK TSRC TSRCA; *1
1* call : TSRC *I
1*--------------------------------------------------------------------*1
1* (BORLAND TURBO C) *1
1* creation Create project file with the following *1
1* contents: *I
1* TSRC *1
1* TSRCA.OBJ *1
1* Before compiling, set Options menu I linker *1
1* option I Case sensitive link to OFF *1
1··············_--_·························_········- ***************.*/
I*~~ Include files ===----=-===-=-=====~==~====~===--=---=====-------=*I
'include <stdlib.h>
'include <dos.h>
418
Abacus 8. Terminale and Stay Residenl Programs
typedef union vel far * VP; 1* VP is a FAR pointer into the VRAM *1
'define MK- FP (seq, ofs) «void far *) «unsiqned lon'l) (seq) «161 (ofs)) )
.endif
'define VOFS(x,y) (80 * ( y ) + ( x ) )
1*-- codes of the individual control keys for buildin'l the hotkey mask *1
fdefine RSHIFT 1 1* ri'lht SHIFT key pressed *1
'define LSHIFT 2 1* left SHIFT key pressed *1
'define CTRL 4 1* CTRL key pressed *1
'define ALT 8 1* ALT key pressed *1
'define SCRL_AN 16 1* Scroll Lock ON *1
'define NUHL AN 32 1* Num Lock ON *1
'define CAPL AN 64 1* Caps Lock ON *1
'define INS AN 128 1* Insert ON *1
'define SCR LOCK 4096 1* Scroll Lock pressed *1
'define NOH_LOCK 8192 1* Num Lock pressed *1
'define CAP_LOCK 16384 1* Caps Lock pressed *1
'define INSERT 32768 1* INSERT key pressed *1
fdefine NOF Ox07 1* normal color *1
'define INV Ox70 1* inverse color *1
'define HNOF OxOf 1* bri'lht normal color *1
'define HINV OxfO 1* bri'lht inverse color *1
'define HEAP_FREE 1024 1* leave lK space on the heap *1
'define TRUE, 1 1* constants for workin'l with BOOL *1
'define FALSE 0
'define NO_END_FTN «void (*) (void)) -1) 1* don't call an end ftn. *1
1*=- Global variables -------========--=-====--===-=====-=-----------=-*1
char id_strin'l[J - "MiTi"; 1* identification strin'l *1
419
8. Terminate D1Id Stay Resident Programs PC System Programming
'*
pointer to the buffer with screen contents
pointer to a blank line
*'*'
/*** •• *********************************************.*.*************** •••
* Function : DIS P I N I T
**----------------------------=---------------------------------------**
* Description Determines the base address of the video RAM. *
* Input parameters : none *
Return value : none
.*.*.**************.************** •• ***********************************/
420
Abacus 8. Terminate and Stay Resident Programs
.._------------------------------------------------------------------_..*
Function
Description
: T S R
is pressed. *
Input parameters none *
* Return value none *
***** ••••••* •••••••• ** •••• ***** •• *** •••••••••••••••••• ····**···*·······1
1············**·*****··**********·*****··*·*·****·*******.*************1
1** MAIN PROGRAM **1
1·**************·*·******·····*··***·**·*******·**·*·**·*************·*1
void main()
I
printf ("TSRC (c) 1988 by MICHAEL TISCHER\n\n");
421
8. TermillQle and Stay Resident Programs PC System Programming
{ /* yes */
printf("TSRC was already installed--now disabling.\n"';
uninst ( endftn ,; /* reinstall prg., call ftn. ENDFKT */
SSS segment word public 'SSS' ;this segment stores all uninitialized
SSS ends ;static variables
DATA segment word public 'DATA' ;all initialized and global static
;variables are stored in this
isegment
DATA ends
422
Abac/U 8. Terminate and Stay Resident Programs
c ss dw 0 ;C stack segment
c_sp dw 0 ;C stack pointer
c ds dw 0 ;C data segment
c_es dw 0 ;C extra segment
i----------------------------------------------------------------------
;-- TSR_INIT: ends the C program and makes the new interrupt ----------
;-- interrupt handler active
423
80 Terminate and Stay Resident Programs PC System Programming
frame equ[bp-bpO]
424
Abacus 8. Terminate and Stay Resident Programs
mov ds,ax
;-- With TURBO-C the stack is found behind the heap and
;-- begins with the end of the segment. It must thus
;-- be moved near the heap.
_tsr_init endp
i----------------------------------------------------------------------
425
8. Terminate and Stay Resident Programs PC System Programming
;----------------------------------------------------------------------
;-- CALL ENO: calls the end function on reinstallation of the TSR
;-- program.
;-- Input 01 - offset address of the routine to be called
Info This function is not intended to be called by a C program.
;----------------------------------------------------------------------
;-- UNINST: reinstalls the TSR program and releases the allocated
426
AbacllS 8. Terminate and Stay Resident Programs
bp2 dw ? ;stores BP
ret adr2 dw ;return address
ftnptr2 dw ;pointer to the end function
sframe2 ends ; end of the structure
;-- determine the seq addr of the current int 9 handler --
mov ax, 3S09h ; get interrupt vector 9h
int 2lh ;OOS interrupt puts seq addr in ES
427
8. Terminate and Stay Resident Programs PC System Programming
pop bp
ret ;back to the called
:------~----------------------------------------------------------------
;-- The new interrupt routine follows ---------------------------------
;----------------------------------------------------------------------
;-- The new interrupt 09h handler -------------------------------------
int09 proc far
;-- test to see if the BIOS disk int is being executed now
428
Abac/U 8. Termi7lllte and Stay Resident ProgtaITIS
;-- BIOS disk interrupt not active, test for hotkey -------
int09 endp
;-- the new interrupt 13h handler -------------------------------------
int13 proc far
429
8. Terminate and Stay Resident Programs PC System Programming
int28 endp
tsrsl: push word ptr [sil ;save word from the DOS stack to the
inc si ;e stack and set SI to the next
inc si ;stack word
loop tsrsl ;process all 64 words
430
Abacus 8. Terminate and Stay ResUUnl Programs
start_tsr endp
;----------------------------------------------------------------------
ends ;endof the code segment
Turbo Pascal offers only one memory model, unlike the various C compilers. The
organization of this model is well suited to TSR programs.
. ,+
"".p
Stack
incr•• sing
Global variable.
''Il10'1'
Pradeflned. constants
addresses
Runtime library routines
Proqram code
PSP
431
8. Terminllte and Stay Resident Programs PC System Programming
The figure above shows that the program code and the required routines from the
various units and the runtime library follow the PSP. After these are the predefined
constants, the global data, and the stack segment. While the size of these program
components are set at compilation and cannot be changed after the program is
loaded into memory, this doesn't apply to the size of the heap, which follows the
stack segment. When new objects are created with the NEW command, the heap
grows toward the end of memory.
Turbo Pascal offers the significant advantage over C compilers of being able to set
the maximum size of the heap, as well as the stack size, with a compiler directive
inside the source code. This is the $M directive, which must be passed the
following parameters:
The figure shows that the segment address of the PSP is found in the variable
PrefixSeg, while the end of the heap is determined with the help of the pointer
variable FreePtr. This variable does not point directly to the end of the heap, but
the segment portion of this pointer contains the end address of the heap minus
$1000. This information is used within the TSR program in the ResPara
procedure, which calculates the number of paragraphs to remain resident after the
installation of the TSR.
432
Abacus 8. Terminate and Stay Resident Programs
Identification string
The Pascal TSR function, the address of which is passed as the first parameter to
Tsrlnit, must be a procedure within the main program and may not be contained in
a unit. Moreover, it may not be converted to a FAR procedure with the $F+
compiler directive, since the assembly language interface assumes that it is a
NEAR procedure. The address of the procedure is determined with the help of the
function OFS and passed to TsrInit, since Turbo Pascal would otherwise place
both the offset address and the segment address on the stack.
The same applies to passing the address of a "cleanup" procedure to the function
Uolnst, which reinstalls the TSR program. If such an address is passed, the
corresponding procedure within the installed TSR program will be called before the
reinstallation. If the value $FFFF is passed as the address of this procedure, this
tells the assembly language function that no "cleanup" procedure is to be called.
To improve the readability of the listing, the constant NO_END_FIN is defined in
the constant definitions at the start of the listing. NO_END_FIN is given the
value $FFFF and should be used when calling the assembly language function
Unlnst.
The following listing can answer any additional questions you may have, and will
make a good starting point for your own TSR programs.
Pascal listing: TSRP.PAS
{************************************.****.*******.*.***** •• ***********j
1* T S RP *'
1*--------------------------------------------------------------------OJ
1*
{*
Description : creates a TSR program with the help of an
assembly lanquage module.
*'
*j
1*--------------------------------------------------------------------*'
I* Author : MICHAEL TISCHER *j
1* developed on : 08/18/1988 *j
1* last update : 05/26/1989 *j
{***********************************************•••********** ••• *******}
program TSRP;
ISM 2048, 0, 5120j I 2KB for the stack and max. 5KB for the heap j
I$L tsrpaj I bind in the assembler module ,
433
8. Terminate and Stay Resident Programs PC System Programming
procedure Oisplnit;
begin
Regs.ah := $Of; function no. 15 = read the video mode
Intr(S10, Regs); ( call the BIOS video interrupt
if Regs.al-7 then ( monochrome video card?
VioPtr '. @MBuf ( yes, set pointer to the monochrome video RAM
else { it's an EGA, VGA, or CGA card
VioPtr := @CBuf; { set pointer to color video RAM
end;
begin
for line:-1 to 25 do { run through the 25 screen lines
for column:-1 to 80 do { run through the 80 screen columns
SPtrA[line, columnJ :- VioPtrA[line, columnJ; (save ch.&attr.
end;
434
Abacus 8. TerminaJe and Stay Resident Programs
none
pointer to the buffer whose contents are to be
copied into the video RAM
*'
*'
{* •••••••••••••••••• **.*** •••••••••••• ** •••••••••••••• ** •••••••• **••••• }
begin
for line:-l to 25 do ( run through the 25 screen lines
for column:-l to 80 do run through the 80 screen columns
Vi oPt r A[line, column] .- BPtrA[line, column]; (get ch. , attr.
end;
begin
ResPara Seg{FreePtrA)+SlOOO-PrefixSeg; { number of paragraphs ,
end;
{**** ••••••• *** •••• *** ••••• ****••••••••••••••• *** ••• *** •••• *••••• *.****.
1* EndProc: Called by the assembler module when the TSR program is *1
(* reinstalled *)
*OUtput
1 Input
(*
none
none *1
*'
(* Info This procedure must be in the main program and may not *1
1* be turned into a FAR procedure by the $F+ compiler *1
1* directive. *)
{* ••••• ***.*** ••• ******** •••• ** •••••••••• *** ••••••••••••••••••••• *****.}
procedure EndProc;
begin
TextBackground( Black ); ( dark background
TextColorl LightGray ); ( light text
writelnl'The TSR program was called ATimes, ' times.');
end;
435
8. TermilUlle and Stay Residenl Programs PC System Programming
begin
inc ( ATimes ); ( increment call counter
DispInit; determine address of the video RAM
GetMemlBufPtr, SizeOf(VBuf) ); { allocate buffer
SaveScreenl Bu!Ptr ); save the screen contents
Line :- WhereY; I get current screen line
Column :- WhereX; ( 'let current screen column
TextBackqround I LightGray ); ( light background
TextColorl Black ); I dark text
ClrScr; clear the whole screen
GotoXY 122, 12);
write I' TSRP Ic) 1988 by MICHAEL TISCHER');
GotoXY 130, 14);
writel'Please press a key ••• ·);
Key :- ReadKey; I wait for a key
RestoreScreenl BufPtr ); { copy the old screen contents back
FreeMeml BuiPtr, SizeOflVBuf) ); I release allocated buffer
GotoXYI Column, Line ); I cursor back to original position
end;
begin
writelnl'TSRP Ic) 1988 by MICHAEL TISCHER');
IdStrinq := 'TROTZKY';
if I IsInstl IdStrinq ) ) then I proqram already installed?
begin I YES
writelnl'The TSR program now disabled.');
UnInstl Ofsl EndProc ) ); I remove the program
436
AbaclLf 8. Terminate and Stay Residenl Programs
; - Constants ----=-=-=-'""------=---------
;maximum length of the 10 string
;-- The following variables store the old addresses of the interrupt
;-- handlers which will be replaced by new interrupt handlers
437
8. Terminate and Stay Resident Programs PC System Programming
;----------------------------------------------------------------------
;-- TSR1N1T: ends the Turbo program and activates the new interrupt ---
;-- handler
438
Abacus 8. Terminate and Stay Residenl Programs
tsrinit endp
;----------------------------------------------------------------------
;-- ISINST: Determines if the program is already installed ------------
;-- Call from Turbo: function IsInst( IdString : IdsType ) : boolean;
;-- Return value: 1, if the program was already installed,
;-- else 0 .
439
8. Terminate and Stay Resident Programs PC System Programming
not_inst: al,dl
II\OV ; put return code in AL
pop ds ; get OS back from stack
pop bp ; get BP back from stack
ret 4 ;back to the caller
i----------------------------------------------------------------------
;-- CALL_END: calls the end function when the TSR is reinstalled ------
;-- Input 01 - offset address of the routine to be called
;-- Info This function is not intended to be called by a Turbo
i-- program
;----------------------------------------------------------------------
;-- UNINST: removes the TSR program and releases the allocated --------
;-- memory.
;-- Call from Turbo procedure UnInst( EndPtr : word ); external;
;-- Info If the value $FFFF is passed as the address,
;-- then no end function will be called.
;-- Note This function should be called only if a previous
;-- call to IS_INST() returned a value of 1.
440
AbaclU 8. Terminate and Stay Resident Programs
441
8. TermiMle and Stay Resident Programs PC System Programming
;----------------------------------------------------------------------
;-- The new interrupt handlers follow ---------------------------------
;----------------------------------------------------------------------
;-- the new interrupt 09h handler -------------------------------------
int09 proc far
442
Abacus 8. Terminate and Stay Resident Programs
int09 endp
mav cs:in_bios,l ;set flag and show that the BrOS disk
;interrupt is active
pushf ;simulate calling the old interrupt
call cs:intI3~tr ;handler via int 13h
mav cs:in_bios, 0 ;BrOS disk interrupt no longer active
;-- Bros disk interrupt not active, test for hot key
int28 endp
443
8. Terminate and Stay Resident Programs PC System Programming
push dx
push bp
push si
push di
push ds
push es
tsrsl: push word ptr lsi] ;save word from the DOS stack on the
inc si ;C stack and set S1 to the next word
inc si
loop tsrsl ;process all 64 words
444
Abacus 8. Terminate and Stay Resident Programs
pop bp
pop dx
pop ex
pop bx
pop ax
j--------------------------------------------------------
CODE ends :end of the code segment
end :end of the program
445
Chapter 9
Sound on the PC
Every PC has a built in speaker which beeps when some errors occur, or when the
keyboard buffer is full. The speaker can also generate other sounds. This chapter
demonstrates sound generation through software.
Tones occur when the cone of a speaker oscillates (moves back and forth). A single
oscillation creates a click instead of a musical sound. If a group of oscillations
sounds in rapid succession, a tone occurs. The pitch (the note value) of a tone
depends on the number of cycles (oscillations) that occur per second. The pitch of a
tone in cycles per second is measured in Hertz. For example, if the speaker
oscillates at a rate of 440 times per second, it generates a tone with a frequency of
440 Hertz. Certain pitches have specific note names assigned to them, such as
A440 (the note that sounds at 440 Hertz). The following table shows the pitches
and frequencies of tones generated by the PC. This range covers 8 octaves (almost
the range of a full piano keyboard):
I Octave 0 1 2 3
C 16.35 C 32.70 C 65.41 C 130.81
ct 17.32 ct 34.65 ct 69.30 ct 138.59
D 18.35 D 36.71 D 73.42 D 146.83
Dt 19.45 Dt 38.89 Dt 77.78 Dt 155.56
E 20.60 E 41.20 E 82.41 E 164.81
F 21.83 F 43.65 F 87.31 F 174.61
FIt 23.12 FIt 46.25 Fil 92.50 FIt 185.00
G 24.50 G 49.00 G 98.00 G 196.00
Gil 25.96 Gt 51.91 Gil 103.83 Gil 207.65
A 27.50 A 55.00 A 110.00 A 220.00
Ail 29.14 Ail 58.27 Ail 116.54 Ail 233.08
B 30.87 B 61.74 B 123.47 B 246.94
447
9. Sound on the PC PC System Programming
I Octave 4 5 6 7
C 261.63 C 523.25 C 1046.50 C 2093.00
C* 277.18 Cf 554.37 ct 1108.74 c* 2217.46
D 293.66 D 587.33 D 1174.66 D 2349.32
D* 311.13 D* 622.25 Df 1244.51 D* 2489.02
E 329.63 E 659.26 E 1328.51 E 2637.02
F 349.23 F 698.46 F 1396.91 F 2793.83
F* 369.99 F* 739.99 Ft 1479.98 Ff 2959.96
G 392.00 G 783.99 G 1567.98 G 3135.96
Gf 415.30 G* 830.61 G* 1661.22 G* 3322.44
A 440.00 A 880.00 A 1760.00 A 3520.00
Ai 466.16 Ai 923.33 Af 1864.66 Ai 3729.31
B 493.88 B 987.77 B 1975.53 B 3951. 07
The speaker in the PC can generate frequencies from 1 Hertz up to more than
1,000,000 Hertz. However, most human ears are only capable of hearing
frequencies between 20 and 20,000 Hertz. In addition, PC speakers don't reproduce
music very well since they play some tones louder than others. Since the speaker
has no volume control, this effect cannot be changed.
.
'~
A sound program should oscillate the speaker according to the frequency of the
tones desired. Here is a rough outline of a possible sound generation program:
• Invoke the instruction to move the cone forward, then undo the instruc
tion (move the cone back to its original position). Repeat these steps in a
loop so that it occurs as many times per second as required by the
frequency of the tone being generated.
• The tone becomes distorted when the tone production loop ends.
8253 timer
Every PC uses one particular chip for tone generation: The 8253 programmable
timer, which actually maintains control of the internal clock. The 8253 can
perform both timing and sound thanks to its ability to enable a certain action at a
certain point in time. It senses timing from oscillations it receives from the PC's
8284 oscillator, which generates 1,193,180 impulses per second. The 8253 can
then be instructed how many of these impulses it should wait before triggering a
certain action. In the case of tone generation, this action consists of sending an
impulse to the speaker. Before executing this action, the chip must be programmed
for the particular frequency it should generate. The frequency must be converted
448
Abacus 9. Sound on the PC
from cycles per second into the number of oscillations coming from the oscillator.
This is done with the help of the following formula:
The result of this formula, the variable counter, passes to the chip. As the formula
demonstrates, the result for a high frequency is relatively low, and the result for a
low frequency is relatively high. This makes sense, since it tells the 8253 chip
how many of the 1,193,180 cycles per second it must wait until it can send
another signal to the speaker. The lower the value, the more often it sends a signal
to move the speaker cone back and forth, causing a higher tone.
Communication between the CPU and the 8253 occurs through ports. First the
value 182 is sent to port 43H. This instructs the 8253 that it should start
generating a signal as soon as the interval between individual signals has been
passed. This interval is the value which was calculated with the formula above.
Since the 8253 stores this value internally as a 16-bit number (a value between 0
and 65,535), it limits the range of tones generated to frequencies between 18 and
1,193,180 Hertz. This number must be transmitted to port 42H. Since this is an
8-bit port, the 16 bits of this number cannot be transmitted simultaneously. First
the least significant eight bits are transmitted, then the most significant eight bits
are transmitted.
Now the second step occurs-the 8253 signal is sent to the speaker. The speaker
access occurs through port 61H, which is connected to a programmable peripheral
chip. The two lowest bits of this port must be set to 1 to transmit the 8253 signal
to the speaker. Since the remaining six bits are used for other purposes, they
cannot be changed. For this reason, the contents of port 61H must be read, the
lowest two bits must be set to 1 (an OR combination with 3) and the resulting
value must be returned to port 61H. A tone sounds, which ends only when the bits
just set to 1 are reset again to O.
449
9. Sound on the PC PC System Programming
GW-BASIC and Turbo Pascal have resident sound commands. The machine
language programmer and C programmer must create their own sound applications.
Demonstration programs follow for both these languages. They can be added to
your own C or assembly language programs.
Both programs produce tones for specific time periods. This is done with the help
of the timer interrupt lCH which is called by the timer interrupt 8H 18.2 times
per second. When the tone generation routine executes, it receives the frequency of
the tone and the tone's duration (length). The duration is measured in 18ths of a
second, so the value 18 corresponds to a second and the value 9 corresponds to a
half-second. This value is stored in a variable.
Immediately before activating the tone output, the interrupt routine of interrupt
lCH turns to a user-defined routine. This routine, called 18.2 times per second,
decrements the tone duration in the variable during every call. When it reaches the
value, the tone duration ends and the tone must be switched off. The routine
allocates a variable to notify the actual sound routine of this end. The sound
routine recognizes this immediately, since it has been in a constant wait loop since
switching on the tone. All this loop does is monitor the contents of this variable.
After recognizing the end of the tone, it stops the sound output and returns the
timer interrupt to its old routine.
450
Abacus 9. Sound ora the PC
The sound routine requires the number assigned to this tone, rather than the
frequency itself. This number is related to the table containing the frequencies of
octaves 3 to 5. The value 0 stands for C of the third octave, 1 stands for C-sharp, 2
for D, 3 for D-sharp, etc.
Note: Both the C program and assembly language program demonstrate the
sound routine by playing a scale over the course of two octaves, with
each note sounding for a half a second each. The machine language
demo program and sound routine are stored in one file. The C
versions of these programs are split into two source code files. The C
demo program contains the sound function call only, and the machine
language program which creates the sound must be linked to the
demonstration program.
Assembler listing: SOUNDA.ASM
;********** ••• *****************.*.****** •••••• ******.**** •••••••• ***.**;
;" SOUNDA ";
;*--------------------------------------------------------------------*;
;" Task : Plays a scale between octaves 3 and 5 of the ";
;" PC's musical range. This routine can be used ";
;" for other applications ";
;*--------------------------------------------------------------------*;
451
9. Sound on the PC PC System Programming
pop dx
xor
shl
bh,bh
bx,l
;BH for addressing note table = °
452
Abacus 9. Sound on the PC
Ids dx,dword ptr old time ;Load old address into OS:OX
int 21h - ;Call DOS interrupt
mov ds,ex ;Return OS
play_tune endp
sound t i endp
Here's the C program to call the sound function and the assembly language listing
of the C sound function.
C listing: SOUNDC.C
/**.************** •••••• **.**********.**.**.***************************/
1* sou N D C *1
1*--------------------------------------------------------------------*1
1* Task : Plays a scale between octaves 3 and 5 of the *1
1* PC musical range, using an assembler function *1
1*--------------------------------------------------------------------*1
1* Author MICHAEL TISCHER *I
1* Developed on : 08/15/1987 */
1* Last update : 05/26/1989 *1
1*--------------------------------------------------------------------*/
1* (MICROSOFT C) */
1* Creation CL lAS SOUNDC.C *1
1* LINK SOUNDC SOUNDCA; *1
1* Call SOUNDC *1
1*--------------------------------------------------------------------*1
1* (BORLl\ND TURBO C) *I
1* Creation Create a project file listing the following: *1
1* soundc *1
1* soundca.obj */
1* Options Before compiling and linking, select the *1
1* Options menu and Linker option. Under the *1
453
9. Sound on tM PC PC System Programming
void mainO
int Note;
printf("Your PC should now be playing a musical scale in the 3rd & a);
printf(" 5th octaves of\nits range. If you aren't hearing the notes");
for (Note - 0; Note < 35; Sound (Note++, 9» /* Playa note once each */
/* 112 second */
printf("End\n");
)
SSS segment word public 'SSS' ;This segment denotes all static, non
SSS ends ;initialized variables
DATA segment word public 'DATA' ;This segment contains all initialized
;global and static varibles
454
Abacus 9. Sound on 1M PC
dw 2873,2711,2559,2415
dw 2280,2152,2031,1917 ;Note values for octave 5
dw 1809,1715,1612,1521
dw 1436,1355,1292,1207
_DATA ends
i - Program --====~=-c=:z:::==_= ___ ~~'=::z __ =:zz:=~~=-======-
proc near
455
9. Sound on tlu! PC PC System Programming
_Sound endp
456
Chapter 10
This chapter explains methods of programming the most popular video cards on
the PC market. Even though the video cards mentioned here differ in their
capabilities, they are all based on the same basic principle. High level languages
such as BASIC, Pascal or C often have their own specific keywords and commands
for controlling screen display. However, many of these commands merely call
BIOS or DOS functions, which are both slow and inflexible in execution.
Direct access
Direct access to the video card is the alternative. Applications from Lotus 1-2-3®
to dBASE® use direct video access coding, to guarantee both speed and that
element of extra control over the video display. The main disadvantage:
Programming in assembly language is required, since the communication here
occurs at the system level. This chapter examines the programming needed for the
best known video cards on the market
Most of the graphic cards on the market are compatible with one of the cards
mentioned in this chapter, and the descriptions stated here should apply to those
cards.
457
10. Accessing and ProgramnUng the Video Cards PC System Programming
What's needed
Before a video card can display a character or graphic pixel on a monitor screen or
CRT (cathode ray tube), the card must know the following:
PC video cards include RAM which collects information about every CRT screen
pixel or screen location. This RAM memory is called video RAM and interfaces
with the PC's RAM, allowing direct access from the microprocessor.
Speed
Rapid screen changes are important in word processing programs and other PC
applications. For example, if you are paging through a word processing document
at high speed, a 25-line, SO-column screen requires the transmission of 2,000
characters through the video card at one time. Fast data transfer is even more
important for high-resolution graphics. For example, the 200x640-pixel ffiM
Color Graphics Adapter transmits 12S,OOO pixels of graphic information at a time.
Display modes
Each type of video card can have more than one display mode. Text and graphics
display may be very different from one another. The monitor cannot distinguish
between the two modes; it just processes the graphic information sent by the video
card (or video controller). For the programmer and the video card, the modes require
completely different programming techniques.
458
Abacus 10. Accessing and Programming the Video Cards
PC text mode uses the 256-character extended character set (see Appendix I). Since
these characters are numbered sequentially from 0 to 255, one byte is enough for
each screen position to display the character at the proper position.
Attribute bytes
Every screen position has an attribute byte which indicates the color or display
attribute of the character (underlined, blinking, inverse video, etc.). This means
that two bytes are needed for each position on the screen. Therefore, a total of 4000
bytes are required for a 25-line, SO-column screen. This appears to be a lot of
memory at first glance, but is fairly small when compared to the memory
requirements for bit-mapped graphic screen. In graphic mode, each dot is
represented by one or more bits. A resolution of 64Ox200 pixels requires 12S,OOO
bits (16K).
Another advantage of text mode is the simplicity in exchanging one character for
another on the screen. The bit-map mode has its own advantages. Besides graphic
displays, text can be displayed as individual dots whose pattern is derived from a
character table in RAM installed by the user. This means that the user can design
his own fonts (character sets).
459
10. Accessing and Programming the Video Cards PC System Programming
----------------------------,,
D~
CRT Signal
controller
~
controller ~
Character
pattern . ~.
Character
generator
t
Attribute
controller
+
VIDEO RAM
•
,---------------------------
Block diagram ofa video card
The monitor
The monitor is the device on which the video data is displayed. Unlike the video
card, the monitor is a "dumb" device. This means it has no memory and cannot be
programmed. All monitors used with PCs are raster-scan devices, in which the
picture is made up of many small dots arranged in a rectangular pattern or raster.
When forming the picture, the electron beam of the picture tube touches each
individual dot and illuminates it if it is supposed to be visible on the screen. This
460
Abacus 10.1 Anatomy of a Video Card
is done by switching on the electron beam as it passes over this dot, causing a
, phosphor particle on the picture tube to light up.
Color monitors
While monochrome monitors need only one electron beam to create a picture,
color monitors use three beams which scan the screen simultaneously. Here a
screen pixel consists of three phosphor particles in the basic colors of light: red,
green, and blue. Each color has a matching electron beam. Any color in the
spectrum can be created by combining these three colors and varying their
intensities.
But since an ionized phosphor particle emits light for only a very brief period of
time, the entire screen must be scanned many times per second to create the
illusion of a stationary picture. PC monitors perform this task between SO and 70
times per second. This repeated re-scanning is called the refresh rate. One rule of
thumb for this rate: The faster the refresh rate, the better quality the picture.
Each new screen image begins in the upper left comer of the screen. From there
the electron beam moves to the right along the first raster line. When it reaches the
end of this line, .the electron beam moves back to the start of the next line down,
similar to pressing the <Return> key on a typewriter. The electron beam then
scans the second raster line, at the end of which it moves to the start of the next
raster line, and so on. Once it reaches the bottom of the screen, the electron beam
returns to the upper left comer of the screen and the process starts over again. The
illustration below shows the path of the electron beam.
Remem ber that the movement of the electron beam is controlled by the video card,
not by the monitor itself.
Horizontal
ON:_ OFF:,/'
461
10. Accessing and Programming flu! Video Cards PC System Programming
The resolution of the monitor naturally controls the number of raster lines and
columns which the electron beam scans when creating a display. Thus, a monitor
which has only 200 raster lines of 640 raster columns each clearly cannot handle
the high resolutions of an EGA card at 640x350 pixels. The four monitor types
used with a PC generally have the following resolutions:
To inform the monitor of the next raster line, the CRTC sends a display enable
signal at the start of each line, which activates the electron beam. While the beam
moves from left to right over each raster column of the line, the CRTC controls
the individual signals for the electron beam(s) so that the pixels appear on the
screen as desired. At the end of the line, the CRTC disables the display enable
signal so that the electron beam's return to the next raster line doesn't make a
visible line on the screen. The electron beam is directed to the left edge of the
following raster line by the output of a horizontal synchronization signal. The
display enable signal is again enabled at the start of the next raster line, and the
generation of the next line begins.
Overscan
Since the time that the electron beam needs to return to the start of the next line is
less than the time the CRTC needs to get and prepare new information from the
video RAM, there is a short pause. But the electron beam cannot be stopped, so
we get something called overscan, which is visible as the left and right borders of
the actual screen contents. Although this is an undesirable side effect in one sense,
it is useful because it prevents the edges of the screen contents from being hidden
by the edge of the monitor. If the electron beam is enabled while it is traveling
over this border, a color screen border can be created.
462
Abacus 10.1 Anatomy of a Video Card
, ,-r
~
/
hori'lon tal
oversean
Screen contents Y r
l vertical overllcan
",
.creen ))ordltr
~-------'•• X raater col~n.
As with the horizontal electron beam return, a pause results which is displayed in
the fonn of overscan, creating a vertical screen border.
Signal timing
The timing of individual signals varies from video mode to video mode. For this
reason, the CRTC has a number of registers which describe the signal outputs and
their timing. The structure of these registers and how they are programmed will be
discussed in the remainder of this section. Many of these registers come from the
registers of the 6845 video controller from Motorola. This controller is used in the
MDA, CGA, and Hercules graphics cards. The EGA and VGA cards use a special
VLSI (very large scale integration) chip as a CRTC, and its registers are somewhat
more complicated. The techniques described here are intended as general
descriptions for all video cards.
463
10. Accessing and Programming the Video Cards PC System Programming
These registers, like all of the other registers on the video card, are accessed via I/O
ports with the assembly language instructions IN and OUT. The registers of the
CRTC are accessed through a special address register, rather than directly from the
address space of the processor. The number of the desired CRTC register is written
to the port corresponding to this address register. Then the contents of this register
can be read into a special data register with the IN assembly language instruction.
If a value is to be written to the addressed register, it must be transferred to the data
register with the OUT instruction. Then the CRTC automatically places it in the
desired register. These two registers are actually found at successive port addresses,
but these addresses vary from video card to video card.
We will include tables throughout the chapter to describe the contents of individual
CRTC registers under the various video modes. Here's an example which shows
how the contents of these registers are calculated and how the individual registers
are related to each other. If you try some of these calculations with your calculator
or pc, you will notice that some of them do not work out evenly. But since the
registers of the CRTC hold only integer values, they will be rounded up or down.
The basis for the various calculations are the bandwidth and the horizontal and
vertical scan rates of a monitor.
Bandwidth and scan rates of different video cards
Video system Resolution Bandwidth Vert. scan rate Horiz. scan
rate
The bandwidths in the figure above specify the number of points which the
electron beam scans per second, and is therefore also called the point or dot rate.
The vertical scan rate specifies the number of screen refreshes per second, while the
horizontal scan rate refers to the number of raster lines which the electron beam
scans per second
464
Abacus 10.1 ANltomy of a Video Card
Starting with these values. let's practice calculating the individual CRTC register
values for the 80x2S character text mode on a CGA card.
Dividing the bandwidth by the horizontal scan rate we get the number of pixels
(screen dots) per raster line.
Bandwidth 14.318 MHz
+ Horizontal scan rate 15.570 KHz
Since the CRTC registers generally refer to the number of characters rather than
pixels. this value must be converted to the number of characters per line. This is
done by dividing the number of pixels per line by the width of the character
matrix. On the CGA card this is eight pixels.
Pixels per line 919
+ Pixels per character 8
This value. decremented by one. is placed in the ftrst register of the CRTC and
speciftes the total number of characters per line. In the second register we load the
number of characters that will actually be displayed per line. The 80x25 character
text mode usually offers 80 characters.
The difference between the total and the number of characters actually displayed per
line is the number of characters which can be displayed between the horizontal
return and the overscan. The difference in this case is 34 characters.
The duration of the horizontal beam return must be entered in the fourth register of
the CRTC. This register stores the number of characters which could be displayed
during this time. rather than the actual time duration. The monitor specifications
deftne this instead of the video card itself. As a rule this number is between 5% and
15% of the total number of characters per line. A color monitor uses exactly ten
characters.
This leaves 24 characters for the overscan (the horizontal screen border). The third
CRTC register specifies how these characters are divided between the left and right
screen borders. This register specifies the number of character positions which will
be scanned before the horizontal beam return occurs. The BIOS specifies the value
90 here. or after ten characters have been displayed for the screen borders. The
remaining 14 characters are placed at the start of the next line and form the left
screen border.
The calculations for the vertical data. the number of vertical lines. the position of
the vertical synchronization signal. etc.. follow a similar scheme. The first
calculation is the number of raster lines per screen. This results from the division
465
10. Accessing and Programming the Video Cards PC System Programming
of the number of lines displayed per second by the number of screen refreshes per
second:
Pixels per line 919
+ Pixels per character 8
Since the characters in CGA text mode are eight pixels high by eight pixels wide,
we again divide by eight to get the number of text lines per screen:
Raster lines 262
+ Pixels per character 8
This result must be decremented by one and then loaded into the fifth register of
the CRTC. The number of displayed lines is loaded into the seventh register. Since
seven fewer lines are displayed than are actually available, these extra lines are used
for the vertical beam return and overscan, whereby the vertical beam return begins
after the 28th line.
The character height must be decremented by one and loaded into CRTC register
nine. The decrement results is 7 in this example. This value also determines the
range for the values loaded into register ten and eleven. They specify the first and
last raster lines of the screen cursor. The cursor position is determined by the
contents of registers 14 and 15. They refer to the distance of the character from the
upper left comer of the screen, instead of line and column. This value is calculated
by multiplying the cursor line by the number of columns per line and then adding
the cursor column. The high byte of the result must be loaded into register 14 and
the low byte in register 15.
The contents of registers 12 and 13 determine the area of video RAM displayed on
the screen. To understand these registers, we first need to know something about
the way video RAM is organized.
The third component of the video system determines what will eventually be
displayed on the screen. In text mode, the video RAM contains the ASCII codes of
the characters to be displayed and their attributes. While the organization of video
RAM in this mode is identical for all of the video cards discussed here, the
organization for graphic mode varies from card to card. The description of each card
discusses the way video RAM organizes graphic modes (more on this later).
466
Abacus 10.1 AnIIlomy of a Video Card
As the illustration below shows, each screen position occupies two bytes in video
RAM. The ASCII code of the character to be displayed is placed in the flISt of
these two bytes, the one with the even address. By using eight bits per character
code, a maximum of 256 different characters can be displayed.
RAM
ocmoooo ....-_...,
25 Charoact ••r. _ __
Attribute
After the ASCII code, and always at an odd offset address, follows the attribute
byte, which defmes the appearance of the character on the screen. The attribute
controller divides it into two nibbles, whereby the upper nibble (bits four to seven)
describes the character background, and the lower nibble (bits zero to three)
describes the character foreground. This results in two values between zero and
fifteen which are interpreted depending on the type of monitor attached. With a
color monitor (and a CGA or EGA card) both values select one of 16 possible
colors. Each character on the screen can thus have its own foreground and
background colors.
A monochrome monitor cannot display colors, regardless of the adapter. Here the
attribute controls whether the character is displayed at high or low intensity,
inverse, or underlined.
467
10. Accessing and Programming the Video Cards PC System Programming
The fIrst character on the screen (the character in the upper left comer) is also the
frrst character in video RAM, located at offset position OOOOR. The next character
to the right is located at offset position 0002R. All 80 characters of the frrst screen
line follow in this manner. Since each screen character takes two bytes of memory,
each line occupies 160 bytes of RAM. The fust character of the second screen line
follows the last character of the frrst line, and so on.
Note: Since only 40 characters per line are displayed in 40-column video
modes, the factor 80 must replace the original 160.
The RAM memory of the video card is integrated into the normal RAM of the PC
system, so you can use normal memory access commands to access video RAM.
You must know the segment address of video RAM, which is used together with
the formula above to fInd the offset position. Section 10.7 shows how this can be
done easily in assembly language, BASIC, Pascal, and C.
Now that we have discussed the most important similarities between the four video
cards, the following four sections describe the capabilities of these cards. In
addition, these sections explain how these capabilities can be used for optimal
screen output
468
Abacus 10.2 The IBM Monochrome Card
This card is excellent for text display. This is achieved with a 9x14 character
matrix, which pennits high-resolution character display. The format of this matrix
is unusual since a character generator containing the bit pattern of each character
can only produce characters 8 pixels wide. Characters from the IBM character set
may not connect with each other (e.g., using box characters to draw a box). A
circuit on the graphics card sidesteps this disadvantage by copying the eighth pixel
of the line into the ninth pixel for any characters whose ASCn codes are between
BOH and DFH. This allows the horizontal box drawing characters to connect
~
Column 0 1 2 3 4 5 6 7 8
0
Row
1
2
3
4
5
6
7
8
9
10
11
12
13
469
10. Accessing and Programming the Video Cards PC System Programming
only 4,000 bytes of memory for those characters, the unused 96 bytes at the end of
video RAM are available for other applications.
The following figure shows the meanings of the different values representing the
attribute byte:
7 6 5 4 3 2 1
Character color
Character Intensity
I.-------/O=normal
1=hlgh Intensity
Back round color
Blinking (or background
1....------------IO=off Intensity)
1=on
Any combination of bits can be loaded into this byte. However, the MDA only
accepts the following combinations:
7 6 5 3 2 1
Besides these bit combinations, bits 3 and 7 of the attribute byte can be set or
unset. Bit 3 defines the intensity of the foreground display. When this bit is set,
the characters appear in higher intensity. Bit 7's purpose varies with the contents
of the control registers (more on this later). For now, all you need to know is that
470
Abacus 10.2 The IBM Monochrome Card
bit 7 can either enable blinking characters, or enable an intensity matching the
background color.
Monochrome cards have two more registers available: the control register and the
status register.
7 6 5 4 3 2 1 Obit
L Always 1
O=Screen off
1=Screen on
Bit 7 of the attribute
byte:
O=brlght background
1=bllnklng
Control register
MDA control register
The control register located at port 3B8H controls the monochrome display
adapter's different functions. As the figure below shows, only bits 0, 3 and 5 are of
°
importance. Bit controls the resolution on the card. Although the card only
supports one resolution (8Ox25 characters), this bit must be set to 1 during system
initialization. Otherwise the computer goes into an infinite wait loop. Bit 3
controls the creation of a visible display on the monitor. If bit 3 is set to 0, the
screen is black and the blinking cursor disappears. If bit 3 is set to 1, the display
returns to the screen. Bit 5 has a similar function: If bit 7 in the attribute byte of
the character is set to 1, it enables blinking characters. If bit 7 contains the value
0, the character appears, unblinking, in front of a light background color. This
means that bit 7· of the attribute byte acts as an intensity bit for the background.
This register can only be written. This makes it impossible for a program to
determine whether the display is turned on or off. The normal value for this
register is 29H, meaning that all three relevant bits default to 1.
471
10. Accessing and Programming the Video Cards PC System Programming
7 6 5 4 3 2 1 Obit
L Horizontal
synchronization
signal: 0=01f, 1=on
O=Current pixel off
1=Current pixel on
Horizontal synchronization
Bit 0 indicates if a horizontal synchronization signal is being sent to the display
screen. The video card sends this signal after creating a screen line (not to be
confused with a text line, which consists of 14 screen lines) on the screen. This
signal informs the electron gun, which "draws" the picture on the screen, that it
should return to the left border of the current screen line. In this case the bit has
the value 1. Bit 3 contains the value of the pixel where the electron beam is
currently located. A 1 signals that the pixel is visible on the screen and 0 means
that the screen remains black at this location.
When you enter a value into one of the 18 registers, the number of the. register (0
17) passes first into the index register. Then the value which is transmitted to the
register passes into the data register. The 6845 then transmits the indicated value to
the proper register. Most of these 18 registers should not be modified, since they
contain impottant data about the screen structure (e.g., synchronization signals)
and incorrect values in these registers can damage the monitor. The following table
shows the meanings of the individual registers and the values which ensure a
correct display.
472
Abacus 10.2 Tile IBM Monoclvome Card
The following program makes full use of the monochrome display adapter's
capabilities. It was written in assembly language. The individual routines are fully
documented and require no additional explanation. The demonstration program built
into the listing shows practical application of the individual routines.
473
10. Accessing and Programming the Video Cards PC System Programming
i - Stack - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
stack segment para stack iDeflnltlon of stack segment
; - Data - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
474
10.2 Tile IBM Monoclvome Card
arrow:
xor
mov
ch,ch
bl,l
;Hi-byte of the counter to
;Asterisk
°
arrowO: push bx ;Push BX on the stack
mov di,offset str3 ;Draw arrow line in string 3
mov cl,15 ;Total of 15 characters in a line
sub cl,bl ;Calculate number of spaces
shr cl,l ;Divide by 2 (for left half)
or cl,cl ;No blanks ?
je arrow1 ; YES --> ARROW1
mov al," ..
rep stosb ;Draw blanks in string 3
arrow1: mov cI,bl ;Number of asterisks in counter
mov al,"·
rep stosb ;Draw stars in string 3
mov cl,15 ;Total of 15 characters in a line
sub cI,bl ;Calculate number of blanks
shr cl,l ;Divide by 2 (for right half)
or cl,cl ;No blanks?
je arrow2 ;YES --> ARROW2
mov al,· ..
475
10. Accessing and Programming the Video Cards PC System Programming
SOFF endp
476
Abacus 10.2 The IBM Monochrome Card
SON endp
;-- COEF: sets the start and end line of the cursor ------------
;-- Input CL - Start line
, Output none
;-- register : AX and OX are changed
cdef proc near
cdef endp
setvk endp
;-- GETVK: reads a byte from one register of the video controllers
;-- Input : AL ~ number of the register
477
10. Accessing and Programming the Video Cards PC System Programming
getvk endp
478
Abacus 10.2 The IBM Monochrome Card
pop bx
pop ax
sub si,16O
pop ds ; stack
dec dl
479
10. Accessing and Programming the Video Cards PC System Programming
scrolldn endp
cls endp
clear endp
480
Abacus 10.2 The IBM Monochrome Card
, Input AH - Attribute/color
i-- DI - offset address of the first character
;- SI - offset address of the strinq to DS
i-- OUtput 01 points behind the last character output
;-- reqister AL, DI and FLAGS are chanqed
; - Info the strinq must be terminated with a NUL-character.
;-- other control characters are not recoqnized
print endp
calo endp
481
10. Accessing and Programming the Video Cards PC System Programming
To avoid conflicts with other video cards (especially color cards), both bits are set
to 0 at the start of the system so that neither graphic mode nor the second display
page are accessible at first. Application programs must configure the Hercules
display adapter through the configuration register if the programs require graphic
mode or the second screen page.
The control register of the Hercules graphic card has some differences from that of
the MDA discussed in the preceding section.
7 6 5 4 3 2 1 Obit
O=bllnklng disabled
"---------1 1=bllnklng enabled
O=dlsplay screen
page 1
1=dlsplay screen
2
482
Abacus 103 The Herclllu Graphic Card
Unlike the IBM monochrome dispJay adapter, bit 0 is unused and doesn't have to
be set to 1 during the system boot Bit 1 determines text or graphic mode: a 0 in
bit 1 enables text mode, while a 1 in bit 1 enables graphic mode. As you shall see
in the following examples, changing these bits isn't enough to switch between
text and graphic modes. The internal registers of the 6845 must be reset as well.
During this process,the screen display must be switched off to prevent the 6845
from creating gatbage during its reprogramming.
The Hercules card has a seventh bit in this register. Its contents determine which of
the two screen pages appear on the monitor screen. If this bit is 0, the first screen
page appears; a 1 calls the second screen page on the screen. Independent of each
other, the user can write to or read from either page at any time. You can only
write to this register; attempts to read this register return the value FFH. Because
of this, it is impossible to switch off the display simply by reading the contents of
the status register and erasing bit 3, regardless of the dispJay mode and the screen
page selected.
7 6 5 4 3 2 1 Obit
L Horizontal
synchronization
signal: O=off, 1=on
O=Current pixel off
1=Current pixel on
Vertical
synchronization
slg nal: O=on, 1=off
Only the significance of bit 7 makes this register different from the IBM
monochrome card. It's always set to 0 when the 6845 sends a vertical
synchronization signal to the display. This signal is always sent when the last
screen line has been constructed. The electron beam, which constructs the display,
then jumps to the fJrSt line of the screen to start constructing a new screen.
Since the Hercules card uses the same processor as the IBM card, the internal
registers of the 6845 and their meaning are identical to the IBM card. The index
register and data register are also located at the same address. The following values
must be assigned to the various registers in the text and graphic modes
respectively:
483
10. Accessing and ProgrOlll11ling ,11£ Video Cards PC System ProgrOlll11ling
484
Abacus 103 The Hercllles Graphic Card
+2000 (h)
+20SA(h)
Lifte 1
Line 5
(90 byt••)
(90 tea)
RAM
+2084 (h) Line 9 (90 bytes)
0000:0000
+3088 (h) Line 331 (90 byte.)
+3E1C(h)
+3E96 (h)
+4000 (h)
+405A (h)
Line 345
unused
Line 2
Line'
(90 bytes)
(362 bytes)
(90 bytes)
(90 byte.)
1
+4084 (h) Line 10 (90 bytes)
+8000 (h)
485
10. Accessing and Programming tM Video Cards PC System Programming
etc. Within one of these bytes, bit 7 corresponds to the left screen pixel and bit 0
corresponds to the right screen pixel.
RAM
0000:0000
7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0 bit
I II I I II I I IIIII II I I
If the screen pixels of a line (0 to 719) and the screen pixels of a column (0 to
347) are sequentially numbered, an equation indicates the address of the bytes
relative to the beginning of the screen page. This address contains the information
for a pixel with the coordinates X/Y.
To determine the bit within the byte which represents the pixel, the following
formula can be used:
Address = 2000H * (Y mod 4) + 90 * int(Y/4) + int(X/B)
The following program demonstrates the abilities of the Hercules display adapter.
The individual routines within this program have some differences from the
routines shown in the monochrome display adapter demo program from the
previous section. The routines here enable access to both screen pages, and support
the Hercules graphic mode.
486
Abacus 103 TIte Hercules Graphic Card
endm
endm
strl db 1,17,16,2,7,0
str2 db 2,16,17,1,7,0
domes db 13,10
db -This program creates a short graphic demo -,13,10
db "and a text demo. Pressing a key during the-,13,10
487
10. Accessing and Programming the Video Cards PC System Programming
grafikt db 3Sh, 2Dh, 2Eh, 07h, SBh, 02h ;Reqister values for the
db S7h, S7h, 02h, 03h, OOh, OOh ;graphic mode
textt db 61h, SOh, S2h, OFh, 19h, 06h ;Reqister values for the
db 19h, 19h, 02h, ODh, OBh, Och ;text mode
o/g lOOh
488
Abacus 10.3 The Hercules Graphic Card
489
10. Accessing and Progrll11l/lUng the Video Cards PC System Progrll11l/lUng
demo endp
config endp
text endp
grafik endp
490
Abacus 10.3 Tile Hercllles Graphic Card
;-- cOEF: sets the start and end line of the cursor-------------------
;-- Input c1 - start line
;-- cH & end line
;-- Output none
register AX and OX are changed
cdef proc near
cdef endp
setbl1nk endp
491
10. Accessing and Programming the Video Cards PC System Programming
getvk endp
492
Abacus 10.3 TM Hercules Graphic Card
scrollup endp
493
10. Accessing and Programming the Video Cards PC System Programming
scrolldn endp
;-- CLEAR: fills a designated display area with space character ------
;-- Input AH - Attribute/color
;-- BL - line upper left
;-- BH - column upper left
;-- DL - line lower right
;-- DK - column lower right
;-- BP - number of the display page (0 or 1)
;-- Output none
; -- register only FLAGS are changed
494
Abacus 103 TM Hercules Graphic Card
print endp
;-- cALO: converts line and column into offset address ---------------
;-- Input BL = line
i- BH = column
;-- Bp - number of the display page (0 or 1)
;-- OUtput 01 offset address
; -- register 01 and FLAGS are changed
calo endp
495
10. Accessing t.md Programming the Video Cards PC System Programming
cgr endp
; - Output none
i-- register AX, DI and FLAGS are changed
mov
or
cX,VIO SEG
bp,bp
;Segment address display page
;Access page 1 ?
spix endp
496
Abacus 10.4 The IBM Color Card
Text modes
Besides the normal text mode of 25 lines and 80 columns, the CGA also has a text
mode consisting of 25 lines and 40 columns. This 40-column mode displays
characters twice as wide as normal 8O-column mode. CGA characters are displayed
in an 8x8 matrix, which results in a less distinct display than monochrome display
adapter text. The CGA's video RAM assignment is almost identical to that of the
monochrome card. The attribute byte is different from that of the monochrome
display adapter.
7 6 5 4 3 2 l O b it
The lower four bits of the attribute byte indicate one of the 16 available colors.
The meanings of the upper four bits depend on whether blinking is active. If it is
active, bits 4 to 6 indicate the background color (taken from one of the first eight
colors of the color palette), while bit 7 determines whether or not the characters
blink. If blinking is disabled, bits 4 to 7 indicate the background color (taken from
one of the 16 available colors).
497
10. Accessing and Programming the Video Cards PC System Programming
Each 80x25 text page requires 4,000 bytes of video RAM. 16K allows a total of
four text pages. The ftrst display page starts at address B800:()()()(), the second at
B800:1000, the third at B800:2000 and the last at B800:3000. The 4Ox25 mode
allows storage of eight display pages, because each display page only requires
2,000 bytes in this mode. The ftrst display page starts at address B800:0000, the
second at B800:0800, the third at B800:1000, etc.
Graphic modes
The eGA supports three different graphic modes, of which only two are usually
used. The color-suppressed mode displays 160xl00 pixels with 16 colors. The
6845 supports this resolution, but the rest of the hardware doesn't offer color
suppressed mode support. The remaining two graphic modes have resolutions of
32Ox200 and 640x200 respectively. The 32Ox200 resolution permits four-color
graphics, while 640x200 resolution only allows two colors.
320x200 resolution
The eGA uses up all 16K of its video RAM for displaying a graphic in 32Ox200
resolution with four colors. This limits the user to one graphic page at a time. Of
the four colors permitted, the background can be selected from the 16 available
colors. The other three colors originate from one of the two user-selected color
palettes, which contain three colors each.
498
Abacu 10.4 The IBM Color Card
Since a total of four colors are available, each screen pixel requires two bits. Four
bits can represent the color numbers (0 to 3). The following values correspond to
the various colors:
The video RAM assignment in this mode is similar to that of the Hercules card
during graphic display. The individual graphic lines are stored in two different
blocks of memory. The frrst block, which begins at address B800:0000, contains
the even lines (0, 2, 4 ... ); the second block, which begins at B800:2000, contains
odd lines (1,3,5).
RAM
0000:0000
499
10. Accessing and Programming the Video Cards PC System Programming
bit 7 6 54 32 1 0
Column 0
I : I I: I : I
i
1 2 3
Column 316 317 318 319
A formula can be derived with the help of this information to determine the byte in
video RAM, similar to the Hercules card. This byte is relative to the starting
address of the screen page, which contains the color information for a pixel. The
screen column (0---319) is designated as X and the screen line (0---199) as Y:
Address = 2000H * (Y mod 2) + 80 * int(Y/2) + int(X/4)
To detennine the number of the two bits within this byte which represents the
pixel, use the following fonnula:
Bit number = 6 - 2 * (X mod 4)
For example, if this fonnula returns 4, this means that the color information for
the dot is coded into bits 4 and 5.
500
Abac/lS 10.4 The IBM Color Card
0000:0000
bit 7
bit 7 6 5 4 3 2 1 0
~I
11r,-;,11~11""';'''
Column 0 1 2 3 4 5 6 7 11111111'
Column 632 ••••••.••• 639
eGA registers
The eGA has a mode selection register at address 308H which is comparable with
the control register of the monochrome display adapter. You can write to this
register but not read it.
501
10. Accessing and Programming the Video Cards PC System Programming
7 6 5 4 3 2 1 0 bit
I r
I I I I J I 1- O.40x25 characters
1.80x25 characters
I O=text mode
1.graphlc mode (320x200)
O=color display
1=monochrome display
O.screenoff
1.graphlc mode (640x200)
O.brlght background
1=bllnklng background
unused
The status of bit 1 switches the eGA from text mode to the 32Ox200 bit-mapped
graphic mode. A 1 in this register selects graphic mode, while a 0 selects text
mode.
Bit 2 should be of interest to any users who want to operate their eGA with a
monochrome monitor. If this bit contains the value 1, the 6845 suppresses the
color signal, displaying monochrome mode only.
Bit 3 is responsible for creating screens. If it contains the value 0, the screen
remains black. This suppression is useful when changing between display modes;
it prevents sudden signals from reaching the monitor which could cause damage.
Bit 4 enables and disables 640x200 bitmapped graphic mode. A 1 in bit 4 enables
this mode, while a 0 disables iL
The various text or graphic modes and the color or monochrome display can be
selected in these modes with this register. Bits 0, 1, 2 and 4 are used for this. The
following table shows how these bits must be programmed to obtain certain
modes:
S02
The eGA also has a status register similar to the status register in the
monochrome display adapter. The following figure shows the conslIUction of this
register, which can be found at address 3DAH. It is a read-only register.
7 6 5 4 321
--r-,..........,.-...,
Obit
To avoid this problem, you should only access video RAM when the 6845 is not
accessing it. This only occurs when a horizontal synchronization signal travels to
the screen, because it requires a moment of time until the electron beam has carried
503
10. Accessing and Programming the Video Cards PC System Programming
"
out this instruction. For this reason, the status register must be read before every
video RAM access on a CGA. This process must be repeated until bit 0 contains
the value 1. When this happens, a maximum of two bytes can then be transmitted
to video RAM.
Demonstration program
The program at the end of this section demonstrates how this process functions.
This delay in video RAM access doesn't occur with monochrome cards because
they are equipped with special hardware logic and fast RAM chips. This is also
true of most of the newer model color cards. Before waiting for the horizontal
synchronization signal, which results in an enormous delay of the display output,
the user should try direct access to video RAM to test his color card's reaction
time.
If many accesses to video RAM occur within a short period of time (e.g., scrolling
the screen), the electron beam doesn't respond fast enough. The screen should be
switched off using bit 3 of the mode selection register. This prevents the 6845
from accessing video RAM, permitting unlimited user access to video RAM.
When data transfer ends, the screen can be switched on again. BIOS uses this
method during scrolling. which results in the flickering "silent movie effect."
Background color •
320x200 graphic mode,
border color In 40x25
text mode
L..._ _ _ _~ =Intenslve background
504
Abacus 10.4 The IBM Color Card
Bit 5 selects the color palette for 320x200 mode. If this bit contains the value I,
the first color palette (cyan, violet, white) is selected. A value of 0 selects the
second color palette (green, yellow, red).
Internal registers
The 18 internal registers of the 6845 on this card are accessed exactly like the
monochrome card. The only difference is that the index and the data register are
located at 3D4H and 3D5H. The following table shows the contents which the
register must have for various display modes.
No. Meaning Text 1 Text2 Graphics
0 Horiz. characters seeded 56 113 56
1 Horiz .. characters displayed «J III 40
2 Horiz. synchronization signal to 45 !ll 45
._. Characters
3 Horiz. synchronization signal 10 10 10
in characters
4 Vert. characters seeded 31 31 127
5 Vert. characters justified 6 6 6
6 Vert. characters displayed ;;S 25 100
7 Vert. synchronization signal to 28 28 112
_. characters
8 Interlace mode 2 2 2
9 Number of scan-lines per line 7 7 1
10 Starting line of blinkin<;L cursor 6 6 6
11 Ending line of blinking cursor 7 7 7
12 Display paqe starting address (high byte) 0 0 0
13 Display page starting address (low byte) 0 0 0
14 CUsrsor character address (high byte) 0 0 0
15 Cursor character address (low byte) 0 0 0
16 Reserved
17 Reserved
These registers are of interest to the user since they define the position and
appearance of the cursor on the screen. Sec#on ;10.1 described programming these
registers. The eGA adds registers 12 and13. They indicate the start of the video
page which must be displayed on the screen, as offset of the beginning of the 16K
RAM on the card (B800:0000), divided by 2. Register 12 contains the most
significant 8 bits of this offset, while register 13 contains lite least significant 8
bits. Normally both registers contain the value 0, displaying the frrst screen page
(beginning at the address B800:00(0) on the screen. For display of the first screen
page, which begins at location B800:1000 in the 8Ox25 text mode, the value
l000H divided by 2 (8ooH) must be entered in both registers.
The last of the three programs in this chapter accesses the color/graphics adapter.
The only significant difference between the two preceding programs lies in the fact
that the video controller can synchronize video RAM access and screen
construction. This is necessary on all video cards where direct access to video
RAM causes a flickering on the screen. The WAIT constant, defmed directly after
the program header, switches synchronization on or off. Its contents decide during
505
10. Accessing and Programming the Video Cards PC System Programming
the assembly of the program, whether to assemble the program lines for
synchronization listed in the source listing. These lines would slow down the
screen considerably, and should only be included if it is absolutely necessary.
endm
S06
endm
; - Stack - - - - - - - - - - - - - - - -
; - Data ---=----------------=------
data segment para 'DATA' ;Definition of data segment
str1 db 1,0
dw 17*160,18*160,19*160,20*160,21*160,22*160,23*160,24*160
graphict db 38h, 28h, 2Dh, OAh, 7Fh, 06h ;register values for the
db 64h, 70h, 02h, 01h, 06h, 07h ; graphic-modes
textt db ?lh, SOh, SAh, OAh, 1Fh, 06h ; register-values for the
db 19h, 1Ch, 02h, 07h, 06h, 07h ;graphic-modes
507
10. Accessing and Progromming tlu! Video Cards PC System Progromming
508
AbacllS 10.4 The IBM Color Card
text endp
grafhi endp
509
10. Accessing and Programming the Video Cards PC System Programming
graflo endp
veprog endp
;-- SETCOL Sets the color of the display frame and Background ----
;-- Input AL = color value
;-- OUtput none
; -- register AX and OX are changed
;-- Info in text mode the lowest 4 bits indicate the frame color
;- in graphic mode the lowest 4 bits indicate the frame
;-- and background color, bit 5 selects the color palette
;-- COEF sets the start and end line of the cursor -------------
;-- Input CL = start line
i-- CH = end line
;-- OUtput none
;-- register AX and OX are changed
cdef endp
510
Abacws 10.4 The IBM Color Card
;-- Info in the Graphic modes the first screen page has the
;-- number 0, the second the number 2
setpage endp
setblink endp
;-- SETVK sets a byte in one register of the video controller ---
;-- Input AL = Number of the register
j-- AH - new content of the register
;-- Output none
;-- register OX and AL are changed
setvk endp
j-- GETVK gets a byte from one register of the video controller
i-- Input AL = Number of the register
i-- Output AL - Contents of register
i-- register DX and AL are changed
getvk endp
SI1
512
AbaclLf 10.4 The IBM Color Card
scrollup endp
513
10. Accessing and Programming the Video Cards PC System Programming
scrolldn endp
;-- CLEAR: fills a designated display area with space characters -----
;-- Input AH - attribute/color
;-- BL - line upper left
;-- BH = column upper left
;-- DL ~ line below right
; -- DH = column below right
;-- BP = number of the screen page (0 to 3)
;-- Output none
; -- regi ster only FLAGS are changed
514
Abacus 10.4 The IBM Color Card
clear endp
515
10. Accessing and Programming tlu! Video Cards PC System Programming
print endp
;-- CALO: Converts line and column into offset address ---------------
;-- Input BL - line
;- BH - column
;-- BP - number of the screen page (0 to 3)
;-- Output 01 - the offset address
;-- register 01 and FLAGS are changed
calo endp
cgr endp
; - BX - column (0 to 319)
516
Abacus 10.4 The IBM Color Card
OUtput none
pixlo endp
; DX - line (0 to 199)
517
10. Accessing and Programming the Video Cards PC System Programming
splx endp
S18
The range of power of this new generation of video cards can be seen in their very
sharp resolutions and their ability to display almost any number of lines on the
screen. The EGA and VGA cards' greatest feature lies in their ability to emulate
other video cards.
We recommend that you avoid programming the hardware registers directly unless
you absolutely must do so. Many tasks can be delegated to the BIOS without
wasting much time. Not only will this keep your program code more compact and
easier to read, it will greatly improve the compaubility of your code with other
video cards. Among the tasks which the various functions of the BIOS video
interrupt can perform are:
Cursor positioning
Setting the size of the character matrix, and thereby the number of text
lines which can be displayed on the screen
Detailed information about traditional BIOS video functions and the new functions
of the EGA/VGA BIOS can be found in Sections 7.4.
519
10. Accessing and Programming the Video Cards PC System Programming
If you need speed and maximum control over the screen, you should still perform
time-critical actions (e.g., manipulating video RAM) "by hand."
Remember that the EGA or VGA card does not contain a 6845 CRTC, despite the
fact that it can perfectly emulate its video predecessors. This means that the status
and control registers of the MDA and eGA cards are unavailable. However, since
the settings that are normally made with these registers can also be performed with
the BIOS, we don't really need these registers. You should also remember that
there are no restrictions to accessing the video RAM of an EGA card or a VGA
card when it is in eGA emulation. It is unnecessary to synchronize screen access
with the activity of the CRTe by reading the status register.
The para1lels between the organization of the video RAM in the eGA and MDA
cards also apply when the text mode is switched to 43 lines (which is impossible
in eGA emulation). As with any other number of displayed lines, this does not
change the basic structure of the video RAM at all. It is larger, but the formulas
for calculating the offset position of a character and its attribute byte within the
video RAM are still valid.
The VGA card is capable of 25, 43 and even 50 lines in text mode, depending on
the monitor in use.
These parallels also apply to the graphics modes already available to the eGA card
The position of the video RAM and its structure are identical to the those of the
CGAcard
520
Abacus 10.5 EGA andVGA Cards
Some EGA cards have even more modes with higher resolution or more colors,
but these modes are not part of the EGA standard and are supported by only a few
programs.
These video modes, in which the video RAM can occupy more than lOOK, show a
structure quite different from those used by the MDA, eGA and Hercules cards.
The maximum of 256K of RAM is divided into four bitplanes which are arranged
in a kind of a three-dimensional organization. From the processor's point of view
these bitplanes reside between segment addresses AOOOH and BOOOH.
Each bitplane contains one bit for each individual pixel. If you place the bitplanes
on top of each other, each pixel is represented by a total of four bits, which
together make up the color value of the pixel. Bitplane zero contains bit zero of
the color value of each pixel, bitplane one contains bit one, and so on. This limits
the number of displayable colors to 16, since four bits (or bitplanes) can represent
~,or 16 different numbers.
The color value obtained from combining individual bitplanes does not correspond
directly to a color. It is actually used as an index into one of the 16 palette
registers of the EGA card, each of which designates a particular color. Since the
EGA card can display a total of 64 different colors, the palette registers allow you
to select 16 of these colors to be displayed on the screen simultaneously. The
individual palette registers can be loaded with the help of the extended EGA BIOS
functions, as described in Section 7.4.
The structure of each bitplane corresponds to the organization of the pixels on the
screen, and parallels that of video RAM in text mode. Since each pixel occupies
one bit in the bitplane, eight consecutive pixels are combined into a byte. The
pixels on each line are placed left to right in successive memory locations. The
length of each line can be determined using the fonnula:
horizontal_resolution / 8
521
10. Accessing and Programming the Video Cards PC System Programming
Since the individual screen lines follow each other in sequence starting from the
top of the screen, the starting address of each line is obtained by multiplying the
line number by this value. The byte within this line which contains the desired
pixel is calculated by dividing the column number by eight (bits per byte). Adding
this to the starting address of the line gives us the following formula, which
calculates the offset address of the byte containing the coordinates (X, Y):
Y * (horizontal_resolution / 8) + X / 8
X columns
AOOO:OOOO
Y lines
The bit number at which the pixel is located in this byte results from the
remainder of the division of the column number by eight:
7 - (column_number MOD 8)
These two formulas can be used to localize a pixel within a bitplane and
implement graphics primitives.
However, the bitplanes cannot be accessed individually because they all lie at the
identical segment address. The EGA card has four latch registers, each of which
contains a complete byte from one of the four bilplanes. When the CPU performs
a read access from the EGA video RAM at segment address AOOOH, one byte is
frrst read from each of the four bitplanes at the specified offset address and loaded
into the four latch registers. This applies to instructions which access memory
522
AbacIU 10.5 EGAandVGACards
directly, such as MOY or LODS, as well as all insttuctions in which a byte from
the video RAM appears as an operand. This can be the case with arithmetic
insttuctions (ADD, SUB, OR, AND, etc.) and comparison instructions (CMP,
CMPS).
The process is similar for writing bytes to the video RAM. In this situation the
contents of the four latch registers are written back to the four bitpJanes.
bits 01234567
.. CPU
n
J
read
access LATCHES
BITPLANES
bitStO~1~~23§4~5~6~7~~~~~~~~~~~~~~~lIn
cPu~ }
write v _
access LATCHES
BITPLANES
Since the latch registers are not directly accessible to the processor, we must
alternate conversion between eight and 32 bits when reading and writing the video
RAM. When reading, 32 bits from the latch registers must be compressed into one
byte, while the eight bits from the CPU when writing must be divided among the
32 bits of the latch registers. The nine graphic controller registers in the EGA card
perform this conversion.
523
10. Accessing and Programming tlul Video Cards PC System Programming
The contents of register number five, the mode register, are responsible for the
behavior of the video RAM. This register controls the current read and write
modes and thereby the manner in which the data from the latch registers is
combined with the other registers in the graphics controller and the CPU data.
7 6 S 4 3 2 1 0 bit
--.---,
Write mode
Possible modes:
0, 1 and 2
Read mode
' - - - - - -.... Posslble modes:
o and 1
Mode register structure in EGA card graphics controller
There are a total of two different read modes and three write modes.
524
Abacus 10.5 EGA and VGA Cards
Read mode 0
Read mode 0 is the simpler of the two read modes. As usual, a read access in this
mode first loads the specified byte from the four bitplanes into the four latch
registers. Then the contents of the latch register specified by the lower two bits of
the read map select register (register four) are tramferred to the CPU.
bits
CPU 2
0
1
3 5
:0:
7
- ,
r ead 3 0 r
aecess LATCHES
BITPLANES
XXXXXX 00
"
Read Map
Select Register
Video RAM read access in read mode 0
The following sequence of assembly language instructions fmt sets read mode 0,
then writes the value 2 into the Read Map Select register, and fmally reads a byte
from offset address 0003H in the video RAM. As a result, the AL register contains
the bit values for the pixels with coordinates (24, 0) to (31, 0) from bitplane 2.
mov dx,3CEh ;port address of the graphics oont. addr. reg.
mov aX,0005h ;write read mode 0 in the mode register
out dX,ax
mov aX,0204h ;write the value 2 (plane number) in the
out dx,ax ;read map select register
mov aX,OAOOOh ;segment address of the video RAM
mov ds,ax ;to DS
mov si,0003h ;offset address into the video RAM
lodsb ;read byte from plane 2
Read mode 1
Read mode 1 specifies which of the eight pixels in the specified byte of video
RAM is set to a certain color. This is determined by the individual bits in the read
byte which correspond to the one of the eight pixels from the specified byte in the
video RAM. If a pixel has the specified color (appropriate bit map), then the
corresponding bit will be I, else O. The bit pattern of the color to be compared
must be loaded into the lower four bits of the Color Compare register. The lower
four bits of the Color Don't Care register show which bitplanes will be taken into
consideration in the comparison. The value 1 includes the given plane in the
comparison, while the value 0 excludes it.
S2S
10. Accessing IJ1Id Programming tlu! Vicko Cards PC System Programming
BITPLANES
t3
tP
~--------------~ ~
1111
Color don't care
register
11
o
Color Compare
Register
To CPU~
526
Abacus 10.5 EGA andVGA Cards
Write mode 0
Writing to the video RAM in write mode 0 results in a number of operations, all
of which depend on the contents of several registers. The contents of the Bit Mask
register determine whether the value of a bit in the four latch registers will be
written unchanged to the found bitplanes or whether it will first be modified. The
individual bits in the Bit Mask register correspond to the individual bits in the four
latch registers. If a bit in the Bit Mask register is 0, the corresponding bits in the
latch registers will be written to the bitplanes unchanged. If this bit is I, a
modification will take place, dependent on the contents of the Function Select
register. As the following figure shows, the bits can be replaced or modified with
the logical operations AND, OR, and XOR.
1 6 5 4 3 2 1 Obit
-....,-
The contents of the Enable Set/Reset register determines from where the other
operand in these operations will come. If the lower four bits contain the value I,
the other operand will come from the lower four bits of the Set/Reset register.
Each of these bits is then combined with the bits from the latch registers as
described by the contents of the Function Select register. All of the bits to be
modified from latch register 0 will then be operated on with bit 0 of the Set/Reset
register. In the same manner, all of the bits to be modified from latch registers I,
2, and 3 are combined with bits 1,2, and 3 of the Set/Reset register, respectively.
The byte which is actually written to the graphics controller becomes irrelevant at
this point-the write access is reduced to a trigger, which cannot have any direct
influence on the contents of the latch register (and therefore the bitplanes).
527
10. Accessing and Programming the Video Cards PC System Programming
Bl.tmaskRJj[[I
1(j(J(jo
I
set/AeoeI: l1!Cj!.st.e<"
. Latch to
D
.. :
Latch
" :
n
" i"
~
Latch t2
Oi ~
W
Latch .3
& l~ :]
liD
J
lD-<:R caacarison
E\rdJm
sela::t
ra#er
The following assembly language fragment assigns the pixels at coordinates (5, 0)
and (7, 0), found at offset address OOOOH in the video RAM, the color 1011 (b).
Since we don't want to change the color of the other pixels, the contents of the
byte are flfSt read into the latch register with a read access to the video RAM. It is
not important which read mode is active because the byte transmitted to the CPU
is irrelevant; all we are interested in is loading the latch register. Since only bits 0
(coordinates (7,0» and 2 (coordinates (5, 0» will be changed, we load the value
00000101b (05h) into the bitmask register. In the Function Select register we
write the value 0 because we want to replace bits 0 and 2 with a new bit
combination. We write the color we want to give to the two bits (1OIIb = OBh) in
the Set/Reset register. We must also write the value I 111(b) (OFH) to the Enable
Set/Reset register of the graphics controller so that the color value will be taken
from the Set/Reset register. We can then execute the write access to video RAM.
mov ax,OAOOOh ;segment address of the video RAM
out dx,ax
out dx,ax
out dx,ax
out dx,ax
Things are different when the Enable Set/Reset register contains the value zero. In
this case all of the bits to be modified from the four latch registers are combined
with the CPU byte latch by latch. Here again the type of operation perfonned
528
Abacus 10.5 EGA and VGA Cards
depends on the contents of the Function Select register. For example, if the OR
operation is selected and bits 1,2,4, and 6 are to be modified, than these bits of
all four latch registers will be individually ORed with bits 1,2,4, and 6 in the
CPU byte.
Latch to Latch i1 Latch t2 Latch #3
mifl~~'~;~M~i~J~~~Jlt~J'~p~U~~r-~~~ll~U~~~·~~~.~~
HJ HH
Write mode 1
Write mode 1 is quite simple compared to the complex operations of write mode O.
The contents of the registers and the CPU byte are irrelevant because the contents
of the four latch registers are loaded unchanged into the specified offset address
within the four bitplanes. This is useful for copying the color values of eight
successive pixels to eight other pixels, for instance. The byte containing the eight
pixels can be read under one of the read modes, placing it in the latch registers.
Then a write access can be made to the byte in video RAM to which you want to
copy the color values. The graphics controller will automatically copy the contents
of the latch registers to the specified position within the four bitplanes.
To write these color values to other locations, you can use additional write
accesses. No more read accesses are necessary, since the latch registers already
contain the appropriate values and their contents are not changed by the write
access.
Write mode 2
529
10. Accessing and Programming the Video Cards PC System Programming
latch registers, independent of the Enable Set/Reset register. Bit zero of the CPU
byte is combined with all bits in latch register zero which are to be modified. The
same applies for CPU bits 1,2, and 3, which are combined with the bits of latch
registers 1,2, and 3, respectively.
Latch to Latch t1 Latch t2 Latch t3
Bibmsl<.
ICJaOOCi ... : ~
M·j ... :r~ . .1,,-.1.
0: 1 r~ '" .~ o! '" : ]
I
I
~ll
CPU l!r1:e
II °lll W It
1O-<:R Ca'rIlarison
-
IJ<lJ<lJ
F\n:t.Im
register
10 (l){1
This mode is good for setting the colors of individual pixels, as we demonstrated
in the example in write mode O. In contrast to write mode 0, the assembly
language fragment is somewhat shorter because neither the Enable SetIReset nor
the Set/R.eset register has to be programmed. Here is the same example using write
mode 2:
mov aX,OAOOOh ;segment address of the video RAM
mov ds,ax ;in DS
xor
mov
bx,bx
aI, [bx]
;load offset address
;load byte ° °
in the latch registers
mov dx,3CEh ;port address of the graphics cont. addr. reg.
mov aX,020Sh ;read mode 0, write mode 2
out dx,ax ;write into the mode register
mov ax,0003h ;write REPLACE mode (0) in the Function
out dx,ax ;Select register
mov ax,OS08h ;write the bit mask to the bitmask register
out dX,ax
mov al,OBh ;new color value in AL
mov [bx] , al ;and from there to the video RAM and
;into the latch regs and bitplanes
Demonstration program
The following program demonstrates the following basic graphics routines:
SJO
If you have followed this section closely, especially the material on the read and
write modes, you won't have any problems following the logic of the various
functions. Since it contains detailed documentation, we won't say anything more
aboutiL
It should be noted that the program is intended for demonstration purposes only.
You can develop it further if you want to make a graphics library out of these
functions. For example, the function PIXPTR loads the segment address of the
video RAM into the ES register for calculating the position of a pixel within the
video RAM each time it is called. This can be eliminated by loading this address
into the register once at the beginning of the program and leaving it there, as long
as the other functions do not change this register.
The graphics controller register programming can also be improved. Here the
various registers are reloaded with the ROM-BIOS default values after the function
has completed. This can be eliminated as long as you do not use the BIOS
functions for character output (in the graphics mode) or the functions for setting
and testing points within the module or program. If you avoid these calls, then
these registers can be reset to their default values once at the end of the program
instead of at the end of each routine.
Assembler listing: VEGA.ASM
;*******************************.**************************************:
;* VEGA *:
:*--------------------------------------------------------------------*:
;* Task : Creates elementary functions for accessinq the *;
;* qraphic modes on an EGA/VGA card *;
:*--------------------------------------------------------------------*:
;* Author : MICHAEL TISCHER *;
;* Developed on : 10/3/1988 *;
;* Last update : 6/19/1989 *;
:*--------------------------------------------------------------------*:
;* Assembly : MASH VEGA; *;
;* LINK VEGA; *;
:*--------------------------------------------------------------------*;
;* Call : VEGA *;
;**********************************************************************;
531
10. Accessing and Programming the Video Cards PC System Programming
; == Stack ----==~==--------------------------------=--
stack segment para stack ;Definition of stack segment
532
Abac/U 105 EGA and VGA Cards
demo endp
533
10. Accessing and Programming the Video Cards PC System Programming
shr bx,l
i-- SETPIX: Sets a graphic pixel in the new EGA/VGA graphic modes -----
i-- Input AX - graphic line
i-- BX - graphic column
i-- CH - pixel color
;-- OUtput none
;-- Registers: ES, DX and CL are changed
534
Abacus 105 EGA andVGA Cards
pop ax ,
setpix endp
;-- GETPIX: Places a pixel's color in one of the new EGA/VGA ----------
;-- graphic modes
;-- Input AX - graphic line
;-- BX = graphic column
;-- Output CH - graphic pixel color
;-- Registers: ES, OX , ex and 01 are changed
getpix endp
;-- FILLSCR: Sets all screen pixels to one color ------ ---------------
;-- Input AX = number of graphic lines on the screen
;-- CH - pixel color
;-- Output none
;-- Registers: ES, AX, CX, 01, OX and BL are changed
535
10. Accessing and Programming the Video Cards PC System Programming
536
Abacus 10.6 Determining tlu! Video Card Type
Remember that the PC can have both a monochrome video card (MOA, HOC or
EGA with a monochrome monitor) and a color video card (EGA, VGA, or CGA)
installed, although only one of the two cards may be active at one time.
All of the tests described here are found at the end of this section in the fonn of
two assembly language programs intended for use with C and Pascal programs.
The functions place the type of video card installed and the type of monitor
connected to it into an array to which the function is passed a pointer. If two video
cards are installed, their order in the array indicates which one is active.
CGAcards
HGCcards
537
10. Accessing and Programming the Video Cards PC System Programming
EGA cards
VGAcards
Since the assembly language routine checks selectively for the existence of a
certain video card, there is a separate subroutine for each type of video card. It bears
the name of the video card for which it tests. These routines have names like
TEST_EGA, TEST_VGA, etc. The tests could be called sequentially, but certain
tests can be excluded if we know they would return a negative result This is case
for the eGA test, for example, if an EGA or VGA card has already been detected
and is connected to a high-resolution color monitor. A eGA card cannot be
installed alongside such a card, so there is no point in testing for it.
There is a flag for each test which determines whether or not the test will be
performed. Before the ftrst test, the VGA test, all of the flags are set to 1 so that
all of the tests will be performed in order. During the testing, certain flags can be
set to 0 for reasons mentioned above, and the corresponding tests will not be made.
VGA test
The tests begin with the VGA test. It is very easy because there is a special
function in the VGA BIOS, sub-function OOH of function IAH, which returns
precisely the information that the assembly language routine needs. The
information is available only if a VGA card and hence a VGA BIOS is installed.
This is the case if the value lAH is found in the AL register after the call. If the
test routine encounters a different value there, the VGA test will be terminated and
the other tests will be performed. This indicates that a VGA card is lli21 installed.
After this function is called, the BL register contains a special device code for the
active video card and the BH register contains a code for the inactive card. The
following codes can occur:
Code MeaniJ!C.i
OOH No video card
OlH MDA card/monochrome monitor
02H CGA card/color monitor
03H Reserved
04H EGA card/h~h-resolution monitor
OSH EGA card/monochrome monitor
06H Reserved
07H VGA card/analog monochrome monitor
OSH VGA card/analo~color monitor
These codes are separated into values for the video card and the monitor connected
to it, and loaded into the array whose address is passed to the assembly language
routine. Since this routine already has information about both video cards, the
following tests do not have to be performed. The routine executes the monochrome
test, however, if the functions discover a monochrome card, since it cannot
distinguish between an MDA and HOC card.
538
Abacus 10.6 De~rmi1ling the Video Card Type
EGA test
After the VGA test comes the EGA test, which it performed only if the VGA test
was unsuccessful, and thus the EGA flag was not cleared. It uses a function which
is found only in the EGA BIOS: sub-function 10H of function 12H. If no EGA
card is installed and this function is not available, the value lOH will still be found
in the BL register after the function call. In this case the EGA test ends.
If an EGA card is installed, the CL register will contain the settings of the DIP
switches on the EGA card after the call. These switches indicate what type of
monitor is connected. They are converted to the monitor codes the assembly
language routine uses and placed in the array along with the code for the EGA card.
The CGA or monochrome test flag is cleared depending on the type of monitor
connected. The EGA routine ends.
CGA test
If the CGA flag has not been cleared by the previous tests, the CGA test follows
the EGA test. As with the monochrome test, there are no special BIOS functions
which can be used and we have to check for the presence of the appropriate
hardware. In both routines this is done by calling the routine TEST_6845, which
tests to see if the 6845 video controller found on these cards is at the specified port
address. On a CGA card this is port address 3D4H, which is passed to the routine
TEST_6845.
The only way to test the existence of the CRTC at a given port address is to write
some value (other than 0) to one of the CRTC registers and then read it back
immediately. If the value read matches the value written, then the CRTC and thus
the video card are present. But before writing a value into a CRTC register, we
should stop to consider that these registers have a major impact on the
construction of the video signals and careless access to them can not only
thoroughly confuse the CRTC, it can even harm the monitor. Registers 0 to 9 are
out of the question for this test, leaving us with registers 10 to 15, all of which
have an effect on the screen contents. The best we can do is registers 10 and 11,
which control the starting and ending lines of.the cursor.
'The assembly language routine fIrst reads the contents of register 10 before it loads
any value into this register. After a short pause so that the CRTC can react to the
output, the contents of this register are read back. Before the value read is compared
to the original value, the old value is fIrSt written back into the register so that the
test disturbs the screen as little as possible. If the comparison is positive, then a
CRTC is present and so is the video card (eGA in this case). The CGA routine
responds by loading the code for a color monitor into the array, since this is the
only type of monitor which can be used with a CGA card.
539
10. Accessing and Programming the Video Cards PC System Programming
Monochrome test
The last test is the monochrome test, which also checks for the existence of a
CRTC, this time at port address 3B4H. If it fmds a CRTC there, then a
monochrome card is installed and we have to figure out if it is an MDA or HOC
hard. The status registers of the two cards, at port address 3BAH, are used to
determine this. While bit 7 of this register has no significance on the MDA card
and its value is thus undefined, it contains a 1 on an HOC card whenever the
electron beam is returning across the screen. Since this is not permanent and
occurs only at intervals of about two milliseconds, the contents of this bit
constantly alternates between 0 and 1.
Hercules
The test routine frrst reads the contents of this register and masks out bits 0 to 6.
The resulting value is used in a maximum of 32768 loop passes, where the value
is read again and compared with the original value. If the value changes. meaning
that the state of bit 7 changes, then an HOC card is probably installed. If this bit
does not change over the course of 32768 loop passes, then an MDA card is in
use.
Here again we place the appropriate code for the video card in the array. The
monitor code is also set to monochrome, since this is the only monitor which can
be connected to an MDA or HOC card.
In other cases we can determine the active video card from the current video mode.
which can be read with the help of function OFH of the BIOS video interrupt. If
the value seven is returned, then the 80x25 text mode of the monochrome card is
active. All of the other modes indicate that a CGA. EGA. or VGA card is active.
This information is used to exchange the order of the two entries in the array if it
does not match the actual situation.
Here we include C and Pascal programs which call the function GetVIOS from the
assembly language module. and demonstrate how GetVIOS works.
540
AbaclLf 10.6 Ddermining tile Video Card Type
C listing: VIOSC.C
1***************************************************** *****************/
1* vI 0 S C *1
1*--------------------------------------------------------------------*1
1* Task : Determines the type of video card and monitor *1
1* installed in the system. *I
1*--------------------------------------------------------------------*1
1* Author MICHAEL TISCHER *1
1* Developed on : 10/02/1988 *1
1* Last update : 06/20/1988 *1
1*--------------------------------------------------------------------*1
1* (MICROSOFT C) *I
1* Creation CL lAS Ic VIOSC.C *1
1* LINK VIOSC VIOSCA *1
1* Call VIOSC *1
1*--------------------------------------------------------------------*1
1* (BORLAND TURBO C) *1
1* Creation Create project file made of the following: *1
1* VJOSC *1
1* VIOSCA.OBJ *1
1* Info Some cards may return errors or "unknown" *1
/**** •••••••••••••••• *** ••• *** •••••••••• ****••••••••••••••••••••••••• **/
void mainO
"VGA- ,
-EGA-,
541
10. Accessing and Programming the Video Cards PC System Programming
"MOA",
"HGC",
"CGA"
};
;Monitor constants
NO_MON 0 ;No monitor
MONO - 1 ;Monochrome monitor
COLOR 2 ;Color monitor
EGA HIRES 3 ;High-resolution or multisync monitor
ANLG MONO - 4 ;Analog monochrome monitor
ANLG COLOR - 5 ;Analog color monitor
542
Abacus 10.6 Determining the Video Card Type
;-- Conversion table for EGA card DIP switch settings ------
DATA ends
;----------------------------------------------------------------------
;-- GET VIOS: Determines types of installed video cards ---------------
543
10. Accessing and Programming the Video Cards PC System Programming
_get_vios endp
;-------------------------------------~---------------------------------
;-- TEST_VGA: Determines whether a VGA card is installed
544
Abacus 10.6 Determining the Video Card Type
endp
;----------------------------------------------------------------------
;-- TEST_EGA: Determines whether an EGA card is installed
proc near
;----------------------------------------------------------------------
;-- TEST_CGA: Determines whether a CGA card is installed
proc near
S4S
10. Accessing and ProgrQII'IIPUng the Video Cards PC System Progrl111l1lling
;----------------------------------------------------------------------
i-- TEST_MONO: Checks for the existence of an MDA or HGC card
;----------------------------------------------------------------------
i-- TEST_6845: Sets carry flag if no 6845 exists in port address of OX
546
Abacus 10.6 Determining the Video Card Type
;----------------------------------------------------------------------
; - FOOND_IT: Transfers video card type to AL and monitor type to
found it endp
;----------------------------------------------------------------------
text ends ;End of code segment
program VIOSP;
NO_MaN 0; { No monitor
MONO "'" 1; Monochrome monitor
COLOR 2; { Color monitor
EGA HIRES 3; High-resolution monitor
ANLG_MONO 4; Monochrome analog monitor
ANLG_COLOR = 5; { Color analog monitor
547
10. Accessing and Programming the Video Cards PC System Programming
(****************************** •• **************************************}
(* PrintSys: Gives information about a video system *)
(* Input - VCARD: Code number of the video card */
(* - MON : Code number of the attached monitor */
I * Output none */
{*****************************************.****************************}
begin
write (' ');
case VCard of
NO_VIOS : write('Unknown'); ( For ·other" code /
CGA write('CGA');
HGC write('HGC');
end;
write (' card/ ');
case Mon of
NO MON write ('unknown monitor'); I For ·other" monitors /
MONO writeln('monochrome monitor');
COLOR writeln('color monitor');
EGA HIRES writeln('high-resolution monitor');
ANLG_MONO writeln('monochrome analog monitor');
ANLG_COLOR writeln('color analog monitor');
end;
end;
begin
GetVios( @VidSys ); ( Check installed video card /
writeln ('VIOSP (c) 1988 by MICHAEL TISCHER');
write ('Primary video system: ');
PrintSys( VidSys[l].VCard, VidSys[l].Monitor );
writeln('13flO);
if VidSys[2].VCard <> NO VIOS then Second video system installed?
begin - I YES
write('Secondary video system:');
PrintSys( VidSys[2] .VCard, VidSys[2].Monitor );
writeln(.13.10);
endi
end.
548
Abacus 10.6 Determining the Video Card Type
;Monitor constants
NO MON - 0 ;No monitor/unrecognized code
MONO - 1 ;Monochrome monitor
COLOR ~ 2 ;Color Monitor
EGA_HIRES - 3 ;High-resolution/multisync monitor
ANLG MONO - 4 ;Monochrorne analog monitor
ANLG:::COLOR - 5 ;Analog color monitor
DATA ends
public getvios
;-- Initialized global variables must be placed in the code segment ---
;----------------------------------------------------------------------
;-- GETVIOS: Determines type(sl of installed video card(s) ------------
Pascal call : GetVios ( vp : Viosptr I; external;
;-- Declaration : Type Vios - record VCard, Monitor: byte;
;-- Return Value: None
549
10. Accessing and Programming the Video Cards PC System Programming
550
Abac/lS 10.6 Determining the Video Card Type
;----------------------------------------------------------------------
;-- TEST_VGA: Determines whether a VGA card is installed
proc near
; Return to caller
;----------------------------------------------------------------------
;-- TEST_EGA: Determine whether an EGA card is installed
551
10. Accessing and Programming 1M Video Cards PC System Programming
;Back to caller
;----------------------------------------------------------------------
;-- TEST_CGA: Determines whether a CGA card is installed
i----------------------------------------------------------------------
;-- TEST_MONO: Checks for MDA or HGC card
i----------------------------------------------------------------------
;--'TEST_6845: Returns set carry flag if 6845 doesn't lie in the
552
AbacllS 10.6 Determining tlu! Video Card Type
;----------------------------------------------------------------------
;-- FOUND_IT: Transfers type of video card to AL and type of
;-- monitor in AH in the video vector
found_it endp
;----------------------------------------------------------------------
code ends ;End of code segment
end ; End of program
553
10. Accessing and Programming the Video Cards PC System Programming
The demonstration programs below implement direct video RAM access routines
which display a string on the screen. Althrough there are some major differences
between the three programs as a result of the differences between the respective
languages (BASIC, Pascal and C), all three programs contain the same elements.
Initialization
Each program includes an initialization routine which determines the segment
address of the video RAM. The routine has a variable which contains the address of
the CRTC address register. There is a direct relationship between the video RAM
and this address register: just as this register is always at port address 3B4H, the
video RAM on a monochrome card is always found at segment address BOOOH.
This combination also applies to color cards, where the address register is at port
address 3D4H and the video RAM is at segment address B800H. If we know the
port address of the CRTC address register, we can determine the segment address of
the video RAM. Once we have determined this address, we can place it in a global
variable and execute the initialization routine.
Output
All three programs have an output routine which uses the segment address we
determined above. Each time the routine displays something, it determines the
starting address of the video page currently displayed on the screen. This ensures
that the output appears on the visible screen, and not on an undisplayed video
page. We can find this from the CRT_START BIOS variable. This variable is
located at address 0040:OO4E, and specifies the offset address of the displayed video
page relative to the video page found at offset address OOOOH.
After this address is determined, we can access the video RAM. The method used in
the program depends on the given programming language. Let's look at each
program in more detail.
The C implementation
From a programming point of view, this is the cleanest of the three
implementations because the video RAM can be treated as a normal variable in C.
We first define the structure VELB, which describes the ASCII/attribute pair as it
appears in the video RAM. We create a new data type, VP, to act as a pointer to
this structure. It is important that this pointer be of type FAR because these
554
Abacus 10.7 Accessing Video RAM from High Level Languages
structures are in the video RAM and therefore outside the C data segment. Smaller
memory models in C require the declaration of this pointer as a FAR pointer.
The DPRINT function loads the LPTR pointer with the address of the screen
output position passed to the routine. LPTR is fIrst loaded with the contents of the
global variable VPTR, and then with the offset address of the active video page, as
found in the CRT_START BIOS variable, LP1R must be cast as a BYTE pointer
because the contents of the BIOS variable refers to bytes, and not to VELB
structures. If the cast operator were missing, the C compiler would generate code
which would fIrst multiply the contents of the BIOS variable by the length of the
VELB structure before adding it, resulting in the wrong value.
We can now add the display position to this pointer. The output position is passed
to DPRINT as row and column coordinates. The video RAM is treated as an array
of 2000 components, each of which is a VELB structure. Since we have computed
the base address of the array in LP1R, all we need is to index into it. We multiply
the row coordinate by 80 (columns per line) and then add the column coordinate.
Finally we have a pointer to the output position in video RAM, which we can
treat like any other C pointer.
Each time through, the loop increments the pointer to the next VELB structure.
We write the ASCII code of the character and the color passed to DPRINT to the
specifIed address. This repeats until the program reaches the end of the string.
C listing: DVIC.C
/******.***** •• ***** •• ***** ••• ** ••• **** •••• ****.***.************** •••• */
1* D v I C *1
1*--------------------------------------------------------------------*1
1* Task : Demonstrates direct access to video RAM. *I
1*--------------------------------------------------------------------*1
1* Author : MICHAEL TISCHER *I
1* Developed on : 10101/1988 *1
1* Last update : 06/2111989 *I
1*--------------------------------------------------------------------*1
1* (MICROSOFT C) *1
1* Creation : CL lAS DVIC.C *1
1* Call : DVIC *I
1*--------------------------------------------------------------------*1
1* (BORLAND TURBO C) *1
1* Creat ion : RUN menu cOJliMnd (no project file needed) *I
/* •• *** •• **************************************.****** •• ***************/
'include <dos.h>
'include <stdlib.h>
'include <string.h>
'include <stdarg.h>
.include <bios.h>
555
10. Accessing and Programming the Video Cards PC System Programming
I;
/-!II<'. Macros _ _ _ _ _ _ _ _ _ _ _ _ _ _ */
/*-- The following constants return pointers to variables from the ---./
/*-- BIOS variable segment at segment address Ox40 ---./
556
Abacus 10.7 Accessing Video RAM from High Level LanglUlges
void init_dprint()
*.
/. * * * ** ** ** *•• * * * * ** •• * * * * ** **.* * * •• *•• * •• * * ** * ** **
Function : CL S
*. * * *'* * ** •• * **. ** * *
*
**--------------------------------------------------------------------**
Task Clears the screen with the help of DPRINT
*
Input parameters - COLOR - Character attribute
Return value None
******•• ********** ••• **********************.****************** •• *******/
J;
register BYTE i; 1* Loop counter *1
for (i-O; 1<24; ++i) 1* Execute each line *1
dprint(O, i, color, blankline); 1* Display blank line *1
557
10. Accessing and Programming the Video Cards PC System Programming
BOOL nokey ()
(
tifdef TURBOC /* Compiling this with TURBO C? */
return(biosk..y( 1 ) - 0 ); /* YES, read keyboard from BIOS */
'else /* Using Microsoft C */
return ( bios keybrd ( KEYBRD READY ) -- 0 ); /* Read from BIOS *1
.endit - - -
}
void main ()
(
BYTE first col, 1* Color of first square on the screen *1
color, 1* Color of current square *1
column, /* Current output position *1
lines;
{
if (++firstcol > WHITE) 1* Reached last color? *1
first co I = BWE; 1* YES, continue with blue *1
color = firstcol; 1* Set first color on the screen */
(
dprint( column, lines, color, -_");1* Block characters can */
dprint( column, lines+1, color, _ _");1* be created by press- *1
color = ++color & 15; 1* ing <Alt><2><1><9> */
}
Turbo Pascal offers the arrays MEMW and MEM for accessing memory which is
outside of the data segment of the Turbo Pascal program. The array MEM consists
of bytes and the array MEMW of words. The two arrays don't actually exist and are
just mapped to the address space, but that doesn't affect their usefulness.
We can write values into the array as well as read from it. This is done with the
following statement:
or
variable := MEMW[ segment address offset address 1
558
Abacus 10.7 Accessing Video RAM from High Level Languages
The MEM array might be easier to use for this particular application since we will
be alternating between ASCII characters and a constant attribute. However, the
output procedure DPrint uses the MEMW array instead, because 16-bit accesses are
performed faster than two successive 8-bit accesses on 16-bit machines.
When accessing the MEMW array, DPrint takes the segment address of the video
RAM from the variable VSeg, which is initialized at the start of the program in
the procedure InitDPrint. As described before, this is done by examining the BIOS
variable which contains the port address of the CRTC address register. This and the
other BIOS variables are declared using the ABSOLUTE keyword, allowing them
to be used in the program like any other global variables.
The offset within the MEMW array is computed from the starting address of the
screen page. The coordinates are passed to DPrint, in which the row coordinate is
multiplied by 160 and the column coordinate by two. When running through the
string to be printed, the memory offset is incremented by two on each pass,
moving it one ASCII/attribute pair to the right.
Pascal listing: DVIP.P
(*.* ••• ********** •• **************** •• *****•••• *.*.****•••••••• *********)
{* DVIP *)
{*--------------------------------------------------------------------*)
{* Task : Demonstrates direct access to video RAM from *)
{* Turbo Pascal *)
{*--------------------------------------------------------------------*)
{* Author : MICHAEL TISCHER *)
{* Developed on : 10/02/1987 *)
{* Last update : 06/20/1989 *)
{.****.** •••••• ****•••••• *** ••••••• ********** ••• *** •••••••••• **********}
program DVIP;
BLUE = $01;
GREEN - $02;
COBALTBWE = $03;
RED = $04;
VIOLET - $05;
BROWN = $06;
LIGHTGRAY = $07;
DARKGRAY - $01;
LIGHTBLUE = $09;
LIGHTGREEN - $OA;
LIGHTCOBALT - SOB;
LIGHTRED = SOC;
LIGHTVIOLET - $00;
YELLCM = $OE;
WHITE = $OF;
559
10. Accessing and Programming the Video Cards PC System Programming
procedure InitDPrint;
begin
if CRTC PORT - S3B4 then { Monochrome card connected?
VSeg :- S8000 { YES, video RAM at 8000:0000
else { NO, must be a color card
vSeg :- SB800; { video RAM at 8800:0000
end;
begin
Offset :- Lines * 160 + Column * 2 + PAGE ors;
Attribute :- Color shl 8; (High byte for word access to video RAM
i :- length { StrOut ); { Determine string length
for j :-1 to i do I Execute string
begin { Put character & attribute directly into video RAM
memw[VSeg:Offsetl :- Attribute or ord( StrOut[j] );
Offset :- Offset + 2; {Set offset to next ASCII/attribute pair
end;
end;
procedure demo;
begin
TextBackGround ( BLACK ); { Turn background black
ClrScr; [ Clear screen
DPrint( 22, 0, WHITE, 'DVIP - (c) 1988 by Michael Tischer');
Randomize; [ Enable random number generator
while not KeyPressed do { Repeat until user presses a key
begin
Column :- Random( 76 ); Select column, row and
Lines :~ Random( 22 ) + 1; color at random
Color :- Random( 14 ) + 1;
DPrint( Column, Lines, Color, '[[[[');( Block character can be
560
AbaclLf 10.7 Accessing Video RAM from Higla Level Languages
beqin
InitDPrint; Initialize output using DPrint
Demo; { Demonstrate DPrint
end.
This version doesn't really fulfill its goal, since it is slower than the already slow
PRINT command. But we have included it for the sake of completeness, and
because it is a good example of how you can access the entire address space of the
8088 from within BASIC,
The commands DEF SEG, PEEK, and POKE are the heart of memory access in
BASIC. DEF SEG sets the segment address of the "current" 64K segment. PEEK
and POKE can then be used to read and write bytes from or to this segment. This
technique is used in the initialization routine at line number 50000, which flrst
dermes the BIOS variable segment as the current segment From there two PEEK
commands read the port address of the CRTC address register and the variable VR
is loaded with the segment address of the video RAM.
This address is used in the output routine at line number 51000 in combination
with the DEF SEG command, which defines the video RAM as the current
segment But flrst we calculate the offset address in the video RAM by reading the
start address of the current screen page from the BIOS variable area and then adding
the offset address of the output position within the video RAM. As in the Pascal
version, this is calculated by adding the product of the row coordinate (variable
CLINE%) by 160 and the column coordinate (COLUMN%) by 2.
561
10. Accessing and Programming the Video Cards PC System Programming
562
Chapter 11
The AT has a battery operated realtime clock on the main circuit board. The clock
is part of the Motorola MC-146818 processor. This processor also contains 64
bytes of battery backup RAM. This RAM accepts clock data and system
configuration data. It can be accessed through port addresses 70H to 7FH.
However, only ports 70H and 7lH are of interest to the user.
Register Meaning
0 Current second
1 Alarm second
2 Current minute
3 Alarm minute
4 Current hour
5 Alarm hour
6 Day of the week
7 Number of day
8 Month
9 Year
10 Clock status reqister A
11 Clock status register B
12 Clock status register C
13 Clock status register D
Every time field (second, minute, hour) has a similar alarm field. These alarm
fields allow the programmer to set the clock to trigger an interrupt at a particular
time of the current day (more on this later).
563
11. Accessing and Programming the AT Realtime Clock PC System Programming
Weekday
The day of the week provides the number of the current weekday: The value I
represents Sunday, the value 2 stands for Monday, 3 for Tuesday, etc.
Year
The year is counted relative to the century (the system assumes 1900). The value
87 in this field represents the year 1987.
The ROM-BIOS set the two lower fields of these registers during the system boot
The interrupt frequency field has a default value of 011O(b). This value results in
an interrupt frequency of 1024 interrupts per second (an interrupt every 976,562
microseconds).
The contents of the time frequency field is 01O(b). This field triggers a time
frequency of 32,768 kiloHertz.
564
Abacus 11. Accessirag and Progrtlll'lnting the AT ReoltitM Clock
of its memory locations occurred. Either an OUT instruction then writes to port
71H or an IN insbUCtion reads the memory contents from port 71H.
TIle following instructions read or write a memory location in the realtime clock:
RBAD: WRI:rE:
mov aI, Memory_location mov aI, Memory_location
out 70h,al out 70h,al
in al,7lh mov aI, New_contents
out 7lh,al
Status register B
Some clock settings can be programmed through status register B. Bit 0 of status
register B controls daylight savings time status. When this bit is set to I, it
indicates that daylight savings time is in effect. A value of 0 (the default value for
this bit) shows that standard time is in effect.
Bit 1 decides whether the clock should operate in 12-hour or 24-hour mode. In 12
hour mode it switches after every 12 hours (midnight and noon) to 1 o'clock again.
The 24-hour mode switches to 1 o'clock after 24 hours. 24-hour mode is active
when you boot the system.
7 6 5 4 3 2 1 0 bit ~~~--:--~....,
III III III ~a~~~ht saving. time
11:no I
l 24-/12-hour format
O=12-hour
1=24-hour
ITlme ana aate torlNlt
O=BCD
h=blnary
IBi0ck generator
~~Off
=on
Call Interrupt atter
time actualization
O=no
1=ye.
Call alarm Interrupt
O=no
1=ye.
Call periodic Interrup
O=no
1=ye.
Actualize time
~--------------------~O=ye.
1=no
565
11. Accessing and Programming the AT Realtime Clock PC System Programming
Bit 2 defines the fonnat in which the time and date fields are stored. If this bit
contains a I, the various dates are stored in binary notation. The year (19)87 is
coded as 0101011 1(b) in BCD fonnat, which is switched on by the value 0 in bit
2. Two numbers are stored in every byte. The higher half is stored in the most
significant four bits and the lower half in the least significant four bits.
27 2 6 2 5 24 2 3 22 21 20 Bit value
76543210
Binary 10111011101111111
o +64+ 0 +16 + 0 + 4 + 2 + 1 = 87
2 3 22 21 2° 2 3 22 21 20 Bit value
7 6 5 4 3 2 1 °
(8*10) + 7 87
Nonnally this bit contains a 0 and the numbers are stored in BCD fonnat
Bit 4 detennines whether an interrupt should be called after the time (and date)
update. This bit must contain a 1 if an interrupt should be called. The system
suppresses this interrupt by setting this bit to 0 during the booting process.
Bit 5 can trigger an alann. The clock reads the alann time from locations 1, 3 and
5 (seconds, minutes and hours) of clock RAM. When the alann time is reached, an
interrupt executes when bit 5 is set to 1. The system suppresses this interrupt
when it sets bit 5 to 0 during the booting process.
Bit 6 controls periodic interrupt calls when it is set to 1. The frequency of the
interrupt calls depends on the interrupt frequency coded into bits 0-3 of status
register A. Since the default value on bootup is a frequency of 1,024 kiloHertz. the
interrupt triggers every 967,562 microseconds. Since bit 6 is set to 0 at the system
566
Abacus 11. Accus;,.g and ProgrQIItIf'U"ll tlte AT Remtime Clock
start. an application program must set it to I before periodic interrupt calls can
execute.
Bit 7 controls the periodic updating of the time and date. once every second. This
bit is set to 0 when you boot the system so that the time constantly increments.
Before entering a new date and time in the various memory locations. this bit
should be ftrSt set to I to prevent the clock from changing the time immediately.
Once you have entered all the data necessary. this bit can be reset and the time can
continue updating.
The routine uses status register C of the clock to determine the reason for the call.
Only bits 4,5 and 6 of this register are of interest to us here. They correspond to
the bits in status register B. For example, when you trigger the alarm interrupt
(which can only occur if bit 5 in status register B was set) then bit 5 in status
register C is also set to indicate that the alarm time has been reached.
7 6 5 4 3 2 1 Obit
Status register C
The fIrst task of the routine which intercepts interrupt 70H is to read status register
C. The routine then determines the reason for the itlterrupt call and reacts
accordingly.
567
11. Accessing and Programming the AT Realtime Clock PC System Programming
Status register D
Status register 0 only has one bit of interest: bit 7. It indicates the stallls of the
battery which maintains the storage of data, even when the PC's power supply is
turned off. If this bit has the value 0, you should replace the battery because the
present battery is dead or near death.
16 Disk descr-hEtion
17 reserved
18 Hard Disk description
19 reserved
20 Configuration
21 Low byte of the main memory in kilobytes
22 High byte of the main memory in kilobytes
23 Low byte of the additional memory in kilobytes
24 High ~te of the additional memory in kilobytes
25-45 reserved
46 High ~te of the checksum for memory locations 16-32
47 Low ~te of the checksum for memory locations 16-32
48 Low byte of the additional memory in kilobytes
49 High byte of the additional memo~ in kilobytes
50 the first two numbers of the centu~ as BCD number
51 Boot information
52-63 reserved
0-2 reserved
568
Abacus 11. Accessing arut Programming the AT Realtime Clock
The main program checks the battery on the clock. If there's power in the battery,
the program calls two routines which read the contents of the memory locations
for the current date and current time from the clock, among other things. This data
appears on the screen.
The main program doesn't access the routine for description of memory locations.
It should be easy to convert the program so that the routine for the description of
memory locations writes to the clock instead of reading date and time. This is just
a suggestion; feel free to experiment.
BASIC listing: RTC.BAS
100 ,** ••• *••• *****.******.**•• ** •• *.*****.** •••• ****.*•••• *****.*.***,
110 ••
120 R T C
1* _______________________________________________________________ .,
*.
569
11. Accessing and ProgrQJffllUng the AT Realtime Clock PC System Programming
240 PRINT· Information from the battery buffered real time clock •
250 PRINT·---~-- _ _ _ _ _ _ _•
260 PRINT
270 ADR% - 14 : GOSUB 50000 'read diagnostic-byte from the RTC
280 IF (CON% AND 128) - 0 THEN 310 'bit 8 - 1 --> battery o.k.
300 END
340 ADR% - 4 : GOSUB 52000 'read the hour and convert to decimal
360 ADR% - 2 : GOSUB 52000 'read the minutes and convert to decimal
380 ADR% - 0 : GOSUB 52000 'read the seconds and convert to decimal
410 ADR% - 6 : GOSUB 52000 'read day of week and convert to decimal
430 FOR I' - 1 TO CON' : READ DAYS: NEXT 'read name of the day
450 ADR' = 7 : GOSUB 52000 'read day of month and convert to decimal
510 PRINT
520 END
530 •
560 •
50000 ••• ****.**** ••••• *** ••••••** ••• **** •• * •••••• ******* •••• *** •• *••••
50010 •• read the content of a memory location of the RTC
50020 .*-------------------------------------------------------------*.
50030 •• Input: ADR\ - the number of the memory location (0 to 63) ••
50040 •• Output: CON' - the content of this storage location ••
50050 .•• ********.*** •• *****.*.*****.*.*** •••*.*.*.***•• ****.*.****.*.'
50060 •
50070 OUT &H70,ADR\ 'number of memory location to RTC-address-register
50080 CON' - INP(&H71) 'read Content from RTC-data-register
50090 RETURN •back to caller
50100 •
51000 ••• ** ••••••• ******* ••• ******* •• ****.** ••••• **** ••••••• **.**•••••.
51010 •• write a memory location in the RTC ••
51020
51030
51040
51050
'*-------------------------------------------------------------*'
••
Input:
•• Output: none
ADR' - the number of the memory location (0 to 63)
CON' - the new content of this memory location ..
*.
••
51060 ' ••••• ***** •••• *••••* •••• ***.* ••••••••• **** •••••*•• ************.1
51070 •
51080 OUT &H70,ADR' 'number of memory location to RTC-address-register
51090 OUT &H71,CON' 'write new content into RTC-data-register
51100 RETURN 'back to the caller
51110 •
52000 •• *** •• ** •• ** •••••••••••••• *.** •• *.****************.* ••• ********.
52010 •• read the content of a date or time memory location ••
52020 •• from the RTC and convert to decimal ••
52030 •• ----------------~-------------------------------------------*.
52040 •• Input : ADR' - the number of the memory location (0 to 63)
52050 .* Output: CON% - the new content of this memory location
52060 •• Info : ADR' is changed by this subroutine ••
52070 1* ••• ***.**** •• *.**.****.****.**•••• **.*****.********* •• ***.** •• 1
52080 •
52090 GOSUB 50000 'read content of the memory location
52100 BCD' - CON' •record content of the memory location
52110 ADR' = 11 'Address of the Status registers B of the RTC
52120 GOSUB 50000 •read its content
52130 IF (CON' AND 2) - 0 THEN 52150 ·test if BCD-mode
570
Abacus 11. Accessing and Programming the AT Realtime Clock
52140 BCD' - (BCD, AND 15) + INT(BCD' I 16) * 10 'convert BCD to decimal
52150 CON' = scot 'set return value
52160 RETURN 'back to caller
program RTCP;
MINUTE 2',
HOUR 4;
DAYOFWEEK 6;
DAY 7;
MONTH 8;
YEAR 9',
STATUSA = 10;
STATUSB - 11;
STATUSC 12;
STATUSD - 13;
DIAGNOSIS - 14;
YEARHUNDRED 50;
t***************************************************·*****************}
{* RTCREAD: reads the content of a memory location of the RTC *)
{* Input the address of the memory location in the RTC *)
{* Output the content of this memory location *)
{* Info if the Address is outside the permitted area *)
{* (0 to 63), the value -1 is returned *)
{***************************** •••• ************************************)
begin
if {Address < 0) or (Address > 63) { is the Address o.k.?
then RTCRead '= -1 { NO!
else
begin
port [RTCAdrPort] := Address; { transmit Address to the RTC
RTCRead := port [RTCOtaPort] { read its Content
end
end;
571
11. Accessing and Programming the AT Realtime Clock PC System Programming
begin
if (RTCRead(STATUSB) and 2 = 0) BCD- or Binary-Mode?
then RTCDT := RTCRead(Address) { is Binary-Mode
else ( is BCD-Mode
begin
Value ' RTCRead(Address); {get Content of the memory location
RTCDT (Value shr 4) * 10 + Value and lSI convert BCD to binary
end
end;
{*********************************************************************}
1* RTCWRITE: write a value into one of the memory locations of RTC *}
(* Input see below *)
(* Output none *)
1* Info the address can be between 0 to 63 *)
{**************************************** •• *************************.*}
begin
port [RTCAdrPort] := Address; { transmit address to the RTC
port [RTCDtaPort] '= Content I write new value
end;
{**************************************************************.******}
(* MAIN PROGRAM *)
{*********************************************************************}
begin
clrscr; ( Clear Screen )
writeln('=====--=======================--==========-==--======"13'10);
572
Abacus 11. Accessing and ProgrfJlMling the AT Realtime Clock
C listing: RTC.C
;** •••••••••• **** •••••• ***.**** •••••••**.**** •••• ** ••• *.*.******.* •• **/
/* R T C */
/*-------------------------------------------------------------------*/
/* Task : provides two Functions for reading and writing */
/* Data in the Real Time clock */
/*-------------------------------------------------------------------*/
/* Author MICHAEL TISCHER */
/* developed on : 8.15.87 */
/* last Update : 9.21.87 */
/*-------------------------------------------------------------------*/
/* (MICROSOFT C) */
/* Creation MSC RTCC; */
/* LINK RTCC; */
/* Call RTCC */
/*-------------------------------------------------------------------*/
/* (BORLAND TURBO C) */
/* Creation : Through the RUN command in the command line */
/****.*****.***** ••• ********* ••• ****.***** •• ** •• *************** ••• ****/
'define YEAR 9
• define STATUSA 10
'define STATUSB 11
'define STATUSC 12
'define STATUSD 13
'define DIAGNOSE 14
'define YEARHUNDRED 50
byte RTCRead(Address)
byte RTCDt(Address)
573
11. Accessing and Programming llu! AT Realtiml! Clock PC System Programming
{
if (RTCRead(STATUSB) & 2) /* BCD- or binary mode? */
return«RTCRead(Address) » 4) * 10 + (RTCRead(Address) & 15»;
else return(RTCRead(Address»; /* is binary mode */
}
void mainO
printf("===-====---=====$-======================----=========\n\n");
574
Chapter 12
Keyboard Programming
The keyboard is an independent umt ill the PC system, and has its own
microprocessor and memory. The processor informs the system when a key is
pressed or released. It does this by sending the system something called a scan code
when a key is pressed or released. In both cases the key is indicated by a code
which depends on the position of the key. These scan codes have nothing to do
with the ASCII or extended keyboard codes to which the system later converts the
keypresses.
Communication with the system is performed over two bidirectional lines using a
synchronous serial communications protocol. In addition to the actual data line
used to transfer the individual bits, the clock line synchronizes the periodic
transmission of signals. Transfers are made in one-byte increments, whereby a stop
bit is transmitted first (with the value 0), followed by the eight data bits,
beginning with the least significant bit. A parity bit, calculated using odd parity,
follows the eighth data bit. The transfer of a byte then concludes with a stop bit,
which forms the eleventh bit of the transfer. At both ends of the communications
line (Le., in the PC and in the keyboard itself) are devices which convert the
signals on the data line to bytes and back again.
Although all types of PCs use this form of communication, we must distinguish
between PCIXT and AT models. These systems use different processors as
keyboard controllers. The Intel 8048 used in the keyboards of Pes and XTs is a
relatively "dumb" device, which can only send the scan codes to the system.
However, the 8042 processor used in AT and 80386 keyboards can do much more.
Here the communication between the system and the keyboard becomes relatively
complex, and the system can even control parts of the keyboard.
575
12. Keybomd Programming PC System Programming
The input buffer can be written at port 60H as well as port 64H. The port which is
used depends on the type of information to be transferred. If the system wants to
send a command code to the keyboard, it must be sent to port 6OH, while the
corresponding data byte is sent to port 64H. Both end up in the keyboard input
buffer, but a flag in the status register indicates whether a command byte (port
64H) or a data byte (port 6OH) is involved.
In addition to this flag, bits 0 and 1 of the keyboard status register are especially
important for communication with the keyboard. Bit 0 indicates the status of the
output buffer. If this bit is I, then the output buffer of the keyboard contains
information which has not yet been read from port 6OH. Reading from this port
will automatically set this bit back to 0, indicating that there is no longer a
character in the output buffer.
Bit 1 of the stams register is always set whenever the system has placed a character
in the input buffer, before this character is processed by the keyboard. Nothing
should be written to the keyboard input buffer unless this bit is equal to 0,
signalling that the input buffer is empty.
7 6 5 4 3 2 Obit
I II II Itll11jl111 II 1
1 =
=Output buffer full
Input buffer full
Command/data
1= Output from port 64(h)
=
o Output from port 60(h)
1 = Keyboard active
1 = Time out error (output)
1 =lime out error (Input)
1 =Parity error
AT keyboard controller status registers
Of the various commands that a system can send to the keyboard, two are of
interest for applications programs because they also playa roll outside a keyboard
interrupt handler. The ftrst of these commands sets the typematic or repeat rate of
the keyboard. This is the number of make codes per second which the keyboard
will send to the system when a key is pressed and held down. It can be between
two and 30 codes per second. To prevent the keys from repeating unintentionally,
this repeat function does not begin until after a certain delay. This delay time can
be set by the user and is encoded in binary as follows:
576
Abacus 12. Keyboard Programming
The repeat rate, also called the typematic rate by IBM, is also encoded in binary.
The following table shows the relationship between the repeat (typematic) rate and
the number of repetitions per second.
This relationship may seem somewhat arbitrary at ftrst, but it does follow a
mathematical formula. The binary value of bits 0, 1, and 2 of the repeat rate form
variable A, and the binary value of bits 3 and 4 form variable B:
(8 + A) * 2B * 0.00417 * l/second
The delay and repeat rate values are combined into a byte by placing the ftve bits
of the repeat rate in front of the delay value. However, we can't just send this value
straight to the keyboard. We must ftrst send the appropriate command code (34H)
and then the repeat parameters. Both bytes must be sent to port 6OH, but we
cannot just send them with an OUT instruction. We have to use a transmission
protocol which includes reading the keyboard status, and which also accounts for
the possibility that the transfer might not work the frrst time. Since we have to do
this for both bytes, we should write a subroutine to do it. The structure of this
subroutine is shown in the following flowchart.
577
12. Keyboard Programming PC System Programming
578
Abacus 12. Keyboard ProgrtJ1ll1tling
We first load an error counter which allows the routine to try to send the byte three
times before an error is returned. Then the keyboard status port is read in a loop
until bit 0 is cleared and the input buffer of the keyboard is empty. Then we can
send the character to port 6OH. To make sure that the character got tht"A'e all right (a
parity error might have occurred, for example), the keyboard sends back a reply
code. This has been received when bit 1 of the ~yboard status port is set.
This register is again read from port 64H in a loop until this condition is met.
Now we can read the reply to our transmission from the keyboard data port. If it is
the code OFAH, which stands for "acknowledge," the transmission was successful.
Any other code indicates an error, which tells the subroutine to decrement the error
counter and repeat the whole process, provided the counter has not reached zero. In
this case the subroutine ends and signals an error to the caller.
Demonstration programs
To give you an example of how this works, the following pages contain programs
in BASIC, Pascal, and C which you can use to set the key repeat parameters on
your keyboard. The heart of these programs is an assembly language routine which
sends the parameters to the keyboard. Within this routine is the subroutine we just
discussed, which is first called to send the Set Typematic instruction to the
keyboard. Another call is used to send the parameters themselves.
In the Pascal and C versions, the key repeat rate and the delay values are specified
as separate parameters following the program name entered at the DOS prompt.
Naturally this is not possible in GW-BASIC, so the two parameters are read
within the program with the INPUT command.
We also included the listing of the assembly routines for the various programs.
The BASIC and Pascal programs include these with DATA or INLINE statements;
the linker links these statements to the C version of the program.
To see the effect of the key repeat rate, first try setting the smallest repeat rate (0)
and then the highest rate (30). Try pressing and holding a key at each of these
settings to see the results.
BASIC listing: TYPMB.BAS
100 ,******•••**************.**.******.******** ••••******.************••
110 • * T Y P MB *.
120 '*----------------------------------------------------------------*'
130 .* Description : Sets the key repeat rate of the AT keyboard. *.
150 • * Author : MICHAEL TISCHER ••
160 •• developed on : 09/08/1988 *.
170" last update : 09/08/1988
180 '.*•• **************.****** •• **********.*.*.************.*** •••••••••
190 •
200 CLS : KEY OFF
210 PRINT "Note: This program may be run only if GWBASIC has been started":
220 PRINT "from the DOS level·
230 PRINT "with the command <GWBASIC Im:60000> and the computer is an AT."
260 PRINT: PRINT·If this is not the case, then please enter <s> for Stop.·
280 PRINT ·Otherwise press any other key ••• ·;
579
12. Keyboard Programming PC System Programming
··
;*----------------------------------------------------------------------*;
;' Author MICHAEL TISCHER ;
;' developed on : 27.08.1988 ;
;' last update : 27.08.1988 ';
··
;*------------------------------------------------------------------------*;
;' to assemble MASM TYPMBP.; ;
;' LINK TYPMBP. ;
;' EXE2BIN TYPMBP. TYPMBP..BIN *;
;' ••. convert to DATA statements and insert in ';
;* a BASIC program *;
;**********************************************************************;
;=:z: Constants -========---====__ =~====~_===-=---
KB STATUS P equ 64h ;status port of the keyboard
-
KB DATA P
- equ 60h ;keyboard data port
580
Abacus 12. Keyboard Programming
org 100h
i----------------------------------------------------------------------
;-- SET_TYPH: Determines the key repeat rate to be sent to the -------
;-- keyboard controller
;-- Call CALL Adresse(TYPRATE', OK')
;-- Info If the key repeat rate can be set, the value will be
; -- placed in TYPRATE, else 0
;----------------------------------------------------------------------
;-- SEND KB: send a byte to the keyboard controller -------------------
;-- Input AH - the byte to be sent
;-- OUtput zero flag: O-error, 1-QK
;-- Registers: AX and the flag register are used
;-- Info this routine is intended for use only within this
;-- module
send kb proc near
581
12. Keyboard Programming PC System Programming
send kb endp
program TYPMP:
*'*'
{********************************************.*************************}
(* SetTypm: Sends the key repeat rate to the keyboard controller
{* Input RATE: the repeat rate to be set
(* Output TRUE, if the value was set, FALSE if an error occurred *'
{* accessing the controller *'
(* Info This function can be bound into a UNIT *'
{************************************************ •••••••••••••••••••••• }
begin
inl1ne {
582
Abacus 12. Keyboard Programming
$32/$D2/$B4/$F3/$FA/$ES/$13/$00/$75/$0A/$8A/$66/S06/SES/
SOB/SOO/S75/S02/SFE/SC2/$FB/S8S/S56/SFF/SEB/S27/S90/$51/
S53/SB3/S03/S33/SC9/$E4/$64/$AS/$02/SEO/SFA/S8A/SC4/$E6/
$60/$E4/$64/$A8/$01/$E1/$FA/$E4/$60/$3C/$FA/S74/$07/SFE/
SCB/S75/$E6/$SO/$CB/$01/$5B/$59/$C3
);
end;
{SF-I
{****************.**.******************.********** •••••• ***************}
{** MAIN PROGRAM **1
{**.*.************** •• *************** ••• *******.******.*******.****** •• }
begin
writeln('13'10, 'TYPMP - (c) 1988 by MICHAEL TISCHER');
ParErr :- true; I assume error in parameters
if ParamCount = 2 then { were 2 parameters passed?
begin { YES
val(Paramstr(I), Delay, FPos1); ( first parameter to integer
val(Paramstr(2), Speed, FPos2); { second parameter to integer
if «FPos1=0) and (FPos2=01) then { error in conversion?
if «Delay < 4) and (Speed <32» then ( no, value OK?
ParErr := false; I yes, then parameters are OK
end;
if ( ParErr ) then { are parameters OK?
begin { no
writeln(' 1 h;
1* Vertical line can be created using <Alt><179>; *1
writeln(' r 1.---1 r-------J.---------l');
1* Upper left corner can be created using <Alt><218>; *1
{* Horizontal line can be created using <Alt><196>: *1
1* Brace pointing 'up' can be created using <Alt><193>; *J
(* Upper right corner can be created using <Alt><191> *1
writeln(' 1 0: 1/4 second 1 1 0 : 30.0 rep./s. h;
writeln(' l-----------------J');
{* Lower left corner can be created using <Alt><192>; *1
{* Horizontal line can be created using <Alt><196>; *1
{* Lower right corner can be created using <Alt><217>; *J
end
583
12. Keyboard Programming PC System Programming
org 100h
;----------------------------------------------------------------------
Determines the key repeat rate to be sent to the
584
Abacus 12. Keyboard Programming
:----------------------------------------------------------------------
:-- send a byte to the keyboard controller -------------------
i-- Input AH = the byte to be sent
:-- OUtput zero flag: O-error, I-DK
Registers: AX and the flag register are used
:-- Info this routine is intended for use only within this
;-- module
send_kb endp
585
12. Keyboard Programming PC System Programming
;---------------------------------------------------------
ende label near
;-= End _ _ _ _ _ _ _ _ ~===__===z_==_ _ _ _ _ _ _ = _ = _ _...
end set_typn
C listing: TYPMC.C
/*********************************************************************./
1* T Y P M C *1
1*--------------------------------------------------------------------*1
1* Description : sets the key repeat rate on the AT keyboard *1
1* according to the preferences of the user. *1
1*--------------------------------------------------------------------*1
1* Author MICHAEL TISCHER *1
1* developed on : 08/28/1988 *1
1* last update : 08/28/1988 *1
1*--------------------------------------------------------------------*1
1* (MICROSOFT C) *1
1* creation CL lAS Ic TYPMC.C *1
1* LINK TYPMC TYPMCA; *1
1* call TYPMC *1
1*--------------------------------------------------------------------*1
1* (BORLAND TURBO C) *1
1* creation via project file with following contents: *1
1* TYPMC *1
1* TYPMCA.OBJ *1
,*****************************.*******.*******************************./
.include <stdlib.h>
extern bool set_typn( byte trate ); 1* sets the key repeat rate *1
/**** •••• ****.**** •••••••• *** •• *****••• *****.**.**.** ••• **** •••••*** ••• /
1** MAIN PROGRAM **1
/***.** ••• ** •••••** •• *** ••••••••••••••••• ** •••••••••••• ********•• ******/
586
Abacus 12. Keyboard Programming
587
12. Keyboard Programming PC System Programming
SSS segment word public 'SSS' ;this segment stores all of the
:::BSS ends ;uninitialized static variables
DATA segment word public 'DATA' ;all initialized global and static
;variables are stored in this segment
_DATA ends
;----------------------------------------------------------------------
;-- SET TYPM: sends the key repeat rate to the keyboard controller ----
bpO dw ;stores BP
_set_typ!\ endp
;----------------------------------------------------------------------
;-- SEND KB: send a byte to the keyboard controller -------------------
;-- Input All = the byte to be sent
588
Abacus 12. Keyboard Programming
send_kb endp
;------------------------------------------------------------------------
text ends ;end of the code segment
We can use this same method to tum the LEOs on the AT keyboard on and off.
The corresponding instruction code is number OEDH, and is called the Set/Reset
Mode Indicators instruction.
After this command code has been successfully transmitted, the keyboard waits for
a byte which reflects the status of the three LEDs. One bit in this byte stands for
one of the three LEOs, which is turned on when the corresponding bit is set.
Bit it LED
0 Scroll Lock
1 Num Lock
2 Caps Lock
589
12. Keyboard Programming PC System Programming
Setting and resetting these bits make sense only when the keyboard mode which
they indicate is enabled or disabled.
These modes are managed in the BIOS, not the keyboard. For example, the
keyboard doesn't automatically convert all of the letters to uppercase in Caps Lock
mode. The keyboard can only associate a key with a virtual key number, rather
than a specific character. This key number is then converted to an ASCII or
extended keyboard code by the BIOS. Naturally this also applies to the Caps Lock
key, which simply sends a scan code to the computer when it is pressed. The BIOS
assigns the Caps Lock function to this key by setting an internal flag which marks
this mode as active, then sends the Set/Reset Mode Indicators instruction to the
keyboard to light the appropriate LED.
Although these keyboard modes are normally enabled and disabled by the user
pressing the corresponding keys, it may be useful to set a mode from within a
program. This is the case for keyboards which have separate cursor keys and a
numerical keypad, for example. Since most keyboards can only enter numbers
when Num Lock mode is on, it makes sense to set this mode automatically when
the system is started.
To do this we just set the appropriate BIOS flag and then tum on the
corresponding LED on the keyboard to inform the user that this mode has been
activated.
In practice, a program just has to set the appropriate BIOS mode, since the BIOS
automatically controls the keyboard LEDs. Whenever one of the functions of the
BIOS keyboard interrupt is called. the BIOS checks to see if the status of the LEDs
matches the keyboard status, as indicated in an internal variable. If a discrepancy
arises, the BIOS automatically sets the LEDs to the status given in the keyboard
status flag.
Since the position of this flag in the BIOS variable segment and the meaning of
the individual bits is completely documented (see also Section 7.14), we can easily
change these modes.
The following programs in BASIC, Pascal, and C offer routines which can enable
or disable the individual modes. It should be noted that although PCs and XTs
have corresponding LEDs, these programs will not work or change the modes
without changing the status of the LEDs on a PC or XT keyboard. This is because
these keyboards are equipped with an 8048 processor, which does not offer the
ability to manage the LEDs. The fact that these LEDs do tum on and off according
to the modes has nothing to do with the BIOS, and is handled directly by the
keyboard.
590
Abacus 12. Keyboard Progrtullllling
220 PRINT "NOTE: This program can be run only if GWBASIC was started from"
230 PRINT "the DOS level with the command <GWBASIC /m:600000> and the"
250 PRINT
260 PRINT "If this is not the case, please enter <s> for STOP."
320 CLS
490 NEXT
560 NEXT
580 END
590 '
50000 ' •• **•• * ••••• ***** ••* •• ******** •••• *****.****.********.* ••••• *.*•.
50010 '* set one or more of the flags in the BIOS keyboard status
50020 ,*--------------------------------------------------------------*,
50030 Input FLAGS\ - the flags to be set *'
50040 '* Output: none *'
50050 '* Info : the variable Z% is used as'a dummy variable
50060 ,*.* •• *** ••• *•••• *** •• **************.****************************1
50070 '
50080 DEF SEG - &H40 'set BIOS variable segment
50090 POKE &H17, PEEK (&H17) OR FLAGS\ 'set the flags
50100 INTR% - &H16 'call BIOS keyboard interrupt
50110 AH\ - 1 'function 1: character ready?
50120 DEF SEG 'switch back to the GW segment
50130 CALL IA(INTR%,AH%,Z%,Z\,Z\,Z\,Z\,Z%,Z%,Z%,Z\,Z%,Z\)
50140 RETURN 'back to the caller
50150 '
51000 1**************** •• *.* ••••• * •• **.*.*** ••••• * •• ***************.***,
51010 '* clear one or more the flags in the BIOS keyboard status
51020 ,*--------------------------------------------------------------*,
591
12. Keyboard Programming PC System Programming
program LEOP;
592
Abacus 12. Keyboard Programmmg
begin
BiosTsByte :- BiosTSByte or Flag; mask out the corresponding bit
Regs.A11 :- 1; function no.: character ready?
intr ($16, Regs); { call BIOS keyboard interrupt
end;
{_._--*.......__.-_...................................... *_._........._}
{* CLRFLAG: clears one of the flags in the BIOS keyboard status byte *)
{* Input : the flag to be cleared (see constants) *1
{* Output : none
{ .... _............ _- ........... --- .....•••.•.• _...
..••...•••....•••.. _ *1
_}
begin
BiosTSByte :- BiosTSByte and ( not Flag ); { mask out bit
Regs.A11 :- 1; { function no.: character ready?
intr($16, Regs); { call BIOS keyboard interrupt
end;
{a_*._.__._._••_._•••••••••_._.__ ••••_.___._••••_._.__••__._._•••••••_.}
{* ••• _••••• _•• - ••••• _._.- •• _._._-._ ••••••••• _••••- ••• -._*_......_.__..-}
{** MAIN PROGRAM **1
begin
writeln('LEDP (c) 1988 by Michael Tischer');
writeln(f13,f10, 'Watch the LEOs on your keyboard!');
593
12. Keyboard Programming PC System Programming
C listing: LEDC.C
,.**...
1*
****.**** •• ****.***••• ** ••••••• ** •••
LED C
******.** •• ** •••••• ** •••• ***/
*1
1*--------------------------------------------------------------------*1
1* Description Sets the various bits in the BIOS keyboard *1
1* flag, causing the LEDs on the AT keyboard to *1
1* flash. *1
1*--------------------------------------------------------------------*1
f* Author MICHAEL TISCHER *f
1* developed on : 22.08.1988 *1
1* last update : 22.08.1988 *1
f*--------------------------------------------------------------------*1
1* (MICROSOFT C) *1
1* creation : CL lAS LEDC.C *1
f* call : LEDC *I
1*--------------------------------------------------------------------*1
f* (BORLAND TURBO C) *f
1* creation : via the command CCMPILE I MAKE *1
1*·-·_·_·····-··_·_····_·····__ ·_··_··-·_·_·_·_·_·__·- *.***••• *** •• ****,
1*-= Include files ==---==-=====-----=--==---====-=-------==---==---==-*1
'include <dos.h>
594
Abacus 12. Keyboard Programming
*BIOS KBF 1= flag; /* set the specified bits in the keyboard flag */
regs.h.ah - 1; /* ftn. no.: character present? */
int86 (Ox16, ®s, ®s); /* call BIOS keyboard interrupt */
1
/**.**.** ••• ****** ••• **** ••• ** •••••••• ***.***••••••• ***.*.****.*.***.***
* Function : CL R F LAG *
**--------------------------=-----------------------------------------**
* Description Clears individual bits or flags in the BIOS
keyboard flag.
*BIOS_KBF &= ~flag; /* mask out bits in the BIOS keyb. flag */
regs.h.ah - 1; /* ftn. no.: character present? */
intB6(Oxl6, ®s, ®s); /* call BIOS keyboard interrupt */
1
/******.*.***************.*.*************** •••• ***.*****.********.**.*.,
/*. MAIN PROGRAM *. /
, ••••••••••••••••• *** •••• *•••••••••••••••••••• *****.*********.**•• *****,
void mainO
{
unsigned i; /* loop counter·/
595
Chapter 13
Expanded Memory
Specification
When the mM PC was being developed in 1980 its capabilities were quite
advanced for its time. This was also true of the size of its main memory. The
maximum size of 640K seemed so large at the time that no one could imagine
what a user would do with so much memory. Thus the frrst PCs were equipped
with 64K, then 128K, and later 256K of memory. But today memory requirements
are much greater and the standard amount of RAM for PCs, and especially ATs,
has grown to the full 640K.
As we enter the age of the 80386 microprocessor, with the introduction of graphic
user interfaces and multitasking operating systems (Windows®, OS/2®), 640K
will soon no longer be enough to make full use of the capabilities of the PC. But
we have reached a boundary that cannot be crossed by just adding more memory
chips to the computer. A normal PC or XT is limited to 640K and an AT to 16
megabytes. The 16 meg is only available in the protected mode of the 80286
processor. and is inaccessible to normal DOS applications.
Adding memory
To provide a way around this problem. some leading PC fIrmS got together several
years ago and devised a way to add more memory to PCs, XTs and ATs that could
also be accessed under DOS. These companies were Lotus (the developers of Lotus
1-2-3), Intel (manufacturer of PC processors) and Microsoft (developers of MS
DOS and OS/2). They developed a standard known as the LIM standard. after the
frrst letters of the company names.
597
13. ExparuUd Memory Specification PC System Programming
memory which ranges beyond 1 megabyte on an AT. The whole system is referred
to as the expanded memory system, or EMS for short.
1 megabyte
FFFF
BIOS
Video RAM
16K pages
Working RAM
0000
There is always at least 64K in the 1 megabyte address space of the PC which is
not used for main memory, BIOS, video RAM, or other system expansions, so the
EMS developers decided to use this as a window into the EMS memory. Usually
this window is at segment address DOOOH, but the EMS hardware allows it to be
changed.
Since this window is under the 1 megabyte memory limit, it can be accessed with
normal assembly language instructions, similar to the way the video RAM is
accessed. Both read and write accesses are possible. We will look at concrete
examples of these accesses later on in this chapter.
598
Abacus 13. Expanded Memory Specification
The whole procedure is -somewhat refined by the fact that the page frame is further
divided into 16K pages. This allows the programmer to access four completely
different, and perhaps widely separated, pages from the EMS memory.
The registers on the EMS card allow the programmer to set which pages of the
EMS memory will be visible in the page frame. The address lines on the EMS
card are programmed so that the EMS pages are mapped into the page frame and
appear in the 8088's address space. This process is known as bank-switching.
In addition to the hardware, the EMS also includes a software interface which
handles programming the EMS registers and other memory management tasks. It
is called the EMM (Expanded Memory Manager) and gives you a standard interface
which you can use to access the EMS cards of different manufacturers. This also
applies for the extended EMS standard (EEMS) developed by AST Research,
Quadram, and Ashton-Tate, which goes far beyond the LIM standanl.
The EMM
Similar to the DOS interrupt 21H, which provides a standard interface to the
operating system functions, the EMM functions can be called through interrupt
67H. Before a program tries to use EMS memory and the corresponding EMM, it
should fltSt check to make sure that an EMS is installed. If it does not do this and
there is no EMM, the results of a call to interrupt 67H are completely
unpredictable. Maybe it just won't work; maybe the system will crash.
To prevent this, a program which uses the EMS should fltSt check to make sure it
exists. To do this we can use the fact that the EMM is bound into the system as a
normal device driver when the computer is booted. As such, it naturally has ~
driver header which precedes it in memory and defmes its structure for DOS. The
name of the driver is found at address 10 in the driver header. The LIM standard
prescribes that this name must be EMMXXXXO. The example programs at the end
of this chapter test for this name by first determining the segment address of the
interrupt handler for interrupt 67H. If the EMM is installed, the segment address
points to the segment into which the EMMXXXXO device driver was loaded.
Since the driver header is at offset address 0 relative to the start of this segment, we
just compare the memory locations starting at 10 with the name EMMXXXXO to
see if the EMS memory and the corresponding EMM are installed.
Once this is verified, access to this memory requires just three steps:
599
13. Expantkd Memory SpecifICation. PC System Programming
2.) If the desired number of pages were successfully allocated. the specified
pages must frrst be loaded into one of the four pages of the page frame so
that data can be written into them or read from them. This results in a
mapping between one of the allocated pages and one of the four physical
pages within the page frame.
3.) When the program is ended or it is done using the EMS storage, the
allocated pages should be released again. If this is not done, the allocated
pages will still be owned by the program (even after it ends) and cannot
be given to other programs.
As with OOS interrupt 2lH, the function number of an EMM call must be loaded
into the AH register before the interrupt call. In contrast to the OOS functions, the
function number does not correspond directly to the value in the AH register and
you must add 3FH to the function number. Thus for a call to function 2H you
would have to load the value 3FH + 2H or 4lH into the AH register. After the
function call this register contains the error status of the function. The value 0
signals that the function was executed successfully, while values greater than or
equal to SOH indicate an error.
About errors
You can get the error codes from the error descriptions in the Appendices, but you
should be aware of one particular error; If the value 84H is in the AH register after
a call to EMM interrupt 67H, it means that an invalid function number was passed
in the AH register.
The following functions are required for a transient program to access the EMS
memory:
Function Task
OIH Get EMM status
02H Get segment address of the page frame
03H Get number of pages
04H Allocate EMS pages
OSH Set mapping
06H Release EMS pages
To guarantee proper operation of the EMS hardware and the EMM, you should
check the EMM status before allocating EMS memory. This is done with function
OIH, which requires no parameters beside the function number in the AH register.
If it returns the value 0 in the AH register, then everything is OK and you can start
working with the EMS memory.
Naturally the number of allocatable EMS pages is limited by the number of free
pages. Thus you should ensure that the memory requirements of the program do
not exceed the available memory. Here we can use function 03H, which returns the
600
Abacus 13. Expanded MDIfOry Specification
number of free EMS pages. This function requires no parameters beside the
function number and returns the number of unallocated pages in the BX register. It
also returns the total number of installed EMS pages in the DX register.
If enough EMS memory exists for our program, or if the memory requirements are
adapted to the available memory, we can then allocate the memory. Function O4H
must be passed the number of pages to be allocated in the BX register. If the
requested number of pages were successfully allocated (AH register contains 0 after
the function call), the caller will find a handle to the allocated pages in the BX
register. This handle must be used to access the allocated pages and identifies the
caller to the EMM. This handle must be saved by the caller and losing it means
not only that the allocated pages cannot be accessed, they can also no longer be
released. This function can be called multiple times by a program to allocate
multiple logical page blocks.
Once we have the page handle we can start accessing the pages. The handle is
passed to the appropriate functions in the DX register. This also applies to
function OSH, which maps a logical page to one of the four physical pages of the
page frame. The number of the logical page is passed in the BX register and the
physical page number in the AL register. Note that both specifications start at
zero. If you have allocated 15 pages, then the numbers of the logical pages run
from zero to 14.
Once the appropriate page is in the page frame, it can be accessed just like normal
memory. The offset address of the start-of-page is calculated from the physical page
number, but the corresponding segment address must be determined with an EMM
function. Since this address does not change while working with the EMS
memory, you can read it once at the beginning of the program and then save it in a
variable. Function 02H returns the segment address of the page frame in the BX
register.
When you are done using the EMS, be sure to return the allocated pages to the
EMM. All you have to do is pass the page handle to function 06H.
In addition to these six functions, which a normal program can use to access EMS
memory, there are six more functions which can be useful under certain
circumstances. These are the following:
Function Task
07H Get EMM version number
08H Save current mappinq
09H Reset saved mappinq
OCH Get number of EMM handles
ODH Get the number of paqes allocated to a handle
OEH Get all handles and numbers of allocated Qaqes
601
13. Expanded Memory Specification PC System Progrtllllllling
Version numbers
Reading the EMM version number is of interest because the LIM standard has
changed somewhat since it was introduced. Some functions are no longer supported
and new functions have been added. The functions presented here are from Version
3.2. which has now been superseded by version 4.0. Version 3.2 represents a good
compromise not only because is it very widely used, but because it is also
completely compatible with Version 4.0. If you don't want to support earlier or
later EMS versions in your program. you should check the version number at the
start of the program. The version number will be returned in the AL register after a
call to function 07H. It is encoded as a BCD number.
Functions 08H and 09H are important for TSR programs which want to use the
EMS memory for their own purposes. When a TSR program interrupts a transient
program and places itself in the foreground, it must take into account the fact that
the interrupted program may have been using EMS memory and had created a
certain mapping. Since this mapping must not be changed when returning to the
interrupted program. it must be saved when the TSR is activated and then restored
when the TSR exits. Function OSH saves the current EMM mapping and function
09H resets the saved status. Both functions must be passed the handle of the
function. In this case it is the handle of the TSR program. not the handle of the
interrupted program.
The last three functions are only important for the memory manager and will not
be discussed here. More information can be found in the appendix in the EMM
function descriptions.
Demonstration programs
The following pages contain two programs, one written in Pascal and one in C,
which illustrate how to use EMS memory. There is no assembly language
program since. in principle, calls to the EMM functions involve just loading
variables and constants into registers and calling the EMM interrupt 67H. Using
the information in the Appendices, it should be easy to write an assembly
language program which uses the EMS. There is no BASIC program because
EMS memory is intended to be used with complex and memory-intensive
applications for which BASIC (or at least OW-BASIC) is not suited.
The two programs are almost identical, so we will limit ourselves to a discussion
of the basic program structure. The programs offer a number of functions and
procedures which can be used to access the various EMM functions. Both
programs also contain a function called EMS_INST (or EmsInst) which determines
if an EMM is installed. In Pascal we have a problem because a pointer has to be
loaded with an address which consists of separate segment and offset addresses.
Since this is not possible in Pascal. there is an INLINE procedure called MK_FP
which (like the C macro of the same name) combines a segment and an offset
address into a (FAR) pointer. The fact that this is a FAR pointer is important
because the page frame is not in the program's data segment and thus cannot be
602
Abacus 13. Expantkd Memory SpecificaJion
addressed via the DS register. This is not a problem in Turbo Pascal because the
code is generated to work with FAR data pointers. In C we have to make sure that
the program is compiled in a memory model which uses FAR pointers for data.
This occurs in compact, large, and huge models.
The main program frrsts tests to see if EMM is present and then uses various
functions to obtain status information about the EMS memory, which it displays
on the screen. Then a page is allocated and mapped to the first page (page 0) of the
page frame. The current contents of the video RAM are copied into this page and
the video RAM is then erased.
After the copy procedure, a message is displayed for the user and the program waits
for a key to be pressed. Then it copies the old screen contents back to video RAM
from page 0 of the page frame and the program ends.
This program shows that the contents of a page in the page frame can be treated
just like ordinary data. After you have created a pointer to the corresponding page
you can manipulate the data on this page, including complex objects like
structures and arrays, just like any other data. It is important to make sure that
your objects fit on one page or that you do not forget to change pages or load a
new page into the page frame to access larger objects.
C listing: EMMC.C
/**********************************************************************/
1* EMMC *1
1*--------------------------------------------------------------------*1
1* Description : a collection of functions for using EMS *1
1* storage (expanded memory) • *1
1*--------------------------------------------------------------------*1
1* Author : MICHAEL TISCHER *1
1* developed on : 08/30/1988 *1
1* last update : 08/30/1988 *1
1*--------------------------------------------------------------------*1
1* (MICROSOFT C) *1
1* creation : CL lAC EMMC.C *1
1* call : EMMC *I
1*--------------------------------------------------------------------*1
1* (BORLAND TURBO C) *1
1* creation : via the RUN command in the menu line *1
/* (no project file) *I
1* Info : Note that the Compact memory model must be *1
1* selected via the compiler model menu option. *1
/************.*******************.*********.***************************/
603
13. Expanded Memory Specification PC System Programming
1*-- MK_FP creates a FAR pointer out of segment and offset addresses -*1
fifndef MK FP 1* is MK FP defined yet? *1
fdefine MK-FP(seg, ofs) «void far *) «unsigned long) (seg) «161 (ofs»)
fendif
1*-- PAGE ADR returns a pointer to the physical page X within the ----*1
1*-- page-frame of the EMS memory. ---*1
1*-- Constants - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * I
fdefine TRUE 1 /* constants for working with BOOL *1
fdefine FALSE 0
fdefine EMS INT Ox67 1* interrupt number for access to the EMH *1
fdefine EMS:ERR -1 1* returned on error */
/*-- Global variables ----------------------------------------------*1
* Return value : EMS ERR on error, else the number of EMS pages
•••••••••••• * ••••••••••••••••••••••••••••••••••••••••••••••••••••••••••,
604
Abacus 13. Expanded. Memory Specification
int ems_free-page()
(
union REGS regs; 1* processor registers for interrupt call *1
regs.h.ah - Ox42; 1* ftn. no.: get number of pages *1
int86 (EMS_INT, 'regs, 'regs); 1* call DIM *1
i f (emm_ec - regs.h.ah) 1* did an error occur? *1
return(EMS_ERR); 1* yes, display error *1
else 1* no error *1
return( regs.x.bx ) ; 1* return number of free pages *1
605
13. Expanded Memory Specification PC System Programming
BYTE ems_version ()
(
union REGS regs; /* processor registers for interrupt call */
/*********************************.*******.*****.*.**************.******
* Function : EMS S AVE MAP *
**--------------------------=---------=-------------------------------**
* Description Saves the mapping between the logical and
* physical pages.
* Input parameters HANDLE: the handle returned by EMS_ALLOC.
* Return value FALSE on error, else TRUE.
606
Abacus 13. Expanded Memory Specification
};
607
13. Expanded Mel'llDry SpecifICation PC System Programming
**--------------------------------------------------------------------**
Description Returns a pointer to the video RAM.
void mainO
{
int numpage, '* number of EMS pages *'
handle, '* handle to access to the EMS memory *'
i; '* loop counter *'
WORD pageseg '* segment address of the page frame *'
BYTE emmver; '* EMM version number *'
printf("EHMC
if ( ems instIl )
{ -
'*
(c) 1988 by MICHAEL TISCHER\n\n");
is EMS memory installed? *'
'* yes *'
'*-- output information about the EMS memory ----------------------*'
emmver' 10 , emmver%lO);
printf ("
getchO; '*
press any key\n");
'*-- allocate a page and map it to the first logical page in ---*'
'*-- page frame. ---*'
if ( (handle - ems alloc(1» EMS ERR)
print err(); - '* Error:.output error message and end program *'
lams
if ( map {handle, 0, 0) )
print_err();
'* set mapping *'
'* Error: output error message and end program *'
'*-- copy 4000 bytes from the video RAM to the EMS memory ---------*'
608
Abacus 13. Expanded Memory SpeciflCaJion
printf("The old screen contents will now be cleared and will be\n");
printf("lost. But since it was stored in the EMS memory, they\n");
printf("can be copied from there back into the video RAM.\n");
printf(" ••• press any key\n");
getch () ; 1* wait for a key *1
1*-- copy the contents of the video RAM from the EMS memory ----*1
1*-- and release the allocated EMS memory again. ----*1
memcpy(vr adr() , PAGE ADR(O) , (000); /*
copy VRAM back *1
if ( !ems-free(handle) 1* release memory *1
print err(); 1* Error: output error message and end program */
printf("END") ;
)
else 1* the EMS driver was not detected *1
printf("No EMS memory installed.\n");
program EMMP;
Uses Dos, CRT; Add DOS and CRT units
{••• ** •• ***.** •••• ******* ••• **********.** ••••••••• ** •• ***** ••••••• *****}
(* MK FP: Creates a byte pointer from the given segment and offset *)
(* addresses. *1
( * Input - Seq - Segment to which the pointer should point *I
(* - Ofs - Offset addr. to which the pointer should point *)
(* Output Entire pointer *1
{* Info The returned pointer can be recast toward any other *1
(* pointer. *1
{••••• **** •• ** ••• **** •••••• *** •••••••••••••••• **** •••• ****** ••• ********.
($F+] This routine is intended for a FAR model, and
should therefore be treated as one UNIT
609
13. Expanded Memory Specification PC System Programming
begin
inUne $88 / $46 / $08 / mov ax, [bp+8] (Get segment address)
end;
begin
(*-- Move pointer to name in device driver header ------------------*1
begin
Regs.ah :- $42; ( Function f: Determine number of pages
Intr(EMS INT, Regs); ( Call EHM
if (Regs~ah <>0 ) then Error occurred?
begin ( YES
EmmEC := Regs.ah; ( Get error code
EmsNumPage := EMS ERR; ( Display error
end
else No error
EmsNumPage .= Regs.dx; ( Return total number of pages
end;
610
Abacus 13. Expanded Memory Specification
begin
Regs.ah :- $42; I Function f: Determine no. of pages
Intr(EMS INT, Regs); I Call EHM
if (Regs~ah <>0 ) then Error occurred?
begin I YES
ElmlEC :- Regs.ah; Mark error code
EmsFreePage :- EMS_ERR; I Display error
end
else I No error
EmsFreePage :- Regs.bx; I Return number of free pages
end;
{** •••••• *****.************.*••• *****************.****.***** •• ***.*****}
{* EmsFrameSeg: Determines the segment address of the page frame *1
{* Input : none *1
{* Output : EMS ERR if error occurs, otherwise the segment address *)
{****.*.**** ••• **•• *******••• ****************** ••• ****.********** •• ****}
function EmsFrameSeg : word;
begin
Regs.ah :- $41; { Function .: Get segment addr. page frame
Intr(EMS INT, Regs); { Call EHM
if (Regs:ah <>0 ) then Error occurred?
begin { YES
ElmlEC :- Regs .ah; Mark error code
EmsFrameSeg : - W EMS ERR; Display error
e~ -
else I No error
EmsFrameSeg :- Regs.bx; { Return segment addr. of page frame
end;
t········**·····**········***···**··****·***····***···.*.*
{* EmsMap
..••.•• **** •• }
Creates an allocated logical page from a physical page in*1
{* the page frame *1
{* Input HANDLE: Handle received from ErnsAlloc *1
{* LOGP : Logical page about to be created *1
(* PHYSP : The physical page in page frame *1
(* Output FALSE if error, otherwise TRUE *1
(*••••••••••••• *****.****** ••••••••••••• * •••••******** •• *** •• ** •••• **.*)
611
13. Exponded Memory Speci[lCalion PC System Programming
begin
Regs.ah '- $44; Function t: Set mapping
Regs.al :- PhysP; I Set physical page
Regs.bx :- LogP; ( Set logical page
Regs.dx :- Handle; I Set EMS handle
Intr(EMS_INT, Regs); ( Call EMM
EmmEC :- Regs.ah; ( Mark error code
EmsMap :- (Regs.ah - 0) ( TRUE is returned if no error
end;
{*••••••••••••••••••••••• _••••••• _ ••••••••••••• - •••••• **•••• ***** ••• *•• )
(* EmsFree Frees memory when given with an allocated handle *)
(* Input : IlANDLE: Handle received by AllocEms *)
(* Output : FALSE i f an error, otherwise TRUE *)
{••••••••••••••••••••••••••••_- ••••••••••- ••••_••••••••••• ** ••••••• ** •• }
begin
Regs.ah :- $46; { Function .: Determine EMH version
Intr(EMS INT, Regs); { Call EMM
if (Regs~ah <>0 ) then Error occurred?
begin ( YES
EmmEC :- Regs.ah; Mark error code
EmsVersion :- EMS_ERR; ( Display error
end
else { No error, compute version number from BCD number
EmsVersion : (Regs.al and 15) + (Regs.al shr 4) * 10;
end;
612
Abacus 13. Expanded Memory Specification
begin
Regs.ah :- $48; Function f: Restore map
Regs.dx :- handle; C Set EMS handle
IntrCEMS_INT, Regs); C Call EMM
EmmEC :- Regs.ah; C Mark error code
EmsRestoreMap '. CRegs.ah - 0) C TRUE returned if no error
end:
{** •••••• **.****** •• **.** ••••••• **.********* •••••••••• ********* ••• *****}
(* PrintErr: Displays an error message and ends the program *j
C* Input none *j
C * Output none *'
C* Info This function is called only if an error occurs during a *j
{*._._....__.-._._._-_._._••......_•..-•..._._-_..•..-•..
C* function call within this module *j
*** ••••• *** ••• }
procedure PrintErr;
begin
writelnC'ATTENTION! Error during EMS memory access');
write C' ••• ');
if CCEmmEC<$80) or CEmmEC>$8E) or CEmmEc-$82» then
writelnC 'Unidentifiable error')
else
case EmmEC of
'available') ;
'be restored');
end;
Halt; C Program end j
end;
{ ••• *******.** ••• ** •••• *** •••••••••• ** •••****.*** ••••••••••• ** ••• ** ••• *)
C* VrAdr: Returns a pointer to video RAM
C* Input : none
C* OUtput : Pointer to video RAM
*'*'
*'
begin
Regs.ah :- SOf; Function t: Determine video mode
Intr C$10, Regs); C Call BIOS video interrupt
613
13. Expanded Memory Specification PC System Progranuning
begin
PaqeAdr :- MK_FPI EmsFrameSeq + (Paqe shl 10), 0 );
end;
beqin
ClrScr; { Clear screen
writeln (' EMHP (c) 1988 by MICHAEL TISCHER','13'10);
if EmsInst then { Is EMS memory installed?
beqin { YES
(*-- Display EMS memory information --------------*)
writeln;
writeln('paqe.');
{*-- Copy 4000 bytes from video RAM into EMS memory --*'
614
Abacus 13. Expanded Memory SpecijiCalion
(*-- Copy contents of video RAM from EMS memory and release --*)
(*-- the allocated EMS memory --*.
Move(PageAdr(O)A, VrAdrA, 4000); ( Copy over video RAM
if not (EmsFree(Handle)) then { Release memory
PrintErr; I Error: Display error message and end program
GotoXY (1, 15);
writeln('END' )
end
else ( EMS driver not available •
writeln('ATTENTION! No EMS memory installed.');
end.
615
I
I
I
I
I
I
I
I
I
I
I
I
I
I
I
I
I
I
Chapter 14
Mouse Programming
A few years ago mice were considered luxuries for PC applications. Today most
PCs have mice connected to them. Part of the mouse's popularity stems from the
development of new and more powerful video standards such as EGA and VGA.
These graphic cards helped advance the graphic user interfaces such as GEM® and
Microsoft Windows®, which are almost unusable without a mouse.
Applications and operating systems alike benefit from mouse support. Ventura
Publisher® and Microsoft Works® both make intensive use of the mouse. In
addition, DOS Version 4.0 accepts mouse as well as keyboard input
A software interface acts as the connection between a program and the mouse.
Microsoft Corporation designed this interface for its own mice, but other mouse
manufacturers accept this interface as a standard. TIle interface was made available
to the industry as a minimum standard to retain compatibility with the Microsoft
mouse.
This function interface is usually installed either through a device driver which is
loaded during system boot, or through a terminate and stay resident (TSR) program
such as MOUSE.COM, included with the Microsoft mouse package.
Mouse functions
Mouse functions may be accessed in the same way as DOS and BIOS functions
(you may wish to review the techniques used for addressing DOS and BIOS
functions-see Chapters 6 and 7 for more information). The individual functions
can be called through interrupt 33H. The identification number of the function
must be passed to the AX register. The other processor registers are used in various
combinations for passing information to a function.
617
14. Mouse Programming PC System Programming
text oriented mouse control. Pixel oriented applications should use a graphic
interface such as Windows or GEM from the start, because they provide friendlier
functions for mouse input than the programming interface offered in this chapter.
About mouse buttons
Unlike the keyboard, which has many keys and keyboard codes for each key, a PC
mouse usually has two or even three mouse buttons. These mouse buttons permit
the user to select data in an application program. Another important piece of
infonnation is the actual position of the mouse's pointer (cursor) on the screen.
The word pointer stems from the pointer'S usual shape: an arrow or a pointing
fmger.
The mouse driver software always interprets the pointer's location on the screen
relative to a virtual graphic screen. This virtual screen's resolution depends on the
video mode and video card currently in use. Since this virtual graphic display
screen is also used within the text modes to determine the mouse's position and
forms the basis for communication with the mouse interface, a conversion occurs
between the graphic coordinates and the mouse pointer's line/column position.
Since every column or line corresponds to eight pixels, the graphic coordinates
must be either divided by eight or left shifted by three places in binary mode,
which mathematically produces the same result The processor executes the
shifting much faster than it can execute the actual division.
More about the mouse pointer
The pointer shows the mouse's relative location on the screen. Its shape can vary
from application to application, and it can even change appearance within an
application. Word processors often display the mouse pointer as a block, similar to
the text cursor. In text mode the application can only determine the starting and
ending line of the pointer. The pointer's size depends on the current character
matrix and video mode. The options for creating a software pointer are more
complex, since two 16-bit values called the screen mask and cursor mask govern
the pointer's appearance.
The mouse driver must determine the appearance of the pointer every time the
pointer changes position on the screen. The cursor mask and screen mask values
are linked with the two bytes which describe the character code and the character
color within video RAM. This linkage occurs in two steps. First the character code
and the attribute byte are linked with screen mask through a binary AND. The
result of this connection is then linked with the cursor mask through an exclusive
OR. The result then appears on the screen.
618
Abacus 14. Moue Progrfll1lming
This type of linkage allows a number of options for changing the pointer's
appearance. Four of the most common pointer options are:
Pointer appears as one specifIC character in one specific color
• Pointer appears as one specific character, but color changes when the
pointer overlaps a character (e.g., inverse video)
• Pointer appears as one specific character, but the character color changes
when the pointer overlaps a character
• Pointer appears as one specific character, but character color changes to a
variant of the character color when the pointer overlaps a character
The standard measurement unit in the mouse interface is the miclcey, named after
Mickey Mouse® (1 mickey = 1/200"). The mouse hardware measures all distances
in multiples of mickeys. We will use this as the measurement standard throughout
the rest of this chapter.
A program should call the function OOH before calling any of the mouse functions.
This resets the mouse driver. It can also determine whether a mouse and mouse
driver exist, by examining the content of the AX register after the function call. If
the AX register contains the value OOOOH after the function call, no mouse driver
was installed. Even if a mouse is connected. the mouse driver no longer exists. If a
mouse driver and mouse exist. function OOH returns the value FFFFH in the AX
register. The BX register contains the number of buttons on the mouse. As
mentioned above. PC mice usually have two mouse buttons. although some mice
have three buttons. Since very few applications need or use three buttons. two
buttons will be all you'll need in most cases.
Function OOH resets the numerous mouse parameters to their default values. The
mouse pointer moves to the center of the screen. The cursor mask and screen mask
are defmed in such a manner that the cursor appears as an inverse video rectangle.
Video page 0 is selected as the default page on which the pointer appears. The
pointer disappears from the screen immediately.
Function 01H displays the pointer on the screen. Load the function number into
the AX register; no other parameters are needed. Since the mouse driver follows the
movement of the mouse even when the mouse pointer has been disabled. it may
not necessarily reappear at the position where it was when it disappeared.
619
14. Mouse Progrtunming PC System Programming
Function 02H removes the mouse pointer from the screen. Load the function
number into the AX register; no other parameters are needed. The calls between
functions 01H and 02H must be called in proper proportions to be effective. For
example, calling function 02H twice in succession means that you must also call
function 01H twice in succession to return the pointer to the screen.
Functions 01H and 02H aren't used very much. Often, all youll need to do is call
function OOH and function 01H at the beginning of a program, and call function
02H at the end of the program. These functions corne into play more frequently if
the application program writes characters directly into video RAM, bypassing the
slow DOS and BIOS display routines. Avoid writing characters over the mouse
pointer, or two things will happen:
1) The mouse pointer disappears if overwritten by another character.
2) The mouse driver produces the wrong character on the screen when the
user moves the mouse pointer. Before the pointer appears at a certain
position on the screen, it records the character which occupied this
position until now. This character is restored to the old position as soon
as the pointer moves to another position on the screen. During a direct
write access to video RAM, the driver does not record that a new character
was output at the position of the pointer. Therefore, the old (and
incorrect) character is displayed on the screen during the movement of the
pointer.
You can avoid this potential source of errors by removing the pointer before
character output, and returning the old character to the screen. The new character
will be stored when the pointer is restored to the screen. This action should not be
done for every character output, since it slows the system down and negates the
advantages of direct access to video RAM. We recommend that you remove the
pointer once from the screen before extensive output such as construction of a
screen window. Mter the operation the pointer can be restored on the screen.
Even though the DOS and BIOS character output functions write their output
directly to video RAM, you shouldn't worry about programming the pointer when
working with these functions The reason is that during installation, the mouse
driver moved interrupt vector IOH, which handles BIOS and DOS screen output, to
its own routine. The driver can then display or disable the pointer as needed.
Function 04H allows movement of the pointer to a specific location on the screen,
without moving the mouse. Pass the function number to the AX register, the new
horizontal coordinate (column) to the ex register, and the new vertical coordinate
(line) to the DX register. Please note that these coordinates, like all other
functions, must be relative to the virtual screen. Text coordinates must be
620
Abac/lS 14. MO/lSe Programming
multiplied by eight (or shifted left three binary places) before they can be passed to
function 04H. The coordinates must be located inside a screen area designated as
the mouse's range of movement
Function OOH sets the complete range of the mouse's movement to the entire
screen area. Functions 07H and 08H limit this range to a smaller area.
Function 07H specifies the horizontal range of movement Pass the function
number to the AX register, the minimum X-coordinate to the ex register and the
maximum X-coordinate to the OX register.
Function OSH specifies the vertical range of movement Pass the function number
to the AX register, the minimum Y-coordinate to the ex register and the
maximum Y-coordinate to the OX register.
After calling these functions the mouse driver automatically moves the pointer
within the range, unless it is already within the indicated borders. The user cannot
move the pointer outside this range.
In addition to the area of movement allotted to the pointer, the mouse driver also
supplies an exclusion area. This exclusion area is a section of the screen which
renders the mouse pointer invisible when the user moves the pointer into this
section. The mouse pointer becomes visible again as soon as the user moves the
pointer away from the exclusion area. This area is undeimed after the call of
function OOH. It can be defined at any time by calling function IOH, but the
mouse driver can control only one exclusion area at a time. The coordinates of the
exclusion area are passed to function IOH in the ex:OX and SI:DI register pairs.
These register pairs specify the upper left corner and lower right corner
respectively. ex and SI accept the X-coordinate, OX and DI the Y-coordinate.
The exclusion area and function 02H play special roles during direct access to video
RAM. Although function 02H removes the pointer from the screen, this can occur
in conjunction with function IOH only if the pointer is already within the
exclusion area, or if the user moves the pointer within the exclusion area. This
makes function IOH practical for situations involving the creation of a larger
display area (e.g., a window). This allows the pointer to remain on the screen as
long as it is not within this exclusion area.
The exclusion area can be removed by calling function OlH or function OOH.
Function OlH makes tIie pointer visible automatically if it is already within the
exclusion area.
621
14. Mouse Programming PC System Programming
Function 10H sets the dispJay page on which the pointer appears. This function is
required only if the program switches a display page other than the current one to
the foreground through direct video card programming. Pass the number of the
display page to the BX register. When BIOS interrupt 10H activates a dispJay
page, this function can be omitted, since the mouse driver will automatically adapt
to the change.
Two parameters determine the speed at which the mouse pointer moves on the
display screen. They specify the reJationship between the distance of a pointer
movement and the pixels traversed in the virtual mouse display screen. Function
OFH allows the user to set these parameters for horizontal and vertical movement
The parameters are passed in the ex and OX registers (horizontal and vertical,
respectively). These numbers indicate the number of mickeys, which correspond to
eight pixels in the virtual mouse display screen. These eight pixels correspond to
one line or column in the text mode display screen.
The default values after calling function OOH are 8 horizontal mickeys and 16
vertical mickeys. In text mode the pointer moves one column after the pointer is
moved 8 mickeys (about .04") horizontally. A jump to the next line occurs only
after the pointer is moved 16 mickeys (about .08") vertically.
These settings normally can be set at default values, since they wode well with all
resolutions in text mode. This function allows changes if you want faster or
slower pointer movement
Function OAH determines the appearance of the pointer in text mode. The cursor
mask and screen mask mentioned above are determining factors of the pointer's
appearance in text mode. Pass OAH to the AX register and the value determining
the cursor's shape to the BX register.
Software-specific pointer
If the BX register contains the value 0, the mouse driver selects the pointer as
specified by the software. The screen mask number must be loaded into the ex
register, and the cursor mask number must be loaded into the OX register. These
numbers indicate the addresses from which the mouse driver can access pointer
shape parameters.
622
AbacMS 14. MolISe Programming
Hardware-specific pointer
If the BX register contains the value l,the mouse driver selects the pointer as
specified by the hardware. Starting line of the hardware pointer must be loaded into
to the ex register, and the ending line must be loaded into the DX register.
• EGA and VGA cards accept values from 0 to 7. The EGA/VGA BIOS
automatically adapts the number selected to the size of the character
matrix currently in use.
The functions listed up until now set the various parameters which control the
mouse driver. The mouse driver also supports a group of functions which read the
mouse's position as well as the status of the mouse buttons. These functions can
be divided into two categories for reading external devices such as the mouse,
keyboard, printer or disk drives. These categories are the polling method and the
interrupt method. The mouse driver supports both methods.
Polling method
The polling method constantly reads a device within a loop. This loop terminates
only when the desired event occurs. Since the execution of this loop requires the
full capabilities of the CPU, no time normally remains to perform other tasks.
Interrupt method
The interrupt method has an advantage over the polling method, since the interrupt
system allows the CPU to execute other tasks until the desired event occurs. Once
this happens, the mouse driver calls an interrupt routine which reacts to the event
and executes further instructions.
The polling method offers four functions which operate in conjunction with the
mouse interface. These functions can be accessed through function 03H, which
return the current pointer position and mouse button status. Function 03H passes
the horizontal pointer position to the CX register and the vertical pointer position
to the DX register. Since these coordinates also refer to the virtual mouse screen,
they must be converted to the text screen's coordinate system by dividing the
components by eight, or by shifting the bits right by three binary places.
623
14. Mouse Programming PC System Programming
The following table shows how the mouse button status is returned to the BX
register. Only the three lowest bits represent the status of one of the two or three
mouse buttons. The bit for the corresponding mouse button contains the value 1
when the user presses that mouse button during the function call.
Mouse button status retumed in the BX register after calling
function 03H
5 4 3 2 1 0 987 6 5 432 1 0 .. Bits
XXXXXXXXXXXXX .. Dis~ard these bits
1 - left mouse button activated
1 - right mouse button activated
1 - center mouse button activated
Function OCH sets the address of a mouse event handler (interrupt routine). The
function number must be passed to the AX register. The segment and offset address
of the event handler must be passed to the ES:DX register pair. The event mask
must be passed to the ex register. The individual bits of this flag determine the
conditions under which the event handler should be called. The following table
shows the ex register coding:
Event mask coding in ex register durinq function OCR call
5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 _ Bits
XXXXXXXXX .. Disregard these bits
1 - Mouse movement
1 - Left mouse button activated
1 - Left mouse button released
1 - Right mouse button activated
1 - Ri~ht mouse button released
1 - Center mouse button activated
1 - Center mouse button released
The mouse driver calls the event handler after executing the function, as soon as at
least one of the specified events occurs. The call is made using the FAR call,
rather than the !NT instruction. This difference is important to remember when
developing an event handler, since the handler must be ended with a FAR RET
instruction rather than an !RET instruction. Similar to an interrupt routine, none
of the various processor registers can be changed when they are returned to the
caller. For this reason the registers must be stored on the stack immediately after
the call, and the register contents must be restored at the end of the routine.
Information is passed to the event handler from the mouse driver through
individual processor registers. The information concerning the event can be found
in the AX register, where each bit has the same significance as in the event mask:
during the call of function OCH (see above table). Individual bits may be set which
have no meaning for the event handler. For example, if the event handler should
only be called when the left mouse button is activated (bit 1), bits 0 and 4 may
624
Abacus 14. Mouse Programming
also be set during the event handler call, because the mouse was moved and the
right mouse button had been released at the same time.
The event handler can obtain the current button status from the contents of the CX
register. The coding is identical during the call to the function 03H. Bits 0 to 2
represent the different mouse buttons. The current pointer position can be found in
the CX and DX registers, representing the horizontal and vertical positions,
respectively. The position can only be set after conversion to the text screen's
coordinate system.
During the development of an event handler, the DS register should point to the
data segment of the mouse driver during the handler call, instead of the interrupted
program. If the event handler accesses its own data segment, it must fIrst load its
address into the DS register.
Function I8H allows the installation of an event handler which reacts to limited
range keyboard events as well as mouse events. This function signals an event if
the <Ctrl>, <Alt> or <Shift> keys are pressed when a mouse button is pressed or
released.
1 - Mouse movement
1 - Left mouse button activated
1 - Left mouse button released
1 - Riqht mouse button activated
1 - Right mouse button released
1 - Shift key pressed during
mouse button event
1 - Ctrl key pressed during mouse
button event
1 = Alt key pressed during mouse
button event
Even during the call of such an alternative event handler, little changes in
comparison with the event handlers which were installed by calling function OCH.
Only the content of the AX register must be interpreted a little differently, since its
construction corresponds to the event mask shown above.
625
14. Mouse Progromming PC System Progromming
installed handler. Three different event handlers can be installed by calling fimction
I8H three times. This is only valid if the three event handlers are equipped with
different event masks. If an event mask passes to function ISH which is already
equipped with a handler, the new handler replaces the existing handler.
Demonstration programs
This chapter lists programs in C and Turbo Pascal which demonstrate mouse
access functions. These programs show the techniques of developing and installing
an event handler, which is the most complicated part of mouse reading. Both
programs include functions or procedures which call various mouse functions.
These routines require little programming-tbey load the processor registers with
the necessary values, then call interrupt 33H. Since the event handler needs the
most programming, the text here will focus on that subject
• The event handler must load the segment address of the higher level
language data segment into the DS register to provide access to global
variables of the program.
These requirements can be met in some versions of Turbo Pascal, Turbo C and
Microsoft C, although some very complex programming would be required. The
traditional solution (write a routine in assembly language) is easier and faster to
implement Therefore, we wrote the event handler itself in assembler, assembled
the program and linked the resulting object module to the higher level language
program.
626
Abac", 14. Mouse ProgrfJlllltling
This infonnation is converted from virtual graphic screen coordinates into text
screen coordinates (25 lines x 80 columns).
The stack handles parameter passing. The C vcnion of AssmHand must pass the
arguments onto the stack in the reverse order of their declamtion. After loading the
DS register and calling the higher level language routine, these arguments must be
taken from the stack again by incrementing the stack pointer by the memory
requirements of the arguments (8 bytes). This is only required fex the C version of
the routine. The Turbo Pascal version performs this taslc on its own.
After calling this routine, the AssmHand routine returns the processor registers to
the stack and passes control to the caller using a FAR RET instruction.
The AssmHand instructions execute very quickly, but the handler itself may require
more execution time than expected. This introduces the problem of recursion, since
an event in connection with the mouse may recur during the handler execution.
The AssmHand driver then must be recalled before the previOUS call terminated.
To avoid this situation and the complications which can occur, AssmHand
maintains a variable named active in its code segment During execution this
variable contains the value 1. Before setting this variable, the program tests if
active already contains the value 1. This indicates that the last call was not yet
completed. If this situation occurs, the handler execution terminates immediately,
thus avoiding recursion.
Even if this method avoids recursion problems, remember that it can produce its
own problems. The suppression of the higher level language handler does not take
note of the event, because the handler was not called by the mouse driver.
Although we offer the recursion trap as an option, we recommend that you
program the higher level language handler as efficiently as possible to avoid using
processor time. This will keep call suppression to a minimum.
This buffer allows division of the screen into individual mouse ranges, each
equipped with its own code, cursor mask and screen mask. These mouse regions
are very important in mouse access. They permit the defmition of objects such as
slidcn, O.K. buttons or menu items. As soon as the user moves the pointer to and
object and presses a mouse button, the object executes a particular step in the
program.
627
14. Mous~ Programming PC System Programming
During the creation of this array, especially during the definition of the cursor and
screenmask in the PtrMask array, the C implementation provides helpful macros
and constants. The Pascal program has functions and constants available for this
purpose. The creation of a variable of the type PfRVIEW, stored in the PtrMask
field within an area descriptor, is handled by the macro or function MouPtrMask.
The cursor and screen mask for the character must be passed to MouPtrMask to
define the pointer's appearance on the screen.
As a second parameter MouPtrMask gets the pointer's color from the cursor mask
and screen mask. Many options for color are possible:
PtrSameCol ensures that the pointer assumes the color of the character
currently overlapped by the pointer.
PtrInvCol makes the pointer appear in the inverse color of the character
currently overlapped by the pointer.
• PtrDifCol displays the pointer on the screen in the color indicated by the
code following PtrDifCol.
The MouEventHandler changes the cursor and screen mask for each area. Since it is
called for every mouse event (including mouse movement). it can determine the
628
14. MOlUe ProgrQllUlling
mouse area where the pointer is currently located. To make this happen as fast as
possible, it tests if the mouse area contains the position of the pointer.
MouEventHandier uses the internal region buffer which was created by MouInit
during the call. It reflects exactly the video RAM structure, and contains one byte
for eVerJ screen position. Each byte contains the code of the area to which the
screen position was assigned. The event handler can use the cmrent position of the
pointer as an index to this area buffer. A single memory access is enough to
determine the mouse area in which the pointer is located. The area code found is
stored in the global variable MouRng, and is used as an index to the array of the
mouse descriptor from which it determines the cursor and screen mask for this area.
The higher level language event handler has another assignment which may be
even more important It controls the variable MouEvent, in which the current
mouse events are stored. This task cannot be performed by simply copying the
mouse events which were passed through AssmHand from the mouse driver. This
only shows the current event, but no preceding events. If the user presses and holds
the left mouse button, then presses the right mouse button, this results in two
event handler calls. This signals each case of an active mouse button. The
preceding call (the active left mouse button) is no longer recognized by the call,
since it reports only the current event (the depressed right mouse button).
The event handler must isolate the various events which are reflected in the
EvFlags variable, and accept only new events in the MouEvent variable. This
variable reflects the current status of the mouse buttons, and the pointer's current
movement or position. MouEvent can handle the most important mouse sensing
tasks, waiting for the occurrence of a certain event (usually a pressed mouse
button).
MouEventWait waits for the occurrence of an event which was specified by the
bitmask that was passed earlier. This bitmask can be dermed through the logical
OR function with the following constants:
The procedurelfunction can be instructed to wait for one or more of these events to
occur. The AND or OR correspond to the logical comparisons of the same names.
Which events occur can be sensed through the results of a bitmask in which the
individual bits represent the various events, and through which the constants
described above can be sensed.
629
14. Mouse Programming PC System Programming
const
630
Abacus 14. Mouse Programming
CursoIMask word;
end;
{- global variables - - - - - - - - - - - - - , - - ,
var NumRanges, { Number of ranges
TLine, { Number of text lines
TCoI byte; { Number of text columns
MouAvail boolean; TRUE if mouse is available
OldPtr, { Old mouse pointer appearances
StdPtr PTRVIEW; { Mask for standard mouse pointer
BufPtr BBPTR; Pointer to range recognition buffer
ActRngPtr: RNGPTR; { Pointer to current range vector
BLen integer; { Range buffer length in bytes
ExitOld pointer; { Pointer to old exit procedure
{-- Variables which are loaded into mouse handler on every call --I
*'
{* PtrInvCoI, PtrlnvColB, and the results of the ptrDifChar *'
{* and PtrDifCol functions also control character' color *'
{********************************* ••• *** •• ************************* ••• *}
end;
{**------------------------------------------------------------------**'
{* Input
{*
ASCII code of the character on which pointer is based
OUtput Cursor and screen mask for this cursor
*'
*)
{* Info: Function result should be computed with the help of the *'
{* MouPtIMask function *)
{•• ******••••••• ***••• **************.****.*.*******••••****************}
function PtrDifChar ( Chars : byte) : word;
631
14. Mouse Programming PC System ProgrtllfUtling
beqin
PtrDifChar :- Chars shl B;
end;
f······**·**·········****·······**·**············**··· •••••............
{* PtrOifCol: Creates the character segment of the cursor and screen *'
}
begin
PtrOifCol .- Color shl 8;
end;
{* •••• *****••• ***** •• *** •• ***•••• *.**** ••• **•• ** ••••••• *.*************.)
1* MoUOefinePtr: Assigns the mouse driver the cursor mask and *}
{* screen mask, from which the driver can create the *}
(* mouse pointer *)
(**------------------------------------------------------------------**)
(* Input Mask - The cursor and screen mask as a parameter of *)
(* type PTRVIEW *)
1* Info: - The mask parameter should be created with the help of *)
(* the MouPtrMask function *)
{* - The most significant 16 bits represent the screen mask,*'
{* the least significant 16 bits represent cursor mask *'
{************.**************** •••••• ************** •• **.****** ••• *******}
begin
if OldPtr <> Mask then { Mask change since last call?
begin { YES
Regs.AX . $OOOa; 1 Funct. no. for ·Set text pointer type"
Regs.BX : 0; { Create software pointer
Regs.CX •• PTRVREC I Mask ). ScreenMask; { Low-word is AND mask
Regs.OX .= PTRVREC( Mask ).CursorMask; High-word ist XOR mask
Intrl $33, Regs); { Call mouse driver
OldPtr .= Mask; ( Reserve new bitmask
end;
end;
begin
632
Abacus 14. Mouse Programming
1-- Determine range in which the mouse should be found and ---I
{-- determine whether range has changes since the previous call
(-- of the handler. If so, the cursor image must be redefined. --,
--I
{**********************************************************************}
{* MouIBufFill: Store the code for a mouse range within the *'
1* modulare range memory *,
1**--------------------------------------------------**'
1* Input xl, yl - Upper left corner of the mouse range *'
{* x2, y2 - Lower right corner of the mouse range *'
1* Code - Range code *,
{*****•• *** ••******** ••• ************.*.***************••• **************}
633
14. Mou.se Programming PC System Programming
begin
ActRngPtr :- BPtr; Reserve pointer to vector
NurnRanges :- Number; { and number of ranges
FillChar ( BufPtr A , BLen, NO RANGE ); { All elements-NO RANGE
for Range:-O to Number-l do- Check out different ranges
with BPtr A [ Range J do
{***************************************.*.*********************** •• ***}
{* MouEventWait: Waits for a specific mouse event */
{**------------------------------------------------------------------**/
{* Input TYP - Type of comparison between different events */
{* WAIT EVENT = Bitmask which specifies the awaited event *1
{* OUtput Bitmask of the occurring event */
{* Info: - WAIT EVENT can be used in conjunction with OR for other*/
{* constants like FN MOO MOVE, FN LEFT PRESS etc. */
{* - Comparison types Can be given as AND or OR. I f AND is */
1* selected, the function returns to the caller if all */
1* anticipated events occur. OR returns the function to *}
1* the caller if at least one of the events occurs. */
{*****************************************************.****************}
begin
Column := MouCol; { Reserve current mouse position /
Line := MouRow;
CEnd : - fal se;
repeat
1-- Wait for one of the events to occur ---------------------------/
634
AbaclAS 14. MOlASe Programming
end
else 1 Event occurs ,
CEnd :- TRUE;
until CEnd;
MouEventWait :- ActEvent;
end;
*'*'
1**------------------------------------------------------------------**'
{* Input EVENT - Bitmask which describes the event, called
{* through an event handler
{* FPTR - Pointer to the event handler of type FNCTPTR *'
'* Info: - EVENT can be used through OR comparisons in conjunc- *'
(* lion with constants like EV MOl) MOVE, EV LEFT PRESS etc*,
{* - The event handler must be a-fAR-procedure, and change *'
(* none of the given processor registers *)
{*••••••• _••••••••••••• _••••••••••••• _--_ ••• _••••••••• ***•••*** •••• **.*}
begin
Regs.AX : - $OOOC; { Funct. no. for ·Set Mouse Handler"
Regs.CX :- event; { Load event mask
Regs.DX := PTRREC( FPtr ).Ofs; { Offset address of handler
Regs.ES :- PTRREC( FPtr ).Seg; { Segment address of handler
Intr{ $33, Regs); { Call mouse driver
end;
{*•• ********* •••• **** ••• ************.****** ••••••• ***.**** ••••• ****.***}
'* MouIGetX: Returns the text column in which the mouse pointer can *'
{* be found *'
{**------------------------------------------------------------------**'
(* OUtput: Mouse column converted to text screen *)
{•••••••••••••• _--_ ••• _•••••• __ •••••••••- •••••••••••••••••••• *••• ***•• *}
begin
Regs.AX : = $0003; Funct. no. for "Get mouse position"
Intr ( $33, Regs) ; { Call mouse driver
MouIGetX .= Regs.CX shr 3; Convert column and return new value
end;
begin
Regs.AX := $0003; Funct. no. for "Get mouse position"
Intr( $33, Regs ); { call mouse driver
MouIGetY :- Regs.DX shr 3; { Convert line and return new value
end;
635
14. Mouse Programming PC System Programming
{*** ••••• ****.*.*.*** ••• *.*••• ***.******* ••• *** •••••••••• ******** ••• *.*)
{* MouShowMouse: Show mouse pointer on the screen *}
{**------------------------------------------------------------------**}
{* Info: Calls between MouShowMouse and MouHideMouse must be evenly *}
{* balanced *}
••••• ********•• *****.**•••••••••••• ****••• ************.****.** •••• *****}
procedure MouShowMouse;
begin
Regs.AX . - $0001; I Funct. no. for "Show Mouse"
Intr ( $33, Regs ); I Call mouse driver
end;
begin
Regs.AX .- $0002; I Funct. no. for "Hide Mouse"
Intr( $33, Regs); I call mouse driver
end;
begin
Regs.AX .= $0008; Funct. no. for "Set vertical limits"
Regs.CX :- integer( yl shl 3; ( Conversion to virtual
Regs.OX :- integer( y2 shl 3; I mouse screen
Intr( $33, Regs ); I call mouse driver
Regs.AX .- $0007; I Funct. no. for "Set horizontal limits"
Regs.CX :- integer( xl shl 3; I Conversion to virtual
Regs.OX :- integer( x2 shl 3; I mouse screen
Intr ( $33, Regs); I Call mouse driver
end;
636
AbacllS 14. MOlISe Programming
begin
Regs.AX :- $OOOf; 1 Funct. no. for "Set mickeys to pixel ratio· 1
Regs.CX :- XSpeed;
Regs.OX :- YSpeed;
Intr( $33, Regs); { Call mouse driver 1
end;
{*.*** ••••••••••••••••• **•••• ****•••••••• ** ••• *** ••• ***••••*** ••• ***••• }
1* MouMoveptr: Moves mouse pointer to a specific position on the *1
1* screen *1
{**------------------------------------------------------------------**1
(* Input COL - New screen column for mouse pointer *)
(* R~ - New s=een line for mouse pointer *1
1* Info: - The coordinates indicate the text screen, and not the *)
(* virtual graphic screen used by the mouse driver *)
{*.***•••• ** ••• ***.**••• ***•••••••••• **.**••••••• **•••••• ****** •••••••• }
begin
Regs.AX := $0004; ( Funct. no. for "set mouse pointer position"
MouCol := col; { Store coordinates in
MouRow :- row; { global variables
Regs.CX :- integer( col shl 3; Convert coordinates and store
Regs.OX :- integer( row shl 3; { in global variables
Intr( $33, Regs ); ( Call mouse driver
begin
StdPtr :- Standard; { Reserve bitmask in global variable 1
637
14. Mouse Programming PC System Programming
procedure MouEnd;
begin
begin
TLine Lines; { Store number of lines and
TCol Columns; columns in global variables
end;
638
Abacus 14. Mouse Programming
(
( xl: 0; y1: 0; x2: 79; y2: 0 ), Top line
( xl: 0; y1: 1; x2: 0; y2: 23 ) , Left column
( xl: 0; y1: 24; x2: 78; y2: 24 ) , Bottom line
( xl: 79; y1: 1; x2: 79; y2: 23 ), Right column
( xl: 79; y1: 24; x2: 79; y2: 24 ) Lower right corner
);
begin
(-- Configure mouse pointer for the different mouse ranges ----------)
Ranges! °
].PtrMask := MouPtrMask( PtrDifChar($18) , PtrInVCol);
Ranges! 1 j.PtrMask := MouPtrMask( PtrDifChar($lb), PtrInVCol);
Ranges! 2 j.ptrMask :- MouPtrMask( ptrDifChar($19), PtrInVCol);
Ranges! 3 j.PtrMask :- MouFtrMask( ptrDifChar($la), PtrInVCol);
Ranges! 4 j.PtrMask :- MouPtrMask( PtrDifChar($58), ptrDifCol($40»;
(-- Wait until the user presses both the left and right mouse -----)
(-- buttons simultaneously while the pointer is in range 4 -----}
i - Program ----=:::--=----=--=--=----===-~~
639
14. MOlUe Programming PC System Programming
;----------------------------------------------------------------------
;-- AssmHand : The event handler which first calls the mouse driver, then
;-- calls the TP MouEventHandler procedure
;-- Direct call from TP not allowed
push ax
push bx
push ex
push dx
push di
push si
push bp
push es
push ds
;-- Call:
pop es
pop bp
pop si
pop di
pop dx
pop ex
pop bx
pop ax
640
Abacus 14. Mouse Programming
AssmHand endp
;------------------------------------------------------------------------
COOE ends ;End of code seqment
C listing: MOUSEC.C
/**********************************************************************/
1* M 0 USE C • C "I
1*--------------------------------------------------------------------"1
1* Task : Demonstrates mouse access from the C language *1
1*--------------------------------------------------------------------*1
1* Author MICHAEL TISCHER *1
1* Developed on : 04/20/1989 *1
1* Last update : 06/14/1989 *1
1*--------------------------------------------------------------------*1
1* Microsoft C *I
I' Creation : CL lAS MOUSEC.C MOUSECA.OBJ *1
I" Call : MOUSEC *1
1*--------------------------------------------------------------------*1
I" Turbo C (integrated system) *1
I" Creation Create a project file containing the following:"1
I" MOUSEC "I
I" MOUSECA.OBJ *1
I" Make sure that memory model is set to small. "I
I" If you didn't assemble the MOUSECA.ASM file *1
I" using the IMX option in MASH, make sure that *1
I" Case-Sensitive Link on Linker options is OFF. *1
I" Disable stack checking before compilation. "I
1* »NOTE: One warning will occur (about the *1
I" ButState in the MouEventHandler function). *1
1* The program will run. Do NOT remove "I
1* the ButState declaration - the AssmHand routine*1
I" needs it« *1
I' Call MOUSEC *1
/*.*************.***.*.********.*.******.*.*.**************************/
tinclude <dos.h>
'include <stdlib.h>
fdefine TRUE 1 1
fdefine FALSE 1 o
641
14. Mouse Programming PC System Programming
'define MouPtrMask( z, f )\
( « (PTRVIEW) f) » 8 « 24) + « ( PTRVIEW) z) » 8 « 16) +\
« (f) , 255) « 8) + «z) , 255)
642
AbaclLf 14. MOlLfe Programming
643
14. Mouse Programming PC System Programming
/*-- Check range in which mouse is currently located, and compare --*/
/*-- to range since last call. If a change occurs, the pointer's --*/
/*-- appearance will have to be changed. ---*/
newrng· * (bbuf + mourow * tcol + moucol); /* Get range */
i f ( newrng ! - moumg ) /* New range? */
MouDefinePtr«newrng==NO RANGE) ? stdptr :
- (cur range+newrng) ->ptr mask);
mourng - newrng; /* Place range n~r in global variables */
)
/********** •••• *** ••• **~** •• *********•••• *•••••••••••• ********* ••• ***•••
Function : M u I B u f F ill
..* _-------------------------------------------------------------------
Task
0
644
Abacus 14. Mouse Programming
/.*.************************.***********.*.***** •• **********************
* Function : M 0 u Eve n tWa i t
**--------------------------------------------------------------------**
Task Waits for a specific event from the keyboard.
Input parameters : TYP - Establishes comparison between
different events.
WAIT EVENT - Bitmask which specifies wait event. *
Return value Bitmask which describes this or another event.
Info - WAIT EVENT can be used with other constants
such-as FN MOO MOVE or FN LEFT PRESS when used *
* in conjunction-with FNOR.-
* - EAND ,FNOR are allowable types. EAND has the *
ability to return to the caller once ALL events*
have occurred; EVOR returns to the caller when *
at least one event occurs.
************************* •••• *.******************* •• **••• ****** •• ******/
/*-- When moving the mouse, the event is only accepted if the --*/
/*-- pointer moves to 'another row or column on the text screen --*/
645
14. Mouse Programming PC System Programming
}
ende - (cur_event !- 0); 1* Are events pending? *'
else 1* Event occurred *'
ende - TRUE;
'*'* *'*'
{
union REGS regs; Processor regs for interrupt call
struct SREGS sregs; Segment register for interrupt call
regs.x.ax OxOOOC;
regs.x.cx - event;
1* Funct. no. for "Set Mouse Handler-
1* Load event mask */
*'
regs.x.dx FP_OFF( ptr ); /* Offset address of handler */
sregs.es = FP_SEG( ptr ); 1* Segment address of handler *1
MOUINTX( regs, regs, sregs ); 1* Call mouse driver *1
}
/**********************************************************.************
* Function : M 0 u I Get Y
**--------------------------------------------------------------------**
Task Determines text row in which pointer lies. *
Input parameters : None
***********************************************************************/
646
Abacus 14. Moue Programming
/*************************************.**************.******* •• *********
Funct ion : M 0 u Hid e M 0 use *
**--------------------------------------------------------------------**
Task Hide mouse pointer from screen. *
Input parameters None *
Return value None *
Info Calls of MouHid~use() and MouShowMouse() must *
be kept balanced.
*********.***.*.* ••• ****.***** ••• ****.****************.*****.**********/
647
14. Mouse Programming PC System Programming
regs.x.cx - xspeed;
regs.x.dx - yspeed;
I
/************.*********.******************* ••••• ****************.****.**
Function : M 0 u M 0 v e P t r ',.. *
**---------~----------------------------------------------------------**
Task Moves the mouse pointer to a specific position *
on the screen. *
Input parameters - COL - new screen column *
- ROW - new screen row
Return value None *
Info - Both parameters apply to the text screen, NOT *
to the mouse driver's virtual graphic screen
***.***** •• **********.********.***************.*.****************.*.***/
648
Abacus 14. Mouse Programming
/ ••• **** ••••• ***.***.** •••••••• ** •••• ****** •••••• *** ••• *.*.********** •••
Function : M 0 u I nit *
**--------------------------------------------------------------------*.
Task Initializes variables and mousec module *
Input parameters Columns, - Text screen resolution *
Lines
Return value TRUE if a mouse is installed, else FALSE *
* Info This function must be called as the first one in *
* the module.
••••••••••••••• **.**** ••••••• **.***** ••••• ****** •••••••••• *********** •• /
649
14. Morue Programming PC System Programming
I;
BSS segment word public 'BSS' ;This segment includes all un
BSS ends ;initialized static variables
_DATA segment word public 'DATA' ;This segment includes all initialized
;global and static variables
_DATA ends
650
Abacus 14. Mouse Programming
;----------------------------------------------------------------------
;-- AssmHand: The event handler called by the mouse driver, then
;-- - called by the MouEventHandler () function
push bx
push ex
push dx
push di
push si
push bp
push es
push ds
pop es
pop bp
pop si
pop dl
pop dx
pop ex
pop bx
pop ax
651
14. Mouse Programming PC System Programming
_AssmHand endp
;------------------------------------------------------------------------
ends ;End of code segment
end ;End of program
652
Chapter 15
Determi:ning Processor
Types
There are number of utility programs on the market today which can tell you about
the configuration of a PC. This information can include the amount of available
RAM, the running DOS version and the type of processor the PC has.
This information can be very useful for developing programs in high level
languages, since code generation can be adapted to the particular processor. For
example, both Microsoft C and Turbo C allow special code generation for the
8088, the 80286 and the 80386, which makes full use of the capabilities of the
particular processor and instruction sel This can dramatically improve performance
for programs which work with large groups of data. One way to take advantage of
this would be to compile the program once for each of the three processor types.
Then a program could be developed to serve as the boot for the actual program.
This boot program would determine the type of processor being used and load the
main program version most compatible with the processor.
This raises the question of how to determine which type of processor is being
used, since unlike other configuration information, we cannot find this out by
making a BIOS or DOS call. Unfortunately, there is no machine language
instruction which instructs the processor to reveal its identity, so we have to use a
trick. This trick relies on a condition which, according to a few hardware
manufacturers, is totally impossible.
This is a test which involves the different ways the various processors execute
certain machine language instructions. Although processors from the 8086 to the
80386 are upwardly software compatible, the development of this processor series
brought small changes in the logic of certain instructions. Since these changes are
only noticeable in rare situations, a program developed for the 8088 processor will
also run correctly on all other processors in the Intel 80x86 series. But if we
653
15. Determining Processor Types PC System Programming
deliberately put a processor into such a situation, we can detennine its identity
from its behavior.
These differences are only noticeable at the assembly language level, so our test
program must be written in assembly language. We have included listings at the
end of this chapter which allow the test routine to be included in Pascal, C and
BASIC programs as well.
NO
80386
YES
80186/88
NEe V20/V30
YES
•• 88 processor
654
Abacus 15. D«urmining Processor Types
As the flowchart above shows, the routine consists of several tests which can
distinguish various processor types from one another. The next test executes only
when the current test returns a negative response.
If all four bits are set, then the processor cannot be an 80286 or an 80386, and the
next test is performed. However, if not all four bits are set, then we have reduced
the set of possible processors to the 80826 and the 80386. Since POPF also
operates differently between these two processors, it is easy to tell them apart We
simply repeat the whole process, this time by placing the value 07000H on the
stack instead of O. When the flag register is loaded with the POPF instruction, bits
12 to 14 of the flag register will be set to 1. If these bits are no longer 1 when the
contents of the flag register are fetched from the stack, then the processor must be
an 80286, which, in contrast to the 80386, sets these three bits back to O. The test
is then concluded for these two processors.
The second test makes use of this behavior by shifting the value OFFH in the AL
register 2lH positions to the right with the SHR instruction. If the processor
executing the instruction is an 80188 or later type, the upper three bits of the shift
counter will ftrst be cleared, and only one shift is performed instead of 21H shifts.
,ss
15. Determining Processor Types PC System ProgrtllNlling
Unlike its predecessors, which would actually shift the value OFFH to the right
021H times and return the value 0, the 80188 and 80186 will return the value
07FH. By checking the contents of the AI. register after the shift we can easy tell
if the processor is an 80188 or 80186 (AI. not zero), or not (AI. equal to 0). If the
processor also fails this test, then we know it is an 808818086 or V20/30.
VlO and V30 processors
The V20 and V30 processors are 8088/8086 "clones" which use the same
instruction set as their Intel cousins, but which operate considerably faster due to
the optimization of internal logic and improved manufacturing. This speed also
results in a higher cost, so some PC manufacturers avoid using these processors.
Once we have distinguished between the 8088/8086 and the V20/30, one last test
is performed for all processors (except the 80286 and 80386). In this test we
determine if the processor is using an 8-bit or a 16-bit data bus. This allows us to
tell the difference between the 8088 and 8086, the V20 and V30, or the 80188 and
the 80186. We cannot determine the width of the data bus with assembly language
commands, but the data bus width is related to the length of the instruction queue
within the processor.
Queue
The queue stores the instructions following the instruction currently being
executed. Since these instructions are taken from the queue and not from memory,
656
Abacus 15. Determining Processor Types
this improves execution speed. This queue is six bytes long on processors with a
16-bit data bus, but only four bytes long on processors with an 8-bit data bus.
The last test is based on this difference in length. The string instruction STOSB
(store string byte) used in connection with the REP prefIX modifies three bytes in
the code segment immediately following the STOSB instruction. These bytes are
placed so that they are found within the queue on a processor with a six-byte
queue; the processor won't even notice the change. On a processor with a four-byte
queue, these instructions are still outside the queue, so the modified versions of the
instructions are loaded into the queue. The program makes use of this by
modifying the instruction INC OX, which increments the contents of the OX
register which contains the processor code in the routine. This instruction is
executed only when the processor has a six-byte queue, and the instruction was
already in the queue by the time the modification was performed.
The following BASIC and Pascal programs use OATA orinline statements instead
of assembly language. However, we included the assembly language versions of
these statements here so that you can follow the program logic. The C
implementation requires direct linking of C and the assembly language routine.
BASIC listing: PROCB.BAS
100 1*****.****************.***************.********.************._****
120 '* ________________________________________________________________
110 1* PRO C B *'
180 •••• *•• *•• **••• ***••••*** ••• **•••• **••• **.*•• *•••••••• ***•• **••••••
190 '
210 PRINT"ATTENTION: This program should only be run when GW-BASIC is loaded from"
230 PRINT: PRINT"If this isn't the case, press the <s> key to stop."
340 END
350 '
1000 DATA "INTEL 8088", "INTEL 8086", "NEC V20", "NEC V30"
1010 DATA "INTEL 80186", "INTEL 8018S", "INTEL 80286", "INTEL 80386"
657
15. Determining Processor Types PC System Programming
1020 '
60000 .*.***•• ******** •• *.***************.*****.*.********.************'
60010 '*
Routine for determining onboard processor type *'
60020 ,*--------------------------------------------------------------*,
60030 '. Input : none *,
60040 ,* Output: PT is the starting address of the assembler routine *,
60050 ,* Call to the routine:CALL PT(PTYPt) *,
60060 1*****.*.***************.***********••• ************* •• *•••• ***** •.
60070 '
60080 PT-60000! 'starting address of BASIC segment routine
60090 DEF SEG 'Define BASIC segment
60100 RESTORE 60140
60110 FOR It - 0 TO 105 READ X% POKE PT+It, X% NEXT 'POKE routine
60120 RETURN 'Return to caller
60130 '
60140 DATA 85,139,236,156, 6, 51,192, 80,157,156, 88, 37, 0,240, 61
60150 DATA 0,240,116, 19,178, 6,184, 0,112, 80,157,156, 88, 37, 0
60160 DATA 112,116, 54,254,194,235, 50,144,178, 4,176,255,177, 33,210
60170 DATA 232,117, 18,178, 2,251,190, 0, 0,185,255,255,243, 38,172
60180 DATA 11,201,116, 2,178, 0, 14, 7,253,176,251,185, 3, 0,232
60190 DATA 23, 0,250,243,170,252,144,144,144, 66,144,251, 50,246,139
60200 DATA 126, 6,137, 21, 7,157, 93,202, 2, 0, 95,131,199, 9,235
60210 DATA 227
org 100h
658
Abacus 15. Determining Processor Types
659
15. Determining Processor Types PC System Programming
proqram PROCP;
{*******.********.***********.************************.****************}
{* GETPROC: Determines processor type in PC *'
{* Input none *,
{* Output
1* Info
(*
Processor code (see CONST)
This function can be used in a proqram when added as
a UNIT
*'
*}
*)
{***** •• ***********.***************************************************}
660
Abacus 15. Determining Processor Types
inline (
$9C/$Sl/$S2/sS7/sS6/S06/s331$C0/s50/s9D/$9C/$58/$25/$001
$FO/s3D/SOO/SFO/$74/$13/SB2/$06/SB8/S00/S70/sS0/$9D/S9C1
SS8/S25/$00/$70/$74/s36/SFE/$C2/$EB/S32/$90/SB2/S04/SBOI
SFF/$B1/$2l/$D2/SE8/$7S/s12/SB2/S02/sFB/$BE/sOO/$00/sB91
$FF/SFF/SF3/S26/SAC/SOB/sC9/S74/$02/$B2/S00/S0E/s07/SFD1
SBO/SFB/SB9/$03/S00/SE8/s16/S00/SFA/SF3/$AA/SFC/s90/S901
S90/$42/S90/SFB/S88/S56/SFF/S07/S5E/S5F/$5A/$59/$9D/SEB/
$07/$90/S5F/S83/$C7/S09/SEB/SE4
);
end;
begin
writeln('PROCP - (c) 1988 by MICHAEL TISCHER');
writeln(f13flO, 'Your PC contains a(n) " ProcName[getproc),
. processor.');
writeln(f13flO);
end.
661
15. Determining Processor Types PC System ProgrtlllUlling
push si
push es
662
Abacus 15. Determining Processor Types
;------------------------------------------------------------
pende label near ; End testing
end getproc
C listing: PROCC.C
/* ••• ****************••••• *********************************************/
1* PRO C C *1
1*--------------------------------------------------------------------*1
1* Task : Determines the processor type in a PC *1
1*--------------------------------------------------------------------*1
1* Author MICHAEL TISCHER *I
1* Developed on : 08/14/1988 *1
1* Last update : 06/22/1989 *1
1*--------------------------------------------------------------------*1
1* (MICROSOFT C) *I
1* Creation CL lAS Ic PROCC.C *1
1* LINK PROCC PROCCA *I
1* Call PROCC *I
1*--------------------------------------------------------------------*1
1* (BORLAND TURBO C) *1
1* Creation Create a project file containing these lines: *1
1* PROCC *1
1* PROCCA.OBJ *1
/*******•• *****••• ***************** •••••• **•• *******.*****•• *****••• *.*/
void main()
{
static char * procname [] - 1* Vector wi pointers to proc. names *1
-Intel 8088-, 1* Code 0 *1
-Intel 8086-, 1* Code 1 *1
-NEC V20-, 1* Code 2 *1
663
15. Determining Processor Types PC System Programming
procname[ qetproc() 1 );
_DATA segment word public 'DATA' ;This segment includes all initialized
;gobal and static variables
DATA ends
;z:_ Constants =========_ _==__ ====--===--===-==_ _==-=_-===-==
p:::80186 equ 5
p_B01BB equ 4
p_v30 equ 3
p_v20 equ 2
p_BOB6 equ 1
p_B08B equ 0
664
Abacus 15. Determining Processor Types
665
15. Determining Processor Types PC System Programming
nop
'Lend: stl ;Re-enable interrupts
;------------------------------------------------------------
pende label near ; End testing
666
Chapter 16
PC Hardware Interrupts
Now that you're more familiar with the DOS and BIOS interrupts that are triggered
by software, let's look at hardware interrupts. As the term suggests, these
interrupts operate mainly through calls from PC hardware.
Well begin with the interrupts which are called directly by the processor. These
eight interrupts can also be triggered by software through the use of the INT
instruction.
The 8088 has two assembly language instructions (DIV and IDlY) which permit
division of a 16-bit or 32-bit whole number by an 8-bit or a 16-bit whole number.
According to the general rules of mathematics, division by zero is illegal. This
means that you cannot perform the equation 485/0. The equation has no resulL
Because of this, the 8088 prohibits any divisions using a denominator of O. If a
division by zero occurs, the processor triggers interrupt O. The vector assigned to it
is pointed to by DOS during its initialization to its own routine. During the call
of this interrupt, the DOS routine call executes. Most versions of DOS display a
"Division by Zero" message. The program then continues with the instruction
following the division that caused the error.
The CPU calls this interrupt when the TRAP bit in the flag register of the CPU is
set to 1. The interrupt then receives a call after every execution of a machine
language instruction. This interrupt allows the user to trace the execution of every
instruction in a assembly language program to determine changes in register
contents or the instructions executed.
667
16. PC HQI'dwQl'e Interrupts PC System Programming
resets the TRAP bit during entry into the interrupt routine. It stores the complete
flag register and the TRAP bit on the stack.
IT an IRET instruction ends this interrupt routine, it automatically sets the TRAP
bit to the old value by restoring the complete flag register from the stack. After
completion of the next instruction, interrupt 1 is recalled. Once the programmer
has obtained all desired information about the program, the TRAP bit can be
disabled. However, the program being examined doesn't know it's being run in
single-step mode, and has no instruction to reset the TRAP bit in the flag register.
During the system boot, DOS points the vector to its own routine. IT a RAM error
does occur, this calls the proper BIOS routine which displays a message on the
screen and stops the system.
This interrupt is also used in utility programs. Unlike the other interrupts, which
are called by two-byte-Iong assembly language instructions (byte l=CDH, byte
2=interrupt number), interrupt 3 can be called with a single-byte assembly
668
Abacus 16. PC Hardware Jnlerrupts
language instruction (CCH). This interrupt is very useful for testing programs up
to a certain point in the code. Interrupt 3 halts a running program. and allows the
user to examine the current contents of the registers.
Applying interrupt 3
Using a specific utility program for reference (e.g., DEBUG), you place a call for
interrupt 3 in the program in process where you want execution to stop. When the
processor reaches this location during program execution, it calls interrupt 3. The
testing program contains a routine which displays the current register contents and
other data. Then this routine replaces the interrupt 3 call with the instruction
which fonnerly occupied its location.
You could argue that instead of the call for interrupt 3, any other interrupt could be
called to interrupt the program, if a suitable interrupt routine had been installed to
display register contents. etc. Interrupt 3 ~ffers some advantages over this. It can
be called with a single-byte instruction. I
This interrupt has no application other than use with a testing/debugging utility.
Otherwise, DOS points to a routine which contains an IRET (Interrupt RETurn)
instruction, which immediately returns the system to the interrupted program.
This interrupt can be called by a instruction which is based on a condition. It's the
INTO (INTerrupt on Overflow) asSembly language instruction which only calls
interrupt 04H when a set overflow bit occurs in the flag register during execution.
This can happen after math operations (e.g., multiplication using the MUL
instruction). if the result of this operation cannot be represented within a set
number of bits. This interrupt can also be called using the normal INT instruction.
but this instruction doesn't read the status of the overflow bit Since this interrupt
is seldom used, DOS sets it to an IRET instruction.
669
16. PC Hardware Interrupts PC System Programming
Interrupt 05H belongs with the BIOS interrupts, even though it is technically a
hardware interrupt. Pressing the <Prt Sc> key calls this interrupt through BIOS.
This key has labels which differ from one manufacturer to another. The Tandy
1000 HD version is labeled <PRINT>, but most others have <PrtSc> labels. This
key sends the current contents of the screen to a printer interfaced to the PC. This
printout is called hardcopy.
DOS initializes the vector of this interrupt in the vector table. Both assembly
language programs and programs written in high level languages can access this
interrupt using the !NT instruction.
At the time of this writing, interrupts 06H and 07H are unused. They are reserved
for later use, but can be used now for other applications.
Interrupts 08H-OFH
Interrupts 08H to OFH are generated by the 8259 interrupt controller. This chip
receives all interrupt demands within the system fIrst. It detennines the priority in
which multiple interrupt requests must be executed. The interrupt given highest
priority passes through the INTR line to the CPU. Up to eight interrupt sources
(devices) can be connected to the 8259, with each device assigned a different
priority. With the help of the interrupt bits in the flag register, the CPU can
suppress all interrupt calls from the 8259 (except NMI interrupt 2-see above).
Interrupt generation from special equipment can be prevented. For this the interrupt
mask register of the 8259 must be accessed through port 2lH. The eighth bit of
this register is connected to the maximum of eight devices which create interrupts.
Bit 0 represents device 0, bit 7 the device with the number 7. If a bit has the value
0, the CPU receives the interrupt calls generated by the device assigned to it from
the 8259. If it contains the value I, the interrupt calls are suppressed. If several
interrupt calls occur at the same time, the device which is connected to bit 0 gets
the highest priority and bit 7 the lowest priority. If the highest priority interrupt
has been processed, theoretically the interrupt with the next priority down can be
transmitted from the 8259 to the CPU.
670
Abacus 16. PC Hardware interrupts
port This tells the 8259 that interrupt processing is done, and the next interrupt
can be called.
The bit assignment in the interrupt mask registers (i.e., device assignments and
priorities) differ between individual members of the PC family. You can usually
assume that the device connected to bit 0 of the interrupt mask register triggers
interrupt 08H. The device connected to bit 1 triggers interrupt 09H, etc. Interrupt
OFH (the last interrupt called by the 8259) is triggered by the device attached to bit
7 of the interrupt mask register. Generally these eight interrupts have designations
ofIRQO, etc. up to IRQ7. IRQ stands for Interrupt ReQuest.
AT interrupt controllers
The AT has two 8259 interrupt controllers, so it can control up to 16 interrupt
sources. The interrupts in the second controller have designations ranging from
IRQ8 to IRQI5. If an interrupt request is made from one of the eight interrupt
sources of the second interrupt controller, it simulates the request from a device
connected to bit 2 of the ftrst interrupt controllers. Because of this, all interrupt
requests from the second interrupt controller have a higher priority than those from
devices 4 to 7 of the ftrst interrupt controllers. If several devices demand attention
from the second interrupt controller, it services the interrupt source with the
highest priority, which is the one connected to the lowest bit in the interrupt mask
register.
Interrupt requests from the devices on the second interrupt controller can be
suppressed by manipulating the corresponding bits in the interrupt mask register.
This register is located at port address AIH, not at 21H like the ftrst interrupt
controller. The interrupt instruction register of the second interrupt controller, to
which the EOI instruction must be sent after the completion of the interrupt from
this controller, is at address AOH inst.ead of 20H. In addition to the EOI instruction
to the second interrupt controller, an EOI instruction must be sent to the ftrst
interrupt controller on port 20H at the end of the interrupt routine. This results
from the interconnection between these two controllers, since every interrupt
request to the second interrupt controller triggers an interrupt request on the frrst
interrupt controller.
671
16. PC Hardware /nJerrllpts PC S,stem Programming
The following fIgures show the interrupt request devices and their priorities.
PC
• decreasing priority
7 6 5 4 3 2 1 0 bit __- - - - - - - . . ,
controller
XT
• decreasing priority
7 6 5 4
Interrupt controller
at port
L - - - i Timer
Keyboard
L.._ _ _ _ _ _ _ ~ ~~d serial Interface
disk
672
Abacus 16. PC Hardware lnlerrupts
AT
765
..
decreasing priority
4 321
..
decreasing priority
The PC's 8253 timer chip oscillates at 1,193,180 cycles per second It receives its
signal from the 8284A clock generator chip. After 65,536 of these signals (about
18.2 cycles per second), it calls interrupt 08H, which the 8259 transmits to the
CPU. Since the occurrence of these interrupt calls is independent of the clock
frequency, this interrupt works well for time measurement. After 18.2 calls means
that a second has elapsed. BIOS points the interrupt vector of this interrupt to its
own routine, which is called 18.2 times per second. The routine increments the
time counter at every call and switches off the disk motor if no access to the disk
has occurred within a certain span of time. After this task has been completed, the
routine calls interrupt lCH. It can be accessed by the user for routines which
depend upon a continuous signal.
The keyboard has either an Intel 8048 processor (for PC/XT) or an 8042 processor
(for An. It controls the keyboard and registers if a key was pressed, released or
pressed and held. The keyboard chip sends a signal to the 8259, which causes the
CPU to call interrupt 09H (unless an interrupt request with a higher priority is
present). The CPU calls a BIOS routine which reads the character from the
keyboard and stores it in the keyboard buffer.
673
16. PC Hardware /nlerrllpts PC System Programming
These interrupts vary with the hardware connected to the computer. Check your
technical manuals and hardware manuals for more information, and experiment.
The system calls interrupt ODH if a hard disk is connected to the computer. This
occurs when a read or write operation ends and BIOS must be informed of this facL
The disk controller(s) calls this interrupt in conjunction with the 8259 when the
controller needs the attention of the CPU. A BIOS routine following this interrupt
communicates on the lowest level with the controller. During the call of this
interrupt, the controller passes certain information to inform BIOS that a read or
write operation was completed, or an error occurred.
A parallel printer calls this interrupt in conjunction with the 8259 when the
controller needs the attention of the CPU.
A T interrupts
Because of the second interrupt controller in the AT, it has more hardware
interrupts than the PC or XT. This second interrupt controller can call interrupts
70H to 77H. These interrupts were available to older PCs for application
programs. Recently manufactured PCs and XTs cannot use these interrupts.
Similar to the first interrupt controller, the device connected with bit 0 of the
second interrupt controller's interrupt mask triggers interrupt 70H. The device on
bit I calls interrupt 71H, bit 2 calls interrupt 72H, etc.
Only interrupts 70H and 75H are called by the interrupt controller because devices
are only connected to bits 0 and 5 of the interrupt mask register. However, the
interrupt vectors of interrupts 71H to 74H and 76H and 77H should not be
redirected.
Interrupt 70H can stop a program because of alarm time, the current time and date,
or just an interrupt call repeated within a certain time span. The interrupt is
normally serviced by a BIOS routine which detects the reason for the interrupt then
responds occordingly.
674
Abac/IS 16. PC Hardware Interrupts
Interrupt 75H informs the ATs CPU that a mathematical coprocessor (80287)
attached to the system requires attention (e.g., because it has completed a certain
calculation).
The AT hard disk: controller calls this interrupt after completing a hanl disk: access.
Demonstration programs
The two sample programs below demonstrate some of the hardware interrupts
described in this chapter. Both programs are resident interrupt drivers which are
installed and deactivated using the same principles as demonsttated by programs
earlier in this book.
The first program displays the current time in the upper right comer of the display
screen. The second program sends the contents of a screen to a ftle instead of a
printer.
Clock timing
Before discussing each program's structure, you should know about the basic
principles of the clock. Interrupt lCH implements the clock. Timer interrupt 8H
calls interrupt lCH 18.2 times per second.
When this routine counts the number of calls that occur, it knows that exactly one
second elapses after 18.2 calls, and that it must display the time on the screen once
every second. This is great, except that the clock can count one, two, even 18
calls-but not 18.2 calls.
One solution would be to have the clock update the screen display after 18
interrupt calls. This would result in the clock running fifteen minutes fast every
day. You can solve this problem using a trick that we use in everyday living. Our
year doesn't have exactly 365 days. Every four years the calender has a leap year,
which keeps OIB' dates on schedule with Earth's realtime clock.
The PERMCLK program does something similar with the clock. After 18 calls of
the timer interrupt routine, the clock advances one second and the new time appears
on the screen. Therefore, the time advances by five seconds after 5x18 (90) calls.
Five seconds in reality equals 5x18.2 (91) calls. To compensate for the missing
call, the program adds a sixth second after 19 calls. This makes the time
measurement more accurate. Since a second actually corresponds to 18.20648193
calls, the clock will still be fast by a few seconds after a day passes. To
compensate for this, an additional second is introduced after 20 calls. This makes
the clock only about a second fast within a 24-hour period. That's fairly accurate,
675
16. PC Hardware /nlerrllpts PC System Programming
especially when you consider that the average PC doesn't remain switched on for
more than eight hours at a time.
;.** •••• **•••••••••••••• **••••• **•• ** •••••••••• **** ••••• **** •• *******;
;* PERMCLK *;
;*------------------------------------------------------------------*;
;* Task : displays the current time on the *;
;* display Screen *;
;*------------------------------------------------------------------*;
;* Author MICHAEL TISCHER *;
;* developed on : 8.10.87 *;
;* last Update : 9.21.87 *;
;*------------------------------------------------------------------*;
;* assembly MASM PERM:LK; *;
;* LINK PERM:LK; *;
;* EXE2BIN PERM:LK PERM:LK.COM *;
;*------------------------------------------------------------------*;
;* Call : PERMCLK •;
; •••••••••••••••••••••••• *** •••***.**.** ••• **••••••••• *••••• **** •••• *;
org 100h
tenmint
db ...
db (1) ;one hours as ASCII
676
Abacus 16. PC HQI'dwQl'e Interrupts
677
16. PC HQ1'dware 1nterrupts PC System ProgrtlllUtling
newint endp
678
Abacus 16. PC HQ1'dwQ1'e lraterrupts
;-- only the PSP, the new interrupt-routine and the -------
;-- Data for it, must remain resident
binascii endp
Installation and reinstallation has similarities to the resident interrupt driver already
discussed. It installs itself during its first call and deactivates itself on the
following call.
679
16. PC Hardware 1nterr"Pts PC System Progrtlnlming
The code following the INSTALL label initializes all the program's variables.
First the DOS function 2CH reads in the current time, converts the time into
ASCn code and places the data in the variables TENHOURS, TENMINT and
TENSECS. These variables, which are part of an AScn string, act as buffers for
the time display and are updated once every second. After these variables have been
initialized, the program installation takes place.
Let's look at the clock itself, the new interrupt routine of interrupt lCH. It begins
in the listing at the label NEWINT. It jumps to the label NEWI1MER to bypass
the identification code. All registers changed by the following commands are stored
on the stack. Then the counter (the variable) NUMCOUNT is decremented.
NUMCOtfflT has nothing to do with time measurement; it determines how often
to display the time on the screen. Normally the clock must be redisplayed when
the time has changed (every second). Since the screen scrolls in some applications
(e.g., DOS), the clock would quickly disappear from the display. To display a
clock that looks stationary, it must be redisplayed more often than once a second.
When NUMCOUNT reaches the value 0, this means that the clock display
reappears with the following commands, even if a new second hasn't occurred.
After NUMCOUNT reaches zero, it resets to its original value so that it can be
decremented again the next time the routine is called. The constant CLOCKNUM
contains the original value (6), which displays the clock ai~ 6/18 second (one
third of a second). You may preset other values to display the clock more or less
often.
At the label NONUM the counter TCOUNT decrements. It contains the number of
remaining calls until a second has elapsed. If the number is equal to zero, a second
has elapsed and a jump occurs to the label NEXTSEC where it resets to 18 so that
the next second can be displayed after 18 calls.
If a second hasn't elapsed, the program tests for whether the variable NUMCOUNT
reached zero and resets to its starting value during this call of the timer interrupt If
this was the case, the time appears on the screen and the interrupt ends. If the time
isn't displayed, the interrupt can be ended directly.
After NEXTSEC resets TCOUNT to 18, the frrst correction counter decrements. If
it is equal to zero, it means that five seconds have elapsed and that the next second
can only be initiated after 19 calls. The TCOUNT counter increases from 18 to 19
and the frrst correction counter resets to five. Then the second correction counter
decrements. If it then contains the value zero, then 31x5 seconds have passed and
the next second can only be initiated after 20 calls.
At the label SETTIME, incrementing the least significant digit of seconds (one) in
the variable ONEMIN sets the new time. A test is made for the start of a new
minute, a new hour or a new day; the time changes accordingly.
680
AbacllS 16. PC Hardware/nterrupts
The label OUTPUT begins the actual time display. OUTPUT reads the current
display page and cursor position. This data passes to the stack so it can be restored
after the time is displayed on the screen. The cursor moves into position and the
program displays the clock, character by character.
In the final step, the previously stored current cursor position is removed from the
stack and set This occurs through a function of the BIOS video interrupt.
This concludes the work of the timer routine. It restores the registers from the
stack, passing them unchanged to the interrupted program. It finally ends with a
jump to the old timer routine.
The HC2FILE program
The second sample program in this chapter reroutes hardcopy data to a fIle instead
of a printer. The program requires the entry of the program name and the path and
name of the hardcopy fIle. This name can contain a device and path designation,
but must have a three digit number as an extension (e.g., 000 or 153). A sample
call would look like this from the DOS prompt:
C>hc2file a:hc.OOl
You would then press <Shift><Prt Sc> as you would for a printed screen
hardcopy. To capture hardcopies in sequence, the number in the flle extension
automatically increments after the creation of every hardcopy fIle. For example, the
flfSt hardcopy goes to a fIle named HC.OOI and a second hardcopy would go to a
file named HC.OO2. During output the individual characters are read from the
current display page, but their colors (an attribute) are not stored. The screen lines
in the file write to disk in sequence (no carriage returns separate lines). You can
view this fIle on the screen using the DOS TYPE command.
The program expects a fIlename during the first call from the DOS level. If you
omit the fllename, the HC2FILE program will not be installed. If you call the
program again after its installation without passing a fllename, it deactivates the
installed hardcopy program and releases the memory it occupied. If the program is
called again with a fIlename after a successful installation, the installed hardcopy
program remains active, and the new name for the hardcopy file takes effect.
Perhaps the new hardcopy interrupt routine may be of interest. You call it after
installation by pressing <Shift> <Prt Sc>.
First it determines the number of the current display page and the current cursor
position using a function of the BIOS video interrupt. It stores these on the stack,
returning them to BIOS after the output of the hard copy. Then it opens the fIle
which is to receive the hard copy. An error message is output if the attempt fails.
In the next step the display screen content is read line for line into a buffer
(starting at the beginning of the PSP) and is written from there to a file. Here also
681
16. PC Hardware /nlerrllpts PC System Programming
an error message is output through DOS if an error is reported and the file is
~
If the hardcopy could be output successfully, the me is closed and the extension of
the ftlename (the number of the hardcopy) is incremented. Once the number 1,000
is reached, the numbering restarts at O.
Warning:
An important restriction during the use of this program must be observed. It can
only be called when no access is made simultaneously by DOS to the disk or hard
disk. If the new hardcopy is called during the DOS access, most systems will crash
because DOS is not capable of controlling several file or disk accesses
simultaneously. DOS is not re-entrant. Remember this limitation when using this
routine, because it cannot be bypassed.
i***************··*********·*******·······************ *** ••••• **•• **;
;* HC 2 F I L E *;
;*-----------------------------------------------------------------*;
;* Task Outputs the Hardcopy of an SO-column-text *;
;* screen in a file instead of the printer. *;
;* The file must have a three digit number *;
;* as extension which is incremented after *;
;* the output of the hard copy so that several *;
;* hard copy files can be created in succession*;
;*-----------------------------------------------------
;* WARNING
------------*i
after installation of this program *;
;* no hard copy may be called during *;
;* a disk or hard disk access. *;
;* The system will crash since DOS is not *;
;* reentrant! *;
;*----------------------------------------------------
;* Author MICHAEL TISCHER
-------------*i
*;
;* developed on : S.11.S7 *;
;. last Update : 9.21.87 *;
;*-----------------------------------------------------------------*;
;* assembly : MASM HC2FILE; *;
;* LINK HC2FILE; *;
;* EXE2BIN HC2FILE HC2FILE.COM *;
;*------------------------------------------------------
;* Call : HC2FILE [(Dr:) (Path) Filename.zzz]
-----------*i
,
:*********************.****************** •••••*****.****************:
org lOOh
682
AbtJclU 16. PC HQI'dwQl'e/1tIeTnIp1s
newhc: sti
;interrupts are again permitted
anp cs:print,O
;printing in progress?
je dohc
;NO --> print out
jmp newhcend
;YES --> do not output hard copy
push ex
push dx
push di
push si
push es
push ds
mov ax,es
;bring CS to AX
mov ds,ax
;and then set OS and ES
mov es,ax
cld
ion string commands count up
mov ah,15
;read current display page
int 10h
;call BIOS video-interrupt
int 10h
;call BIOS video-interrupt
push dx
; store on the stack
mov ah,3Ch
;create function number for file
xor ex, ex
;should become normal file
mov dx,130
;filename at DS:130
int 21h
; call DOS-interrupt 21H
jc error
;carry-flag set --> Error
mov bl,-l
;begin with line 0
cmp bl,25
;all lines printed?
je datclose
;YES --> close file
call hcl1ne
;NO --> output a line
jnc nextl1ne
;no error --> next line
mov ah,3Eh
;close function nr. for file
mov bX,handle
;access-key
int 21h
;call DOS-interrupt 21H
mov ah,41h
;erase function nr. for file
mov dX,130
;filename at DS:130
int 21h
;call DOS-interrupt 21H
683
16. PC Hardware 1nterrllpts PC System Programming
newint endp
;-- HCLINE Write a display line into the file ---------------
i-- Input BL - the number of the line
;-- BH - the number of the display paqe
i-- OUtput Carry-flaq - 1 : Error
;-- Reqister AX, ex, OX, SI, 01 and FLAGS are chanqed
684
16; PC HardwareJnlerrupts
db "was changed",13,10,"$"
pop ds ;restore OS
685
16. PC Hardware InlerTupts PC System ProgrfJl1lllling
hc1nit endp
686
Chapter 17
FDISK is the hard disk partitioning program available in MS-DOS. You probably
used the FDISK command if you installed your own hard drive, or if you've
enhanced a PC with an operating system such as XENIX, CP/M-86 or OSfl.
FDISK is the key to operating high capacity hard disks and to installing multiple
operating systems on one computer.
FDISK represents only one step of a three step formatting process. This process
formats and partitions a hard disk drive, preparing it for one or more operating
systems.
Some XT-compatible PCs had to be low level formatted using the DEBUG
program. DEBUG called the low level format routine from the hard disk
controller's ROM-BIOS. Most hard disk manufacturers now provide programs
which make the low level formatting process much simpler.
Partitioning
The next step in formatting the hard disk is partitioning. As the name suggests,
this process divides the hard disk into defInite regions. The original purpose of
partitioning was to divide hard disks into areas which could be occupied by
different operating systems, without the operating systems conflicting with one
another.
The drop in hardware prices in the late 1980s provided another reason for
partitioning. Hard disks became available at low prices with capacities of 40
megabytes and more.
687
17. Hard Dis/c Partitioning PC System Programming
This posed a problem. Versions of DOS below Version 3.3 could only support a
maximum of 32 megabytes per hard disk. In addition, earlier versions of DOS
couldn't partition hard disks into several units.
DOS version 3.3
Version 3.3 of DOS still limited hard disk access to a maximum of 32 megabytes,
but offered some alternatives to the user. DOS 3.3 allowed the configuration of a
primary partition in the first 32 megabytes of the hard disk, as well as 23
additional extended partitions using drive specifiers of D to Z. Since every extended
partition can have up to 32 megabytes, this partitioning increased the maximum
hard disk capacity to 768 megabytes. FDISK names these partitions PRJ DOS and
EXT DOS.
DOS version 4.0
DOS version 4.0 pennits mass storage device support up to 2 gigabytes, thanks to
revised device drivers. However, many users still prefer partitioning their hard disk
unit into logical hard disks (smaller drives), since file management is easier on the
logical drives than having hundreds of ftles on one drive.
FDISK creates a special sector called the partition sector which it places on the
first hard disk sector (head 0, cylinder 0, sector 1). BIOS loads this partition sector
into memory address OOOO:7COO, unless the user has placed a disk in drive A:
before power-up or reset If the computer fmds the code sequence 55H, AAH in the
last two bytes of this 512-byte sector, it treats this sector as executable and starts
program execution with the first byte of the sector. Otherwise, BIOS displays an
error message and either starts an infinite loop or starts ROM BASIC, depending
on the manufacturer and version of the system.
Hard disk partition sector li!Yout
Addr. Content
'!'Y£.e
+OOOH Partition code
+lBEH 1st ent~ in the partition table 16 ~tes
+lCEH 2nd entl"Y in the partition table 16 ~es
+lDEH 3rd entl:"Y in the partition table 16 ~es
+lEEH 4th entry in the partition table 16 bytes
+lFEH Partition sector rec~nition code (AA55H) 2 ~tes
Length: 200H (512) ~tes
The program code in the boot sector recognizes the active partition and the
operating system to be started. The boot sector and the required operating system
code loads and executes. Since this program code by definition must also be at
memory address OOOO:7COO, the partition code moves to memory address
0000:0600 and releases the memory for the boot sector.
688
Abacus 17. Hard Disk Partitioning
The routine obtains the location of the boot sector to be loaded from the hard disk,
and the boot sector's corresponding partition. The partition table located in the
partition sector at address IBSH contains this information.
Partition table entry layout
OOH = inactive
80H = boot partition
+OlH Read/write head where partition starts 1 byte
+02H Sector and cvlinder where partition starts 1 word
+04H Partition type 1 byte
OOH = entry not occupied
OlH - DOS with l2-bit FAT (primary partition)
02H = XENIX
03H = XENIX
04H = DOS with l6-bit FAT (primary partition)
OSH = extended DOS-Partition (after DOS 3.3)
06H = DOS-4.0 partition with more than 32 meg
DBH = Concurrent DOS
Other codes possible in conjunction with other
operatinq systems or s~ecial driver software
+OSH Read/write head at end of partition 1 byte
+06H Sector and cylinder at end of partition 1 word
+08H Distance of first sector of the partition 1 dword
(boot sector) from partition sector
(measured in sectors)
+OCH Number of sectors in this partition 1 dword
Length: lOR (16) bytes
Every partition is described within this table through a 16-byte structure. Since the
table is almost at the end of the partition sector, there is only room available for
four entries. This limits the number of partitions to four. To provide more
partitions on a hard disk, some manufacturers offer a special configmation program
which moves the table ahead within the partition sector and installs new partition
code which accesses the reconfigured table. The basic format of the table remains
unchanged. Remember that individual partition entries do not always start with the
first table entry. The partition of a hard disk can be described through the first,
second, third or even fourth table entry.
The boot partition can be recognized through the first field of the partition
structure. The value OOH stands for "inactive," while the value 80H indicates the
partition for booting. If the partition code detects no bootable partition, more than
one partition, or even unknown code during the table check, the booting process
terminates and the system goes into an endless loop. The only alternative is to
reset the system.
If the partition code recognizes the partition to be booted, it can determine the
position of this partition on the hard disk through the two following bits. The
sector and cylinder number are coded in the form compatible with BIOS interrupt
689
17. Hard Disk Partitioning PC System Progrflllflftlng
13H (disk/hard disk). Bits 6 and 7 of the sector number represent bits 8 and 9 of
the cylinder number. Interrupt 13H and its functions are the only means of
accessing the hard drive. DOS functions are unavailable until after the system
boots DOS.
Even though this information is enough to load the boot sector of the starting
partition, the partition table contains some additional information which is
important for later changes and additions. The position of the boot sector is
followed by a field which describes the type of operating system hidden behind the
partition.
Besides ttJe starting sector, the ending sector of the partition is indicated in the
partition sector. The position of this sector is again described through an indication
of the head, cylinder and sector numbers. The last two fields of a table entry
contain the number of sectors within the partition, the distance of the boot sector
of the partition from the partition secD, as counted in sectors.
When the partition table is checked, it usually determines that the fmt partition
starts with sector one, track zero of the second read/write head, instead of
immediately following the partition sector. This wastes almost all of track one of
the fmt read/write head, almost the complete first track of the first head is wasted,
not counting the partition sector in the fmt sector of this track.
The extended DOS partitions suffer from some inconsistencies. First of all, OOS
Version 3.3 allows only one extended partition on a hard disk, other than the
primary partition. FDISK provides the extended partition with a partition sector
containing a partition table instead of program code. This table consists of two
entries:
1.) A deSCription of the extended partition proper, along with a partition type
value of either 1 (DOS partition with 12-bit FAT) or 4 (DOS partition
with 16-bit FAT)
The following programs in Pascal and C display the contents of the partition
sector, and follow the partition sectors of any extended partitions.
690
AbacllS 17. Hard Disk Partitioning
SecCyl
Read/wri te head number
*'
end;
{***.******************************************************************}
{* GetSecCyl:, Determines the combined sector/cylinder coding of BIOS *'
{* sector and cylinder number *'
(**------------------------------------------------------------------**)
1* Input : SecCyl : Value to be decoded *'
691
17. Hard Disk Partitioning PC System Programming
begin
Sector :- secCyl and 63; Exclude bits 6 and 7 )
Cylinder :- hi( SecCyl ) + ( lo( SecCyI) and 192 ) sh12;
end;
begin
writeln;
DR := DR + $80; I Prepare drive number for BIOS
if ReadPartSec( DR, 0, 1, ParSec) then I Read partition sector
begin I Sector is readable
Regs.AH := 8; I Read drive data
Regs.DL := DR;
Intr( $13, Regs); I call hard disk interrupt
GetSecCyI( Regs.eX, Sector, Cylinder );
writeln('r-----------------------------------------,+
---------1');
Upper left corner can be typed using <Alt><201>
Top horiz. line can be typed using <Alt><205>
Upper right corner can be typed using <Alt><187»
writeln('1 Drive ',DR-$80, ': " Reqs.DH+1:2,
, Heads with " Cylinder:5, , cylinders and "
Sector:3, , sectors I');
( Vert. lines can be typed using <Alt><186>
writeln('1 Partition table in partition sector ,+
I ') ;
Vert. lines can be typed using <Alt><186>
writeln ('{--T--T T T'+
-----------·T---T~');
I Left T can be typed using <Alt><204>
692
Abacus 17. Hard Disk Partitioning
begin
writeln( .13.10'-------------------------------- FIXPARTP - (c)',
, 1989 by MICHAEL TISCHER ---' );
HrdDrive :- 0; { Default is first hard disk
if ParanCount - 1 then other drive specifier given?
begin { YES
val ( Param5tr (1), HrdDrive, DError ); { ASCII/decimal
if DError <> 0 then Conversion error?
begin ( YES
writeln(.13.10'Il1egal drive specifier!');
exit; End program
end;
end;
ShowPartition( HrdDrive ); { Display partition sector)
end.
693
17. Hard Disk Partitioning PC System Programming
C program: FIXPARTC.C
/******************************************••********* *****************1
1* F I X PAR T C • C *1
*--------------------------------------------------------------------*1
1* Task : Displays hard disk partitioninq *1
I*----------------------~---------------------------------------------*1
1* Author MICHAEL TISCHER *1
1* Developed on : 04/26/1989 *1
1* Last update : 06/22/1989 *1
1*-----------------------------------------------------------------~--*I
1* call : FIXPARTC [ Drive number 1 *1
1* Default is drive 0 (Drive C:) *1
/.*************.* •••• **********••• ************•• ******••• *.************,
'include <dos.h>
'include <string.h>
'include <stdlib.h>
'define TRUE (1 -- 1 )
BYTE ReadPartSec( BYTE HrdDrive, BYTE Head, WORD SecCyl, PARSPTR Buf )
694
Abacus 17. Hard Disk Partitioning
return IRegs.x.cflag;
I
/*.** ••••••••••••••••••• ** •••••••• ** ••••••• ** •••• ** ••••••••• **** •••••••,
/* GetSecCyl: Determines the combined sector/cylinder coding from */
/* BIOS sector/cylinder number */
/* Input SecCyl Value to be decoded */
/* Sector Reference to the sector variable */
j* Cylinder Reference to the cylinder variable */
/* Output: none */
j** •••••••••••• **** •• **** •••••••••••••••••••••* ••••••• • ** •••• **** •••••• /
I
,.**..... *** •• ****.*** ••••••••••• ***.** •• ** •••••• ** ••••••• *** ••• *** •••• /
/* ShowPartition: Displays hard disk partitioninq on the screen */
/* Input: LW : Number of the hard disk (0, 1, 2, etc.) */
/* OUtput: none */
/ ••• *******.**•••••••• **.*** •••••••••••••••••••• **** •••••••••••••••••• */
Cylinder; /* number */
printf ("\n");
Regs.h.dl - LW;
printf ( · f - - - - - - - - - - - - - - - - - - -
------------l\n") ;
/* Upper left corner can be typed using <Alt><201> */
/* Horizontal line can be typed using <Alt><205> */
/* Upper right corner can be typed using <Alt><lB7> */
printf ( "I Drive '2d: '2d heads with '4d"
I\n");
695
17. Hard Disk PartitimUng PC System Programming
case OxOl
break;
printf( -DOS, l2-Bit FAT · );
case Ox02
break;
printf( "XENIX · );
case Ox03
break;
printf( "X~IX · );
case Ox04
break;
printf(
break;
"DOS, l6-Bit FAT · );
/*--
Display physical and logical parameters --------------------*/
GetSecCyl ( AP •StartSec. SecCyl, &Sector, &Cylinder );
printf( "1'2d \5d '3d", AP.StartSec.Head, Cylinder, Sector );
/* Vertical line can be typed using <Alt><179> */
GetSecCyl (AP.EndSec.SecCyl, &Sector, &Cylinder );
printf( "1\2d \5d \3d", AP.EndSec.Head, Cylinder, Sector );
/* Vertical line can be typed using <Alt><179> */
printf( "1'6lu 1\6lu I\n", AP.SecOfs, AP.SecNlDD );
I
/* First and second vertical lines can be typed using <Alt><179> */
/* Third vertical line can be typed using <Alt><186> */
printf ( -L-..l--..l ..l J."
696
Abacus 17. Hard Disk Partitioning
,-----:1--.L--.!\n" );
1* Left angle can be typed using <Alt><200> *1
1* Horizontal lines can be typed using <Alt><205> *1
1* Ts can be typed using <Alt><207> *1
1* Right angle can be typedusinq <Alt><188> *1
else
'97
Chapter 18
The PC Ports
Chapter 2 of this book described a series of CPU support chips which help the
CPU control the system. These chips stay in constant contact with the CPU,
which delegates tasks to and obtains information from the support chips.
Ports
The ports represent the interfaces between the CPU and the other system hardware.
A port can be viewed as an 8-bit-wide data input or output connected to a particular
piece of hardware. A port has an assigned address with values ranging from 0 to
65,535. The CPU uses the data bus and address bus to communicate with the
ports. If the CPU needs access to a port, it transmits a port control signal. This
signal instructs the other hardware that the CPU wants to access a port instead of
RAM. Ports have addresses which are also assigned to memory locations in RAM,
but these addresses have nothing to do with those memory locations. The port
address is placed on the lowest 16 bits of the address bus. This instructs the system
to transfer the eight bits of information following on the data bus to the proper
port. The hardware connected with this port receives the data and responds
accordingly.
The 80(x)xx processor series has two instructions that control this process from
within a program. The IN instruction sends data from the CPU to a port; the OUT
instruction transfers data from a port into the CPU.
The system can set the port address of a certain hardware device-this address is not
a constant value. For this reason, there are many similarities in port addressing
between the PC, XT and AT. There are few differences between the PC and XT,
but many differences exist between the PC and AT.
699
18. TIu! PC Ports PC System Progran&11ling
The following table shows the port addresses of individual chips in each system.
Component
PC/XT AT
DMA controller (8237A-5)
OOO-OOF OOO-OlF
Interrupt controller (8259A)
020-021 020-03F
tirrer
040-043 040-05F
Programmable Peripheral Interface (PPI 8255A-5)
060-063 none
Keyboard (8042)
none 060-06F
Realtime clock (MC146818)
none 070-07F
DMA page register
080-083 080-09F
Interrupt controller 2 (8259A)
none OAO-OBF
DMA controller 2 (8237A-5)
none OCO-ODF
Math coprocessor
none OFO-OF!
Math coprocessor
none OF8-0FF
Hard disk controller
320-32F 1FO-1F8
Garre port
200-20F 200-207
IExpansion unit
210-217 none
Interface for second parallel printer
none 278-27F
Second serial interface
2F8-2FF 2F8-2FF
Prototype card
300-31F 300-31F
Network card
none 360-36F
Interface for first parallel printer
378-37F 378-37F
Monochrorre Display Adapter and
BO-3BF 3BO-3BF
'parallel printer connection
Color/Graphics Adapter
3DO-3DF 3DO-3DF
Disk controller
3FO-3F7 3FO-3F7
First serial interface
3F8-3FF 3F8-3FF
700
Chapter 19
Interaction between
Keyboard, BIOS and DOS
• oos
BIOS
• hardware
We've examined each level separately throughout this book. This chapter
investigates the interaction between the three levels. We'll use the keyboard as an
example, because it best illustrates the connection between the three levels. We'll
start with the lowest level (the hardware itself) and progress to the highest level (an
application program which communicates with the user through the keyboard).
Hardware level
The hardware level consists of the keyboard itself, which connects to the CPU
through a cable. This keyboard contains either an Intel 8048 (PC/XT) or 8042
(AT) processor. The processor's task monitors the keyboard to determine whether a
key was depressed or released. If a user depresses a key for longer than half a
second, the 8048 enables key repeat at a rate of 10 characters per second. While the
8048 can only repeat at this frequency, the 8042's repeat frequency can be changed
to other values. This repetition continues until the user releases the key. The
keyboard processor assigns each key a number, instead of a character or ASCII
code. It views control keys such as <Shift> and <Ctrl> like any other key. In the
83-key standard PC keyboard, the processor assigns numbers to the keys ranging
from 1 to 83 decimal.
701
19. Inleraction between Keyboard. BIOS and DOS PC System Programming
BIOS level
When you press a key, this key code passes to the CPU as a byte. When you
release the key the processor passes the code to the CPU again, along with an
added 128. This is the same as setting bit 7 in the byte. The keyboard instructs the
8259 interrupt controller that the CPU should trigger interrupt 9H. If the CPU
responds we reach the next level, because a BIOS routine is controlled through
interrupt 9H. While this routine is being called, the keyboard processor sends the
key code to port 60H of the main circuit board using the asynchron,ous
transmission protocol. The BIOS routine checks this port and obtains the number
of the depressed or released key. This routine then generates an ASCII code from
this key code.
This task is more complex than ftrst appears, since the BIOS routine must test for
a control key such as <Shift> or <Alt>. Depending on the key or combination of
keys, either a normal ASCII code or an extended keyboard code may be required.
The extended key codes include any keys which don't necessarily input characters
(e.g., cursor keys).
Once BIOS determines the correct code, this code passes to the 16-byte BIOS
keyboard buffer. If it is full, the routine produces a beep which informs the user of
an overflow in the keyboard buffer. The processor returns to the other tasks which
were in progress before the call to interrupt 9.
The next level, BIOS interrupt 16H, reads the character in the keyboard buffer and
makes it available to a program. This interrupt includes three BIOS routines for
reading characters from the keyboard buffer, as well as the keyboard status (e.g.,
which control keys were pressed). These three routines can be called with an !NT
assembly language instruction from an application program.
DOS level
The keyboard's device driver routines represent the DOS level. These DOS routines
read a character from the keyboard and store the character in a buffer, using the
BIOS functions from interrupt 16H. In some cases, the DOS routines may clear
the BIOS keyboard buffer. If the system uses the extended keyboard driver
ANSI.SYS, ANSI.SYS can translate certain codes (e.g., function key I) into other
codes or strings. For example, it's possible to program the <FlO> key to display
the DIR command on the screen. You can theoretically call device driver functions
from within an application program, but in practice DOS functions usually address
these functions.
DOS is the highest level you can go. Here you'll ftnd the keyboard access
functions in DOS interrupt 21H. These functions call the driver functions,
transmit the results and perform many other tasks. For example, characters and
strings can be read and displayed directly on the screen until the user presses the
<Return> key. These strings are called by an application program and form the end
of this chain of events.
702
AbaclLS 19. Interaction between Keyboard, BIOS and DOS
Application program
Interrupt 21 (h) (DOS routine) 0)
DOS keyboard driver
o
Interrupt 16(h) (BIOS routine)
o
Keyboard buffer
o
o
o
Levels of keyboard access
(2) Reads a character with the functions of interrupt16H and converts it into
other characters <X' character strings as needed
(3) Reads keyboard status or a character from the keyboard buffer and transfers
it to the calling program
(5) Receives codes from the keyboard, converts them into ASCII or extended
keyboard codes and adds them to the keyboard buffer
When you consider the many levels through which a key code has to travel before
reaching an application program, you might be thinking that direct keyboard access
would be much faster. In principle that's true, but the process as described above
offers several advantages. One advantage is that the system offers complex
functions which reduce programming work, such as simultaneously displaying a
line on the screen as you enter it from the keyboard. Also, using higher level
functions make programs hardware independent, so that they'll run on PCsthat
may not be hardware-compatible with the IBM PC but still use DOS as the
operating system.
703
19. Interaction between Keyboard, BIOS and DOS PC System ProgrfJl'lllning
The program which concludes this chapter demonstrates a method of changing the
system levels. The challenge is to increase the size of the BIOS keyboard buffer.
The keyboard buffer usually holds up to 16 characters before emitting beeps to tell
the user that the buffer is full.
The assembler program which follows increases the size of the keyboard buffer to
128 characters (256 bytes). It generates extended interrupt handlers for hardware
keyboard interrupt 09H and BIOS keyboard interrupt 16H.
;****************************************************.*****************:
;* KEYBUF *;
:*---------------------------------------------------------
;* Task
-----------*i
Installs extended keyboard reading interrupt *;
;* routines and implements a virtual keyboard *:
;* buffer of up to 256 bytes (128 characters). *;
;* An initial call installs the program, while a *:
;* second call disables the program. *;
:*--------------------------------------------------------------------*:
;* Author MICHAEL TISCHER *;
;* Developed on : 08/24/1988 *;
;* Last update : 06/23/1989 *;
;*--------------------------------------------------------------------*;
;* Assembly : MASH KEYBUF; *;
;* LINK KEYBUF; *;
;* EXE2BIN KEYBUF KEYBUF.COM *;
;*--------------------------------------------------------------------*;
;* Call : KEYBUr *;
i**··*·········*****·*····*···*********··***·····***** **** •••••••••• ***;
;== BIOS variable segment ----=-==~==-- ___--=____==---====------__--=_==
bios segment at 40h ;Segment begins at 0040:0000
org 1ah
704
Abac/lS 19. Inluaction between Keyboard, BIOS and DOS
70S
;----------------------------------------------------------------------
instend equ this byte ;Everything must remain resident up
;to this meroory location
706
AbacllS 19. Inleraction between Keyboard, BIOS and DOS
707
19. Interaction between Keyboard, BIOS and DOS PC System Programming
; - Ende - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
708
Appendices
Interrupt hex_numberH
Interrupt_name
The output listing identifies the register that contains information returned by the
function after the call is completed. The register assignment depends on whether or
not the function call is successfully executed. If a specific value is supposed to be
in the AX register after a successful execution, but the function doesn't execute
properly, then the value in this register won't have any meaning. Problems in each
function will be addressed as needed.
In addition to the description of the input and output registers, details about the
function may also be included. For example, the function may be used in
conjunction with another function. There may also be information about any
changes in register contents caused by the function call. This is very important to
the assembly language programmer who wants to keep data in a register after the
function call. This programmer wants to avoid any changes in the contents of the
registers.
709
Appendix A
Important Hardware
Interrupts
The CPU calls this interrupt when it encounters a divisor of 0 during one of the
two assembly language division instructions (DIY or IDN). According to the rules
of mathematics, dividing a number by 0 is illegal. During the booting process,
this interrupt points to a routine that, when called, displays the "Division by Zero"
error message (or a similar message) on the screen. The interrupt continues with
the execution of the current program.
The CPU calls this interrupt when the TRAP bit in the flag register of the CPU
has been set to 1. Then the interrupt is called after the execution of each assembly
language instruction. This allows the user to follow these instructions, determine
the changes in register contents and determine which instructions are executed. To
prevent the call of the interrupt after the execution of every instruction in the trap
routine (which would create an endless loop and a stack overflow), the processor
resets the TRAP bit upon entry to the trap routine. If the trap routine ends with
the IRET instruction, it automatically resets the TRAP bit to its old value by
restoring the complete flag register from the stack. Because of this, the execution
of the next instruction calls interrupt 1 again. Once the programmer has obtained
the necessary information about a program from single step mode, the TRAP
mode (or TRAP bit) can be disabled.
710
AbaclLS' Appendix A: ImportOlll Hardware Interrupts
The hardware calls this interrupt when an error is discovered in the RAM chips.
The system calls the non-maskable interrupt because this type of error impairs the
capabilities of the system, and can lead to a crash. The NMI has the highest
priority of all interrupts and therefore is executed faster than other interrupts. The
NMI usually calls a BIOS routine which informs the user of a memory error,lists
the number of defective memory chips and stops the system.
If the NMI detects an error, the math coprocessor included in some PCs can also
trigger the NMI. Even though NMI usually cannot be suppressed, the PC allows
an exception to this rule. Some PC/XT and AT models have a special port (port
AOH on PCs and XTs, port 70H on ATs). If a 0 value is written to one of these
ports, the NMI interrupt is disabled . If the ports return the value SOH, the NMI
interrupt is enabled.
While the other interrupts can be called with a two-byte assembly language
instruction (first byte CDH, second byte the number of the interrupt), interrupt 3
is called by the single-byte instruction CCH. This interrupt can be used to test
programs when you want to execute the program up to a certain instruction, then
stop and display the current register contents. Utilities designed for program testing
like DEBUG implement this by placing calls for interrupt 3 where the break
should occur. When the program is executed and the processor reaches the
instruction, it calls interrupt 3. The program testing utility contains a routine
which displays the register contents and other information.
BIOS calls this interrupt when the user presses the <Prt Sc> key. The system then
makes a hardcopy by sending the current screen contents to a printer. BIOS
711
Appendix A " Importanl Hardware InlUTwpts PC System Programming
initializes the interrupt vector from the vector table and points to the BIOS
hardcopy routine in ROM-BIOS. Assembly language and programs written in
higher level languages can use this interrupt with the INT instruction to get a
hardcopy during program execution.
712
Appendix B
713
Appendix B: BIOS Inte""pts and FlUlCtions PC System ProgrlDlUlling
714
Abacus Appendix B. BIOS Interrupts and Functions
04H Read date from realtime clock (AT only) ................... 761
715
Appendix B: BIOS Interrupts and F/UlCtions PC System ProgrQ11lllUng
Selects and initializes a video mode and clears the screen. This function is a fast
method of clearing the screen while maintaining the current video mode.
Input: AH= OOH
AL = Video mode
0: 4Ox25 text mode, monochrome (color card)
1: 40x25 text mode, color (color card)
2: 80x25 text mode, monochrome (mono card)
3: 8Ox25 text mode, color (color card)
4: 32Ox200 4-color graphics (color card)
5: 32Ox200 4-color graphics (color card)
(colors displayed in monochrome)
6: 640000 2-color graphics (color card)
7: Internal mode (mono card)
Output: No output
Remarks: The colors for modes 4, 5 and 6 can be set with function 11.
The contents of the BX, CX, OX registers and the SS, CS and OS
segment registers are not affected by this function. The contents of all
other registers may change, especially the SI and DI registers.
Defines the starting and ending lines of the cursor. This cursor exists independently
of the current display page.
Input: AH= OlH
CH = Starting line of the cursor
CL = Ending line of the cursor
Output: No output
Remarks: The values allowed for the cursor's starting and ending line depend on the
installed video card The following values are permitted:
716
AbacllS AppeNJiJe B. BIOS Irtlernlpts and FllllClions
You can use this function to set the cursor only within the permitted
ranges. Setting cursor lines outside these parameters may result in an
invisible cursor or system poblems.
The contents of the BX, ex, ox registers and the segment registers SS,
es and OS are not affected by this function. The contents of all the other
registers may change, especially the SI and DI registers.
Repositions the cursor, which determines the screen position for character output
by using one of the BIOS functions.
Input: AH= 02H
BH = OispJay page number
OH = Screen line
OL = Screen column
Output: No output
Remarks: The blinking cursor moves through this function when the addressed
display page is the current display page.
Values for the screen line parameter range from 0 to 24.
Values for the screen column parameter range from 0 to 79 (for an 80
column display) or from 0 to 39 (for a 40-column display), depending on
the selected video mode.
You can make the cursor disappear by moving it to a nonexistent screen
position (e.g., column 0, line 25).
The number of the display page parameter depends on how many dispJay
pages are available to the video card.
The contents of the BX, ex, ox registers and the SS, es and OS
segment registers are not affected by this function. The contents of all
other registers may change, especially the SI and DI registers.
717
Appendix B: BIOS InterrMpIs ONJ FlUlCtions PC System Programming
Senses the text cursor's position, starting ~ne and ending line in a display page.
Input:
AH= 03H
BH = Display page number
Output:
OH = Screen line in which the cursor is located
OL = Screen column in which the cursor is located
CH = Starting line of the blinking cursor
CL = Ending line of the blinking cursor
Rema.tks:
The number of the display page parameter depends on how many display
pages are available to the video card.
Line and column coordinates are related to the text coordinate system.
The contents of the BX register and the SS, CS and OS segment registers
are not affected by this function. The contents of all the other registers
may change, especially the SI and DI registers.
718
Abacus Appendix B. BIOS Interrupts and Frurctions
Output: No output
Remarks: The number of the display page depends on the number of display pages
available to the video card.
Switching between various display pages does not affect their contents
(the individual characters).
The contents of the BX. CX. OX registers and the SS. CS and OS
segment registers are not affected by this function. The contents of the
other registers, such as the SI and DI registers. may change.
Clears window or scrolls a portion of the current display page up by one or more
lines. depending on the input.
Output: No output
The contents of the lines scrolled out of the window are lost and cannot
be restored.
719
Appendbc B: BIOS Interrupts and FlIIICtions PC System Programmin.g
The contents of the BX. CX. OX registers and the SSt CS and OS
segment registers are not affected by this function. The contents of all
other registers may change. especially the SI and DI registers.
Clears window or scrolls a portion of the current display page up by one or more
lines. depending on the input.
Input: AH= 07H
AL = Number of window lines to be scrolled downward (O=clear window)
CH = Screen line of the upper left corner of the window
CL = Screen column of the upper left corner of the window
DH = Screen line of the lower right corner of the window
OL = Screen column of the lower right corner of the window
BH = Color (attribute) for blank line(s)
Output: No oUlput
Remarks: This function only affects the current display page.
Initializing a window (placing a 0 in the AL register) fills the window
with blank spaces (ASCII code 32).
The contents of the lines scrolled out of the window are lost and cannot
be restored.
Reads the ASCII code of the character at the current cursor position and its color
(attribute).
Input: AH= OSH
BH = Display page number
Output: AL = ASCII code of the character
AH = Color (attribute)
720
Abacus AppendiJc B. BIOS Interrupts and P/U'lCtions
Remarks: The number of the display page depends on the number of display pages
made available to the video card.
This function can also be called in graphic mode. The function compares
the bit pattern of the character on the screen with the bit pattern of the
character in character ROM of the video card and with the character
patterns stored in a RAM table whose addresses appear in interrupt IFH.
If the character cannot be identified, the AL register contains the value 0
after the function call.
The contents of the BX, CX, DX registers and the SS, CS and DS
segment registers are not affected by this function. The contents of the
other registers may change, especially the SI and DI registers.
Writes a character with a certain color (attribute) to the current cursor position in a
predefined display page.
Input: AH= 09H
BH = Display page number
CX = Number of times to write the character
AL = ASCII code of the character
BL = Attribute
Output: No output
Remarks: If the character should be displayed several times (the value of the CX
register is greater than I), all characters must fit into the current screen
line in the graphic mode.
The control codes (e.g., bell, carriage return) appear as normal ASCII
codes.
This function can display characters in graphic mode. The patterns of the
characters, with the codes from 0 to 127, are determined by a table in
ROM. The patterns of the characters with the codes from 128 to 255 are
determined by a RAM table that was previously installed by OOS the
GRAFfABL command.
In text mode, the contents of the BL register define the attribute byte of
the character. In graphic mode this register determines the color of the
character. The 64Ox200 bitmap mode only allows the values 0 and 1 for
selecting colors from the color palette. The 320x200 bibDap mode only
allows the values 0 to 3 for selecting colors from the color palette.
If the graphic mode is active during character output and bit 7 of the BL
register is set, an exclusive OR is performed on the character pattern and
the graphic pixels behind the character pattern.
721
Appendix B: BIOS /nurrllpts and FlUlClions PC System Programming
After character output, the cursor remains in the same position as the
character.
The contents of the BX, ex, DX registers and the SS, es and DS
segment registers are not affected by this function. The contents of all
other registers may change, especially the SI and DI registers.
Remarks: If the character should be displayed several times (the value of the ex
register is greater than 1), all characters must fit into the current screen
line in the graphic mode.
The control codes (e.g., bell, carriage return) appear as normal ASeII
codes.
This function can display characters in graphic mode. The patterns of the
characters with the codes from 0 to 127 are determined by a table in ROM
and the patterns of the characters with the codes from 128 to 255 are
determined by a RAM table previously installed by the GRAFfABL
command.
In text mode, the contents of the BL register define the attribute byte of
the character. In graphic mode this register determines the color of the
character. The 640x200 bitmap mode only allows the values 0 and 1 for
selecting colors from the color palette. The 320x200 bitmap mode only
allows the values 0 to 3 for selecting colors from the color palette.
If the graphic mode is active during character output and bit 7 of the BL
register is set, an exclusive OR is performed on the character pattern and
the graphic pixels behind the character pattern.
722
Abacus Appendbc B. BIOS Interrupts and FlUlCtions
Output: No output
Remarlcs: In graphic mode, the color value passed defines the color of both the
border and background. In text mode, the background color of each
character is defmed individually, so the passed color value only defmes the
color of the screen border.
The contents of the BX, CX, OX registers and the SS, CS and OS
segment registers are not affected by this function. The contents of all
other registers may change, especially the SI and DI registers.
Selects one of the two color palettes for the 32Ox200 bitmapped graphic mode.
Output: No output
Remarlcs: Two color palettes are available. They have the numbers 0 and 1 and
contain the following colors:
723
Appendix B: BIOS Interrupts and FlllfCtions PC System Programming
The contents of the BX, ex, ox registers and the SS, CS and OS
segment registers are not affected by this function. The contents of all
other registers may change, especially the SI and DI registers.
Reads the color value of a pixel at the specified coordinates in the current graphic
mode.
Input: AH= OOH
OX = Screen line
ex = Screen column
Output: AL = Pixel color value
Remarks: The pixel color value parameter depends on the current graphic mode.
64Ox200 bitmapped mode permits the values 0 and 1 only. In the
320x200 bitmapped mode, the values 0 to 3 are permitted, which gener
ates a certain color according to the color palette chosen. 0 represents the
selected background color; 1 represents the first color of the selected color
palette; 2 represents the second color of the color palette, etc.
The contents of the BX, ex, ox registers and the SS, es and OS
segment registers are not affected by this function. The contents of all
other registers may change, especially the SI and DI registers.
724
Abacw Appendix B. BIOS 17Ilemlpts and F/I.1ICtions
Output: No output
Remarks: This function executes control codes (e.g., bell, carriage return) instead of
reading them as ASCII codes. For example, the function sounds a beep
instead of printing the bell character.
The contents of the BX, CX, DX registers and the SS, CS and DS
segment registers are not affected by this function. The contents of all
other registers may change, especially the SI and DI registers.
725
Appendix B: BIOS Inlerrupts and FlUlClions PC System ProgrlJl1llfUng
Reads the number of the current video mode, the number of characters per line and
the number of the current display page.
Input: AH = OFH
Output: AL = Video mode
0: 40x25 text mode, monochrome (color card)
1: 4Ox25 text mode, color (color card)
2: 8Ox25 text mode, monochrome (mono card)
3: 8Ox25 text mode, color (color card)
4: 32Ox200 4-color graphics (color card)
5: 32Ox200 4-oolor graphics (color card)
(colors represented in monochrome)
6: 640x200 2-oolor graphics (color card)
7: Internal mode (mono card)
AH = Number ofcharacters per line
BH = Current display page number
Remarks: The contents of the BX, ex, ox registers and the SS, es and OS
segment registers are not affected by this function. The contents of all
other registers may change, especially the SI and DI registers.
726
Abacus Appendix B. BIOS InlemllJts and FlUfCtions
Remarks: Modes 1 and 3 set the cursor position following the last character of the
character sUing. On the next call of a BIOS function for character output.
the next stting of characters appears following the original character
sUing. This does not occur in the modes 0 and 2.
In modes 0 and 1, the buffer contains only the ASCII codes of the
characters to be displayed. The BL register contains the color of the
character string. However, in modes 2 and 3 each character has its own
atttibute byte when the character is stored in the buffer. The BL register
doesn't have to be loaded in this mode. Even though the character sUing is
twice as long in these modes as the number of the characters to be
displayed, the ex register requires only the number of ASCII characters
in the string and not the total length of the character stting.
Control codes (e.g., bell) are interpreted as control codes only, and not as
chanK;ters.
When the sUing reaches the last position on the screen, the display scrolls
upward by one line and output continues in the first column of the last
screen line.
The contents of the BX, CX, DX registers and the SS, CS and DS
segment registers are not affected by this function. The contents of all
other registers may change, especially the SI and DI registers.
Reads the configuration of the system as recorded during the booting process.
Input: No input
Output: AX = Configuration
PC and XT: Bit 0: 1 if the system has one or more disk drives
Bit 1: Unused
Bits 2-3: RAM available on main circuit board
00: 16K
01: 32K
10: 4SK
ll:64K
Bits 4-5: Video mode after system boot
00: Unused
01: 4Ox25, color card
02: SOX25, color card
03: S0x2S,monocard
Bits 6-7: Number of disk drives in the system if bit 0 is equal to 1
00: 1 disk drive
01: 2 disk drives
10: 3 disk drives
11: 4 disk drives
727
Appendix B: BIOS Interrupts and Functions PC System Programming
Bit 8:
owhen a DMA chip is present
Bits 9-11:
Number of RS-232 cards connected
Bit 12:
1 when system has a joystick attached
Bit 13:
Unused
Bits 14-15:
Indicates the number of printers available
AT: Bit 0: 1 if the system has one or more disk drives
Bit 1: 1 when a math coprocessor exists in the system
Bit 2-3: Unused
Bit 4-5: Video mode during system boot
00: Unused
01: 4Ox25,colorcard
02: 8Ox25, color card
03: 8Ox25, mono card
Bits 6-7: Number of disk drives in the system if bit 0 is equal to 1
00: 1 disk drive
01: 2'disk drives
10: 3 disk drives
11: 4 disk drives
Bit 8: Unused
Bits 9-11: Number ofRS-232 cards connected
Bit 12-13: Unused
Bits 14-15: Indicates the number of printers available
Remarlcs: The type of PC must be known (pc, XT or A1) in order to properly
interpret the meanings of the individual bits of the configuration word.
728
Abacus Appendix B. BIOS Interrllpts and FlUlCtions
Resets the disk controller ~d any connected disk drives. A reset should be executed
after each disk operation during which an error occwred.
Remarks: The value in the DL register is unnecessary since all the disk drives
execute a reset. XT and AT models use this register to determine whether
a reset should be peIformed on the disk drives or the hard disk.
Reads the status of the disk drive since the last disk operation.
Remarks: The value in the DL register is unnecessary, since disk drives constantly
return their status. XT and AT models use this register to determine
whether the status of the hard disk should be checked.
729
Appendix B: BIOS Interrupts and FlUfCtions PC System Programming
Remark: The number of sectors to be read into the AL register is limited to sectors
which logically follow each other on a track on one side of the disk.
730
Abacus Appendiz B: BIOS Interrupts and F/UlCtwns
Writes one or more sectors to a disk. The data to be transmitted are taken from a
buffer.
Remark: The number of sectors that can be written in the AL register is limited to
sectors which logically follow each other on a track on one side of the
disk.
731
Appendix B: BIOS Interrupts and FlU'lCtions PC System Programming
The contents of the BX, CX, DX, SI, 01, BP registers and the segment
registers are not affected by this function. The contents of all other
registers may change.
Compares one or more sectors on disk with the data stored in a buffer. This can be
used to verify that the data was properly saved to disk.
The contents of the BX, CX, DX, SI, 01, BP registers and the segment
registers are not affected by this function. The contents of all other
registers may change.
732
Abacu Appendix B: BIOS Interrupts and FlUtCtions
CH = Track number
Output:
Carry fJag=O: Operation completed (AH=O)
Remark:
The number of sectors to be fonnatted is limited to sectors which
logically follow each other on a track on one side of the disk.
The buffer passed in ES:BX contains an entry consisting of four
consecutive bytes for every sector to be formatted.
1: Track number
2: Pagenumber
3: Logical sector number
4: Number of bytes in this sector:
0: 128 bytes
1: 256 bytes
2: 512 bytes (PC standard)
3: 1,024 bytes
The logical sector number increments continuously, but may not be the
same as the physical sector number.
The following error codes can occur:
733
Appendix B: BIOS InleTrupts and F/UlCtions PC System ProgramnUng
Senses disk change and drive type. The AT supports both the standard 320/360K
drives and the 1.2 megabyte drives.
Remark: The AT has a controller which selectively controls 2 disk drives and a
hard disk, or one disk drive and 2 hard disks. In the latter case, the flrst
hard disk has the number 1 and can be accessed with this function.
The contents of the BX, CX, DX, SI, DI, BP registers and the segment
registers are not affected by this function. The contents of all other
registers may change.
Senses a disk change. The AT supports both the standard 320/360K drives and the
1.2 megabyte drives. This function reads any disk change that may have occurred
since the last disk access.
Remarks: The contents of the BX, CX, DX, SI, DI, BP registers and the segment
registers are not affected by this function. The contents of all other
registers may change.
734
Abacus Appendix B: BIOS Intemq1ts and FlUlCtions
The contents of the BX, CX, OX, SI, 01, BP registers and the segment
registers are not affected by this function. The contents of all other
registers may change.
735
Appendix B: BIOS Interrupts and FlUlCtions PC System Programming
Resets the hard disk controller and any interfaced bani disk drives. A reset should be
executed after every bani disk operation during which an enu was reported.
Remarlcs: The rust hard disk drive is assigned the number SOH, the second is
assigned the number S1H.
The value in the OL register is unnecessary since all the hard disk drives
execute a reset. XT and AT models use this register to determine whether
a reset should be perfonned on the disk drives or on the hard disk.
The contents of the BX, ex, OX, SI, 01, BP registers and the segment
registers are not affected by this function. The contents of all other
registers may change.
Reads the status of the hard disk since the last hard disk operation.
73(;
Abacus Appendix B: BIOS InlerrKpts and FlUlCtions
RemaIks: The first hard disk drive is assigned the number 80H. the second is
assigned the number 8tH.
The contents of the BX. CX. DX. SI. DI. BP registers and the segment
registers are not affected by this function. The contents of the other
registers may change.
737
Appendix B: BIOS Inlerrllpts and FlUlCtions PC System Programming
Remarlcs: The first hard disk drive is assigned the number 80H, the second is
assigned the numbeJ' 81H.
Since the eight bits of the CH register can address only 256 cylinders at a
time, bits 6 and 7 of the CL register (sector number) form bits 8 and 9 of
the cylinder number, which enables the addressing of up to 1,023
cylinders at a time.
IT several sectors are being read and the system reaches the last sector of a
cylinder, reading continues at the ftrst sector of the next cylinder of the
next read/write head. IT the system reaches the last read/write head, reading
continues on the first sector of the following cylinder on the first
read/write head.
The following error codes can occur:
The contents of the BX, CX, DX, SI, 01, BP registers and the segment
registers are not affected by this function. The contents of all other
registers may change.
Writes one or more sectors to the hard disk. The data to be transmitted are taken
from a buffer in the calling program.
Input: AH = 03H
AL = Number of sectors to be written (1-128)
BX = Offset address of buffer
CR = Cylinder number
CL = Sector number
DR = Read/write head number
DL = Hard disk number (80H or 81H)
ES = Buffer segment address
738
Abacus Appendix B: BIOS lrtlerrupts and F/UlCtions
Remarks: The frrst hard disk drive is assigned the number 80H, the second is
assigned the number 81H.
Since the eight bits of the CH register can address only 256 cylinders at a
time, bits 6 and 7 of the CL register (sector number) form bits 8 and 9 of
the cylinder number, enabling the addressing of up to 1,023 cylinders at a
time.
If several sectors are being written and the system reaches the last sector
of a cylinder, writing continues at the first sector of the next cylinder of
the next read/write head. If the system reaches the 1ast read/write head,
writing continues on the first sector of the following cylinder on the fust
read/write head:
The contents of the BX, CX, DX, SI, DI, BP registers and the segment
registers are not affected by this function. The contents of all other
registers may change.
739
Appendix B: BIOS /1JIerrllpts and Functions PC System Programming
Verifies one or more sectors of a hard disk. Unlike the corresponding floppy disk
function, the data on the hard disk are not compared with the data in memory.
During data storage, four check bytes are stored for every sector; these check bytes
verify the contents of a sector.
Remarks: The first hard disk drive is assigned the number SOH, the second is
assigned the number S1H.
Since the eight bits of the CD register can only address 256 cylinders at a
time, bits 6 and 7 of the CL register (sector number) form bits S and 9 of
the cylinder number, which enables the addressing of up to 1,023
cylinders at a time.
If several sectors are being verified and the system reaches the last sector
of a cylinder, verification continues at the first sector of the next cylinder
of the next read/write head. If the system reaches the last read/write head,
verification continues on the first sector of the following cylinder on the
first read/write head.
The following error codes can occur:
740
AbacllS Appendix B: BIOS Interrupts and FlU1Ctions
The contents of the BX, ex, ox, SI, DI, BP registers and the segment
registers are not affected by this function. The contents of all other
registers may change.
Formats a complete cylinder (17 sectors) of a hard disk. A buffer, which contains
information about the sectors to be formatted. must be passed to the function.
Remarks: The fIrst hard disk drive is assigned the number 80H, the second is
assigned the number 8IH.
Since the eight bits of the CH register can only address 256 cylinders at a
time, bits 6 and 7 of the CL register (sector number) form bits 8 and 9 of
the cylinder number, which enables the addressing of up to 1,023
cylinders at a time.
741
Appendix B: BIOS Interrupts and FlUlCtwns PC System Programming
The contents of the BX, CX, DX, SI, 01, BP registers and the segment
registers are not affected by this function. The contents of all other
registers may change.
Remarks: The first hard disk drive is assigned the number 80H, the second is
assigned the nwnber 81H.
Since the eight bits of the CH register can address only 256 cylinders at a
time, bits 6 aDd 7 of the CL register (sector number) form bits 8 and 9 of
the cylinder nwnber, enabling the addressing of up to 1,023 cylinders at a
time.
The total capacity of the hard disk unit in bytes can be calculated with the
following formula:
742
AbaclLf Appendix B: BIOS Inteml/JI. tmd FlI1ICtions
The contents of the BX, CX, OX, SI, DI, BP registers and the segment
registers are not affected by this function. The contents of all other
registers may change.
Interfaces other hard disk drives for access through BIOS functions.
Remarlcs: The frrst hard disk drive is assigned the number SOH, the second is
assigned the number SlH.
BIOS takes the information about the hard disk drive to be interfaced
(number of units, read/write heads, etc.) from a table. The address of this
table for the hard disk unit numbered SOH is stored in interrupt vector
41H. and the unit numbered SIH is stored in interrupt 46H.
743
Appendix B: BIOS inlemllJts and FlUlCtions PC System Progrtun11Ung
The contents of the BX, CX, OX, SI, DI, BP registers and the segment
registers are not affected by this function. The contents of all other
registers may change.
Reads one,Or more sectors from the hard disk drive into a buffer. Besides the actual
512 bytes stored in the sector, the function also reads the four check bytes (ECC).
Remarks: The flTst hard disk drive is assigned the number 80H, the second is
assigned the number 81H.
Normally the controller computes the four check bytes. Here the buffer
reads the information direct
Since the eight bits of the CH register can only address 256 cylinders at a
time, bits 6 and 7 of the CL register (sector number) form bits 8 and 9 of
the cylinder number, enabling the addressing of up to 1,023 cylinders at a
time.
If several sectors are being read and the system reaches the last sector of a
cylinder, reading continues at the flTSt sector of the next cylinder of the
next read/write head. If the system reaches the last read/write head, reading
continues on the flTSt sector of the following cylinder on the flTst
readIwrite head.
The following error codes can occur:
744
Abacus Appertdbc B: BIOS Interrupts and FlUlCtiom
Writes one or more sectors to the hard disk drive. Besides the actual 512 bytes
stored in a sector, four check bytes (ECC) stored at the end of every sector are
transmitted from the buffer.
Input: AH= OBH
AL= Number of sectors to be read (1-127)
BX = Offset address of buffer
CH = Cylinder number
CL = Sector number
DH = Read/write head number
DL = Hard disk number (80H or 81H)
ES = Buffer segment address
Output: Carry fIag=O: Operation completed (AH=O)
Carry flag=1: Error (AH=error code)
Remarks: The first hard disk drive is assigned the number 80H, the second is
assigned the number 81H.
Normally the controller calculates the four check bytes. Here the system
reads them direct from the buffer.
Since the eight bits of the CH register can only address 256 cylinders at a
time, bits 6 and 7 of the CL register (sector number) form bits 8 and 9 of
the cylinder number, enabling the addressing of up to 1,023 cylinders at a
time.
If several sectors are being written and the system reaches the last sector
of a cylinder, writing continues at the first sector of the next cylinder of
the next read/write head. If the system reaches the last read/write head,
writing continues on the fIrst sector of the following cylinder on the fIrst
read/write head.
745
Appendix B: BIOS InlUrupts and FJUtCtions PC System Progrflll'lNling
The contents of the BX, CX, OX, SI, DI, BP registers and the segment
registers are not affected by this function. The contents of all other
registers may change.
Resets the hard disk controller and any interfaced hard disk drives. A reset should be
executed after every hard disk operation during which an error was reported.
Input: AH= OOH
OL = Hard disk drive number (SOH or 81H)
Output: Carry flag=O: Operation completed (AH=O)
Carry flag=l: Error (AH=error code)
Remarks: The value in the OL register is unnecessary since all the hard disk drives
execute a reseL XT and AT models use this register to detennine whether
a reset should be perfonned on the disk drives or on the hard disk.
746
AbaclLS' Appendix B: BIOS IlIlerrupts tmd FlUlCtions
The contents of the BX, CX, OX, SI, DI, BP registers and the segment
registers are not affected by this function. The contents of all other
registers may change.
Detennines if the drive is ready (i.e., the last opemtion has been completed and the
drive can perform the next task).
Rerruuks: The first hard disk drive is assigned the number 80H, the second is
assigned the number 81H.
The contents of the BX, CX, OX, SI, DI, BP registers and the segment
registers are not affected by this function. The contents of all other
registers may change.
747
Appendix B: BIOS Inlerrllpts and FlUtCtioru PC System ProgrO»i11Ung
Remarlcs: The first hard disk drive is assigned the number 80H, the second is
assigned the number 81H.
The contents of the BX, CX, DX, SI, DI, BP registers and the segment
registers are not affected by this function. The contents of all other
registers may change.
Remarlcs: The fIrst hard disk drive is assigned the number 80H, the second is
assigned the number 8tH.
748
Abacus Appendix B: BIOS InleTrlqKs and FlUlCtions
The contents of the BX. CX. OX. SI, 01, BP registers and the segment
registers are not affected by this function. The contents of all other
registers may change.
Determines whether or not the computer hardware assigned numbers 80H and 81H
are hard disk drives. The AT contains a controller capable of controlling both hard
disks and disk drives. This controller can manage either two disk drives and one
hard disk, or one disk drive and two hard disks.
Input: AH= ISH
OL = Hard disk drive number (SOH or 81H)
Output: Carry flag=<>: Operation completed (AH=drive type)
0: Equipment not available
1: Drive does not recognize disk change
2: Drive recognizes disk change
3: Hard disk unit
Remarlcs: The ftrst hard disk drive is assigned the number 80H, the second is
assigned the number 8IH.
The contents of the BX, CX, OX, SI, 01, BP registers and the segment
registers are not affected by this function. The contents of all other
registers may change.
749
Appendix B: BIOS Interrupts and Functions PC System Programming
Initializes and configures a serial port This configuration includes parameters for
word length, baud rate, parity and stop bits.
Input: AH= OOR
DX = Nwnber of serial port (O=first serial port, l=second serial port)
AL = Configuration parameters
Bits 0-1: Word length
10(b) = 7 bits
11(b) = 8 bits
Bit 2: Number of stop bits
00(b)= none
01 (b) = odd
11 (b) = even
OOO(b) = 11 0 baud
750
Abacus Apperulbt B: BIOS Interrupts and FlUlCtions
Remarks: The contents of the BX, CX, DX, SI, DI, BP registers and the segment
registers are not affected by this function. The contents of all other
registers may change.
Remarks: This function should only be called if function 3 has determined that a
character is ready for reception.
The contents of the BX, CX, DX, SI, DI, BP registers and the segment
registers are not affected by this function. The contents of all other
registers may change.
751
Appendix B: BIOS Interrupts and FJUlCtions PC System Programming
The contents of the BX, CX, OX, SI, 01, BP registers and the segment
registers are not affected by this function. The contents of all other
registers may change.
The contents of the BX, SI, 01, BP registers and the segment registers are
not affected by this function. The contents of all other registers may
change.
752
AbacllS Appendbc B: BIOS Inlerrllpts and FlUlCtioras
The contents of the BX, CX, SI, DI, BP registers and the segment
registers are not affected by this function. The contents of all other
registers may change.
Reads the positions of joysticks interfaced to a PC if game ports and joysticks are
present
The contents of the SI, DI. BP registers and the segment registers are not
affected by this function. The contents of all other registers may change.
753
Appendix B: BIOS Intemlpts and FlIIICtions PC System Programming
Responds to pressure oc release of the <Sys Req> key. The keyboard routine calls
this function.
Input: AlI= 85H
AL = 0: <Sys Req> key depressed
AL = 1: <Sys Req> key released
Output: No output
Remarks: This function acts as an intennediary foc application programs, so that the
application program will respond appropriately when the user presses the
<Sys Req> key.
Returns control to the calling program after a certain amount of time has elapsed.
Input: AlI= 86H
CX = High word of pause time in microseconds
DX = Low word of pause time in microseconds
Output: No output
Remarks: A microsecond is a millionth of a second.
The contents of the BX, SI, 01, BP registers and the segment registers are
not affected by this function. The contents of all other registers may
change.
Moves areas of RAM from below the 1 megabyte limit to the range above the 1
megabyte limit, and from above the 1 megabyte limit to below the 1 megabyte
limit.
Input: AH= 87H
CX = Number of wocds to move
ES = Segment address of global descriptor table
SI = Offset address of global descriptor table
Output: Carry flag=O: No erroc
Carry flag=1: Error:
AlI=I: RAM parity erroc
AlI=2: Inconect GDT on function call
AlI=3: Protected mode could not be initialized
754
Abacus Appendix B: BIOS 11IIe"upts and F/D'ICtions
Remarks: See Section 7.10.1 for more infonnation about the global descriptor table
(GOT).
The contents of the BX, ex, DX, SI, DI, BP registers and the segment
registers are not affected by this function. The contents of all other
registers may change.
The contents of the BX, ex, DX, SI, DI, BP registers and the segment
registers are not affected by this function. The contents of all other
registers may change.
Output: No output
Remarks: This function should be called only if you know how virtual mode
operates. Improper use of this function can easily lead to a system crash.
755
Appendix B: BIOS Inlerrllpls and FlUlCtiorts PC System ProgrQIIIIIUng
Reads a character from the keyboard buffer. If the buffer doesn't contain a character,
the function waits until a character is entered. Then the character is read and
removed from the keyboard buffer.
Input: AH= OOH
Output: AL = 0: Extended key code:
AH =Extended key code
AI> 1: Nonnal key activated:
AL = ASCII code of key
AH =Scan code of key
Remarks: ASCII code definition occurs independent of the keyboard. Scan codes
apply only to the type of keyboard attached to the PC. See Appendix J for
a list of ASCII codes and Section 7.11 for a list of extended key codes.
The contents of the BX, CX, DX, SI, 01, BP registers and the segment
registers are not affected by this function. The contents of all other
registers may change.
The contents of the CX, DX, SI, 01, BP registers and the segment
registers are not affected by this function. The contents of all other
registers may change.
756
AbacllS AppendiJc B: BIOS Interrupts and FlUlCtions
Reads and returns the status of certain control keys and various keyboard modes.
Input: AH= 02H
Output: AI. = Keyboard status
7 6 5 4 3 2 1 o
I I I 1- 1=Rlght SHIFT key pressed
I
I 1=Left SHIFT key pressed
1=CTRL key pressed
1=ALT key pressed
1=SCROLL LOCK on
1=NUM LOCK on
1=CAPS LOCK on
1=INSERT on
Keyboard status
Remarlcs: The contents of the BX, ex, DX, SI, 01, BP registers and the segment
registers are not affected by this function. The contents of all other
registers may change.
757
Appendix B: BIOS lnurrupts and FlUlCtiolv PC System ProgrOllU1ling
Remarlcs: Parallel port LPTI is assigned the number 0, parallel port LPT2 is
assigned the number 1 and parallel port LPI'3 is assigned the number 2.
The contents of the BX, ex, DX, SI, Dl, BP registers and the segment
registers are not affected by this function. The contents of all other
registers may change.
Initializes the printer interfaced to the PC. This function should be executed before
executing function 0 (see above).
Remarlcs: Parallel port LPTI is assigned the number 0, parallel port LPT2 is
assigned the number 1 and parallel port LPI'3 is assigned the number 2.
The contents of the BX, ex, DX, SI, DI, BP registers and the segment
registers are not affected by this function. The contents of all other
registers may change.
Remarks: Parallel port LPTI is assigned the number 0, parallel port LPT2 is
assigned the number 1 and parallel port LPT3 is assigned the number 2.
The contents of the BX, ex, DX, SI, DI, BP registers and the segment
registers are not affected by this function. The contents of all other
registers may change.
758·
Abacus AppendiJe B: BIOS Interrupts and FlDICtilms
Accesses BASIC in ROM if a system disk cannot be found during the system
bootstrap process.
Input: No input
Output: No output
Remarks: Very few PCs or compatibles have built-in ROM BASIC (this is a
throwback from the early days of the pc). IT a PC doesn't have ROM
BASIC, interrupt 18H returns the system to the calling program.
However, if the PC does has ROM BASIC, interrupt 18H calls BASIC.
In most cases, the only way to return to DOS is by warm-starting the
computer (pressing the <Ctrl><Alt><Delete> keys) or turning the
computer off and on again. Some versions of ROM BASIC allow an exit
to DOS by entering the SYSTEM command from BASIC.
Input: No input
Output: No output
Remarks: Pressing the <Ctrl><Alt><Delete> keys invokes this interrupt from the
keyboard.
Reads the current clock count. The clock count increments 18.2 times per second.
This calculates the time elapsed since the computer was switched on.
759
Appendix B: BIOS Interrupts and Fu.nctions PC S,stem ProgrtllrllrUng
Remarlcs: The AT, which has a battery powered realtime clock, sets the clock count
to the current time when the computer boots. PCs (which don't have
realtime clocks) set the counter to 0 during booting.
The contents of the BX, CX, OX, SI, 01, BP registers and the segment
registers are not affected by this function. The contents of all other regis
ters may change.
Sets the contents of the current clock count, which increments 18.2 times per
second. This calculates the time elapsed since the computer was switched on and
sets the current time through this function.
Input: AH= 01H
CX = High wool of clock count
OX = Low wool of clock count
Output: No output
Rematks: The AT, which has a battery powered realtime clock, sets the clock count
to the current time when the computer boots. PCs (which don't have
realtime clocks) set the counter to 0 during booting. PC owners should
use this function to set the current time.
The contents of the AX, BX, CX, OX, SI, 01, BP registers and the
segment registers are not affected by this function. The contents of all
other registers may change.
The contents of the BX, SI, 01, BP registers and the segment registers are
not affected by this function. The contents of all other registers may
change.
760
AbaclLf Appendix B: BIOS Interrupts and FlUlCtions
The contents of the BX, SI, 01, BP registers and the segment registers are
not affected by this function. The contents of all other registers may
change.
The contents of the BX, SI, 01, BP registers and the segment registers are
not affected by this function. The contents of all other registers may
change.
761
Appendix B: BIOS Inlerrllpts and FlIIICtioras PC System Programming
Output: No output
Sets alarm time for the current day. The alarm time triggers interrupt 4AH.
CH= Hours
CL= Minutes
DH= Seconds
Output:
Carry flag=O: O.K.
Remarks:
All alarm settings must be in BCD format.
During booting, interrupt 4AH points to an IRET command. If this
interrupt doesn't point to a particular routine responding to the alarm,
nothing will happen once the alarm time is reached.
Only one alarm time can be active at a time. If another alarm setting
already exists, you must first delete it by using interrupt 26-1AH,
function 7 (see below).
The contents of the BX, CX, SI, 01, BP registers and the segment
registers are not affected by this function. The contents of all other
registers may change.
762
AbacllS Appettdix B: BIOS Intemlpts and FlUlCtions
Remarlcs: This function must be called when you want to change an alarm setting.
Reset the alarm, then use function 06H to set the new alarm time.
The contents of the BX, CX, SI, 01, BP registers and the segment
registers are not affected by this function. The contents of all other
registers may change.
This routine sets a flag to indicate that the user has pressed <Ctrl><Break>.
Following the execution of one of the DOS functions, this flag is tested for
character input or output. If the system encounters <Ctrl><Break>, the current
program stops. In addition, when a batch file is in process, the program asks
whether the batch fIle should be continued or terminated.
Pressing <Ctrl><C> doesn't activate the interrupt. This key combination forces
DOS to end the currently executing program. However, the DOS functions for
character input/output search for this key combination.
Input: No input
Output: No output
Remarlcs: Before returning control to the calling program, this interrupt must
restore all registers to their previous values.
763
Appendix B: BIOS Interrupts 0IId FlUlCtions PC System Programming
The timer IC calls interrupt 8H approximately 18.2 times per second. After ending
its task, it calls interrupt 1CH in order to allow an application program access to
the signals from the timer IC. During booting, BIOS initializes the interrupt
vector of interrupt 1CH so that it points to an IRET command, which prevents
any response if the interrupt is called. For example, this interrupt can be pointed to
a user routine to create a constant display clock on the screen.
Input: No input
Output: No output
Remarks: This interrupt must restore all registers to their previous values before
returning control to the calling program.
Sets a pointer to a table. The vector of this interrupt in the vector table, starting at
address 0000:0074, stores the offset and segment address of this table. The table
itself contains a collection of parameters used by BIOS for initializing a certain
video mode. This involves the 16 memory locations on the video card, whose heart
is a 6845 video processor. For this reason the table to which the vector points and
which is part of the ROM-BIOS, consists of 16 consecutive bytes that indicate the
contents of individual registers for a certain video mode. The frrst of these 16 bytes
is copied into the first register of the 6845, the second byte into the second
register, etc. The table in ROM contains a total of four 16-byte entries: 4Ox25
color mode, 8Ox25 color mode, 8Ox25 monochrome mode and one entry for the
various color graphics modes.
Do not call this interrupt If you do, the system will attempt to read the video
table as executable code and will crash.
Input: No input
Output: No output
Sets a pointer to a table. The vector of this interrupt in the vector table starting at
address 0000:0078 stores the offset and segment address of this table. The table
itself contains a collection of parameters used by BIOS in disk drive access. BIOS
has a table in ROM, but deviates the interrupt vector of interrupt 30 to its own
table which allows faster disk access than the BIOS table (see Section 7.7 for more
information about this table).
764
AbaclU ApperuliJc B: BIOS Interrllpts and FlUfCtions
Do not call this interrupt If you do call it. the system will attempt to read the
drive table as executable code and will crash.
Input: No input
Output: No oulput
Sets a pointer to a table. The vector of this interrupt in the vector table, starting at
address OOOO:OO7C, stores the offset and segment address of this table. The table
itself contains character patterns for the characters possessing ASCII codes 128 to
255. BIOS needs this table in order to display the graphic mode characters on the
screen. These characters are displayed by placing the character patterns, which are
stored in this table, on die screen as individual pixels.
Since the character patterns for codes 0 to 127 are already stored in a table in
ROM-BIOS, this table contains only the character patterns for codes 128 to 255.
The DOS GRAFTABL command loads a table for codes 127 to 255 into RAM and
points the interrupt vector of interrupt 31 to this table. A user table can be added to
display on the screen, in graphic mode, certain characters that are not part of the
normal PC character set. The construction of the table requires that eight
consecutive bytes define the appearance of the character. The first eight bytes of the .
table derme the appearance of ASCII code 128, the next eight bytes derme ASCII
code 129, etc. Each set of eight bytes represent the eight lines which denote a
character in graphic mode. The eight bits of each byte indicate the eight columns
of pixels for each line.
Do not call this interrupt If you do call it, the system will attempt to read the
character table as executable code and will crash.
Input: No input
Output: No oUlput
Appendix C
OlH Character input with echo (Ver. 1 and up) ................. 773
08H Character input without echo (Ver. 1 and up) ............. 778
OCH Reset input buffer and then input (Ver. 1 and up) .......780
Character output
Function Description Page Number
Program termination
Function Description rue
Number
4CH Terminate with return code (Ver. 2 and up) ................ 825
766
Abacus Appendix C: DOS /lIIeTrllpts fIIIII. FlDICtions
Subdirectory access
Function Description PaKe Number
RAM control
Function Description PaKe Number
767
AppendiJe C: DOS Interr"Pts and F/UlCtions PC System Programming
DTA
Function Description rue
Number
Search directory
Function Description rue Number
16H Create or truncate fIle (PCB) (Ver. I and up) ............. 786
23H Get file size in records (FCB) (Ver. I and up) ............ 792
28H Random block write (FCB) (Ver. I and up) ............... 795
3CH Create or truncate fIle (handle) (Ver. 2 and up) ........... 806
40H Write to file or device (handle) (Ver. 2 and up) ........... 809
768
Abacus Appendix C: DOS lrtlerTupts and FlUlCtiorts
Interrupt vectors
Function Description Pa&e Number
25H Set interrupt vector (Ver. 1 and up) .......................... 793
35H Get interrupt vector (Vee. 2 and up) .........................801
PSP access
Function Description Pa~ Number
26H Create PSP (Vee. 1 and up) .................................... 793
62H Get PSP address (Ver. 3 and up) .............................. 839
Country-specific runctions
Function Description Pa~ Number
38H Get country (Vee. 2 and up) .................................... 802
38H Get country (sub-function 0) (Ver. 3 and up) .............802
38H Set country (sub-function I) (Ver. 3 and up) .............. 804
Other rUDctions
Function Description Pa~ Number
59H Get extended err<X' information (Ver. 3 and up) ........... 831
769
Appendbc C: DOS Interrupts and Functions PC System Programming
Interrupt 22H
Terminate address ...........................................841
Interrupt 23H
<Ctri><C> handler address ............................841
Interrupt 24H
Critical error handler address .........................842
Interrupt 25H
Absolute disk read .......................................... 843
Interrupt 26H
Absolute disk write ........................................844
Interrupt 27H
Terminate and stay resident ...........................845
Interrupt 2FH
Print spooler
Function
Description Pge Number
OOH
Get print spooler install status ................................846
01H
Send file to print spooler ....................................... 846
02H
Remove fIle from print queue .................................847
03H
Cancel all fIles! in print queue ................................847
04H
Hold print job for status check................................ 846
Interrupt 21H functions-arranged by function numbers
Function
Description Pge Number
OOH
Program terminate (Ver. 1 and up)...........................773
01H
Character input with echo (Ver. 1 and up) ................. 774
02H
Character output (VeL. 1 and up) .............................774
03H
Auxiliary input (Ver. 1 and up) ............................... 775
04H
Auxiliary output (VeL. 1 and up) .............................775
05H
Character output to printer (VeL. 1 and up) ......•......... 776
06H
Direct character input/output (Ver. 1 and up) .............776
07H
UnfIltered character input without echo (Ver. 1 and up)777
08H
Character input without echo (Ver. 1 and up) .............778
09H
Output chaIacter string (Ver. 1 and up) .....................778
OAH
Buffered input (Ver. 1 and up).................................779
OBH
Get input status (Ver. 1 and up) ..............................780
OCH
Reset input buffer and then input (Ver. 1 and up) .......780
ODH
Disk reset (Ver. 1 and up) ...................................... 781
OEH
Set default disk drive (Ver. 1 and up) ........................781
OFH
Open fIle (FCB) (Ver. 1 and up) ..............................782
10H
Close fIle (FCB) (Ver. 1 and up) .............................782
llH
Search for first match (PCB) (Ver. 1 and up) .............783
12H
Search for next match (PCB) (Ver. 1 and up) .............784
13H
Delete fIle (FCB) (VeL. 1 and up) ...........•................ 784
14H
Sequential read (FCB) (Ver. 1 and up) ......................785
15H
Sequential write (FCB) (Ver. 1 and up).....................786
16H
Create or truncate fIle (PCB) (VeL. 1 and up) .............786
17H
Rename fIle (FCB) (Ver. 1 and up) .........•................ 787
19H
Get default disk drive (Ver. 1 and up) ....................... 788
lAH
Set DTA address (Ver. 1 and up) ...........••................ 788
IBH
Get allocation information for default drive
21H
Random read (FCB) (VeL. 1 and up) ......................... 790
22H
Random write (PCB) (VeL. 1 and up) .......................791
23H
Get fIle size in records (PCB) (VeL. 1 and up) ............ 792
770
Appendix C: DOS Inlerrllpts awl FlIlICtions
28H Random block write (PCB) (Ver. 1 and up) ............... 795
30H Get MS-DOS version number (Ver. 2 and up) ..........• 799
31H Terminate and stay resident (Ver. 2 and up) ..•...........• 799
3CH Create or truncate ftle (handle) (Ver. 2 and up) .........•. S06
40H Write to ftle or device (handle) (Ver. 2 and up) ........... 809
43H Set file attributes (sub-function 1) (Ver. 2 and up) ...... 812
771
4FH Search for next match (handle) 0/er. 2 and up) ..........• 827
57H Get file date and time (sub-function 0) 0/er. 2 and up). 829
57H Set file date and time (sub-function 1) 0/er. 2 and up). 829
SEH Set printer setup (sub-function 2) 0/er. 3 and up) ....... 836
63H Get lead byte table (sub-function 0) 0/er. 2.25 only) ... 840
772
Abacus Appendix c: DOS Interrllpts and FlUfCtions
Restores the three interrupt vectors whose contents were stored in the PSP before
the program call, terminates the currently running program and returns control to
MS-DOS. If the program redirected the vectors to its own routine, these vectors
cannot be overwritten by another program. However, the terminating program
releases the RAM it had occupied. Before turning control over to the calling
program, this memory releases and all data buffers cleM.
Input: CS =Segment address of the PSP
Output: No output
Remarks: COM programs automatically store the segment address of the PSP in the
CS register. EXE programs require additional programming to load the
segment address of the PSP into the CS register. Since the code and the
PSP are stored in two separate segments, the address of the PSP must be
loaded into the CS register. The code executes from another segment,
which makes it impossible to call interrupt 32. To help overcome this
problem, the value 0 and then the segment address of the PSP are pushed
onto the stack. If aFAR RETURN command then executes, the program
execution continues in the PSP segment at offset address O. There a call
for interrupt terminates the program.
For the flfSt version of DOS, this interrupt is the usual method for ending
a program. To terminate a program in DOS Version 2 and up, functions
31H or 4CH of DOS interrupt 21 H should be called instead.
Terminates execution of the currently running program and returns control to the
calling program. Before this happens, the three interrupt vectors, whose contents
had been stored in the PSP before the call of the program, are restored. If the
program redirects these vectors to its own routine, they cannot be overwritten by
another program. However, the terminating program does release the RAM it had
occupied. Before turning control over to the calling program, the function releases
this memory and clears all buffers.
Input: AH= OOH
CS = segment address of the PSP
Output: No output
Remarlcs: COM programs automatically store, in the CS register, the segment
address of the PSP. Since the code and the PSP are stored in two separate
segments, you cannot execute this function from an EXE program.
773
Appendix C: DOS Interrupts 0IId Functions PC System Programming
Instead of this function, use either function 31H or 4CH of interrupt 21H
for terminating a program.
Reads a character from the standard input device and displays it on the standard
output device. When the function is called but a character doesn't exist, the
function waits until a character is available. Since standard input and output can be
redirected, this function is able to read a character from an input device other than
the keyboard and send it to an output device other than the screen. The characters
that are read may originate from other devices or from a me. If the character comes
from a file, the input doesn't redirect to the keyboard once it reaches the end of the
file. So, the function continues to try to read data from the file after it passes the
end
Remarks: If extended key codes are read, the function passes code 0 to the AL regis
ter. The function must be called again to read the actual code.
The contents of the AH, BX, CX, DX, SI, 01, BP, CS, DS, SS, ES and
the flag registers are not affected by this function.
Displays a character on the standard output device. Since this device can be
redirected, the character can be displayed on another output device or sent to a me.
This function doesn't test whether or not the storage medium (disk or hard disk) is
already full. Therefore, it will continue to try to write characters to this me.
Input: AH= 02H
DL = code of the character to be output
Output: No output
Remarks: Control codes such as backspace, carriage return and linefeed are executed
when the function sends characters to the screen. If the output is redirected
to a file, control codes are stored as normal ASCII codes.
774
AbacllS Appendix C: DOS Interrupts and FlIIICtions
The contents of the processor registers and the flag registers are not
affected by this function.
Reads a character from the serial port. Access defaults to the device with the
designation COMI, unless a MODE command previously redirected serial access.
Remarks: Since the serial port has no internal buffer, it can receive characters faster
than it can read them. The unread characters are then ignored.
The BIOS functions called from interrupt 14H are a more efficient way to
access the serial port. Since they also allow reading of the serial port
status, these functions offer more flexibility than the OOS functions.
The contents of the AH, BX, CX, DX, SI, DI, BP, CS, DS, SS, ES and
the flag registers are not affected by this function.
Output: No output
Remarks: As soon as the receiving device sends a signal to the function indicating
that it is ready to receive it, the function transmits the character. Control
then returns to the calling program.
775
Appendix C: DOS Interrupts and FlIIICtions PC System Programming
Otherwise DOS defaults to 2400 baud, one stop bit, no parity and a word
length of 8 bits.
The BIOS functions called from interrupt 14H are a more efficient way to
access the serial port. Since they also allow reading of the serial port
status, they offer more flexibility than the DOS functions.
The contents of the processor registers and the flag registers are not
. affected by this function.
Sends a character to the printer. Access defaults to the device with the designation
LPTI (identical to PF~, unless a MODE command previously redirected printer
access. •
Input: AH= 05H
DL = Character code to be printed
OutPut: No output
Remarlcs: The function transmits the character only when the printer signals that it
is ready to receive it. Then control returns to the calling program.
The BIOS functions called from interrupt 17H are more ef~cient for
printer access. They offer more flexibility than the DOS printer functions
for character output
The contents of the processor registers and the flag registers are not
affected by this function.
Reads characters from the standard input device and displays them on the standard
output device. The read or written character isn't tested by the operating system
(e.g., <Ctrl><C> has no effect on the program). Since standard input and output
can be redirected, this function can read a character from an input device other than
the keyboard and sends it to an output device other than the screen. The characters
read may originate from other devices or from a rtle. When writing characters, this
function doesn't test whether or not the storage medium (disk or hard disk) is
776
Abacus AppendiJc C: DOS inlt!1'rllpts and FlIIICtions
already full. Also, the calling program cannot detennine whether all the characters
have been read from an input fIle.
During character input, the function doesn't wait until a character is available.
Instead, the function retwlls control to the calling program.
Input: AH= 06H
DL = 0-254: Send character code
DL = 255: Read a character
Output: Character output: No output
Character input: Zero flag=1: No character ready
Zero f1ag=O: Character read is in the AL register
Remarks: If extended key codes are read, the function passes code 0 to the AL regis
ter. The function must be called again to read the actual code.
ASCn code 255 (blank) cannot be displayed with this function because
the function interprets ASCII code 255 as a command to input a character.
The contents of the AR, BX, CX, DX, SI, DI, BP, CS, DS, SS and ES
registers are not affected by this function.
Reads a character from the standard input device without displaying the character on
the standard output device. If a character doesn't exist when the function is called,
the function waits until a character is available. The read character is not tested by
the operating system (e.g., <Ctrl><C> has no effect on the program). Since
standard input and output can be redirected, this function can read a character from
an input device other than the keyboard. The characters that are read may originate
from other devices or from a file. If the characters come from a file, the input
doesn't redirect to the keyboard once it reaches the end of file. This causes the
function to continue to try reading data from the file after it passes the end of fIle.
Input: AR= 07H
Output: AL = Chara;ter read
Remarks: If extended key codes are read, the function passes code 0 to the AL regis
ter. The function must be called again to read the actual code.
The contents of the AH, BX, CX, DX, SI, DI, BP, CS, DS, SS, ES and
the flag registers are not affected by this function.
777
Appendix C: DOS InleTT'IIpIS and FlUfCtUms PC System Programming
Reads a character from the standard input device without dispJaying the character on
the standard output device. If no character exists when the function is called, the
function waits until a character is available.
Since standard input can be redirected, this function can read a character from an
input device other than the keyboard. The characters read may originate from other
devices or from a file. If the characters come from a file, the input doesn't redirect
to the keyboard on reaching the end of file, so the function continues to tty reading
data from the file after it passes the end of fIle.
Remarks: If extended key codes are read, the function passes code 0 to the AL regis
ter. The function must be called again to read the actual code.
The contents of the AH, BX, CX, OX, SI, DI, BP, CS, OS, SS, ES and
the flag registers are not affected by this function.
Displays a character string on the standard output device. Since this device can be
redirected, the character may be dispJayed on another output device or sent to a file.
This function doesn't test whether or not the storage medium (disk or hard disk) is
already full, and will continue to try to write the string to a file.
Input: AH= 09H
OS = String segment address
OX = String offset address
Output: No output
Remarlcs: The string must be stored in memory as a series of bytes which contain
the ASCII codes of the characters to be output A dollar sign character "$"
(ASCII code 36) indicates, to DOS, the end of the string.
Control codes, such as backspace, caniage return and linefeed, are executed
within the string.
The contents of the processor registers and the flag registers are not
affected by this function.
778
Abacus Appendix C: DOS Inlerllpts and FlIIICtions
Since standard input can be redirected, this function can read a character from an
input device other than the keyboard. The characters read may OOginate either from
other devices or from a file. If the characters come from a file, the input doesn't
redirect to the keyboard on reaching the end of file, so the function continues to tty
reading data from the file after it passes the end.
Input: AH= OAH
OS = Buffer' segment address
OX = Buffer offset address
Output: No output
Remarlcs: The frrst byte of the buffer accepts the maximum number of characters
(including the carriage return which ends the input) which can be read into
the buffer, starting at memory location 2. In order to inform the function
of the maximum number of characters it may read, this information must
be entered, by the calling program, into the buffer before the function
call.
After completion of the input, DOS places the number of characters read
(excluding the carriage return) in memory location 1.
The buffer must be the number of the characters to be read plus 2 bytes.
When the input reaches the second to last memory location in the buffer,
the computer beeps if you attempt to enter any character other than the
<Return> key (end of input).
Extended key codes occupy two bytes in the buffer. The first byte
contains the code 0, and the second byte contains the extended key code.
The <Backspace> and cursor keys let you edit the input without storing
these keys in the buffer.
The contents of the processor registers and the flag registers are not
affected by this function.
779
AppendiJC C: DOS Inlerrllpts and Functions PC System ProgrfllNlling
Detennines whether a character is available for reading from the standard input
device.
Input AR= OBH
Output: AL = 0: No character available
AL = 255: One or more characters available for reading
Remarks: If the function encounters a <Ctrl><C> character (ASCII code 3), it calls
interrupt 23H.
The contents of the AR, BX, CX, OX, SI, DI, BP, CS, OS, SS, ES and
the flag registers are not affected by this function.
Clears the input buffer then calls one of the character input functions. Since all the
character input functions get their characters from the standard input device and
standard input may redirected, this function only operates when the keyboard is the
standard input device. In this case the characters could be entered before the
function call but not read by a function. These existing characters are erased to
ensure that the function call only reads characters which were inputted after its call.
Input: AR= OCH
AL = Function to be called during call of function 10
OS = Input buffer segment address
OX = Input buffer offset address
Output: Functions I, 6, 7 and 8: AL = Character to be read
Function 10: No output
Remarks: Functions 1,6,7,8 and 10 can be passed to the function as calling func
tions.
The contents of the AR, BX, CX, OX, SI, DI, BP, CS, OS, SS, ES and
the flag registers are not affected by this function.
780
Abacus AppendiJc c: DOS Interrupts and Frmctions
Sends all data stored in an internal DOS buffer to a block driver device (e.g., disk
drive, hard disk). The open ftles (handles or FCBs) remain open.
Renwks: Despite this function call, all open mes must be closed in an ordedy
manner. Otherwise the current directory entry of the file may not update
properly, which prevents access to new file data.
The contents of the processor registers and the flag registers are not
affected by this function.
Defines the the current default disk drive. Its designation appears as a prompt on
the screen when the command interpreter expects input from the user. The drive
indicated here will be used for all me access in which no special device was
specified.
Input: AH = OEH
OL = Drive number
Output: AL = Number of installeddnves or volumes
Renwks: Drive A: has code number of 0, drive B: code number I, etc.
Even if the PC has only one disk drive and one hard disk, the number of
volumes in the AL register can be greater than two because the hard disk
can be divided into multiple volumes. In addition, the PC can have one or
more RAM disks as part of its configuration. For a PC with a single disk
drive, you can only have two volumes because drive A: also simulates
driveB:.
BIOS interrupt 11H does a better job of reading the number of disk drives
than this function.
The contents of the AH, BX, ex, ox, SI, 01, BP, es, OS, SS, ES and
the flag registers are not affected by this function.
781
Appendix C: DOS lnurrupts ond FlUlCtions PC System Progrtlltlllting
If the file was found, DOS enters, into the FCB, the file size, the date and
the time of its creation or last modification.
DOS sets the record length at 128 bytes. This record length can be
changed in the FCB before opening a file. If you need a longer record
length, the DTA must be moved (the original DTA is only 128 bytes
long).
If random file access is performed, the random record field in the FCB
must be set after the file opens successfully.
The file pointer points to the first byte of the file after the file opens.
The contents of the AH, BX, CX, DX, SI, 01, BP, CS, DS, SS, ES and
the flag registers are not affected by this function.
Writes all data currently in the DOS buffer to the file and closes the file. In
addition, the directory entry changes to reflect the new file size and the date and
time of the most recent modification to the file.
Input: AH= IOH
DS = FCB segment address of the file
DX = FCB offset address of the file
Output: AL = 0: File closed and directory entry revised
AL = 255: File not found in directory
Remarlcs: Only open files can be closed.
For disk files, the disk which was in the drive when the function call
occurred must also be the disk that contains the file. Otherwise, the
782
Abacus Appendix C: DOS Interrupts and Functions
The contents of the AH, BX, CX, OX, SI, 01, BP, CS, OS, SS, ES and
the flag registers are not affected by this function.
Searches for the fIrst occurrence in the disk directory of the fIlename indicated in
the FCB.
Remarks: The FCB passed to the function contains the drive specifier and the
fIlename for which the function should search.
The fIlename can contain the wildcard "1" to search for a group of fIles.
The search is made only in the current directory of the indicated device.
If the function searches for a normal file, a normal FCB can pass the
information to the function. However, if you wish to search for a fIle
with special attributes (volume name, subdirectories, hidden fIles, etc.),
extended PCBs must be used.
If a fIle was found, the OTA contains an FCB of the same type as the
FCBs. This FCB in the OTA contains the found filename. For this
reason, the OTA must always be large enough to accept either a normal
or an extended PCB.
The OTA can be switched to its own buffer using function IAR, to
ensure that it is large enough to accept the FCB.
The contents of the AH, BX, CX, OX, SI, 01, BP, CS, OS, SS, ES and
the flag registers are not affected by this function.
783
Appendix C: DOS Interrupts and Functions PC System Programming
Searches for additional occurrences in the disk directory of the filename indicated in
the FCB, after the file was found by function 17 (see above).
Remarks: This function can only be called after calling function llH.
The FCB passed to the function contains the drive specifier and the
flIename for which the function should search.
If another. filename was found its name is recorded in the FCB at the
beginning of the OTA.
The OTA can be switched with function lAH to its own buffer to ensure
that it is large enough to accept the FCB.
The contents of the AH' BX, CX, DX, SI, 01, BP, CS, OS, SS, ES and
the flag registers are not affected by this function.
Remarks: The FCB passed to the function contains both the device on which the
flies to be erased are located and the name of the file.
The filename can contain the wildcard "?" to erase a group of files.
Only files in the current directory of the indicated device may be erased.
If the function is used to delete a normal file, a normal FCB can pass the
information to the function. However, if you want to delete a file with
special attributes (volume name, subdirectories, hidden files, etc.),
extended FCBs must be used.
784
Abacus Appendix C: DOS Interrupts and Functions
The contents of the AH, BX, CX, OX, SI, 01, BP, CS, OS, SS, ES and
the flag registers are not affected by this function.
Remarks: The function can only be called after the file was opened by the indicated
FCB.
The OTA reads the block. If the OTA is not large enough, function IAH
must move the OTA into its own buffer.
The FCB records the size of the block and the corresponding number of
oytesread.
Error 2 occurs when the OTA reaches the end of a segment and the block
being read extends beyond the end of the segment
Error 3 occurs when a partial block appears at the end of the file. The
block is read in anyway and blank spaces bring the block up to the
allocated block size.
After reading a block, the me pointer resets to the beginning of the next
block so that the next function call automatically reads the next block.
The contents of the AH, BX, CX, OX, SI, 01, BP, es, OS, SS, ES and
the flag registers are not affected by this function.
785
AppendiJe C: DOS InleTrupts and F/UlCtions PC System Programming
Remarlcs: The function can only be called after the file was opened by the indicated
FCB.
The OTA writes the block it contains to the file. If the OTA is not large
enough to hold the file, function IAH must be used to move the OTA
into its own buffer.
The FeB records the size of the block and the corresponding number of
bytes written.
Error 2 occurs if the OTA reaches the end of a segment and the block
being written extends beyond the end of the segment
After writing a block, the file pointer resets to the beginning of the next
block, so that the next function call automatically writes the next block.
The contents of the AH, BX, CX, OX, SI, 01, BP, CS, OS, SS, ES and
the flag registers are not affected by this function.
Creates a new file, or dumps the contents of an existing file (file size=O bytes).
This function call allows other functions to read or write to the open file.
Remarks: The contents of an existing fIle called by this function are lost.
After calling this function, the fIle is already open; you don't need to open
the file using function OFH (see above).
786
Abacus Appendix C: DOS IfIlerrMprs and FlUlCtitms
If you open the fIle using an extended FeB, you can assign certain
attributes to the fIle (e.g., volume name, hidden file, etc.).
After opening the fIle, the fIle pointer moves to the frrst byte of the fIle.
The contents of the AH, BX, ex, OX, SI, DI, BP, es, OS, SS, ES and
the flag registers are not affected by this function.
Renames one or more files in the current directory of the specified device.
Input: AH= 17H
OS = FCB segment address
OX = FCB offset address
Output: AL = 0: File(s) renamed
AL = 255: No file found, or new filename matches old filename
Remarlcs: The FeB here is a special FCB, based on a normal FeB. The first 12
bytes contain the drive specifier and the name of the file to be renamed.
However, this type of FeB has the new drive specifier and the new
filename stored starting at memory location lOH. The drive specifier must
be identical for both filenames.
The name of the fIle to be renamed can contain the wildcard "1", which
renames several files. If the new filename contains the wildcard "1", the
places in the fIlename and extension where a question mark appears in
this parameter remain unchanged.
The contents of the AH, BX, ex, OX, SI, DI, BP, es, DS, SS, ES and
the flag registers are not affected by this function.
787
Appendix C: DOS Inlerrllpts and FlUfCtioru PC System ProgrtlllllttUsg
The contents of the AH, BX, CX, OX, SI, DI, BP, CS, OS, SS, ES and
the flag registers are not affected by this function.
Transfers the OTA (Disk Transfer Area) to another area of memory. The OTA acts
as buffer memory for all FCB supported file accesses.
Output: No oulput
Remarks: This function must be called if the existing DTA has insufficient memory
to handle the transmitted data.
When the program starts, MS-DOS places the OTA at address 128 in the
PSP. Since the program starts after address 255 of the PSP, it is 128
bytes long.
DOS does not test the length of the OTA. Instead it assumes that the
OTA is large enough to accept the transmitted data. If this is not the case,
a DOS function can overwrite the excess data.
DOS recognizes an error during various functions if the OTA is at the end
of a segment and the data to be transmitted exceeds the end of the
segment.
The contents of the processor registers and the flag registers are not
affected by this function.
788
Abacus Appendix C: DOS InterrllplS and Functions
DX = Number of clusters
The contents of the All, BX, CX, DX, SI, 01, BP, CS, DS, SS, ES and
the flag registers are not affected by this function.
DL = Drive specifier
DX = Number of clusters
The contents of the All, BX, CX, DX, SI, 01, BP, CS, DS, SS, ES and
the flag registers are not affected by this function.
789
Appendix C: DOS Interrupts and Functions PC System Programming
The record whose address is stored in the FCB starting at location 21H is
read.
The DTA reads the record. If the DTA is not large enough, function IAH
must be called to move the DTA into its own buffer.
The FCB records the size of the record and the corresponding number of
bytes read.
During the function call, the file pointer moves to the beginning of the
record being read so that a subsequent call of a sequential read (function
14H-see above) reads the same record sequentially.
The record number does not increment following the function call, so a
new call of this function would read the same record.
Error 2 occurs when the DTA reaches the end of a segment and the record
being read extends beyond the end of the segment
790
Abacus Appendix C: DOS inlerrllpts and Functions
Error 3 occurs when a partial record appears at the end of the file. The
record is read in anyway and blank spaces bring the record up to the
allocated record size.
The contents of the AH, BX, CX, DX, SI, 01, BP, CS, DS, SS, ES and
the flag registers are not affected by this function.
The record whose address is stored in the FCB starting at location 21H is
read.
The record is written from the DT A to the file. If the DTA is not large
enough, function IAH must move the DTA into its own buffer.
The FCB records the size of the record and the number of bytes read.
During the function call, the file pointer moves to the beginning of the
record being read. This instructs subsequent calls of a sequential read
(function 14H-see above) to read the same record sequentially.
The record number does not increment following the function call, so a
new call of this function would read the same record.
Error 2 occurs when the DTA reaches the end of a segment and the record
being written extends beyond the end of the segment
The contents of the AH, BX, CX, DX, SI, 01, BP, CS, DS, SS, ES and
the flag registers are not affected by this function.
791
Appendix c: DOS InlUrllpts and FlUlCtioru PC System Progronaming
Remarks: The FeB passed contains the drive specifier as well as the name and
extension of the me to be examined.
Unlike the other FeB supported me accesses, the PCB requires the record
size before the application can call this function.
Sets the record number in the FeB to the current position of the fIle pointer.
Random access may begin at the point at which earlier sequential accesses left off.
Output: No output
Remarlcs: The function can only be called after the fIle was opened by the indicated
FeB.
The contents of the processor registers and the flag registers are not
affected by this function.
792
Abacus AppendiJc c: DOS Interrupts fl1fIl. FlIIICtions
The contents of the processor registers and the flag registers are not
affected by this function.
For DOS Version 2 up, use the EXEC function 4BH to load and execute
additional programs instead of this function.
The contents of the processor registers and the flag registers are not
793
Appendix C: DOS Inlerrllpts and Functions PC System Programming
The starting record is the record whose address is stored in the FeB,
starting at location 21H.
The record data passes to the OTA. If the OTA is not large enough,
function lAH must move the OTA into its own buffer.
The FeB records the size of the record and the corresponding numbeJ- of
bytes read.
Mter the function call, the file pointer moves to the end of the last record
that was read so that it points to the next record (following the last record
reOO>.
Error 2 occurs when the DTA reaches the end of a segment and the record
being read extends beyond the end of the segment
Error 3 occurs when a partial record appears at the end of the file. The
record is read in anyway and blank spaces bring the record up to the
allocated record size.
The contents of the AH, BX, ex, ox, SI, 01, BP, CS, DS, SS, ES and
the flag registers are not affected by this function.
794
Abacus AppertdiJc C; DOS intt!n'''Pts and FJUlCtions
The starting record is the record whose address is stored in the FeB
starting at location 21H.
The FeB records the size of the record and the corresponding number of
bytes read.
The data is written from the OTA to the flle. If the OTA is not large
enough, function IAH must move the DTA into its own buffer.
After the function call, the flle pointer moves to the end of the last. record
written so that it points to the next record, which follows the last record
written. The record number increments by the number of records written.
Error 2 occurs when the DTA reaches the end of a segment and the record
being written extends beyond the end of the segment
The contents of the AH, BX, ex, ox, SI, 01, BP, es, os, SS, ES and
the flag registers are not affected by this function.
Transfers an ASCII format rueruime into the proper fields of an FCB. The ruename
can include a drive specifier, fIlename and fIle extension.
Input: AH = 29H
DS = Segment address of fllename in memory
SI = Offset address of ruename in memory
ES = FCB segment address
01 = FCB offset address
795
Appendix C: DOS Intemlpts and FlllfCtions PC System Programi'lUng
AL = Transmission parameters:
Bit 1 = 1: The drive specifier in the FCB changes only if the fllename
passed contains a drive specifier
0: The drive specifier changes anyway. If the filename passed
contains no drive specifier, the the FeB defaults to 0
(current drive)
Bit 2 =
1: The filename in the FCB changes only if the filename
parameter passed contains a filename
0: The fllename changes. If the fllename passed does not con
tain a fllename, the fllename in the FCB fills with spaces
(ASCII code 32)
Bit 3 = 1: The flle extension in FCB changes only if the fllename
passed contains an extension
0: The flle extension in the FeB changes. If the filename
passed has no extension, the extension field is padded with
spaces (ASCII code 32)
Bits ~: Should contain the value 0
Remarks: The filename must end with an end character (ASCII code 0).
If the fllename contains the wildcard ".", all corresponding fields in the
FCB fiU with the wildcard "?".
The contents of the AH, BX, ex, ox, SI, 01, BP, es, OS, SS, ES and
the flag registers are not affected by this function.
The contents of the AH, BX, ex, ox, SI, 01, BP, es, OS, SS, ES and
the flag registers are not affected by this function.
796
Abacus Appendbc c: OOS Interrupts and FlUICtions
Sets the current system date as returned by function 2AH (see above).
Input: AlI= 2BH
CX= Year
OH= Month
OL= Day
Output: AL= 0: O.K.
AL = 255: Date incorrect
If the PC does not have a realtime clock, the date remains in effect until
the PC is switched off or rebooted.
The contents of the AlI, BX, CX, OX, SI, 01, BP, CS, OS, SS, ES and
the flag registers are not affected by this function.
The contents of the AlI, BX, CX, OX, SI, 01, BP, CS, OS, SS, ES and
the flag registers are not affected by this function.
Input: AH = 2DH
CH= Hours
CL= Mmiites
OH= Seconds
OL = hundredths of a second
797
Appendix C: DOS l111errllpts and FlUlCtiolU PC System Programming
If the PC does not have a realtime clock. the time remains in effect until
the PC is switched off or rebooted.
The contents of the AH. BX. ex. DX. SIt DI. BP, es, DS, SSt ES and
the flag registers are not affected by this function.
Sets the verify flag. This flag determines whether data should be verified after a
write operation to a block driver for proper ttansmission.
Input: AH= 2EH
DL= 0
AL = 0: Don't verify data
AL = 1: Verify data
Output: No output
RemaIks: This flag can be controlled at the user level with the VERIFY ON and
VERIFY OFF commands.
The contents of the processor registers and the flag registers are not
affected by this function.
Returns the address of the DTA (Data Transmission Area). which serves as a data
buffer for all FeB supported me accesses.
Input: AH= 2FH
Output: ES = DTA segment address
BX = DTA offset address
Remarks: This function determines the address of the DTA. but not the DTA's size.
After the start of a program. the DTA starts at memory location 128 of
the PSP and has a length of 128 bytes.
The contents of the AH. BX. ex. DX, SIt DI. BP. es, DS. SSt ES and
the flag registers are not affected by this function.
798
Abacus Appendix C: DOS Inlerrllpts and FlUlCtions
Remarlcs: The major (whole) version number represents the number preceding the
decimal point. For example, the version number 3.3 returns the major
version number 3.
The contents of the OX. SIt DI. BP, es, OS. SS, ES and the flag
registers are not affected by this function.
Terminates the currently executing program and returns control to the calling
program. The current program remains in memory for later recall.
Output: No output
Remarlcs: The return code in the AL register indicates whether or not the program
called by it correctly executes. The calling program can read this number
by calling function 77 (40H). This value can be tested from within a
batch file using the ERRORLEVEL and IF commands.
Memory blocks reserved by function 48H are not affected by the value in
the OX register because they can only be released by calling function
49H.
799
Appendix C: DOS Irtlerrupts and FlUfCtions PC System Progromming
Reads the <Ctrl><Break> flag. This determines whether DOS should test for
active <Ctrl><C> or <ctrl><Break> keys on each function call, or on character
input/output calls. <Ctrl><C> and <ctrl><Break> trigger interrupt 23H.
Remarks: Since the <Ctrl><Break> flag is not part of the environment block of a
program, it affects all programs which call the DOS character functions
that test for <Ctrl><C> or the <Break> key.
The contents of the AH, BX, CX, OX, SI, 01, BP, CS, OS, SS, ES and
the flag registers are not affected by this function.
Sets and unsets the <Ctrl><Break> flag. This detennines whether DOS should test
for the activation of the <Ctrl><C> or <Ctrl><Break> keys on each DOS
function call or character input/output calls. <Ctrl><C> and <Ctrl><Break>
trigger interrupt 23H.
Output No output
Remarks: Since the <Ctrl><Break> flag is not part of the environment block of a
program, it affects all programs which call the DOS character functions
that test for <Ctrl><C> or the <Break> key.
The contents of the processor registers and the flag registers are not
affected by this function.
~ I
800
Abacus Appel'lllU C: DOS Intf!ITupts and FlUlCtions
Returns the current contents of an interrupt vector and the address of the interrupt
routine that belongs to it.
The contents of the AH, BX, ex, ox, SI, DI, BP, es, OS, SS, ES and
the flag registers are not affected by this function.
Returns information about the device (the block driver) from which the
available memory space can be calculated.
Input: AH= 36H
OL = Device code
The remaining memory on the medium can be computed from the number
of bytes per sector multiplied by the number of sectors per cluster,
multiplied by the number of free clusters.
The contents of the SI, DI, BP, es, OS, SS, ES and the flag registers are
not affected by this function.
801
Appendix C: DOS Inlemlf'ts and Functions PC System Programming
The buffer must have at least 32 bytes allocated for recording the various
country-specific parameters.
Following the function call, the individual bytes of this buffer contain the
following information :
The contents of the processor registers and the flag registers are not
affected by this function.
802
Abacus Appendu: C: DOS Interrupts and FlUfCtions
Remruks: Before the function call, function 30H should be used to determine the
OOS version. This can help the programmer compensate for differences
between OOS versions during the call and return of this function.
The buffer must have at least 32 bytes allocated for recording the various
country specific parameters.
Following the function call, the individual bytes of this buffer contain the
following infonnation:
Bytes 0-1: Date format
0= USA: Month-day-year
1 = Europe: Day-month-year
2 = Japan: Year-month-day
Bytes 2-6: Currency indicator (string terminated by an end character)
Byte 7: ASCII code of the thousand character (comma/period)
Byte 8: 0
Byte 9: ASCII code of decimal character (period/comma)
Byte 10: 0
Byte 11: ASCn code of the date separation character
Byte 12: 0
Byte 13: ASCn code of the time separation character
Byte 14: 0
Byte 15: Currency fonnat
bit 0 = 0: Currency symbol before the value
bit 0 = 1: Currency symbol after the value
bit 1 = 0: No spaces between value and currency symbol
bit 1 = 1: Space between value and currency symbol
Byte 16: Precision (number of decimal places)
Byte 17: Time fonnat
bit 0 = 0: 12-hour clock
bit 0 = 1: 24-hour clock
Bytes 18-21: Address of character conversion routine (see below)
Bytes 22-33: reserved
The contents of the AH, BX, CX, OX, SI, DI, BP, CS, OS, SS, ES and
the flag registers are not affected by this function.
803
Appendix C: DOS lnurrupts and FlI1ICtions PC System Programming
This function only allows setting of the country code, for which DOS has
preset parameters. These parameters cannot be changed from this function.
The contents of the AH, BX. CX, OX, SI, 01, BP, CS, OS, SS and ES
registers are not affected by this function.
An error can occur if any element of the path designation doesn't exist, a
subdirectory already exists by that name, or the directory to be made is a
subdirectory of the root directory and it is already filled.
804
Abacus Appendi:x c: DOS Inlerrupts and FlUlCtions
The contents of the BX, ex, DX, SI, DI, BP, es, DS, SS and ES
registers are not affected by this function.
Output:
-
Carry t1ag=O: Subdirectory deleted
Carry f1ag=l: Error (AX = error code)
AX=3: Path not found
AX=5:<k.cess denied
AX=6: Directory to be deleted is the current directory
Remarks: The subdirectory path passed is an ASen string which is tenninated by
an end character (ASen code 0). e:
An error can occur if any element of the path designation doesn't exist,
the subdirectory is the current directory, or the directory to be deleted still
contains fIles.
The contents of the BX, CX, OX, SI, DI, BP, CS, OS, SS and ES
registers are not affected by this function.
805
AppendiJc C: DOS Inlerrupts ond F&lllCtions PC System ProgrfllMJing
An error can occur if any element of the path designation doesn't exist.
The contents of the BX, CX, OX, SI, DI, BP, CS, OS, SS and ES
registers are not affected by this function.
Remarks: The various bits of the fIle attribute can be combined with each other.
An error can occur if any element of the path designation doesn't exist, if
the file must be created in the root directory which is already full, or if a
fIle with the same name already exists but cannot be cleared because it is
write protected (bit 0 in the fIle attribute byte =1).
If the function call executed successfully, all other handle functions can be
called with this handle once the file opens. '
The contents of the BX, CX, OX, SI, DI, BP, CS, OS, SS and ES
registers are not affected by this function.
806
AbacllS AppendiJC C: DOS Inl.rupts tlIId FlUlCtions
Bit 3: O(b)
Bits ~: File sharing mode
000(b) = Only current program can access the file (FCB mode)
00 1(b) = Only the current program can access the file
01O(b) =Another program can read but not write the file
011(b) = Another program can write but not read the file
l00(b) =Another program can read and write the file
Bit 7: Handle flag
o=Child program of the current program can access file handle
1 =Current program can access file handle only
DS = Filename segment address
DX = Filename offset address
Output: Carry flag=O: O.K. (AX = file handle)
Carry flag= 1: Error (AX = error code)
AX=I:Missing ftle sharing software
AX=2: File not found
AX=3: Path not found or ftle doesn't exist
AX=4: No handle available
AX=5: Access denied
AX=12: Access mode not pennitted
Remarks: The filename must be available as an ASCII string terminated by an end
character (ASCn code 0). The ftlename parameter can contain a driver
specifier, path, ftlename and extension. No wildcards are allowed. If you
omit the drive specifier or path, OOS accesses the current drive or current
directory.
If the function call executes successfully, all other handle functions can be
called with this handle once the file opens.
DOS Version 2 uses only bits 0 to 2 of the access mode. All other bits,
even under Version 3, should be 0 to ensure proper execution of the call.
DOS Version 3 uses the ftle sharing mode in bits 4 to 6 of the access
mode only if the ftle is on a mass storage device which is part of a
network. These three bits decide if and how the ftle, while it is open
807
Appendix c: DOS Interrupts Q1fd F'lUICtions PC System Programming
using the current call, may be accessed by other programs from other PCs
,/ on the network.
Error 12 can occur only und« DOS Version 3 and only within a network
when the file is already opened by another program and if no other
program can gain access tolhat file.
The contents of the BX, CX, OX, SI, 01, BP, CS, DS, SS and ES
registers are no~ affected by this function.
Writes any data in the OOS buffers to a currently open file, then closes the file. If
changes occur to the file, the new file size and the last date and time of
modification are adde3 to the directa:)'.
Input: AH= 3EH
BX = Handle to be closed
Output: Carry flag=O: O.K.
Carry flag=l: Error (AX = error code)
AX=6: Unauth<Xized handle or file not opened
Remarks: Do not accidentally call this functiOn with the numbers of the previous
handle (the numbers 0 to 4) because the standard input device or standard
output device may close. This 'Nould leave you unable to enter characters
from the keyboard or display characters on the screen.
The contents of the BX, CX, OX, SI, 01, BP, CS, OS, SS and ES
registers are not affected by this function.
808
Abacus Appendix C: DOS Itt1errllflts and FlUtCtions
Remarks: Characters can be read from a file or from a device (e.g., the standard input
device [keyboard], which has the handle 0).
When the carry flag resets after the function call but the AX register has
the value 0, this means that the file pointer has already reached the end of
the file before the function call. So, no files could be read.
When the carry flag resets after the function call but the contents of the
AX register are smaller than the contents of the ex register before the
function call, this means that the desired number of bytes wasn't read
because the end of the file was reached.
After the function call, the file pointer follows the last byte read.
The contents of the BX, ex, DX, SI, DI, BP, es, DS, SS and ES
registers are not affected by this function.
When the carry flag resets after the function call but the AX register has
the value 0, this means that the file pointer has already reached the end of
the file before the function call. Therefore no files could be written.
When the carry flag resets after the function call but the contents of the
AX register are smaller than the contents of the ex register before the
function call, this means that the desired number of bytes were not
written because the end of file was reached.
After the function call, the file pointer follows the last byte written.
809
Appendix C: DOS InterrMpts and Functions PC System Programming
The contents of the BX, CX, OX, SI, 01, BP, CS, OS, SS and ES
registers are not affected by this function.
Oeletes the filename passed to the function. Through the call of this function, a
file is erased and its name is passed to the function.
Input: AlI= 41H
OS = Filename segment address
OX = Filename offset address
Output: Carry flag=<>: O.K.
Carry flag=l: Error (AX =error code)
AX=2: File not found
AX=5: Access denied
Remarks: The ftlename must be available as an ASCII string terminated by an end
character (ASCII code 0). The filename parameter can contain a drive
specifier, path, ftlename and extension. No wildcards are allowed. If you
omit the drive specifier or path, OOS accesses the current drive or current
directory.
An error occurs when any element of the path designation doesn't exist or
when the file has the attribute Read Only and therefore can not be written
to or deleted. This attribute can be changed by using function 43H.
The contents of the BX, CX, OX, SI, 01, BP, CS, OS, SS and ES
registers are not affected by this function.
Moves the file pointer of a previously opened file by using its handle. This allows
random access because the individual records don't have to be read in sequence. 1be
new file pointer position is given as an offset from the current position, either
from the beginning of the file or from the end of the file. The offset itself is
indicated as a 32-bit number.
Input: All = 42H
AL = Offset code
AL--o: Offset is relative to the beginning of the file
AL=1: Offset is relative to the current position of the file pointer
AL=2: Offset is relative to the end of the file
BX= Handle
CX = High word of the offset
810
AbacIloS' Appendix c: DOS [1IIerTllpts and FlUtClions
Rematks: IT offset codes 1 and 2 are accessed, negative offsets may be used to move
the ftle pointer backwards or to place the pointer at the beginning of the
ftle. It's possible to set the fIle pointer before the end of the ftle, which
causes an error during the next read or write access to the ftle.
The position of the ftle pointer passed after the function call is always
relative to the beginning of the fIle. The offset code used during the
function call is independent of this fIle pointer position.
Passing offset code 2 and offset 0 returns the size of the fIle. This action
moves the ftle pointer to the last byte of the ftle and the pointer's
position returns to the calling program after the function call.
The contents of the BX, CX, , SI, 01, BP, CS, OS, SS and ES registers
are not affected by this function.
811
Appendix C: DOS lrllerr"Pts and F/UlCtWru PC System Programming
omit the drive specifter or path, ooS accesses the current drive or current
direday.
An error occurs when any element of the path designation or the ftle does
not exist.
The contents of the BX, CX, , SI, 01, BP, CS, OS, SS and ES registers
are not affected by this function.
An error occurs when any element of the path designation or the ftle does
not exist.
The contents of the BX, CX, OX, SI, 01, BP, CS, OS, SS and ES
registers are not affected by this function.
812
Abacus Appendix c: DOS Interrupts and Functions
The contents of the BX, CX, OX, SI, 01, BP, CS, OS, SS and ES
registers are not affected by this function.
813
Appendix C: DOS Inlemlpls 0I'Id FlUlCtlons PC System Programming
Remarlcs: A handle is passed but it is not the name of the addressed character device.
which must be connected with this device. This can be one of the five
pre-assigned handles (0 to 4). A handle could have previously been
opened, with the Open function. fer a certain device and then passed to the
function. For example. since the standard input and output devices
(bandles 0 and 1) can be redirected, this method assures that the indicated
device is accessed.
To change various device attribute bits with this function, use sub
function 0 to read the device attributes first. Then this sub-function can
reset the device attribute bits in the device driver.
This function is especially useful for switching between cooked mode and
raw mode within a character driver (bit 5).
The contents of the BX, CX, OX, SI, OJ, BP, CS, OS, SS and ES
registers are not affected by this function.
Reads data from a character device. This function defmes the number of bytes of
data to read from the buffer, which contains the data taken from the character
device.
Input: AH = 44H
AL= 2
BX= Handle
814
Abac/U Appendix C: DOS Interrllpts and FlUlCtions
Remarks: A handle is passed, but it is not the name of the addressed character device
which must be connected with this device. This can be one of the five
pre-assigned handles (0 to 4). A handle could have previously been opened
with the Open function (function number 30H) for a certain device, then
passed to the function. For example, since the standard input and output
devices (handles 0 and 1) can be redirected, this method assures that the
indicated device is ~
An error always occurs if the handle passed is connected with a block
driver instead of a character driver.
The contents of the BX, CX, OX, SI, 01, BP, CS, OS, SS and ES
registers are not affected by this function.
Sends data from an application program directly to a character device. The calling
function defines the number of bytes to be transferred from a buffer to the device.
Input: AH= 44H
AL= 3
BX= Handle
CX = Number of bytes to be transmitted
DS = Buffer segment address
DX = Buffer offset address
Output: Carry flag=O: O.K.
AX = Number of bytes sent
Carry fla&=l: Error (AX = Enorcode)
AX=I: Unknown function code
AX=6: Handle not opened or does not exist
Remarks: A handle is Passed. but it is not the name of the addressed character device
which must be connected with this device. This can be one of the five
pre-assigned handles (0 to 4). A handle could have previously been opened
with the Open function (function number 61) for a certain device, then
passed to the function. For example, since the standard input and output
devices (handles 0 and 1) can be redirected, this method assures that the
indicated device is accessed.
815
Appendix C: DOS Interrupts and FlUlCtions PC System Programming
Reads data for an application directly from a block device. The calling function
defines the number of bytes to be copied by the device into a buffer.
Input: AH= 44H
AL= 4
BX = Device designation
Remarks: Instead of defining the device driver, the device designation parameter
defines the device from which data will be received. Code 0 represents
device A;, 1 represents device B:. etc.
The driver defines the data type and SlIUCtme.
The contents of the BX, CX, OX, SI, 01, BP. CS, OS, SS and ES
registers are not affected by this function.
Sends data from an application program directly to a character device. The calling
function defines the number ofbytes to be transferred from a buffer to the device.
Input: AH= 44H
AL= 5
BX = Device designation
816
AbacllS ApperuliJc C: DOS Il1IeTrllpts and Frurctions
Remarlcs: The handle passed can refer to either a character driver or a file.
The contents of the BX, CX, OX, SI, 01, BP, CS, OS, SS and ES
registers are not affected by this function.
Determines whether a device driver can receive data from an application program.
817
Appendix C: DOS Interrupts and FlUlCtions PC System Programming
Remarks: The handle passed can refer to either a charactec driver or a file.
IT the handle refers to a file, the block device driver signals its readiness to
receive data, even if the medium containing the flle is full and no
additional data can be appended to the end of the file.
The contents of the BX, CX, DX, SI, 01, BP, CS, DS, SS and ES
registecs are not affected by this function.
Determines whether the block device medium (e.g., disk, hard disk, etc.) can be
changed.
Remarks: The device designation parameter defines the device being addressed instead
of the device driver. Code 0 represents device A:, 1 represents device B:,
etc.
The contents of the BX, CX, DX, SI, 01, BP, CS, OS, SS and ES
registers are not affected by this function.
Determines whether a drive (block device) is local (part of the PC making the
inquiry) or remote (part of another PC in a networlc).
BL = Device designation
818
Abacus AppendbcC: OOS inlerrllpts and FlUlCtions
Remarks: You can access this sub-function only if networking software has
previously been installed.
The contents of the BX, CX, OX, SI, 01, BP, CS, OS, SS and ES
registers are not affected by this function.
Determines whether a fIle associated with this handle is local (part of the PC
making the inquiry) (X'remote (part of another PC in a network).
Output: =
OX IOCTI.. code
=
Bit 15 0: Local
=
Bit 15 1: Remote
=
Carry flag=: I: Error (AX Error code)
AX=I: Invalid function number
AX=6: Handle not opened or does not exist
Remarks: You can access this sub-function only if networking software has
previously been installed.
The contents of the BX. ex, OX, SI, 01, BP, CS, OS, SS and ES
registers are not affected by this function.
Sets the variables that specify the number of attempts at file access. One PC
within a network may try to access a file that is already being accessed by another
PC. The PC attempting access repeats the fIle access procedure the number of
times and the number of waiting periods dermed by these variables.
Remarks: You can only access this sub-function if networking software has
previously been installed.
819
Appendix C: DOS Int.errupts and FU1IClions PC System Programming
The contents of the BX, CX, OX, SI, 01, BP, CS, OS, SS and ES
registers are not affected by this function.
Creates a duplicate of the handle passed. This duplicate handle interfaces with the
same file or device as the [ust handle. If the [ust handle refers to a file, the value of
the [ust handlez's file pointer joins with the file pointer of the duplicate handle.
Input: AH= 45H
BX= Handle
Output: Carry flag=O: O.K. (AX = the new handle
Carry flag: 1: Error (AX = Error code)
AX=4: No additional handle available
AX=6: Handle not opened or does not exist
Remarlcs: Without having to close the file, this function updates a file directory
entry after its modification. A file can be closed using function 62 (3EH).
If the file pointer of one of the two handles changes position due to the
call of a read or write function, the other file pointer also changes
automatically.
The contents of the BX, CX, OX, SI, 01, BP, CS, OS, SS and ES
registers are not affected by this function.
Refers a second file handle to the save device or file as the first file handle. The
second handle's file pointer also contains the same value as the first handle's file
pointer.
Input: AH= 46H
BX = First handle
CX = Second handle
Output: Carry flag:::(): O.K.
Carry flag= 1: Error (AX =Error code)
AX=4: No additional handle available
AX=6: Handle not opened or does not exist
Remarlcs: If the function call connects the second handle to an open file, the file
closes before the foraxi duplication.
If the file pointer of one of the handles changes position due to the call of
a read or write function, the other file pointer also changes automatically.
820
Abacus Appendix c: DOS InleTTlipts and Functions
The contents of the BX, ex, ox, SI, 01, BP, es, os, SS and ES
registers are not affected by this function.
The path description in the buffer terminates with an end character (ASCII
code 0). This description has no drive specifier or \ character (root
directory specifier). If the root directory is the current directory, the end
character becomes the first character in the buffer.
The contents of the BX, ex, OX, SI, 01, BP, CS, OS, SS and ES
registers are not affected by this function.
821
Appendix C: DOS 1nlemlf,ts ond FlUlCtions PC System Programming
This function always fails when executed from within a COM program
because the PC assigns the total amount of free memory to a COM
program when it executes.
The contents of the ex, OX, SI, DI, BP, CS, OS, SS and ES registers
are not affected by this function.
Changes the size of a memory area previously reserved using function 72 (3FH
see above).
Input: AH= 4AH
BX = New memory area size in paragraphs
ES = Memory area segment address
Output: Carry flag=(): O.K.
Carry flag= 1: Error (AX = Error code)
AX=7: Memory control block destroyed
AX=8: Insufficient memory
BX = Number of paragraphs available
811
Abac/lS AppendiJC C: DOS InleTrllpts and FlIIICtions
The contents of the CX, OX, SI, 01, BP, CS, OS, SS and ES registers
are not affected by this function.
Executes another program from within a program and continues execution of the
original program after the called program finishes its run. The function requires the
name of the program to be executed and the address of a parameter block, which
contains information that is important to the function.
Input: AH= 4BH
AL= 0
ES = Parameter block segment address
BX = Parameter block offset address
OS = Program name segment address
OX = Program name offset address
Output: Carry flag=O: O.K.
Carry flag= 1: Error (AX = Error code)
AX=I: Invalid function number
AX=2: Path or program not found
AX=5: Access denied
AX=8: Insufficient memory
AX=10: Wrong environment block
AX=11: Incorrect format
823
Appendix. C: DOS Interrllpts and FlUtCtiorts PC System ProgrQ11J11ljrag
After the call of this function, all registers are destroyed except the CS
and IP registers. For later recall, save their contents before the function
call.
The program called should have all the handles available to the calling
program.
824
Abacus AppendiJe C: DOS Inlerrllpts and Frmctions
Terminates a program and passes an end code for which function 77 (4DH-see
below) searches. This function releases the memory previously occupied by the
terminated progmm.
Input: AH= 4CH
AL = Return code
Output: No output
Rematks: This function may be used for program termination instead of the other
functions listed earlier.
This function call restores the contents of the three interrupt vectors that
were stored in the PSP when the program started execution.
Before passing control to the calling program. all handles opened by this
program close, along with the corresponding meso This is not applicable
to files accessed using FCBs.
A batch file can test for the return code using the ERRORLEVEL and IF
batch commands.
825
Appendix C: DOS Interrupts and Functiolls PC System Programming
Checks a program, called from another program by the EXEC function, for the
return code passed by the called program when it terminates.
The search defaults to nonnal files (attribute 0). Any set attribute bits
extends the search to normal fIles and any other file types.
If a matching file occurs, the first 43 bytes of the DTA contain the
following information about this file:
Bytes 0-20: Reserved
Byte 21: File attribute
Bytes 22-23: Time of last modification to fIle
826
AbacllS Appendix C: DOS Inlerrupts tIIId FlU/Ctions
This function may only be called to search for the first occurrence of a
file. If you want to search for a group of files using wildcards, function
4FH (see below) must be called.
The contents of the BX, CX, DX, SI, DI, BP, CS, DS, SS and ES
registers are not affected by this function.
Searches for subsequent occurrences of the filename listed after function 78 (above)
executed successfully.
Input: AH= 4FH
Remarks: If a matching file occurs, the first 43 bytes of the DTA contain the
following information about this file:
Bytes 0-20: Reserved
Byte 21: File attribute
Bytes 22-23: Time of last modification to file
Bytes 24-25: Date of last modiftcation to file
Bytes 26-27: Low word of file size
Bytes 28-29: High word of file size
Bytes 30-42: ASCII filename and extension tenninated
by an end character (ASCII code 0)
This function can only be called if function 4EH has been called once and
if the DTA remains unchanged.
The contents of the BX, CX, DX, SI, DI, BP, CS, DS, SS and ES
registers are not affected by this function.
827
Appendix C: DOS Inlerrllpts and FlIIICtWns PC System Programming
Remarlcs: Function 2EH (see above) controls the status of the verify flag.
The contents of the AH, BX, CX, OX, SI, 01, BP, CS, OS, SS, ES and
flag registers are not affected by this function.
Renames a fIle or moves the fIle to another directory of a block device. Moving is
possible only within the different directories of one particular device (i.e., you can't
move a fIle from a hard disk directory to a floppy disk directory).
Input: AH= 56H
OS = Old fIlename segment address
OX = Old ftlename offset address
ES = New fIlename segment address
01 = New ftlename offset address
Output: Carry flag=O: O.K.
Carry f1ag=I: Error (AX = Error code)
An error occurs if you attempt to move the file to a filled root directory.
The contents of the BX, CX, OX, SI, 01, BP, CS, OS, SS and ES
registers are not affected by this function.
828
Appendix C: DOS ]ntt!l7'lIpts and FlUlCtions
Gets the date and time of the creation or last modificadon of a file.
Input: AH= 57H
AL= 0
BX= Handle
Output: Carry flag=O: O.K.
CX=Tune
OX=DaIe
Carry flag=1: Error (AX=Error code)
Remarks: In order for it to be accessed with a handle, the file must have been
previously opened or created using one of the handle functions.
The time appears in the ex register in the following format
Stores the date and time of the creation or last modification of a file in the
corresponding file and device.
829
Appendix C: DOS Inlerrllpts and FIl1ICIifms PC System Programming
Rematks: In order to be accessed with a handle, the file must have been previously
opened or created using one of the handle functions.
First fit: DOS starts searching at the start of memory and allocates the
first memory block it fmds of the requested size;
Best fit: DOS searches all available memory blocks and allocates the
smallest suitable memory block it finds (the most efficient method);
Last fie DOS starts searching al the end of memory and allocates the first
memory block it finds of the requested size.
The contents of the BX, ex, ox, SI, DI, BP, es, OS, SS and ES
registers are not affected by this function.
830
Abacus Appendix C: DOS lntt!ITllpts and FlUlCtions
Defmes the method currently in use by MS-DOS for allocating blocks of memory.
If a program allocates memory using function 48H, different programs in memory
may already have memory blocks assigned to them. Since these requested memory
blocks vary in size, DOS has three methods of allocating memory to a program:
First fit DOS starts searching at the start of memory and allocates the
flfSt memory block it fmds of the requested size;
Best fit DOS searches all available memory blocks and allocates the
smallest suitable memory block it fmds (the most efficient method);
Last fit: DOS starts searching at the end of memory and allocates the first
memory block it finds of the requested size.
Input: AH= 58H
AL= 1
BX = Allocation strategy
BX=O: First fit (start from beginning of memory)
BX=l: Best fit (search for best-fitting memory block)
BX=2: Last fit (start from end of memory)
Output: Carry flag=O: O.K.
Carry flag=l: Error (AX =Enor code)
AX=l: Invalid function number
Remarks: The allocation strategy applies to all programs.
The contents of the BX, CX, DX, SI, 01, BP, CS, DS, SS and ES
registers are not affected by this function.
831
Appendix C: DOS /nleTl'IIpts and FIUICtiorts PC System ProgrQlfl/flbsg
832
Abacus Appendix C: DOS Interrupts and Functions
Code Error
26: Unknown medium type
27: Sector not found
28: Printer out of paper
29: Write error
30: Read error
31: General failure
32: Sharing violation
33: Lock violation
34: Unauthorized disk change
35: FCB not available
80: File already exists
81: Reserved
82: Directory cannot be created
83: Terminate after call of interrupt 24H
Code Error
1: No memory available on the medium
2: Temporary access problem-may end soon
3: Access unauthorized
4: Internal error in system software
5: Hardwareerror
6: Software failure not caused by running application program
7: Application program error
8: File not found
9: Invalid file format/type
10: File locked
11: Wrong medium in drive, bad disk or medium problem
12: Other error
The following codes describe the action needed to fix the error:
Code Error
1: Repeat process several times, then ask user to abort/ignore
2: Repeat process several times pausing each time, then ask
user to abort/ignore
3: Ask user for correct information (e.g., filename)
4: Terminate program as completely as possible
5: Terminate program NOW (no file closing, etc.)
6: Ignore error
7: Ask user to remove error source and repeat process
833
Appendix C: DOS Inlerr"pts and FlUlCtWns PC System Programming
Code Error
1: Unknown
2: Block device (disk drive, hard disk, etc.)
3: Network
4: Serial device
S: RAM
The contents of the CS, OS, SS and ES registers are not affected by this
function. All other register contents are destroyed.
Creates a temporary file in memory for storage during program execution. The
filename doesn't matter because the access occurs through the assigned handle.
Since this function allows several files open at the same time, DOS creates
filenames from the current date and time. Every temporary file is ensured its own
particular name because the function cannot be called more than once at a time.
Input: AH= SAH
CX = File attribute
OS = Directory segment address
OX = Directory offset address
Output: Carry fIag=O: O.K.
AX=Handle
OS=Complete filename segment address
OX=Complete filename offset address
Carry flag=1: Error (AX =Error code)
AX=3: Path not found
AX=S: Access denied
RemaIks: The directory name passed is an AScn string which is terminated by an
end character (ASCn code 0). It can contain a path designation and drive
specifier. No wildcards are allowed. If no drive specifier or path
designation exists, the function accesses the cmrent drive or directory.
834
AbacllS Appendix C: DOS InleTTllpts awl FlUlClions
The contents of the BX, CX, OX, SI, 01, BP, CS, OS, SS and ES
registers are not affected by this function.
Creates a file in the specified directory based upon an ASCII file famal If no drive
specifier or path is provided, the file opens in the default (current) directory.
Input: AH= 5BH
CX = File attributes:
Remarlcs: An error occurs when any element of the path designation doesn't exist,
when the filename already exists in the specified directory, or when an
attempt is made to create the file in an already full root directory.
The file defaults to the normal read/write attribute, which allows both read
and write operations. This attribute can be changed by using function
43H.
Input: AH = 5CH
AL = Function code
BX = File handle
835
Appendix C: DOS Interrupts and F/UlCtions PC System Programming
Returns the address of an ASCII string which defmes the local computer type
within a network.
Input: AH= 5EH
AL=OO
OS = User buffer segment address
OX = User buffer offset address
Output: Carry flag=O: Successful execution
CH = 00: Name undefined
CH > 00: Name defined
CL = NETBIOS name number (when CHoOO)
OS = Identifier segment address (when CHoOO)
OX = Identifier offset address (when CHoOO)
Carry flag= 1: Error (AX = Error code)
AX=1: Invalid function code
Remarks: The computer type is a 15-byte-Iong string terminated by an end character
(ASClI code 0).
836
AbacllS Appendix C: OOS Inlerr"Pts and Frmctions
Gets the printer setup string assigned to a particular network printer by using
function SEH, sub-function 2 (see above).
Input: AH = 5EH
AL= 03 I
Gets the system redirection list This list assigns local names to network printers,
fJles or directories.
Input: AH = 5FH
AL=02
BX = Redirection list index (see Remarks below)
837
AppendiJc C: DOS Interrupts and FtmCtions PC S,stem Programming
BL = Device type
3: Printer
4: Drive
BP = Destroyed
CX = Parameter value in memory
OX= ~yed
OS = ASCn format local device name segment address
SI = ASCII format local device name offset address
ES = ASCn format networt: name segment address
DI = ASCn funnat networt: name offset address
Carry flag=1: Error (AX =Enor code)
AX=l: Invalid function code
AX=18: No more fdes available
Remarks: The contents of register CX come from function SFH, sub-function 3 (see
below).
BL=3:Printer
BL=4: Drive
838
Abac/lS AppenIJa C: DOS Il11errllplS and FlUlCtions
word as the device name, OOS tries to open access to the network using
the password.
Gets the segment address of the PSP from the currently executing program.
Input: AH= 62H
839
Appendix C: DOS Interrupts and Functions PC System Programming
Output: No output
840
Abacus Appendix C: DOS InJerrwpts and Functions
BX = Code page:
BX = -1: active CON device
CX = Length of buffer allocated to receive information
DX = Country ID number
DX = -1: Default
ES:DI = Address of buffer allocated to receive information
841
Appendix C: DOS Interrupts and Functions PC System Programming
Remarks: The PSP's default table reserved for the process can control 20 handles.
An error occurs if the content of the BX register is greater than 20, or if
insufficient memory exists to allocate a block for the extended table.
If the number in the BX register is greater than the number of entries
assigned by the FILES entry in the CONFIG.SYS file, no error occurs.
However, attempts at opening a file or device fail if all file entries are in
use, even if file handles are still available.
Writes all DOS buffers associated to a specific handle to the specified device. If the
handle points to a file, the file's contents, date and size are updated.
842
Abacus Appendix C: DOS Interrupts and Functions
DOS stores the contents of this interrupt vector in the PSP of the program to be
executed before passing control to the program. This prevents program changes to
the vector, which could prevent DOS from calling the tennination routine.
Contains the address of a routine which executes when the user presses <Ctrl><C>
or <Ctrl><Break>. You should never directly call this routine.
DOS stores the contents of this interrupt vector in the PSP of the program to be
executed before passing control to the program. This prevents program changes to
the vector, which could prevent DOS from calling the tennination routine.
Represents a routine called during hardware access (e.g., disk drive) when a critical
error occurs. You should never directly call this routine.
843
Appendix C; DOS Interrupts and Functions PC System Programming
The error routine restores the SS, SP, DS, ES, BX, CX and DX registers to the
same values that they contained during the call. During execution it can only
access functions 1 to OCH of interrupt 2lH. It should be tenninated by an IRET
instruction and pass one of the following codes to the AL register:
0: Ignoreerror
1: Repeat the operation
2: Tenninate program using interrupt 23H
3: Fail system call (Version 3 and up only)
If a program changes the content of this interrupt vector, the program can
tenninate without restoring the memory contents. Since RAM can be released and
used by other programs, the critical error routine can be overwritten by another
program in memory. When this occurs, a critical error could cause a system crash
because a completely different code now exists at the location of the old error
handler routine.
Before passing control to the program, DOS stores the contents of this interrupt
vector in the PSP of the program to be executed. This prevents program changes
to the vector, which could prevent DOS from calling the tennination routine.
During program termination, the contents of the interrupt vector pass from the
PSP to the vector; then the system calls the routine.
844
Abacus Appendix C: DOS Interrupts and Functions
Remarlcs: In the AL register 0 represents drive A:, 1 represents drive B:, etc.
All the sectors of the medium can be accessed. OOS itself uses this
interrupt to read the root directory and the FAT of a medium. The data are
read from the medium into the buffer of the calling program. After the
function call, the contents of all registers, except the segment register,
may change.
After the interrupt call, the stack pointer changes position because two
bytes stored on the stack during the call are removed and not returned.
These bytes represent the flag register, which can be read from the stack
using the POPF instruction. The old value of the stack pointer can be set
by adding- 2 to its contents. If you omit the stack pointer correction, the
stack could overflow. Because of this, you cannot call this interrupt from
higher level languages. You must call it from assembly language.
The contents of the BX, CX, DX, SI, DI, BP, CS, DS, SS and ES
registers are not affected by this function. The contents of all other
registers may change.
Remarks: In the drive specifier 0 represents drive A:, 1 represents drive B:, etc.
All the sectors of the medium can be accessed. OOS itself uses this
interrupt to write the root directory and the FAT to a medium. The data
are written from the buffer of the calling program to the medium. After
the function call, the contents of all registers, except the segment register,
may change.
845
Appendix C: DOS Interrupts and Functions PC System Programming
After the interrupt call, the stack pointer changes position because two
bytes stored on the stack during the call are removed and not returned.
These bytes represent the flag register, which can be read from the stack
using the POPF instruction. The old value of the stack pointer can be set
by adding 2 to its contents. If you omit the stack pointer correction, the
stack could overflow. Because of this, you cannot call this interrupt from
higher level languages. You must call it from assembly language.
The contents of the BX, CX, DX, SI, DI, BP, CS, DS, SS and ES
registers are not affected by this function. The contents of all other
registers may change.
Terminates the currently executing program and returns control to the program that
called the current program. Unlike other functions used for program termination,
the memory used by the current program keeps the program code for later recall.
Input: CS = PSP segment address
DX = Number of bytes + 1 to be reserved
Output: No output
An error occurs during the call of this interrupt if the value in the DX
register ranges from FFFIH to FFFFH.
846
Abacus Appendix C: DOS Interrupts and Functions
Remarks: The five-byte print packet contains print spooler information. The first
byte indicates the DOS version (O=Versions 3.1 to 3.3); the remaining
bytes indicate the segment and offset addresses of the file specification.
847
Appendix C: DOS Interrupts and Functions PC System Programming
Cancels all files waiting in the print spooler queue for printing.
Remarks: The print queue segment and offset addresses point to a set of 64-byte
filenames in the queue. Each entry contains an ASCII file specification.
The first filename in the queue is the file currently printing in the print
spooler. The last filename in the queue has a zero in the first byte of the
specification. j
848
Appendix 0
EMM Functions
Returns the error status of the EMM after calling any EMS functions.
Input: AH= 40H
Output: AH = EMM status
AH=OOH: O.K.
AH=80H: Internal error, EMM possibly destroyed
AH=81H: EMS hardware error
Remarks: Do not call this function unless you know that EMS memory and a
corresponding EMM are installed (see Chapter 13 for more infonnation).
This function should be the flfSt EMM call a program makes, to ensure
that the hardware and software are functioning properly.
849
Appendix D: EMM FflllCliotv PC System ProgrtJ1ll11ling
8S0
Appendix D: EMM FlIIICtions
The handle used when calling this function must have been returned by a
previous call to EMM function 4H.
The logical pages are numbered from 0 on. so that the value 0 must be
passed to access the first logical page. The largest value allowed is the
number of allocated pages minus one.
Before accessing the physical page, the segment address of the page frame
must be determined with function 2H.
851
Appendix D: EMM FlllfCtions PC Sy8lem ProgrfJlfUlling
Remmks: Do not call this function unless you know that EMS memory and a
corresponding EMM are installed (see CIJapa 13 fm mme infonnation).
The handle used when calling this functicn must have been returned by a
previous call to EMM function 4H.
All of the pages allocated to this handle are released by this function. It is
impossible to release individual pages.
Mter a successful call to this function the handle is no longer valid and
cannot be used for accessing EMS memory.
If the function returns an error, you should repeat the call at least three
times or the pages will remain allocated and will not be available for
other programs.
Saves current mapping between the four physical pages in the page frame and the
associated logical pages.
Input: AH = 47H
DX= Handle
852
Abacus AppettdiJe D: EMM F/lllCtions
853
Appendix D: EMM FlUlCtiotu PC System Programming
854
Abacus Ap~Nlix D: EMM FlUfCtioru
855
Appendix E
Output: No output
Remarlcs: Modes 0 and I, 2 and 3, 4 and 5 differ in the output of the color signal
that is suppressed in the fIrst mode. This isn't possible on an EGA/VGA
card so the modes are identical. If bit 7 of the AL register is set when this
function is called, the contents of the video RAM will not be erased when
the new mode is enabled. The task is to program the video controller and
defIne a color palette. The contents of registers BX, ex, ox, SI, DI, BP
and the segment registers are not affected by this functi6n.
856
AbacllS Appendix E: EGAlVGA BIOS FlUlCtions
Defmes the starting and ending lines of the screen cursor. This function is
independent of the display page being displayed.
Output: No output
Remarks: Since the possible values depend on the size of the current video mode's
character matrix, the values in the CH and CL registers always refer to an
eight-line character matrix. The values should thus be between zero and
seven. The EGA/VGA BIOS adapts these values to the current size of its
own character matrix.
The contents of registers BX, CX, DX, SI, 01, BP and the segment
registers are not affected by this function.
Output: No output
Remarlcs: The cursor moves only if the specified display page is the current page.
The values for the screen line and column are based on the resolution of
the current display mode.
The number of the display page is based on how many display pages the
card has available.
The contents of registers BX, CX, DX, SI, 01, BP and the segment
registers are not affected by this function.
857
AppendU: E: EGAlVGA BIOS FlUlCtions PC System ProgrtJlllllli.ng
Remadcs: The screen line and screen colwnn parameters refer to the text coordinate
system, even if a graphic mode is active.
The starting and ending lines of the cursor are returned correctly only in
the text modes. They have no meanings in graphic modes.
The contents of registers BX, SI, 01, BP and the segment registers are not
affected by this function.
Selects the current display page, and thereby the page which appears on the screen
(text mode only).
Input: AH= OSH
AL = Display page nwnber
Output: No output
Remarks: The number of available display pages depends on the amount of video
RAM installed on the EGANGA card.
When a new page is selected the screen cursor will be moved to the
position of the text cursor on this page.
Switching between different pages does not change the contents of these
pages.
The contents of registers BX, CX, DX, SI, 01, BP and the segment
registers are not affected by this function.
858
Appt!1lda E: EGAlVGA BIOS FlIIICtions
859
Appendix E: EGAlVGA BIOS F/UfCtions PC System Programming
Output: No output
Remarlcs: Normally the contents of the current display page are scrolled. but in
320x200 four-color graphic mode this function only affects display page
O.
Clearing the screen window (nwnber of lines = 0) is the same as filling it
with spaces (ASCII code 32).
The contents of the lines scrolled out of the window are lost and cannot
be recovered.
Reads and returns the ASCII code and color (attribute) of the character at the current
cursor position.
Remarks: This function can also be called in the graphic mode, whereby the bit
pattern of the character on the screen will be compared with the bit
patterns of the characters. If the character cannot be identified, the AL
register will contain the value zero after the call.
In the 320x200 four-color graphic mode this function only affects display
pageO.
The contents of registers BX, CX, OX, SI, 01, BP and the segment
registers are not affected by this function.
860
AbacllS
This function does not move the cursor to the next screen position.
The contents of registers BX, ex, ox, SI, DI, BP and the segment
registers are not affected by this function.
Output: No output
Appendix E: EGAlVGA BIOS FlUlCtioras PC System ProgrfllNllillg
Remarks: If the graphic mode is active and the specified character is to be printed
more than once (the value of the ex register is greatez than I), all of the
characters must fit on the current screen line.
The conb'Ols codes for bell, carriage return, etc. are not recognized as such
and are dispJayed as nonnal ASCII characters.
This function can also be used to output characters in the graphic mode,
in which case the character patterns are taken from one of the EGA
character tables.
This function does not move the cursor to the next screen position.
The contents of registers BX, ex, DX, SI, 01, BP and the segment
registers are not affected by this function.
Selects the border and background color for the graphic or text mode.
Output: No output
Remarks: This function should be called only when the EGANGA card is in the
320x200 or 640x200 graphic mode. Use function 10H for all other
modes.
Bits zero to three of the BL register set the background and border color.
Setting bit four will enable high-intensity colors.
The contents of registers BX, ex, DX, SI, 01, BP and the segment
registers are not affected by this function.
Selects one of the two color palettes for the 320x200 graphic mode.
Input: AU = OBH
BH= 1
BL = Color palette number
862
Abacus Appendix E: EGAlVGA BIOS FlUlCtions
Output: No output
Renuub: This function should be called only when the EGA/VGA card is in the
320x200 or 640x200 graphic mode. Use function 10H for all other
modes.
The EGA/VGA BIOS emulates the two CGA color palettes with the
numbers 0 and 1. They contain the following colors:
Palette 0: green, red, yellow
Palette 1: cyan, magenta, white
The contents of registers BX, CX, DX, SI, 01, BP and the segment
registezs are not affected by this function.
Output: No output
Remarks: The color value depends on the colors available in the current display
mode.
If bit seven of the AL register is set, the color value will be XORed with
the previous color value of the pixel.
The display page is ignored in the 320x200 four-color graphic mode.
The contents of registers BX, CX, OX, SI, 01, BP and the segment
registers are not affected by this function.
863
ApperuliJc E: EGAlVGA BIOS FllltCtWns PC System Programming
Rematks: The color value depends on the colors available in the current display
mode.
The display page is ignored in the 320x200 four-color graphic mode.
The contents of registers BX, CX. DX. SI, DI. BP and the segment
registers are not affected by this function.
Reads the number of the current display mode. the number of characters per line,
and the number of the current display page.
Input: AH= OFH
Output: AI.. = Video mode:
0: 4Ox2S-character text, 16 colors (EGA/VGA - color monitor)
1: 4Ox2S-character text, 16 colors (EGA/VGA - color monitor)
864
Abacus Appl!lfdix E: EGAlVGA BIOS FlDfCtions
Remark: The contents of registers BX, CX, DX, SI, 01, BP and the segment
registers are not affected by this function.
Output: No output
Remarlcs: Since the register number is not checked by the BIOS, you can also
program the other registers in the attribute controller. These include the
mode control register, overscan register and others.
The contents of registers BX, CX, DX, SI, 01, BP, and the segment
registers are not affected by this function.
Input: AH = 10H
AL= 01H
BH = Bordercolor
865
AppendiJe E: EGAIVGA BIOS FlUlCtiom PC System Programming
Output: No OUlpUt
Remark: The contents of registers BX, ex, DX, SI, 01, BP and the segment
registers are not affected by this function.
Determines whether bit 7 in the attribute byte of a character in the text mode will
enable character blinking, or display characters on a high-intensity background.
Input: AH= 10H
AL= OOH
BL = Blinking attribute
BL=O: high-intensity background
BL=I: blinking
Output: No output
Remark: The contents of registers BX, ex, DX, SI, 01. BP and the segment
registers are not affected by this function.
866
AbaclLf Appendix E: EGAlVGA BIOS FlIIICtions
Remarks: Since the BIOS doesn't verify the nwnber of the palette register read, this
fwlciion can read all the registers of the attribute controller.
The contents of registers BL, CX, OX, SI, 01, BP and all segment
registers are not affected by this function.
Remarlcs: The contents of registers BL, ex, OX, SI, 01, BP and all segment
registers are not affected by this function.
Output: No output
Remarlcs: The buffer must be a minimwn of 17 bytes long to allow room for all
the palette registers (bytes 0-15) plus the overscan register (byte 16).
The contents of registers BL, CX, OX, SI, 01, BP and all segment
registers are not affected by this function.
Input: AH = lOH
BX = Nwnber of the OAC color register (0-255)
CH = Green value
CL = Blue value
OH = Red value
867
Appendix E: EGAlVGA BIOS Functions PC System PTOgrtJl7Utfing
Output: No output
If the sum of BX and ex is greater than 255, the first DAC color register
is reloaded after the last register is loaded.
The contents of registers BL, CX, DX, SI, DI, BP and all segment
registers are unchanged by this function.
868
AppendiJC E: EGAlVGA BIOS FlUlCtions
869
Appendix E: EGAlVGA BIOS FlUlCtiorv PC System Progrommirag
870
Abacus Appendix E: EGAIVGA BIOS FlUlCtions
Converts a specified range within a OAC color table into gray scales.
Input: AH = 10H
AL= IBH
BX = Number of fIrst DAC color register to be converted
CX = Total number of OAC color registers to be converted
Output: No output
Remarlcs: Conversion into grays results from changes to the red, green and blue
values, as well as the intensity of these values. The default factor for red
is 0.3, the default factor for green is 0.59, and the default for blue 0.11.
871
Appendix E: EGAlVGA BIOS FlI1ICtioru PC System Progrtlll'lming
The contents of registers BX. ex. ox. SI, DI, BP and all segment
registers are not affected by this function.
Loads a user-defmed character set from RAM into one of the two EGA character
tables.
Input: AH= llH
AL= OOH
BH = Lines per character (also bytes per character)
BL = Character table (0 or 1)
ex = Number of characters in table
ox = ASCII code of first character in table
ES = Segment address of character table in RAM
BP = Offset address of character table in RAM
Output: No output
Remarks: A maximum of 512 characters can be loaded per c~ter table.
The loaded character set is not activated, nor are the CRTe registers
programmed to the size of the characters. The changes will not be visible
on the screen unless the character definitions are loaded into the active
character table.
The contents of registers BX. ex. ox, SI, DI, BP and the segment
registers are not affected by this function.
Loads the entire 8x14-pixel character set from EGA/VGA ROM-BIOS into one of
the two character set tables.
872
Abacus AppmdiJc E: EGAlVGA BIOS FlUlCtions
Remarks: The loaded character set is not activated, nor are the CRTC registers
programmed to the size of the characters. The changes will not be visible
on the screen unless the character definitions are loaded into the active
character table. The EGA card displays 43 lines on the screen, while the
VGA card displays SO lines.
The contents of registers BX, ex, DX, SI, 01, BP and the segment
registers are not affected by this function.
Remarks: Bits zero and one of the BL register specify the number of the character
set to be accessed when bit three of the attribute byte of the character is
zero.
Bits two and three of the BL register specify the number of the character
set to be accessed when bit three of the attribute byte of the character is
one.
If the contents of bits zero and one are identical to the contents of bits
two and three of the BL register, then bit three of the character attribute
byte has no effect on the character displayed. Only 256 different characters
can then be displayed on the screen.
The contents of registers BX, ex, DX, SI, 01, BP and the segment
registers are not affected by this function.
873
Appendix E: EGAlVGA BIOS FlUlCtions PC System Programming
Remm: The loaded character set is not activated, nor are the CRTC registers
programmed to the size of the characters. The changes will not be visible
OIl the screen unless the character definitions are loaded into the active
character table. The VGA card displays 25 text lines on the screen.
The contents of registers BX, ex, ox, SI, 01, BP and the segment
registers are not affected by this function.
874
Abac"", Apptmtl.ix E: EGAlVGA BIOS FlUlClions
Output: No output
Remarks: The function sets the EGA screen to display 25 lines of text, or sets the
VGA screen to display 28 lines of text.
The starting and ending lines of the screen cursor are automatically
adapted to the height of the new charactez matrix.
The contents of registers BX, CX, DX, SI, DI, BP and the segment
registers are not affected by this function.
Loads the entire 8x8-pixel character set from the ROM-BIOS of the EGNVGA
card into one of the two character set tables, and activates it by programming the
CRTC registers.
Output: No output
Remarks: The function sets the screen to display 43 lines of text (EGA) or 50 lines
of text (VGA).
The starting and ending lines of the screen cursor are automatically
adapted to the height of the new character matrix.
The contents of registers BX, CX, DX, SI, DI, BP and the segment
registers are not affected by this function.
875
Appendix E: EGAlVGA BIOS FlIIICtions PC System Programming
Loads a complete 8x16 character set from the VGA card BIOS into one of the two
character set tables, and activates it through CRTe register programming.
Input: AH= lOH
AL= 14H
BL = Character table (0 or 1)
Output: No output
Remarks: When this function is called, the VGA card displays 25 lines of text on
the screen.
The starting and ending lines of the screen cursor automatically change to
match the height of the new character matrix.
The contents of registers BX, ex, DX, SI, DI, BP and all segment
registers are not affected by this function.
Returns various information about the current status of the character generator.
Input: AH= llH
AL= 03H
BH = Type of information desired
BH=O: contents of interrupt vector IFH
BH=1: contents of interrupt vector 43H
BH=2: address of the ROM 8x14 character table
BH=3: address of the ROM 8x8 character table
BH=4: address of the second half of the 8x8 character table
BH=5: address of the alternative ROM 9x14 character table
BH=6: Address of the alternative ROM 8x16 character table
BH=7: Address of the alternative ROM 9x16 character table
Output: ex = Height of current character matrix
DL = Number of columns per line - 1
ES = Segment address of the pointer
BP = Offset address of the pointer
Remarks: The contents of registers BX, ex, DX, SI, DI, BP and the segment
registers es, DS and SS are not affected by this function.
876
AbacllS Appendix E: EGAlVGA BIOS FwtCtions
BL=O:64K
BL=l: 128K
BL=2: 192K
BL=3:256K.
Remarks: The contents of registers OX, SI, 01, BP and the segment registers are
not affected by this function.
Installs an alternative hardcopy routine which prints as many lines as are displayed
on the screen. The hardcopy routine of the nonnal ROM-BIOS always prints 25
lines and is not suited for creating a hardcopy of the EGNVGA modes, which
display more than 25 lines on the screen.
Input: AlI= 12H
BL= 20H
Output: No oulput
Remark: The contents of registers BX, ex, ox, SI, 01, BP and the segment
registers are not affected by this function.
877
Appendix E: EGAlVGA BIOS FlIIICtions PC System Programming
Remarks: The selected number of scan lines can only be displayed when the
appropriate video card and monitor are in use. For example, a CGA
monitor can only display 200 scan lines, even if the video card can
operate in a higher resolution.
The contents of registers BX, CX, DX, SI, DI and BP and all segment
registers are not affected by this function.
Toggles the automatic loading of palette registers in VGA BIOS. The system
either loads alternate display modes when function OOH is invoked, or loads default
values.
AL=l:No
Output: No output
Remarks: The contents of registers BX, CX, OX, SI, 01, BP and all segment
registers are not affected by this function.
Enables or disables direct CPU access to video RAM and its different I/O ports.
Input: AH = 12H
BL= 32H
=
AL Access status
AL=O: Access enabled
Output: No output
Remarks: The EGA BIOS doesn't recognize this function, but you can still suppress
video card access directly using bit 1 of the output register (port address
3C2H).
The contents of registers BX, CX, DX, SI, 01, BP and all segment
registers are not affected by this function.
878
Abacus Appendix E: EGAJVGA BIOS FJUlCtions
Toggles automatic gray scaling in VGA BIOS. This is different from function
10H, sub-function IBH, which enables selective gray scaling in OAC color
registers.
Al...=1: Off
Output: No output
The contents of registers BX, CX, OX, SI, 01, BP and all segment
registers are not affected by this function.
Toggles text cursor emulation mode. Calling function 01H (for defining the
starting and ending lines of the cursor) doesn't compensate for character matrices in
different resolutions. This function controls that change when in VGA mode.
Input: AH = 12H
BL= 34H
AL = Cursor emulation mode
Al...=0: On
Al...=1: Off
Output: No output
Remarks: The contents of registers BX, CX, OX, SI, 01, BP and all segment
registers are not affected by this function.
Al...=1: Off
Output: No output
879
Appendix E: EGAlVGA BIOS Functions PC System Programllling
Remarks: The contents of registers BX. ex. ox. SI. DI. BP and all segment
registers are not affected by this function.
Control codes such as bell and carriage return are interpreted as control
codes and not as normal ASCII codes. An error occurs when carriage
return and linefeed are printed on a display page other than zero. however.
These characters may be printed on display page O. regardless of the
display page specified in BH.
When the last screen position is reached the screen will move up one line
and the output will continue with the first column of the last screen line.
880
Abac"" AppendiJc E: EGAlVGA BIOS FlUfClions
bit seven of the BL register is set, the color value will be XORed with
the old col<r value.
This function can also be used to print characters in the graphic mode, in
which case the.character patterns will be taken from one of the EGNVGA
chamcter tables.
The contents of registers BX, ex, ox, SI, 01, BP and the segment
registers are not affected by this function.
881
Appendix F
Moves the mouse pointer to the center of the screen and clears the pointer
from the screen. When enabled, the default pointer appears as an inverse
video square. The representation is always in display page 0, independent
of the current display mode. The entire screen area becomes the total IaDge
of mouse movement.
882
Abacus Appendix F: MOIIM DriW!1' Interrupts
The mouse driver follows the mouse movement even when the mouse
pointer is not displayed on the screen.
After calling this function, the mouse pointer may not appear at the same
location as it was when the pointer was previously removed by calling
function OOH or function 02H.
883
Appendix F: Mouse Driver Interrupts PC System Programming
The mouse pointer moves to the new position, even if the mouse is not
currently visible. Once re-enabled, the mouse pointer appears at this new
position.
884
Abacus Appendi:Jc F: Mouse L?river Intemlpts
885
Appendix F: Mouse Driver Interrupts PC System Progrtunllling
Rernarlcs: The coordinates returned in the ex and DX registers refer to the pixel
positions in the virtual mouse display screen rather than physical
positions on the actual display screen.
The activation counter for the mouse button addressed is reset to 0 when
this function is called.
Defines the horizontal range of movement for the mouse pointer. Once set. the
user cannot move the mouse pointer out of this range.
Input AX= 0007H
ex = Minimal horizontal pointer position
DX = Maximum horizontal pointer position
Output: No output
Remarks: The coordinates passed in the ex and DX registers refer to the pixel
positions in the virtual mouse display screen rather than physical
positions on the actual display screen.
If the mouse pointer is outside of this range when function 07H is called.
the mouse driver automatically moves the mouse pointer within the
limits of the range of movement. If the value in the DX register is less
than the value in the ex registers. the two parameters are exchanged.
Defines the vertical range of movement for the mouse pointer. Once set. the user
cannot move the mouse pointer out of this range.
Output: No output
Remarks: The coordinates passed in the ex and DX registers refer to the pixel
positions in the virtual mouse display screen rather than physical
positions on the actual display screen.
If the mouse pointer is outside of this range when function 07H is called.
the mouse driver automatically moves the mouse pointer within the
limits of the range of movement
886
Abacus Appendix F: Mouse Driver Inlerrllpts
If the value in the DX register is less than the value in the ex registers,
the two parameters are exchanged.
Defines the appearance of the mouse pointer in graphic mode, as well as the
bitfield which compensates for the pixels around the mouse pointer.
Output: No output
Remarks: The bitfield consists of 64 bytes, of which the first 32 are an AND
comparison, and the remaining 32 are an OR combination. Both sets of
bytes are based upon the current pixel pattern.
Defines the bitmask which specifies the appearance of the mouse pointer in text
mode.
Output: No output
Remarks: If the software pointer is selected, the code of the character beneath the
mouse pointer and its attribute byte are combined logically with the mask
in the CX register through a binary AND, and then with the value in the
DX register through an exclusive OR (XOR). The attribute byte is
combined with the most significant byte (CH and DH). The character code
is combined with the least significant byte (CL and DL).
The hardware pointer is the same shape as the normal text mode cursor.
Monochrome mode values for the starting and ending lines range from 0
to 13. Color mode values for the starting and ending lines range from 0 to
7.
887
Appendix F: Mouse Driver Interrupts PC System Programming
Sets the address of an event handler called by the mouse driver when a particular )
mouse event occurs.
Input AX= OOOCH
CX = Events which trigger the call of the event handler (event mask)
Bit 0: Mouse movement
Bit 1: Left mouse button activated
Bit 2: Left mouse button released
Bit 3: Right mouse button activated
Bit 4: Right mouse button released
Bit 5: Center mouse button activated
Bit 6: Center mouse button released
Bits 7-15: Unused
ES = Segment address of handler
DX = Offset address of handler
Output: No output
Remarks: The event handler is called by the mouse driver through a FAR call
assembler instruction, and therefore must be tenninated with a FAR RET
instruction. None of the various processor registers may be returned to the
caller with a changed content.
The mouse driver passes the following information to the event handler
through the processor registers during the call:
AX = event
mask. The bits correspond to the various events as indicated
in the CX register during the installation of the event handlec. In
888
Abacus Appendix F: MolISe Driver i1tlerrllpts
addition, other bits can be set, since the value reflects the current
status of the mouse driver, and is not limited to the selected events.
Remarks: Lightpen emulation only makes sense when used with an application
which supports the lightpen, or makes lightpen reading routines available
(e.g., the PEN command in PC-BASIC).
The lightpen and mouse are closely related in programming: The position
of the mouse pointer is directly related to the lightpen's position on the
screen, and pressing the left and right mouse button has the same result as
pressing the button on the lightpen.
889
Appendix F: Mouse Driver InlemAf)u PC System Programming
The lightpen and mouse are closely related in programming: The position
of the mouse pointer is directly related to the lightpen's position on the
screen, and pressing the left and right mouse button has the same result as
pressing the button on the lightpen.
Calling function DOH (Reset mouse driver) changes any previously set
values to the default values.
890
Abacus Appendix F: Mouse Driver InIe","pts
Designates any area of the screen as an exclusion area. The mouse pointer
disappears if moved into the exclusion area.
Input AX= 0010H
CX = X-coordinate, upper left comer of exclusion area
DX = Y-coordinate, upper left comer of exclusion area
SI = X-coordinate, lower right comer ofexclusion area
DI = Y-coordinate, lower right comer of exclUSion area
Output: No output
Remarlcs: The coordinates passed in the CX, DX, DI and SI registers refer to the
pixel positions in the virtual mouse display screen rather than physical
positions on the actual display screen.
Sets the maximum limit for doubling mouse speed. If the speed of the mouse
movement exceeds a certain limit, the mouse driver doubles the mouse pointer
speed by doubling the movement's relationship between points and mickeys.
To prevent doubling of the mouse speed. the limit can be set higher.
891
Appendix F: Mouse Driver Interrupts PC System Programming
Installs a new event handler for certain mouse events, but also retains the address
of the old event handler.
Input AX= 0014H
CX = Events which should trigger event handler call
Bit 0: Mouse movement
Bit 1: Left mouse button activated
Bit 2: Left mouse button released
Bit 3: Right mouse button activated
Bit 4: Right mouse button released
Bit 5: Center mouse button activated
Bit 6: Center mouse button released
Bit 7-15: Unused
The mouse driver passes the following information to the event handler
through the processor registers during the call:
892
Abac/lS Appendix F: MolISe Driver Interr"p1s
11200 inch).
Returns the size of the mouse status buffer, in which a program can store the
complete status of the mouse driver.
Input AX= OOI5H
893
Appendix F: Mouse Driver Inlerrllpts PC System Programming
This function works well when called before executing a program using
the EXEC function. This allows the mouse status to be saved in
memory. then restored from within the called program.
Reads all mouse parameters from a buffer where they had been stored by function
16H.
Output: No output
This function permits a program to install a limited range event handler. This
handler can be called by the mouse driver when certain mouse events occur in
conjunction with the keyboard
Remarks: At least one of bits 5 to 7 must be set in the event mask of the CX
register to ensure that the event reacts to at least one of the control keys.
If the programmer prefers not to read the Shift, Ctrl or Alt keys along
with mouse buttons. use functions OCH or 14H instead.
894
Abacus Appenda F: Mouse Driver lnurrMpts
Remarks: The event handler is called by the mouse driver through a FAR call
assembler instruction, and therefore must be terminated with a FAR RET
instruction. None of the various processor registers may be returned to the
caller with a changed content.
The mouse driver passes the following information to the event handler
through the processor registers during the call:
895
Appendix F: Mouse Driver Interrupts PC System. Progrt11ll1lling
The function call fails if no alternate event handler with the indicated
event mask was previously installed.
To prevent doubling of the mouse speed. the limit can be set higher.
Calling function OOH (Reset mouse driver) changes any previously set
values to the default values.
896
AbaclLf Appendix F: Mouse Driver InlerrMpts
Returns the parameters previously set by calling function 1AH or functions OFH
and 13H.
Input AX= OOlBH
Output: BX = Number of horizontal mickeys
CX = Number of vertical mickeys
DX = Maximum limit for doubling the mouse speed
Detennines the frequency at which the mouse hardware reads the current mouse
position and mouse button status.
Input AX= oolCH
BX = Interrupt rate
Bit 0: No interrupts
Bit 1: 30 interrupts per second
Bit 2: 50 interrupts per second
Bit 3: 100 interrupts per second
Bit 4: 200 interrupts per second
Bits 5-15: Unused
Output: No output
Remarks: This function is only available for the Inport mouse.
H more than one bit is set in the BX register, only the least significant
bit which is set counts.
897
Appendix F: Mouse Driver Interrupts PC System Progromming
Calling this function only makes sense if the application program wprks
with several display pages, as available on COA, EGA and VGA cards.
Deactivates the current mouse driver and returns the address of the previous
interrupt handlers for interrupt 33H.
Input AX= OOlFH
Output: AX = Error status
AX=FFFFH: Error
AX=OOlFH: O.K.
ES = Segment address of previous event handler
BX = Offset address of previous event handler
Remarks: This call releases any previously installed and active mouse driver
interrupt routines. The exception to this is the handler for interrupt 33H.
but the caller can reload this interrupt vector with its original value since
this address is returned in the ES:BX register pair.
898
Appendix F: Mouse Driver InlerrllplS
Remarks: Unlike function OOH, this function does not perform a total mouse
hardware reset
'> i
Interrupt 338, function 248 Mouse
Determine mouse type
Determines the type of mouse installed and the version number of the mouse
driver.
CH=5: HP mouse
CL = IRQ number
CL=O: PS/2
CL=2, 3, 4, 5 or 7: IRQ number in the PC
Remarks: If the version number of the mouse driver is for example 6.24, the value
6 is returned in the BH register and the value 24 is returned in the BL
register.
899
Appendix G
Introduction to Number
Systems
Throughout this book we talked about numbers notated in the binary and
hexadecimal systems instead of the normal decimal system. This Appendix
presents a brief introduction to these number systems.
Decimal system
Before explaining the new number systems. you should know the basic concepts
of the decimal system. The decimal number 1989 can also be written as
1*1000+9*100+8*10+9*1. This shows that if you number the digits from right
to left. the ftrst number represents a column of ones. the second number represents
a column of tens. the third number represents a column of hundreds and the fourth
number represents a column of thousands. The numbers increase from right to left
in powers of 10.
The first digit of any number system has the value 1. The factor by which the
value increases from one column to the next differs among the number systems.
This factor corresponds to the numbers with which the number system works. The
factor is 10 with the decimal system because ten different numbers are available for
each digit (0 to 9).
This principle of powers for each column also applies to the binary and
hexadecimal systems.
Binary system
Since a computer recognizes the numbers 0 and 1 on its lowest functional level,
the binary system is essential to computing. The value of the numbers double
from column to column because the binary system only uses powers of two for
each column (i.e., the numbers 0 and 1 instead of the numbers 0 to 9).
900
Abacus Appendix G: InlrodllCtion to Number Systems
Now let's count the binary places starting from right to left as we did in the
decimal example described above. The first (right hand) position counts as one, the
second as two, the third as four and the fourth as eight The places then follow as
16,32,64,I28,etc.
Unlike the binary system. the hexadecimal system operates with more basic
numbers than the decimal system. This system counts single digits from 0 to F.
Since only the ten numbers of the decimal system are able to represent a number,
the numbers from 10 to 15 in hexadecimal use the letters A to F in addition to the
numbers 0 to 9. AH stands for 10, BH for 11, CH for 12, DH for 13, EH for 14
and PH for 15.
By using 16 numbers or letters for each position, the value by which each position
increments is 16.
The first position has the value I, the second 16, the third 256 and the fourth
4,096.
For example, the hexadecimal number FB3H converts into 4,019 decimal, or
15*256+11*16+3*1.
Hex and binary
The hexadecimal system and the binary system are easily converted back and forth.
For example, one four-digit binary number converts to a single-digit hexadecimal
number. Because of this, the hexadecimal system is an important part of assembly
language programming. It's much simpler to convey a byte (an eight-bit number)
using two hexadecimal digits than it is for the developer to compute a 16-bit
binary equivalent.
This book denotes all binary numbers by the letter (b), and all hexadecimal
numbers by the letter H.
The following illustrations should help explain number systems more clearly.
901
Appendix G: IntrodllCtion to Number Systems PC System Programming
Places 5 4 3 2 1
Binary 16 8 4 2 1
902
Appendix H
Glossary of T"erms
Address
The Intel-80xx family of microprocessors form an address from one of the four
segment registers, in conjuQction with another register or a cOnstant. The contents
of the segment register becomes the segment address, and the other register or
constant becomes the offset address. Both addresses are logical addresses that are
related to a physical address (the actual number of a memory location). This
physical address can be determined by multiplying the segment register by 16 and
adding the offset address.
Address area
The number of memory locations addressable by a microprocessor.
Address bus
A line connecting the CPU with memory (RAM and ROM). If the CPU wants to
address a memory location, it must ftrst place its address on the address bus in
order to set the "switches" for access to this memory location.
Arena header
The data structure which precedes the memory area of the TP~ assigned to a
program. DOS uses this area to store the memory area's size and other
information.
903
Appendix H: Glossary o/Terms PC System ProgrQl1fl1ling
ASCII
Abbreviation for American Standard Code for Information Interchange.
ASCII is a standardized assignment of numbers from 0 to 2SS that represents
characters (e.g., letters, numbers). The ASCII codes from 0 to 127 comprise the
standard ASCII character set, while the codes from 128 to 255 comprise the
extended ASCII character set.
Assembly language
A small number of simple instructions that the processor can understand. Every
higher level language program is finally translated into these instructions for
processing by the CPU.
AT
Abbreviation for Advanced Technology. AT computers have an 80286
processor.
Attribute
A byte following each character that defmes the character's color and appearance for
display on the screen.
AUTOEXEC.BAT
Filename for the automatically executing batch fIle for which DOS searches during
the booting process. After DOS is loaded and started, it searches the root directory
of the device from which it booted for a fIle named AUI'OEXEC.BAT. During the
booting process, this batch file executes programs and parameters through the
command processor.
Batch files
Text files saved with the file extension .BAT. These files contain DOS commands
or command sequences. Batch file execution treats these commands as if the user
had entered the commands from the keyboard.
Baud
A measurement of data transfer speed. One baud roughly equals one data bit per
second.
BCD
Abbreviation for Binary Coded Decimal. This number represents a two-digit
decimal number encoded in one byte. The upper four bits represent the most
significant digit and the lower four bits represent the least significant digit.
904
Abac/U Appendix H: Glossary o[Terms
Binary system
The number system understandable by a computer at its lowest level. Binary
notation counts from 0 to 1. The first position of a binary number has the value I,
the second has the value 2, the third has the value 4, the fourth has the value 8,
etc.
BIOS
Abbreviation for Basic Input/Output System. It contains the device drivers
which perform access to the peripheral devices such as the keyboard, monitor, disk
drives, etc. The BIOS is located in addresses FOOO:EOOO--FOOO:FFFF.
BIOS interrupts
Interrupts lOH to 17H and interrupt lAH, through which the many functions of
the ROM-BIOS can be called.
BIOS version
Release date of the BIOS as stored in the eight bytes starting at memory location
FOOO:FFF5. This version appears in the form Month/Day/Year.
Block driver
The device drivers which control access to devices that process data in data blocks
(disk drives and hard disks). Block drivers are addressed through a letter (drive
specifier) which enables one block driver to control several devices with different
letters. The disk driver has the drive specifiers A: and B:, while the hard disk driver
can be addressed with the specifier C:.
Boot sector
Contained on every mass storage medium from which DOS can be booted. Sector
o contains certain information and a short program which loads a DOS boot
routine, then initializes DOS.
Booting
The process that starts after the user has switched on the computer. BIOS tests and
initializes the various circuit chips in the system, then loads the operating system.
BPB
Abbreviation for BIOS Parameter Block. The BPB defines the format and
design of a mass storage device (disk drive and hard disk) for DOS. It is available
in the boot sector of every mass storage device, but must be passed to DOS by the
initialization routine of a block device driver.
CALL
Assembly language instruction that biggers the execution of a subroutine. Mter
the routine ends, a RET instruction executes, which is followed by the instruction
following the initial CALL.
90S
Appendix H: Glossary o/Terms PC System Programming
Carry nag
Bit 0 in the processor's flag register. Many operating system functions use it to
tell the calling program whether the called function executed correctly, or if an
error occurred. In the latter case, the carry flag is set (1) after the function call.
Character driver
A device driver which controls access to devices that process characters as bytes.
The screen, keyboard and printer are device drivers. Character drivers have their own
names, such as CON, PRN and AUX.
Child program
A program which is called by another program. For example, if the FORMAT
command is called from the DOS level, the parent program is the command
processor.
CLI
Clear interrupts instruction. This instruction instructs the CPU to ignore all
subsequent interrupt requests until the S11 (STart Interrupts) instruction re-enables
interrupt response (the NMI [Non-Maskable Interrupt] is exempt from this
instruction).
Clock driver
A character device responsible for getting the time and date from DOS,
incrementing the time and date and p!lSSing the incremented amounts back to DOS.
Clock generator
Produces several million pulses per second and synchronizes various components
of the system wid! each other.
Cluster
Multiple sectors of a mass storage device. Files and subdirectories can be stored in
different clusters. The number of sectors per cluster varies from one device to
another.
COM files
Executable programs which must be stored within a 64K memory segment COM
fIles combine program code, data and stack in this 64K area.
COMMAND.COM
The fIle containing the MS-DOS command processor.
Command line
A line from which program or batch fIle calls can be entered into the command
processor.
906
AbaclU Appendix H: Glo&!ary o[Tmns
Command parameters
The name for all characters passed in the command line. following the program or
batch file calls. The EXEC function copies these parameters into the PSP of the
loaded program.
Command processor
Also called shell. The command processor is a part of the operating system which
accepts and processes user input Its main function is to load and start application
programs and batch files.
CON
Abbreviation for CONsole driver. the two device drivers which control the
keyboard and the screen.
CONFIG.SYS
The DOS configuration file. It contains certain commands for configuring OOS. as
well as additional device drivers. CONFIG.SYS loads and executes only once
(dlDing the booting process).
Control characters
ASCII characters which represent certain non-alphanumeric characters. This applies
to all ASCII codes less than 32. The PC only uses ASCII codes O. 7. 8. 9. 10. 11.
12 and 13 as control characters.
Cooked mode
Character mode that checks for certain unusual characters. which are either
converted to other characters or completely filtered out Character drivers operate
either in raw mode or cooked mode.
CP/M·SO
Early operating system. the predecessor of MS-OOS. CP/M is used by computers
that are based upon Z-80 microprocessors.
CPU
Abbreviation for Central Processing Unit. The microprocessor which forms
the "brain" of a computer.
CRC
Abbreviation for Cyclical Redundancy Check. The CRC tests for errors
during data transfer to and from a disk.
907
AppendixH: Glossary ofTums PC System Programming
CRT
Abbreviation for Cathode Ray Tube. A CRT generates a screen display with
the help of an electron beam which sends electrical impulses to a glass screen at
the end of the CRT.
DASD
Abbreviation for Direct Access Storage Device. In DOS and BIOS
terminology this concept is used for disk drives and hatd disks.
Data bus
A data line which connects the CPU with memory (RAM and ROM). Data can be
transmitted between the CPU and memory over this line.
Device driver
Driver systems which interface DOS and hardware by making basic functions
available for communicating with the hardware. Device driver functions can be
called by the higher level DOS functions. DOS differentiates between character
drivers and block drivers.
Disks
Flat plastic materials containing magnetic media for storing data. Formatted disks
are partitioned into tracks and sectors.
Disk controller
Regulates the activities of the disk drive.
Disk status
Lists the status of the last disk operation. It indicates if and when an error occurred
during this disk access.
Disk formats
The PC market supports several disk formats. PC and XT disk drives use 5-1/4"
disks that are formatted on one or two sides. Each side contains 40 tracks with
eight or nine sectors per track (each sector stores 512 bytes). The capacity of these
disks is between 160K (single-sided) and 360K (double-sided). The AT uses 5-1/4"
disks with two formatted sides. each side containing 80 tracks with 15 sectors per
track (each sector stores 512 bytes). The total capacity of these disks is 1.2
megabytes.
The newest disk formats on the market allow the use of 3-1/l" micro floppy disks.
Display page
Also called screen page and video page. Some video cards can control one or more
display pages. Only one of these pages can be displayed on the screen at one time.
908
Abacus AppendixH: Glossary o[Terms
DMA
Abbreviation for Direct Memory Access. Transmits data from the circuit
chips of a peripheral device direcdy into memory. without making a detour
through the CPU. \ .
DMA controller
A chip capable of transferring large amounts of data direcdy into memory without
passing through the CPU. A good example is the access to a disk drive or hard
disk drive.
DOS
Abbreviation for Disk Operating System. DOS sets up basic file handling
tasks for communicating between computer and disk drive(s).
DTA
Abbreviation for Disk Transrer Area. File and directory accesses use the DTA
for disk data transmission. Its size depends upon the current opemtion. where the
calling program must ensure that enough memory exists to accept the transmitted
data. After the start of a program, DOS places the beginning of the DTA into
memory location 128 of the PSP, which makes 128 bytes available.
ECC
Abbreviation for Error Correction Code. ECC is used when data is stored on a
hard disk. Unlike the CRC, the ECC permits the recognition of errors as well as
their correction within certain parameters.
EGA
Abbreviation for Enhanced Graphic Adapter. This is a special, high
resolution variation on the Color/Graphics Adapter (CGA).
EMM
Abbreviation for Expanded Memory Manager. Allows access to EMS memory.
EMS
Abbreviation for Expanded Memory System. This section of RAM goes beyond
the 1 megabyte limit set by PCs and XTs. EMS is only accessible through the
EMM.
End character
Also called return code. The end character is ASCII code O. which is sometimes
assigned the name NUL. It usually indicates the last character in a character string.
909
Appendix H: Glossary o/Terms PC System Programming
Environment block
Every program has an assigned environment block whose address is stored in the
PSP of the current program. The environment block itself consists of a series of
ASCII strings which contain certain infonnation, such as the search path for files
(pATH).
EOI
Abbreviation for End or Interrupt. This insbUction indicates. the completion of
a hardware triggered interrupt to the interrupt handler.
EXE files
Executable programs which can be of any length and can store their code, data and
stack in different memory segments (see also COM files).
EXEC
DOS function for loading and executing programs. The command processor also
uses this function to execute applications programs and batch files.
FAR instructions
Machine language insbUctions that contain an address of a variable or a subroutine
with a segment address and an offset address. They can address variables or
subroutines located in another memory segment (farther away than 64K).
FAT
Abbreviation for File Allocation Table. This is a table located on every
external storage medium (disk and hard disk). It informs DOS which areas of a
storage medium are available, which areas are already occupied with data, and
which areas are useless because of defects. The FAT also links together the
different parts of a file.
FCB
Abbreviation for File Control Block. DOS controls file access to RAM using
FCBs.
Fixed disk
Another term for hard disk.
910
Abacus Apeendix H: Glossary o/Terms
Filter
A program that reads characters from the standard input device, manipulates them
in some desired way, and then displays them on the standard output device.
Flag register
A 16-bit register in which several of these bits indicate certain aspects of the
processor's status.
Function
A routine that can be called with a DOS or BIOS interrupt
Garbage collection
A routine that removes variables which are no longer required from the variable
memory of a BASIC program. Every BASIC interpreter has garbage collection.
GDT
Abbreviation for Global Descriptor Table. The GOT describes the individual
memory segments when the processor is in protected mode.
General registers
The processors of the Intel-80xx family have the following general registers: AX,
BX, CX, OX, 01, SI and BP. They are all 16 bits wide. The AX, BX, CX and OX
registers can be separated into two 8-bit registers. These two half registers are
designated as AH, AL, BH, BL, CH, CL, OH and OL.
Handle
A numerical value that acts as a key for access to files and devices. It is passed by
DOS to a program which calls one of the functions for opening or creating a file
or device.
Hard disk
A mass storage unit consisting of several magnetic media stacked on top of one
another. Unlike disks, hard disks are divided into cylinders and sectors. Each of
these disks can store data on both their top and bottom sides.
Hardware interrupt
An interrupt or interrupt request, called by PC hardware, to attract the attention of
the CPU to a device (e.g., the keyboard). Certain devices only call certain
interrupts.
911
Appendix H: Glossary of Terms PC System Programming
Hexadecimal system
A number system distantly related to the binary system. The basic numbering of
this system goes from 0 to 15, instead of from 0 to 9 (the numbers 10 to 15 are
represented by the letters A, B, C, D, E and F). The first position of a hexadecimal
number bas the value I, the second 16, the thiId 256, the fourth 4,096, etc.
IN
Assembly language instruction to read data from a port into the CPU.
Internal commands
All commands whose code is stored in the ttansient portion of the command
processor, and, therefore, don't have to be loaded from a storage medium (e.g.,
DIR, COpy and VER).
Interrupt
An interruption of a program through an interrupt call, the execution of an
interrupt routine and, finally, the resumption of the interrupted program. The
processors of the Intel-8Oxx family can process 256 different interrupts which are
divided into hardware and software interrupts.
Interrupt controller
Monitors the various interrupt requests within the system and decides which
interrupts to process first.
Interrupt routine
The program called during the appearance of an interrupL Each interrupt has its
own interrupt routine. whose address is stored in the interrupt vector table. The
interrupt routine must be terminated with a machine language IRET instruction.
IRET
The Interrupt RETurn assembly IJmguage instruction. IRET terminates the
execution of an interrupt routine and then continues the execution of the program
at the location following the interruption of the program.
912
Abacus Appendix H: Glossary otTer"",
Keyboard status
Indicates whether the user has pressed the <Shifl>, <Ctrl> or <All> keys, and
whether the <Insert>, <CapsLocb, <NumLocb or <ScrollLock> modes are
active.
Kilobyte
Math coprocessor
"
Relieves the CPU of the processing of complicated floating-point mathematical
formulas. It also accelerates the processing of worksheets within a spreadsheet
program.
Megabyte
Memory allocation
In all pes the lower 640K is assigned to RAM. The video RAM follows, and then
the ROM, which extends to the 1 megabyte memory limit. ATs may have up to
15 megabytes of additional RAM.
Microprocessor
The brain of a computer. Its main task is to execute assembly language
instructions.
Model identification
The type of PC used, as coded into address FOOO:FFFE. FCH stands for AT, FEH
often stands for XT and FFH often stands for PC.
MS-DOS
Abbreviation for MicroSoft Disk Operating System. MS-DOS is the
primary PC operating system.
Multiprocessing
The simultaneous execution of several programs (not supported by DOS at the
time of this writing).
913
Appendix H: Glossary of Terms PC System Progronuning
NEAR instructions
Assembly language instructions that contain the offset address of only a variable or
a subroutine (no segment address). These insttuctions can address variables or
subroutines located only within the current 64K memory segmenL
Nibble
Also spelled nybble. Bytes can be subdivided into two nibbles. The low nibble
occupies bits 0 to 3 of a byte, while the high nibble occupies bits 4 to 7 of a byte.
NMI
Abbreviation for Non-Maskable Interrupt. The NMI remains constantly
active. It is the only interrupt not affected by the CLI assembly language
instruction.
OUT
An assembly language instruction which sends data to a port.
Overlay
A program loaded into memory allocated for it by another program. The calling
program calls certain routines within this overlay as needed.
Paragraph
A group of 16 bytes in the 8088 which starts at a memory location divisible by 16
(e.g., 0, 16, 32, 48, etc.).
Parent program
A program that can execute another program (see child program) and continue its
own processing after the child program's execution. For example, if a FORMAT
command is called from DOS level, the command processor is the parent program.
Parity
A process used to detect errors during serial data transmission. Either even or odd
parity can be used.
PC
Abbreviation for Personal Computer (i.e., all computers equipped with a 8088
or 8086 processor).
Peripheral interface
Connects the CPU to various peripheral devices (e.g., speaker).
914
Abacus Appendix H: Glossary of Terms
Ports
The connections between the CPU and various other circuit chips within the
system. Each chip has one or more assigned ports. which have a specific address.
The CPU addresses the individual chips by writing values into the proper port or
by reading values from the proper port.
Printer status byte
Describes the current status of the printer. It can indicate whether the printer is out
of paper. is switched ONLINE or has not responded (time-out).
PRN
The device designation of the printer.
Program counter
Also called IP (Instruction Pointer). The program counter and the CS segment
register combined form the memory address from which the processor will read the
next command to be executed.
Protected mode
Allows multiprocessing, more than 1 megabyte of memory and control over
virtual memory on computers possessing the 80286 and 80386 processors.
PSP
Abbreviation for Program Segment Prefix. The PSP is a 256 byte long data
structure, which is placed in front of every program to be executed but not stored
with the file on disk or hard disk. The program itself or program data start after
this data structure.
RAM
Abbreviation for Random Access Memory. This is the memory that the user
can read from and write to.
Raw mode
Character mode that transmits all characters from a device to the calling program
without any changes (see cooked mode).
Real mode
Forces 80286 and 80386 processors to emulate dual high-speed 8088 processors
incapable of multiprocessing or control of more than 1 megabyte of memory.
Register
Memory locations inside the processor that provide faster access than memory
locations in RAM.
915
Appendix H: Glossary o/Terms PC System Programmillg
Reset
A resetting and reboot of the system. You can trigger a reset by pressing the
<Alt><Ctrl><Delete> key combination.
Resident
Programs that remain in memory after execution without being overwritten by
other programs or data. Resident programs can be recalled later.
ROM
Abbreviation for Read Only Memory. ROM can only be read, not written.
ROM BASIC
A small BASIC interpreter, placed in the ROMs of older PCs starting at address
FOOO:6000. ROM BASIC is called by the system when BIOS fails to load the
operating system.
RS·232
An interface that permits the computer to communicate with other devices over
only one line. The individual data is transmitted serially (i.e.• bit by bit).
RTC
Abbreviation for RealTime Clock. The battery backed clock on the AT.
Scan code
A code passed to the CPU by the keyboard processor when a key is pressed or
released. It indicates the number assigned to the key within the keyboard. For this
reason, the scan codes of the various PC keyboards differ from each other.
Sector
The smallest data division of a disk or hard disk. A sector contains 512 bytes.
Segment descriptor
Describes the location and size of the segment in addition to other information. It
is used in protected mode on the 80286 and 80386 processors. All segment
descriptors are gathered in the global descriptor table (GO'!).
Segment register
The processors of the Intel-SOxx family have four 16-bit segments that define the
beginning of a 64K memory segment. They are named OS, ESt CS and SS.
Software interrupts
An interrupt or interrupt request called by a program using the INT instruction.
Each of the 256 existing interrupts can be called using this instruction.
916
AbaclU Appendix H: Glossary o[Ter"",
Timer
L-
Similar to the clock. The timer generates a cyclical signal used to measure time.
TPA
Abbreviation for Transient Program Area. This is the part of RAM below the
1 megabyte limit not occupied by DOS that is used for storing programs and data.
UART
Abbreviation for Universal Asynchronous Receiver Transmitter. A chip
that acts as the controller for the serial interface.
Video controller
Displays a picture on the screen by sending the proper signals to the monitor.
Video RAM
RAM, which is used for storing characters or graphics for display on the screen,
made available by a video card. It can be addressed like normal RAM.
Virtual memory
Pemits program access to memory, which it assumes to be RAM but is actually a
mass storage device. Virtual memory must first be loaded into RAM for access.
Volume
Part of a mass storage device that has files, its own FAT, its own root directory
and its own subdirectories. Each volume can have its own volume name. While
disks can store only one volume under DOS, hard disks can be divided into several
volumes to accommodate several operating systems.
917
Appendix I
Scan Codes
918
Appendix J
0 00 32 20 64 40 @ 96 60 .
1 01 Q 33 21 a65 41 A 97 61
2
3 ••
02
03 #
34
35
22
23
"
c
66
67
42
43
B
C
98
99
62
63
b
4
5
04
05 .• 36
37
24
25
$
%
68
69
44
45
D
E
100
101
64
65
d
e
6
7
06
07 •• 38
39
26
27
&
, 70
71
46
47
F
G
102
103
66
67
f
q
8 08 a 40 28 ( 72 48 H 104 68 h
9 09 0 41 29 ) 73 49 I 105 69 i
10 OA • 42 2A * 74 4A J 106 6A j
11 OB cf 43 2B + 75 4B K 107 6B k
12 OC 9 44 2C 76 4C L 108 6C 1
13 00 } 45 2D - 77 4D M 109 6D m
14 OE J.I 46 2E • 78 4E N 110 6E n
15 OF l:t 47 2F / 79 4F 0 111 6F 0
16 10 ~ 48 30 0 80 50 P 112 70 P
17 11 • 49 31 1 81 51 Q 113 71 q
18
19
12
13
*
!!
50
51
32
33
2
3
82
83
52
53
R
S
114
115
72
73
r
s
20 14 ! 52 34 4 84 54 T 116 74 t
21 15 § 53 35 5 85 55 U 117 75 u
22 16 _ 54 36 6 86 56 V 118 76 v
23 17 t 55 37 7 87 57 W 119 77 w
24 18 t 56 38 8 88 58 X 120 78 x
25 19 J. 57 39 9 89 59 Y 121 79 Y
26 1A -+ 58 3A 90 5A Z 122 7A z
27 1B + 59 3B 91 5B [ 123 7B {
28 1C ~ 60 3C < 92 5C \ 124 7C I
I
29 1D ++ 61 3D = 93 5D ] 125 7D }
30 1E & 62 3E > 94 5E A
126 7E
31 1F • 63 3F ? 95 5F 127 7F
•
919
Appendix J: ASCII Character Set PC System Programming
128
r 80r ~. 160r AOr a~. 192r cor ~. 224r EOr a~.
C; L
129 81 ii 161 A1 i 193 C1 J.. 225 E1 8
130 82 e 162 A2 6 194 C2 T 226 E2 r
131 83 a 163 A3 11 195 C3 I- 227 E3 'Ir
132 84 a 164 A4 ft 196 C4 228 E4 1::
133 85 a
a
165 A5 N 19~ C5 + 229 E5 a
134 86 166 A6 • 198 C6 ~ 230 E6 ~
135 87 Q 167 A7 II 199 C7 I~ 231 E7 f'
136 88 e 168 A8 <. 200 C8 II: 232 E8 t
137 89 e 169 A9 - 201 C9 If 233 E9 9
138 8A e 170 AA~ 202 CA:!!: 234 EA n
139 8B i 171 AB ~ 203 CB 'if 235 EB &
140 8C 1 172 AC % 204 CC I~ 236.tEC co
141 80 i 173 AD 205 CO = 237 ED cp
142 8E A 174 AE« 206 CE {~ 238 EE €
143 8F J.. 175 AF » 207 CF ::!:: 239 EF n
144
145
90
91
E
ae
176
177
BO
B1 ~1~~~~
208
209
DO JL
01 T
240 FO
241 F1
=
±
146 92 If. 178 B2 I 210 02 11" 242 F2 ~
B3 I 03 11.
147
148
149
93
94
95
"
6
0
179
180
181
B4 ~
B5 ~
211
212
213
04 b
05 f
243 F3
244 F4
245 F5
~
r
J
150 96 11 182 B6 ~I 214 06 0" 246 F6 +
151 97 U 183 B7 11 215 07
* 247 F7 ~
152
153
98
99
Y
6
184
185
B8 =t
B9 {I
216
217
08
09 J
+ 248 F8
249 F9 .
0
920
Index
8086
3,903
AUTOEXEC.BAT 57,149,199,904
8088
3,8,903
80186
3,903
BASIC 96
80286
3,903
Basic Input Output System (BIOS)
80386
3,903
I, 711, 905
Address 8,903
BIOS architecture 220
Address notation 9
BIOS configuration functions 713
Address register 8
BIOS floppy disk functions 713
Address space 8
BIOS hard disk functions 714
AHregister 45
BIOS IntemIpts:
ASCII 904
Interrupt 13H, function 15H 734
ASSIGN 149
Interrupt 13H, function 16H 734
921
Index PC System Programming
911
Abacus Index
Configuration 289
Determine memory size 728, 755
CRT 458,908
909
462,857,872
Directory lister programs 96
<Ctrl><Break> 800
Disable lightpen emulation 889,890
Cycles 447
Disk change 303, 735
DASD 908
Disk transfer area (DTA) 62,90
Data segment 10
Display attributes 460
Date 54,395,715,759-762,
Display page 856-858, 908
796,797,829
Division by zero 710
923
Index PC System Programming
DTA 62,99,768,788,827,909
Interrupt 67H, function 9 853
EGA 254,463,909
Environment block 112,208, 823, 910
EGNVGA Interrupts:
825.910
Interrupt lOH, function OOH 856
EXEC function
Interrupt lOH, function OAH 861
60,66,110,132,823.910
865-866
Extended memory mapping 851
872-874
Extended memory status 849
875,876
Extended partitions 688
877-878
Extended write 745
EMM Interrupts:
Extra segment 11
924
Abacus Index
198,214,910
Get verify flag 828
208
GRAFfABL 234, 721, 764
FORMAT 202
Hankopy 670,711
Function 911
Interrupt om 710
GDT 337,911
Interrupt 04H 711
9lS
ImUx PC System Programming
Instruction pointer 10
Media change 734
Interrupts 19
Model identification byte 291,913
instruction 711
Monochrome Display Adapter (MDA)
JOIN 212
Mouse buttons 618
Joysticks 753
Mouse event handlers 888,891
Kilobyte 913
Interrupt 33H, function ODH 889
LASTDRIVE 212
Interrupt 33H, function OFH 890
Macros 48
Interrupt 33H, function lEH 898
Make directory 93
Interrupt 33H, function IFH 898
Maskable interrupts 23
Interrupt 33H, function 02H 883
Match 826-827
Interrupt 33H, function 03H 884
926
Abacus Index
927
Index PC System Programming
Program counter 6, 10
674.761-763
208,769,793,915
Recalibrate hard disk 329. 748
Prompt 57
Redirection of interrupts 156
Raster 462
Reset alarm time 763
Read 161
Reset input buffer and then input 780
Readchrumcter 720,751,775,860
Reset mouse driver. 882, 899
928
Abacus Index
Segmented address 8
Single step 667
Segread 40
Single step interrupt 710
Setting 333
Transfer shift register 333
Scan 461
Transient commands 51
Shell 907
Transient Program Area (1PA) 119,903
929
Index PC System Programming
Wait 754
Wildcards 96
Woo 16
Word length 331,332
Write 163
930
Companion Diskette
PC System Programming
Companion diskettes
For your convenience, the program listings contained in this book are available on
two IBM 5 1/4 inch floppy diskettes. You should order the diskettes if you want to
use the programs but don't want to type them in from the listings in the book.
All programs on the diskettes have been fully tested. You can change the programs
for your particular needs. The two-diskette set is available for $19.95 + $2.00 for
postage and handling withing the U.S.A. ($5.00 foreign orders).
When ordering, please give your name and shipping address. Enclose a check,
money order or credit card information. Mail your order to:
Abacus
931