The following is a typical program sequence to access a file using the handle family of functions (Figure 8-7):
1.Get the filename from the user by means of the buffered input service (Int 21H Function 0AH) or from the command tail supplied by MS-DOS in the PSP.
2.Put a zero at the end of the file specification in order to create an ASCIIZ string.
3.Open the file using Int 21H Function 3DH and mode 2 (read/write access), or create the file using Int 21H Function 3CH. (Be sure to set the CX register to zero, so that you don't accidentally make a file with special attributes.) Save the handle that is returned.
4.Set the file pointer using Int 21H Function 42H. You may set the file-pointer position relative to one of three different locations: the start of the file, the current pointer position, or the end of the file. If you are performing sequential record I/O, you can usually skip this step because MS-DOS will maintain the file pointer for you automatically.
5.Read from the file (Int 21H Function 3FH) or write to the file (Int 21H Function 40H). Both of these functions require that the BX register contain the file's handle, the CX register contain the length of the record, and the DS:DX registers point to the data being transferred. Both return the actual number of bytes transferred in the AX register.
In a read operation, if the number of bytes read is less than the number requested, the end of the file has been reached. In a write operation, if the number of bytes written is less than the number requested, the disk containing the file is full. Neither of these conditions is returned as an error code; that is, the carry flag is not set.
6.If the program is not finished processing the file, go to step 4; otherwise, close the file (Int 21H Function 3EH). Any normal exit from the program will also close all active handles.
recsize equ 1024 ; file record size
.
.
.
mov ah,3dh ; open input file
mov al,0 ; mode = read only
mov dx,offset fname1 ; name of input file
int 21h
jc no_file ; jump if no file
mov handle1,ax ; save token for file
.
.
.
mov ah,3ch ; create output file
mov cx,0 ; attribute = normal
mov dx,offset fname2 ; name of output file
int 21h
jc disk_full ; jump if create fails
mov handle2,ax ; save token for file
.
next: . ; process next record
.
mov ah,3fh ; sequential read from
mov bx,handle1 ; input file
mov cx,recsize
mov dx,offset buffer
int 21h
jc bad_read ; jump if read error
or ax,ax ; check bytes transferred
jz file_end ; jump if end of file
.
.
.
mov ah,40h ; sequential write to
mov bx,handle2 ; output file
mov cx,recsize
mov dx,offset buffer
int 21h
jc bad_write ; jump if write error
cmp ax,recsize ; whole record written?
jne disk_full ; jump if disk is full
.
.
.
jmp next ; process next record
.
file_end: . ; reached end of input
.
mov ah,3eh ; close input file
mov bx,handle1
int 21h
.
.
.
mov ah,3eh ; close output file
mov bx,handle2
int 21h
.
.
.
mov ax,4c00h ; exit with return
int 21h ; code of zero
.
.
.
fname1 db 'OLDFILE.DAT',0 ; name of input file
fname2 db 'NEWFILE.DAT',0 ; name of output file
handle1 dw 0 ; token for input file
handle2 dw 0 ; token for output file
buffer db recsize dup (?) ; buffer for file I/O
Figure 8-7. Skeleton of an assembly-language program that performs sequential processing on an input file and writes the results to an output file using the handle file and record functions. This code assumes that the DS and ES registers have already been set to point to the segment containing the buffers and filenames.