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