The Art of
ASSEMBLY LANGUAGE PROGRAMMING

Chapter Thirteen (Part 6)

Table of Content

Chapter Thirteen (Part 8) 

CHAPTER THIRTEEN:
MS-DOS, PC-BIOS AND FILE I/O (Part 7)
13.3.9 - File I/O Examples
13.3.9.1 - Example #1: A Hex Dump Utility
13.3.9.2 - Example #2: Upper Case Conversion

13.3.9 File I/O Examples

Of course, one of the main reasons for making calls to DOS is to manipulate files on a mass storage device. The following examples demonstrate some uses of character I/O using DOS.

13.3.9.1 Example #1: A Hex Dump Utility

This program dumps a file in hexadecimal format. The filename must be hard coded into the file (see "Accessing Command Line Parameters" later in this chapter).

                include         stdlib.a
                includelib      stdlib.lib
cseg            segment         byte public 'CODE'
                assume          cs:cseg, ds:dseg, es:dseg, ss:sseg

; Note CR and LF are already defined in STDLIB.A

tab             equ     09h

MainPgm         proc    far

; Properly set up the segment registers:

                mov     ax, seg dseg
                mov     es, ax                  ;Leave DS pointing at PSP

;---------------------------------------------------------------
;
; First, parse the command line to get the filename:

                mov     si, 81h                 ;Pointer to command line
                lea     di, FileName            ;Pointer to FileName buffer
SkipDelimiters:
                lodsb                           ;Get next character
                call    TestDelimiter
                je      SkipDelimiters

; Assume that what follows is an actual filename

                dec     si                      ;Point at 1st char of name
GetFName:       lodsb
                cmp     al, 0dh
                je      GotName
                call    TestDelimiter
                je      GotName
                stosb                           ;Save character in file name
                jmp     GetFName

; We're at the end of the filename, so zero-terminate it as 
; required by DOS.

GotName:        mov     byte ptr es:[di], 0
                mov     ax, es                  ;Point DS at DSEG
                mov     ds, ax

; Now process the file

                mov     ah, 3dh
                mov     al, 0                   ;Open file for reading
                lea     dx, Filename            ;File to open
                int     21h
                jnc     GoodOpen
                print
                byte    'Cannot open file, aborting program...',cr,0
                jmp     PgmExit

GoodOpen:       mov     FileHandle, ax          ;Save file handle
                mov     Position, 0             ;Initialize file position
ReadFileLp:     mov     al, byte ptr Position
                and     al, 0Fh                 ;Compute (Position MOD 16)
                jnz     NotNewLn                ;Every 16 bytes start a line
                putcr
                mov     ax, Position            ;Print offset into file
                xchg    al, ah
                puth
                xchg    al, ah
                puth
                print
                byte    ': ',0

NotNewLn:       inc     Position                ;Increment character count
                mov     bx, FileHandle
                mov     cx, 1                   ;Read one byte
                lea     dx, buffer              ;Place to store that byte
                mov     ah, 3Fh                 ;Read operation
                int     21h
                jc      BadRead
                cmp     ax, 1                   ;Reached EOF?
                jnz     AtEOF
                mov     al, Buffer              ;Get the character read and
                puth                            ; print it in hex
                mov     al, ' '                 ;Print a space between values
                putc
                jmp     ReadFileLp

BadRead:                print
                byte    cr, lf
                byte    'Error reading data from file, aborting.'
                byte    cr,lf,0

AtEOF:          mov     bx, FileHandle          ;Close the file
                mov     ah, 3Eh
                int     21h

;---------------------------------------------------------------

PgmExit:        ExitPgm
MainPgm         endp

TestDelimiter   proc    near
                cmp     al, ' '
                je      xit
                cmp     al, ','
                je      xit
                cmp     al, Tab
                je      xit
                cmp     al, ';'
                je      xit
                cmp     al, '='
xit:            ret
TestDelimiter   endp
cseg            ends

dseg            segment byte public 'data'

PSP             word    ?
Filename        byte    64 dup (0)              ;Filename to dump
FileHandle      word    ?
Buffer          byte    ?
Position                word    0

