|
Table of Content | |
| CHAPTER FIFTEEN: STRINGS AND CHARACTER SETS (Part 7) |
| 15.7 -
Sample Programs 15.7.1 - Find.asm 15.7.2 - StrDemo.asm 15.7.3 - Fcmp.asm |
| 15.7 Sample Programs |
In this section there are three sample programs. The first
searches through a file for a particular string and displays the line numbers of any lines
containing that string. This program demonstrates the use of the strstr
function (among other things). The second program is a demo program that uses several of
the string functions available in the UCR Standard Library's string package. The third
program demonstrates how to use the 80x86 cmps instruction to compare the
data in two files. These programs (find.asm
strdemo.asm
and fcmp.asm) are available on
the companion CD-ROM.
; Find.asm
;
; This program opens a file specified on the command line and searches for
; a string (also specified on the command line).
;
; Program Usage:
;
; find "string" filename
.xlist
include stdlib.a
includelib stdlib.lib
.list
wp textequ <word ptr>
dseg segment para public 'data'
StrPtr dword ?
FileName dword ?
LineCnt dword ?
FVar filevar {}
InputLine byte 1024 dup (?)
dseg ends
cseg segment para public 'code'
assume cs:cseg
ds:dseg
; Readln- This procedure reads a line of text from the input
; file and buffers it up in the "InputLine" array.
ReadLn proc
push es
push ax
push di
push bx
lesi FVar ;Read from our file.
mov bx
0 ;Index into InputLine.
ReadLp: fgetc ;Get next char from file.
jc EndRead ;Quit on EOF
cmp al
cr ;Ignore carriage returns.
je ReadLp
cmp al
lf ;End of line on line feed.
je EndRead
mov InputLine[bx]
al
inc bx
jmp ReadLp
; If we hit the end of a line or the end of the file
; zero-terminate the string.
EndRead: mov InputLine[bx]
0
pop bx
pop di
pop ax
pop es
ret
ReadLn endp
; The following main program extracts the search string and the
; filename from the command line
opens the file
and then searches
; for the string in that file.
Main proc
mov ax
dseg
mov ds
ax
mov es
ax
meminit
argc
cmp cx
2
je GoodArgs
print
byte "Usage: find 'string' filename"
cr
lf
0
jmp Quit
GoodArgs: mov ax
1 ;Get the string to search for
argv ; off the command line.
mov wp StrPtr
di
mov wp StrPtr+2
es
mov ax
2 ;Get the filename from the
argv ; command line.
mov wp Filename
di
mov wp Filename+2
es
; Open the input file for reading
mov ax
0 ;Open for read.
mov si
wp FileName
mov dx
wp FileName+2
lesi Fvar
fopen
jc BadOpen
; Okay
start searching for the string in the file.
mov wp LineCnt
0
mov wp LineCnt+2
0
SearchLp: call ReadLn
jc AtEOF
; Bump the line number up by one. Note that this is 8086 code
; so we have to use extended precision arithmetic to do a 32-bit
; add. LineCnt is a 32-bit variable because some files have more
; that 65
536 lines.
add wp LineCnt
1
adc wp LineCnt+2
0
; Search for the user-specified string on the current line.
lesi InputLine
mov dx
wp StrPtr+2
mov si
wp StrPtr
strstr
jc SearchLp ;Jump if not found.
; Print an appropriate message if we found the string.
printf
byte "Found '%^s' at line %ld\n"
0
dword StrPtr
LineCnt
jmp SearchLp
; Close the file when we're done.
AtEOF: lesi FVar
fclose
jmp Quit
BadOpen: printf
byte "Error attempting to open %^s\n"
cr
lf
0
dword FileName
Quit: ExitPgm ;DOS macro to quit program.
Main endp
cseg ends
sseg segment para stack 'stack'
stk db 1024 dup ("stack ")
sseg ends
zzzzzzseg segment para public 'zzzzzz'
LastBytes db 16 dup (?)
zzzzzzseg ends
end Main
This short demo program just shows off how to use several of the string routines found in the UCR Standard Library strings package.
; StrDemo.asm- Demonstration of some of the various UCR Standard Library
; string routines.
include stdlib.a
includelib stdlib.lib
dseg segment para public 'data'
MemAvail dw ?
String byte 256 dup (0)
dseg ends
cseg segment para public 'code'
assume cs:cseg
ds:dseg
Main proc
mov ax
seg dseg ;Set up the segment registers
mov ds
ax
mov es
ax
MemInit
mov MemAvail
cx
printf
db "There are %x paragraphs of memory available."
db cr
lf
lf
0
dd MemAvail
; Demonstration of StrTrim:
print
db "Testing strtrim on 'Hello there '"
cr
lf
0
strdupl
HelloThere1 db "Hello there "
0
strtrim
mov al
"'"
putc
puts
putc
putcr
free
;Demonstration of StrTrimm:
print
db "Testing strtrimm on 'Hello there '"
cr
lf
0
lesi HelloThere1
strtrimm
mov al
"'"
putc
puts
putc
putcr
free
; Demonstration of StrBdel
print
db "Testing strbdel on ' Hello there '"
cr
lf
0
strdupl
HelloThere3 db " Hello there "
0
strbdel
mov al
"'"
putc
puts
putc
putcr
free
; Demonstration of StrBdelm
print
db "Testing strbdelm on ' Hello there '"
cr
lf
0
lesi HelloThere3
strbdelm
mov al
"'"
putc
puts
putc
putcr
free
; Demonstrate StrCpyl:
ldxi string
strcpyl
byte "Copy this string to the 'String' variable"
0
printf
byte "STRING = '%s'"
cr
lf
0
dword String
; Demonstrate StrCatl:
lesi String
strcatl
byte ". Put at end of 'String'"
0
printf
byte "STRING = "
'"%s"'
cr
lf
0
dword String
; Demonstrate StrChr:
lesi String
mov al
"'"
strchr
print
byte "StrChr: First occurrence of "
'"'
"'"
byte '" found at position '
0
mov ax
cx
puti
putcr
; Demonstrate StrStrl:
lesi String
strstrl
byte "String"
0
print
byte 'StrStr: First occurrence of "String" found at position '
0
mov ax
cx
puti
putcr
; Demo of StrSet
lesi String
mov al
'*'
strset
printf
byte "Strset: '%s'"
cr
lf
0
dword String
; Demo of strlen
lesi String
strlen
print
byte "String length = "
0
puti
putcr
Quit: mov ah
4ch
int 21h
Main endp
cseg ends
; Allocate a reasonable amount of space for the stack (2k).
sseg segment para stack 'stack'
stk db 256 dup ("stack ")
sseg ends
; zzzzzzseg must be the last segment that gets loaded into memory!
zzzzzzseg segment para public 'zzzzzz'
LastBytes db 16 dup (?)
heap db 1024 dup (?)
zzzzzzseg ends
end Main
This is a file comparison program. It demonstrates the use of the 80x86 cmps instruction (as well as blocked I/O under DOS).
; FCMP.ASM- A file comparison program that demonstrates the use
; of the 80x86 string instructions.
.xlist
include stdlib.a
includelib stdlib.lib
.list
dseg segment para public 'data'
Name1 dword ? ;Ptr to filename #1
Name2 dword ? ;Ptr to filename #2
Handle1 word ? ;File handle for file #1
Handle2 word ? ;File handle for file #2
LineCnt word 0 ;# of lines in the file.
Buffer1 db 256 dup (0) ;Block of data from file 1
Buffer2 db 256 dup (0) ;Block of data from file 2
dseg ends
wp equ <word ptr>
cseg segment para public 'code'
assume cs:cseg
ds:dseg
; Error- Prints a DOS error message depending upon the error type.
Error proc near
cmp ax
2
jne NotFNF
print
db "File not found"
0
jmp ErrorDone
NotFNF: cmp ax
4
jne NotTMF
print
db "Too many open files"
0
jmp ErrorDone
NotTMF: cmp ax
5
jne NotAD
print
db "Access denied"
0
jmp ErrorDone
NotAD: cmp ax
12
jne NotIA
print
db "Invalid access"
0
jmp ErrorDone
NotIA:
ErrorDone: putcr
ret
Error endp
; Okay
here's the main program. It opens two files
compares them
and
; complains if they're different.
Main proc
mov ax
seg dseg ;Set up the segment registers
mov ds
ax
mov es
ax
meminit
; File comparison routine. First
open the two source files.
argc
cmp cx
2 ;Do we have two filenames?
je GotTwoNames
print
db "Usage: fcmp file1 file2"
cr
lf
0
jmp Quit
GotTwoNames: mov ax
1 ;Get first file name
argv
mov wp Name1
di
mov wp Name1+2
es
; Open the files by calling DOS.
mov ax
3d00h ;Open for reading
lds dx
Name1
int 21h
jnc GoodOpen1
printf
db "Error opening %^s:"
0
dd Name1
call Error
jmp Quit
GoodOpen1: mov dx
dseg
mov ds
dx
mov Handle1
ax
mov ax
2 ;Get second file name
argv
mov wp Name2
di
mov wp Name2+2
es
mov ax
3d00h ;Open for reading
lds dx
Name2
int 21h
jnc GoodOpen2
printf
db "Error opening %^s:"
0
dd Name2
call Error
jmp Quit
GoodOpen2: mov dx
dseg
mov ds
dx
mov Handle2
ax
; Read the data from the files using blocked I/O
; and compare it.
mov LineCnt
1
CmpLoop: mov bx
Handle1 ;Read 256 bytes from
mov cx
256 ; the first file into
lea dx
Buffer1 ; Buffer1.
mov ah
3fh
int 21h
jc FileError
cmp ax
256 ;Leave if at EOF.
jne EndOfFile
mov bx
Handle2 ;Read 256 bytes from
mov cx
256 ; the second file into
lea dx
Buffer2 ; Buffer2
mov ah
3fh
int 21h
jc FileError
cmp ax
256 ;If we didn't read 256 bytes
jne BadLen ; the files are different.
; Okay
we've just read 256 bytes from each file
compare the buffers
; to see if the data is the same in both files.
mov ax
dseg
mov ds
ax
mov es
ax
mov cx
256
lea di
Buffer1
lea si
Buffer2
cld
repe cmpsb
jne BadCmp
jmp CmpLoop
FileError: print
db "Error reading files: "
0
call Error
jmp Quit
BadLen: print
db "File lengths were different"
cr
lf
0
BadCmp: print
db 7
"Files were not equal"
cr
lf
0
mov ax
4c01h ;Exit with error.
int 21h
; If we reach the end of the first file
compare any remaining bytes
; in that first file against the remaining bytes in the second file.
EndOfFile: push ax ;Save final length.
mov bx
Handle2
mov cx
256
lea dx
Buffer2
mov ah
3fh
int 21h
jc BadCmp
pop bx ;Retrieve file1's length.
cmp ax
bx ;See if file2 matches it.
jne BadLen
mov cx
ax ;Compare the remaining
mov ax
dseg ; bytes down here.
mov ds
ax
mov es
ax
lea di
Buffer2
lea si
Buffer1
repe cmpsb
jne BadCmp
Quit: mov ax
4c00h ;Set Exit code to okay.
int 21h
Main endp
cseg ends
; Allocate a reasonable amount of space for the stack (2k).
sseg segment para stack 'stack'
stk db 256 dup ("stack ")
sseg ends
; zzzzzzseg must be the last segment that gets loaded into memory!
zzzzzzseg segment para public 'zzzzzz'
LastBytes db 16 dup (?)
zzzzzzseg ends
end Main
Chapter Fifteen: Strings And
Character Sets (Part 7)
28 SEP 1996