home *** CD-ROM | disk | FTP | other *** search
- {═════════════════════════════ FIND.PAS ═════════════════════════════}
- { Usage: Find (From Editor, just Run) }
- {═════════════════════════════ FIND.PAS ═════════════════════════════}
-
- {- This demonstration illustrates the advantage of using assembly }
- {- language to improve execution speed of time consuming operations. }
- {- Searches about 30,000 bytes of memory for the string FindString }
- {- and repeats 10 times. On my 8MHz 8086 based machine this takes }
- {- 0.7 seconds in assembly language and about 10 times that long in }
- {- Pascal. You can dramatically improve operations on large text }
- {- files by using BlockRead (into a Buffer), Find(BufPtr,256,CrLf) }
- {- (to find line ends), and Move (into a standard String variable) }
- {- in place of repeated calls to ReadLn. }
-
-
- {═══════════════════════════════ Find ═══════════════════════════════}
- { Search memory (case sensitive) for string FindStr. Return number }
- { of characters skipped to find a match, or SearchLimit if no match }
- { Checks entire FindStr even if end of FindStr is beyond SearchLimit }
- { Thus: Find(StartAddr,1,FindStr)=0 only if FindStr is at StartAddr }
- {═══════════════════════════════ Find ═══════════════════════════════}
- FUNCTION Find( VAR StartAddr; SearchLimit:WORD; FindStr:STRING ): WORD;
- BEGIN
- ASSEMBLE
- ;- NOTE that the [Bp] specification required to reference parameters
- ;- and local variables is supplied automatically by TP&Asm.
- ;- You may code the [Bp]'s explicitly if you prefer ( StartAddr[Bp] ),
- ;- and you may disable presumptions for "WYSIWYG" assembly.
- ;- Remember - TP&Asm knows how to find all your Pascal variables because
- ;- it assembles during the compile step!
-
- Cld ; Set forward direction for Lodsb/w and Cmpsb
- Mov Cx,SearchLimit ; Maximum bytes to search
- Mov Dx,Cx ; Save in Dx
- Les Di,StartAddr ; point Es:[Di] to StartAddr
-
- Lea Si,FindStr ; NOTE: String Value is located in Stack Segment
- Lodsw ; Al <-- Ss:[Si], Ah <-- Ss:[Si+1], Si <-- Si+2
-
- ;- Lodsw normally loads from Ds:[Si], however TP&Asm correctly presumes
- ;- and supplies the Ss override necessary to obtain access to FindStr.
- ;- You may code the override explicitly if you prefer ( Ss LodsW ),
- ;- and you may disable presumptions for "WYSIWYG" assembly.
-
- Xchg Ah,Al ; Now FindStrLen is in Ah, FindStr[1] is in Al
-
- ScanLoop:
- RepNE Scasb ; Fast Scan Es:[Di] for Al; Di <-- [match]+1
- jNE Finish ; If no match found, return SearchLimit saved in Dx
- Push Cx,Di ; Save Cx & Di in case this 'Find' is premature
- Xor Ch,Ch ; Clear Ch
- Mov Cl,Ah ; Load FindStrLen
- Dec Cl ; FindStr[1] has already been checked
- L1:
- CmpsB ; Compare Ss:[Si] =? Es:[Di], Inc Di, Inc Si
- LoopE L1 ; Repeat while equal, Dec Cx
- Pop Di,Cx ; Restore Cx & Di, Find NEXT occurrance of Al
- jNE ScanLoop ; - Jmp only if exitted LoopE with NE (miscompare)
- Inc Cx ; Arrive here if string found
- Sub Dx,Cx ; Find number of bytes skipped
- Finish:
- Mov Find,Dx ; Put in function result
- END; {Assemble}
- END; {FUNCTION Find}
-
-
- {═════════════════════════════ PasFind ══════════════════════════════}
- { Same as FUNCTION Find but written in Pascal rather than Assembly }
- {═════════════════════════════ PasFind ══════════════════════════════}
- FUNCTION PasFind(VAR StartAddr; SearchLimit:WORD; FindStr:STRING):WORD;
- VAR m,n:WORD;
- FindArray: ARRAY[0..$7FF0] OF CHAR Absolute StartAddr;
- BEGIN
- m := 0;
- FOR n := 0 TO SearchLimit DO BEGIN
- IF FindArray[n] = FindStr[1] THEN BEGIN
- WHILE FindArray[n+m]=FindStr[1+m] DO m:=m+1;
- IF m >= Length(FindStr) THEN BEGIN
- PasFind := n; Exit;
- END; {IF m >= Length(FindStr) THEN }
- m := 0;
- END; {IF FindArray[n] = FindStr[1] THEN }
- END; {FOR n := 0 TO SearchLimit DO }
- PasFind := SearchLimit;
- END; {FUNCTION PasFind}
-
-
- {═════════════════════════════ GetTime ══════════════════════════════}
- { Compatible with Version 4.0 to 5.5 DOS Unit Procedure. }
- {═════════════════════════════ GetTime ══════════════════════════════}
- PROCEDURE GetTime( VAR Hour, Minute, Second, Hundredth: WORD);
- VAR HrMin, SecHn: WORD;
- BEGIN
- Assembly
- Mov Ah,2Ch
- Int 21h ; Get System time into Cx:Dx
- Xor Ah,Ah
- Mov Al,Ch ; Now Ax = System hour
-
- ;- Use the parameter pointers to store VAR results in assembly language ..
- Les Di,Hour ; Es:[Di] points to Hour
- Es Mov [Di],Ax ; Save Hour value in Es:[Di]
-
- ;- .. or save into local variables ..
- Mov HrMin,Cx
- Mov SecHn,Dx
- End; {Assembly}
-
- {- .. and let the compiler do the work: -}
- Minute := Lo(HrMin);
- Second := Hi(SecHn);
- Hundredth := Lo(SecHn);
- END; {PROCEDURE GetTime}
-
-
- {══════════════════ A couple of Display Functions ═══════════════════}
- TYPE Str2 = STRING[2];
- FUNCTION TwoDgt(N: WORD): Str2; VAR Tmp: Str2;
- BEGIN
- Str(N:2,Tmp); IF N<10 THEN Tmp[1] := '0'; TwoDgt := Tmp;
- END; {FUNCTION TwoDgt}
-
- TYPE Str12 = STRING[12];
- FUNCTION TimeDisplay: Str12;
- VAR Hour, Minute, Second, Hundredth: WORD;
- BEGIN
- GetTime( Hour, Minute, Second, Hundredth );
- TimeDisplay := TwoDgt(Hour) +':' +TwoDgt(Minute) +':' +TwoDgt(Second)
- +'.' +TwoDgt(Hundredth);
- END; {TimeDisplay}
-
-
- {════════════════════════════ WaitForKey ════════════════════════════}
- PROCEDURE WaitForKey; {- Assembly/Inline Directive -}
- Assembly
- Mov Ah,0
- Int 16h
- END; {Assembly WaitForKey}
-
-
- VAR
- BigArray: ARRAY[1..30000] OF BYTE;
- FindString: String[80];
- FindLoc,n : WORD;
-
- CONST
- MaxSearch = 32000;
- Repeats = 10;
-
- BEGIN
-
- FillChar(BigArray,SizeOf(BigArray),' ');
- FindString := 'Find This String';
-
-
- WRITELN(#13#10'Press a key to begin Assembly Find Test:'#13#10);
- WaitForKey;
- WRITELN('Started search at ',TimeDisplay);
-
- FOR n := 1 TO Repeats DO FindLoc := Find(BigArray,MaxSearch,FindString);
-
- IF FindLoc = MaxSearch THEN WRITE('String NOT FOUND!')
- ELSE WRITE('Found at ',FindLoc);
- WRITELN(' Should Find at: ', 1+ SizeOf(BigArray));
- WRITELN('Finished search at ',TimeDisplay,#13#10);
-
-
- WRITELN('Press a key to begin Pascal Find Test:'#13#10);
- WaitForKey;
- WRITELN('Started search at ',TimeDisplay);
-
- FOR n := 1 TO Repeats DO FindLoc := PasFind(BigArray,MaxSearch,FindString);
-
- IF FindLoc = MaxSearch THEN WRITE('String NOT FOUND!')
- ELSE WRITE('Found at ',FindLoc);
- WRITELN(' Should Find at: ', 1+ SizeOf(BigArray));
- WRITELN('Finished search at ',TimeDisplay,#13#10);
-
-
- WRITELN('Press a key to exit'#13#10);
- WaitForKey;
-
- END.