UMBC CMSC 211

UMBC | CSEE


Introduction

Early file processing used a data structure called a File Control Block (which could not contain files with directary names in them. To overcome this obstacle, the FCB must be wrapped in another layer, which is modeled after the UNIX/C file system. Files are referred to internally by an integer called a file handle. As a result, filenames are variable lenght and terminated with a zero (ASCIIZ string).

At the start of execution, each program has five standard handles which are open:
stdin 0 the keyboard
stdout 1 the display
stderr 2 the display
stdaux 3 standard AUX:, usually COM1:
stdprn 4 standard printer device PRN:, usually LPT1:
One powerful property of the file system is file independence. In addition to being able to manipulate disk files, programs can access printers, keyboards, serial ports, etc, with the same set of operations as a disk file.

This device independence leads to Input/Output redirection and a specialized redirection known as pipes. The program can be started at the command line with:

PROGNAME < inputFile > outputFile The operating system will cause handle 0 to change from the default of the keyboard, making the file inputFile to be used instead. Likewise handle 1 will use the file outputFile. The program PROGNAME does not have to be recompiled or anything to take advantage of this, if it was written to use handle 0. Those programs that were written to go directly to the keyboard instead of handle 0, can not be redirected.

A pipe is a connection from one program to another,

PROG1 | PROG2 In this case, the standard output of PROG1 becames the standard input of PROG2. This concept is used in both DOS and UNIX. This is used to create filters, which modifies the output of one program before giving it so another. UNIX uses filters whenever you try to print something, because the output has to be formatted for a certain type of printer.

Handles and Opening, Creating, and Closing Files

All of the DOS calls in this chapter will indicate an error by returning with the Carry Flag set and the error number stored in the AX register.

When we want to use a filename, we put into the .DATA segment in the form of:

theNameDB'A:\source\myprog.asm',0
We can open a file with the macro _Open or _Creat (there is no mistake, the 'e' is missing). We must give it a filename. An acesstype can be given, read-only is the default. Optionally, we can give it a segment if different that what is in the ds register. The open function opens an existing file. The creat creates creates a file, unless it exists, in which case, the file is emptied and opened. I highly recommend you use the save version sOpen and sCreat, because of the number of registers that are modified.

The following is the instructions for using the macros:

;;		_Open	filename, accessmethod[, segment]
;;			accessmethod is one of the three integers 
;;			  0, 1, or 2, or one of the corresponding r 2, or  
;;			  one of the corresponding symbolic values Read, 
;;                        Write, or ReadWrite
;;			If successful, returns Carry Flag clear 
;;				and handle in AX
;;
;;	
;;     _Creat	filename[, segment]
;;			If successful, returns Carry Flag clear
;;			  	and handle in AX

The macro _Open uses a couple of new pseudo-ops: IFB (if blank), ELSE (goes with any IF), ENDIF (terminates the IF definition), and IFIDNI (if identical, case insensitive).

_Open   MACRO   filename, accesstype, segm
        _LdAddr dx, 
        _LdSeg  ds, 
        mov     ah, 3dh
IFB     <&accesstype&>
        mov     al, 0
ELSE
    IFIDNI <&accesstype&>, 
        mov     al, 0
    ELSE
        IFIDNI <&accesstype&>, 
        mov     al, 1
        ELSE
            IFIDNI <&accesstype&>, 
        mov     al, 2
            ELSE
        mov     al, accesstype
            ENDIF
        ENDIF
    ENDIF
ENDIF
        int     21h
        ENDM
  

There is also a close DOS call. While all open files are closed automatically when the program executes, it is good programming style to close the files explicitly and as soon as possible. It takes a handle as a parameter.

There are two measures available to protect files, one is to set the file to read-only with the DOS command

attrib +r filename The other is to use the proper accessmethod in program. If you are only going to read the file, open it as Read!

The filename can not have any leading, embedded, or trailing white space (blanks or tabs). Also, the access type must identically if you use the symbolic version or the integers 0 - 2. Otherwise you will get weird results. The segment is optional, and is used if the filename is defined in a segment where ds is not pointing to currently.

In UTIL.LIB, there is a procedure, CCheck, with no parameters, that will handle checking for errors. However, this procedure will print out a message and terminate the program if there is an error. You may want to have to program try to gracefully recover after an error, such as enter in a new filename if an existing file could not be found.


UMBC CSEE