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
; 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
; 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