dseg            ends

sseg            segment byte stack 'stack'
stk             word    0ffh dup (?)
sseg            ends

zzzzzzseg       segment para public 'zzzzzz'
LastBytes       byte    16 dup (?)
zzzzzzseg       ends
                end     MainPgm
13.3.9.2 Example #2: Upper Case Conversion

The following program reads one file, converts all the lower case characters to upper case, and writes the data to a second output file.

                include         stdlib.a
                includelib      stdlib.lib
cseg            segment byte public 'CODE'
                assume  cs:cseg, ds:dseg, es:dseg, ss:sseg

MainPgm         proc    far

; Properly set up the segment registers:

                mov     ax, seg dseg
                mov     ds, ax
                mov     es, ax

;----------------------------------------------------------------
;
; Convert UCCONVRT.ASM to uppercase
;
; Open input file:

                mov     ah, 3dh
                mov     al, 0           ;Open file for reading
                lea     dx, Filename    ;File to open
                int     21h
                jnc     GoodOpen
                print
                byte    'Cannot open file, aborting program...',cr,lf,0
                jmp     PgmExit

GoodOpen:       mov     FileHandle1, ax ;Save input file handle

; Open output file:

                mov     ah, 3Ch         ;Create file call
                mov     cx, 0           ;Normal file attributes
                lea     dx, OutFileName ;File to open
                int     21h
                jnc     GoodOpen2
                print
                byte    'Cannot open output file, aborting program...'
                byte    cr,lf,0
                mov     ah, 3eh         ;Close input file
                mov     bx, FileHandle1
                int     21h
                jmp     PgmExit         ;Ignore any error.

GoodOpen2:      mov     FileHandle2, ax ;Save output file handle

ReadFileLp:     mov     bx, FileHandle1
                mov     cx, 1           ;Read one byte
                lea     dx, buffer      ;Place to store that byte
                mov     ah, 3Fh         ;Read operation
                int     21h
                jc      BadRead
                cmp     ax, 1           ;Reached EOF?
                jz      ReadOK
                jmp     AtEOF

ReadOK:         mov     al, Buffer      ;Get the character read and
                cmp     al, 'a'         ; convert it to upper case
                jb      NotLower
                cmp     al, 'z'
                ja      NotLower
                and     al, 5fh         ;Set Bit #5 to zero.
NotLower:       mov     Buffer, al

; Now write the data to the output file

                mov     bx, FileHandle2
                mov     cx, 1           ;Read one byte
                lea     dx, buffer      ;Place to store that byte
                mov     ah, 40h         ;Write operation
                int     21h
                jc      BadWrite
                cmp     ax, 1           ;Make sure disk isn't full
                jz      ReadFileLp

BadWrite:               print
                byte    cr, lf
                byte    'Error writing data to file, aborting operation'
                byte    cr,lf,0
                jmp     short AtEOF

BadRead:                print
                byte    cr, lf
                byte    'Error reading data from file, aborting '
                byte    'operation',cr,lf,0

AtEOF:          mov     bx, FileHandle1 ;Close the file
                mov     ah, 3Eh
                int     21h
                mov     bx, FileHandle2
                mov     ah, 3eh
                int     21h

;----------------------------------------------------------------

PgmExit:        ExitPgm
MainPgm         endp
cseg            ends

dseg            segment byte public 'data'

Filename        byte    'ucconvrt.asm',0        ;Filename to convert
OutFileName     byte    'output.txt',0          ;Output filename
FileHandle1     word    ?
FileHandle2     word    ?
Buffer          byte    ?
Position        word    0

dseg            ends

sseg            segment byte stack 'stack'
stk             word    0ffh dup (?)
sseg            ends

zzzzzzseg       segment para public 'zzzzzz'
LastBytes       byte    16 dup (?)
zzzzzzseg       ends
                end     MainPgm

Chapter Thirteen (Part 6)

Table of Content

Chapter Thirteen (Part 8) 

Chapter Thirteen: MS-DOS, PC-BIOS and File I/O (Part 7)
28 SEP 1996