Tuesday, November 20, 2007

IBM PC Assembly Language Tutorial 4

IBM PC Assembly Language Tutorial 4

Learning about DOS

I think the best way to learn about DOS internals is to read the

technical appendices in the manual. These are not as complete as

we might wish, but they really aren't bad; I certainly have learned a lot

from them. What you don't learn from them you might eventually learn

via judicious disassembly of parts of DOS, but that shouldn't really

be necessary.

From reading the technical appendices, you learn that interrupts

20H through 27H are used to communicate with DOS. Mostly, you

will use interrupt 21H, the DOS function manager.

The function manager implements a great many services. You

request the individual services by means of a function code in the

AH register. For example, by putting a nine in the AH register and

issuing interrupt 21H you tell DOS to print a message on the console

screen.

Usually, but by no means always, the DX register is used to pass

data for the service being requested. For example, on the print

message service just mentioned, you would put the 16 bit address

of the message in the DX register. The DS register is also implicitly

part of this argument, in keeping with the universal segmentation

rules.

In understanding DOS functions, it is useful to understand some

history and also some of the philosophy of MS-DOS with regard to

portability. Generaly, you will find, once you read the technical

information on DOS and also the IBM technical reference, you will

know more than one way to do almost anything. Which is best? For

example, to do asynch adapter I/O, you can use the DOS calls

(pretty incomplete), you can use BIOS, or you can go directly to the

hardware. The same thing is true for most of the other primitive I/O

(keyboard or screen) although DOS is more likely to give you added

value in these areas. When it comes to file I/O, DOS itself offers

more than one interface. For example, there are four calls which

read data from a file.

The way to decide rationally among these alternatives is by

understanding the tradeoffs of functionality versus portability. Three

kinds of portability need to be considered: machine portability,

operating system portability (for example, the ability to assemble

and run code under CP/M 86) and DOS version portability (the

ability for a program to run under older versions of DOS>.

Most of the functions originally offered in DOS 1.0 were direct

descendents of CP/M functions; there is even a compatibility

interface so that programs which have been translated instruction for

instruction from 8080 assembler to 8086 assembler might have a

reasonable chance of running if they use only the core CP/M function

set. Among the most generally useful in this original compatibility set

are

09 -- print a full message on the screen

0A -- get a console input line with full DOS editing

0F -- open a file

10 -- close a file (really needed only when writing)

11 -- find first file matching a pattern

12 -- find next file matching a pattern

13 -- erase a file

16 -- create a file

17 -- rename a file

1A -- set disk transfer address

The next set provide no function above what you can get with BIOS

calls or more specialized DOS calls. However, they are preferable

to BIOS calls when portability is an issue.

00 -- terminate execution

01 -- read keyboard character

02 -- write screen character

03 -- read COM port character

04 -- write COM port character

05 -- print a character

06 -- read keyboard or write screen with no editing

The standard file I/O calls are inferior to the specialized DOS calls

but have the advantage of making the program easier to port to CP/

M style systems. Thus they are worth mentioning:

14 -- sequential read from file

15 -- sequential write to file

21 -- random read from file

22 -- random write to file

23 -- determine file size

24 -- set random record

In addition to the CP/M compatible services, DOS also offers some

specialized services which have been available in all releases of

DOS. These include

27 -- multi-record random read.

28 -- multi-record random write.

29 -- parse filename

2A-2D -- get and set date and time

All of the calls mentioned above which have anything to do with files

make use of a data area called the "FILE CONTROL BLOCK"

(FCB). The FCB is anywhere from 33 to 37 bytes long depending on

how it is used. You are responsible for creating an FCB and filling in

the first 12 bytes, which contain a drive code, a file name, and an

extension.

When you open the FCB, the system fills in the next 20 bytes, which

includes a logical record length. The initial lrecl is always 128 bytes,

to achieve CP/M compatibility. The system also provides other

useful information such as the file size.

After you have opened the FCB, you can change the logical record

length.

If you do this, your program is no longer CP/M compatible, but that

doesn't make it a bad thing to do. DOS documentation suggests you

use a logical record length of one for maximum flexibility. This is

usually a good recommendation.

To perform actual I/O to a file, you eventually need to fill in byte 33 or

possibly bytes 34-37 of the FCB. Here you supply information about

the record you are interested in reading or writing. For the most part,

this part of the interface is compatible with CP/M.

In general, you do not need to (and should not) modify other parts of

the FCB.

The FCB is pretty well described in appendix E of the DOS manual.

Beginning with DOS 2.0, there is a whole new system of calls for

managing files which don't require that you build an FCB at all.

These calls are quite incompatible with CP/M and also mean that

your program cannot run under older releases of DOS. However,

these calls are very nice and easy to use. They have these

characteristics

1. To open, create, delete, or rename a file, you need only a

character string representing its name.

2. The open and create calls return a 16 bit value which is simply

placed in the BX register on subsequent calls to refer to the file.

3. There is not a separate call required to specify the data buffer.

4. Any number of bytes can be transfered on a single call; no data

area must be manipulated to do this.

The "new" DOS calls also include comprehensive functions to

manipulate the new chained directory structure and to allocate and

free memory.

No comments: