home *** CD-ROM | disk | FTP | other *** search
- ;* ------------------------------------------------------- *
- ;* STRING1.ASM *
- ;* Verbesserte Stringroutinen für Turbo-Pascal 4.0 und 5.0 *
- ;* (c) 1989 Norbert Juffa & TOOLBOX *
- ;* ------------------------------------------------------- *
- CODE SEGMENT BYTE PUBLIC 'CODE'
- ASSUME CS:CODE
-
- PUBLIC Pos, Delete, Insert, Instr
-
- ;* ------------------------------------------------------- *
- ;* FUNCTION Pos (SuchStr, Str2: STRING): BYTE; *
- ;* *
- ;* Pos sucht "Suchstr" in Str2 und gibt die Position des *
- ;* ersten Zeichens zurück, ab dem Suchstr komplett in Str2 *
- ;* enthalten ist. Sonst liefert die Funktion den Wert 0. *
- ;* *
- ;* Algorithmus: Zuerst wird überprüft, ob die Länge von *
- ;* "SuchStr" größer als die von Str2 ist. In diesem Fall *
- ;* kann SuchStr natürlich nicht in Str2 vorkommen und die *
- ;* Funktion liefert 0. Sonst wird berechnet, wieviele Zei- *
- ;* chen von Str2 bei der Suche berücksichtigt werden müs- *
- ;* sen. Daraufhin wird eine Schleife ausgeführt, in der *
- ;* als erstes das erste Zeichen von SuchStr in Str2 gesucht*
- ;* wird. Wird dieses nicht gefunden, so kommt SuchStr mit *
- ;* Sicherheit nicht in Str2 vor. Ansonsten müssen noch die *
- ;* weiteren Zeichen verglichen und bei Mißerfolg die *
- ;* Schleife erneut ausgeführt werden, bis das Ende von Str2*
- ;* erreicht ist. *
- ;* ------------------------------------------------------- *
-
- Pos PROC FAR
- CLD ; Autoinkrement
- PUSH BP ; TP-Framepointer sichern
- MOV BP, SP ; neuer Framepointer für
- ; Zugriff auf Parameter
- PUSH DS ; TP-Datensegment sichern
- LES DI, [BP+6] ; Adresse von Str2
- LDS SI, [BP+10] ; Adresse von SuchStr
- LODSW ; AL = Länge SuchStr,
- ; AH = 1. Zeich. v. SuchStr
- XOR CH, CH ; initialisiere Ergebnis
- DEC AL ; Länge SuchStr - 1
- MOV CL, ES: [DI] ; Länge Str2
- SUB CL, AL ; Länge Str2 <=
- ; Länge SuchStr - 1 ?
- JBE NichtGefnd ; ja, Str2 zu kurz
- MOV BH, CL ; relevante Länge von
- ; Str2 retten
- INC DI ; zeigt auf 1.Zeich v. Str2
- XCHG AL, AH ; AL = 1. Zeich. SuchStr,
- ; AH = Länge SuchStr
- MOV BP, SI ; Zeiger auf 2. Zeichen
- ; von Suchstr sichern
- Suche: REPNZ SCASB ; suche nach 1. Zeichen von
- ; SuchStr in Str2
- JNZ NichtGefnd ; SuchStr nicht in Str2
- MOV BL, CL ; verbleibende Länge v.Str2
- MOV CL, AH ; Anzahl der noch zu
- ; vergleichenden Zeichen
- MOV DX, DI ; Zeiger auf aktuelles
- ; Zeichen von Str2
- REPZ CMPSB ; vergleiche restl. Zeich.
- ; v. SuchStr mit Str2
- MOV SI, BP ; Zeiger auf 2. Zeichen
- ; von SuchStr
- MOV DI, DX ; Zeiger auf aktuelles
- ; Zeichen von Str2
- MOV CL, BL ; verbleibende Länge v.Str2
- JNZ Suche ; weitersuchen, wenn keine
- ; vollst. Übereinstimmung
- SUB BH, BL ; Pos = Länge Str2 -
- ; verbliebene Länge Str2
- MOV CH, BH ; Pos
- NichtGefnd:MOV AL, CH ; Pos
- XOR AH, AH ; auf Wortbreite erweitern
- POP DS ; Datensegment restaurieren
- POP BP ; Framepointer restaurieren
- RET 8 ; Parameter vom Stack
- Pos ENDP ; und zurück
-
- ;* ------------------------------------------------------- *
- ;* FUNCTION Instr (SuchStr, Str2 : STRING; *
- ;* StartPos : BYTE) : BYTE; *
- ;* *
- ;* Instr sucht Suchstr in Str2 ab der Position StartPos *
- ;* und gibt die Position des ersten Zeichens zurück, ab *
- ;* dem Suchstr komplett in Str2 enthalten ist. Sonst *
- ;* liefert die Funktion den Wert 0. *
- ;* *
- ;* Algorithmus: Zuerst wird überprüft, ob SuchStr leer ist *
- ;* oder ob die Länge von SuchStr größer als die von Str2 *
- ;* ist. In diesem Fall kann SuchStr nicht in Str2 vor- *
- ;* kommen. Hierauf wird ausgerechnet, wieviele Zeichen von *
- ;* Str2 bei der Suche berücksichtigt werden müssen. *
- ;* Daraufhin wird eine Schleife ausgeführt, in der als *
- ;* erstes das erste Zeichen von SuchStr in Str2 gesucht *
- ;* wird. Wird dieses nicht gefunden, so kommt SuchStr mit *
- ;* Sicherheit nicht in Str2 vor. Ansonsten müssen noch die *
- ;* weiteren Zeichen verglichen werden und bei Mißerfolg *
- ;* die Schleife erneut ausgeführt werden, bis das Ende von *
- ;* Str2 erreicht ist. Zum Schluß wird das Ergebnis noch *
- ;* einmal an die durch StartPos verurschte Verschiebung *
- ;* angepaßt. *
- ;* ------------------------------------------------------- *
-
- Instr PROC FAR
- CLD ; Autoinkrement
- PUSH BP ; Framepointer retten
- MOV BP, SP ; neuer Framepointer
- PUSH DS ; Datensegment retten
- LES DI, [BP+8] ; Adresse Str2
- LDS SI, [BP+12] ; Adresse SuchStr
- XOR BX, BX ; initialisieren
- OR BL, [BP+6] ; Startposition
- JZ NoChange ; nichts ändern, wenn 0
- DEC BX ; Startposition
- ; dekrementieren
- NoChange: PUSH BX ; Startposition retten
- LODSW ; AL = Länge SuchStr,
- ; AH = 1. Zeichen SuchStr
- XOR CH, CH ; Ergebnis initialisieren
- SUB AL, 1 ; Länge SuchStr - 1
- JB NotFound1 ; wenn Länge SuchStr-1 < 0,
- ; SuchStr n. gef.
- MOV CL, ES: [DI] ; Länge von Str2
- SUB CL, AL ; Länge Str2 - Länge
- ; SuchStr + 1
- SUB CL, BL ; zu durchsuchende Länge
- ; von Str2
- JBE NotFound1 ; wenn Str2 kürzer
- ; als SuchStr, fertig
- INC DI ; 1. Zeichen von Str2
- ADD DI, BX ; Zeichen bei StartPos
- ; in Str2
- MOV BH, CL ; Länge Str2 retten
- XCHG AL, AH ; AL = 1. Zeichen SuchStr,
- ; AH = Länge SuchStr
- MOV BP, SI ; Zeiger auf 2. Zeichen
- ; SuchStr retten
- Suche1: REPNZ SCASB ; Suche 1. Zeichen von
- ; SuchStr in Str2
- JNZ NotFound1 ; nicht gefunden, also
- ; SuchStr nicht in Str2
- MOV BL, CL ; verbleibende Länge
- ; von Str2 retten
- MOV CL, AH ; Anzahl noch zu
- ; vergleichender Zeichen
- MOV DX, DI ; Zeiger auf aktuelles
- ; Zeichen von Str2 retten
- REPZ CMPSB ; vergl. restl. Zeichen
- ; von SuchStr und Str2
- MOV SI, BP ; Zeiger auf 2. Zeichen
- ; von SuchStr
- MOV DI, DX ; Zeiger auf aktuelles
- ; Zeichen von Str 2
- MOV CL, BL ; verbleibende Länge
- ; von Str2
- JNZ Suche1 ; weitersuchen, wenn
- ; SuchStr nicht gefunden
- SUB BH, BL ; Offset = Länge Str2 -
- ; verbliebene Länge Str2
- MOV CH, BH ; Offset
- POP BX ; Startposition vom Stack
- SUB SP, 2 ; Stackpointer korrigieren
- ADD CH, BL ; Pos = Startpos + Offset
- NotFound1: MOV AL, CH ; Pos
- XOR AH, AH ; auf Wortbreite erweitern
- ADD SP, 2 ; gerettete Startposition
- ; vom Stack entfernen
- POP DS ; Datensegment restaurieren
- POP BP ; Framepointer restaurieren
- RET 10 ; Parameter vom Stack
- Instr ENDP ; und zurück
-
- ;* ------------------------------------------------------- *
- ;* PROCEDURE Delete (VAR St : STRING; *
- ;* Startposition, Anzahl : INTEGER) *
- ;* *
- ;* Delete löscht ab der Startposition Anzahl Zeichen aus *
- ;* dem String. *
- ;* *
- ;* Algorithmus: Allgemein werden die Zeichen des Strings, *
- ;* die hinter dem letzten gelöschten Zeichen stehen, auf *
- ;* die Startposition verschoben. Als erstes wird überprüft,*
- ;* ob die Startposition < 1 ist. Ist dies der Fall, so *
- ;* wird Startposition auf 1 gesetzt und die Anzahl ent- *
- ;* sprechend korrigiert. Dann wird überprüft, ob die *
- ;* Startposition vielleicht hinter dem Stringende liegt. *
- ;* Ist dies der Fall, so bleibt der String unverändert. *
- ;* Nun wird die Anzahl der Zeichen berechnet, die zwischen *
- ;* dem letzten gelöschten Zeichen und dem Stringende *
- ;* liegen. Diese Zeichen müssen verschoben werden. Ist *
- ;* diese Anzahl <= 0, weil bis zum Stringende (bzw. *
- ;* darüber hinaus) gelöscht wird, so ergibt sich die neue *
- ;* Länge des Strings zu Startposition-1. Ansonsten müssen *
- ;* Zeichen verschoben werden und die neue Länge ergibt sich
- ;* aus der alten Länge abzüglich der gelöschten Zeichen. *
- ;* ------------------------------------------------------- *
-
- Delete PROC FAR
- PUSH DS ; Datensegment retten
- MOV BX, SP ; neuer Framepointer
- LES CX, SS:[BX+6] ; CX = Anzahl,
- ; ES = Startposition
- MOV AX, ES ; Startposition
- DEC AX ; Startposition - 1
- CWD ; DX = $FFFF wenn AX < 0
- ; (sonst DX = 0)
- AND DX, AX ; Startposition - 1
- SUB AX, DX ; 0 (sonst Startpos. - 1)
- ; = neue Startpos. - 1
- ADD DX, CX ; Startpos. - 1 + Anz.
- ; (sonst Anz.) = neu. Anz.
- JLE Ende ; Abbruch, wenn Anzahl <= 0
- LDS SI, SS:[BX+10]; Adresse des Strings
- MOV CL, [SI] ; Länge des Strings
- XOR CH, CH ; Stringlänge auf Wort
- ; erweitern
- SUB CX, AX ; Länge - Startposition + 1
- JLE Ende ; Abbruch, wenn <= 0
- ; (Startposition > Länge)
- SUB CX, DX ; Länge-Anzahl-Startpos.+1
- ; = Anz. versch. Zeich.
- JG Weiter ; weiter, wenn Zeichen
- ; zu verschieben
- MOV [SI], AL ; neue Länge des Strings
- ; = Startposition - 1
- JMP Short Ende ; fertig
- Weiter: MOV DI, DS ; beide Segmente
- MOV ES, DI ; zeigen auf den String
- SUB [SI], DL ; neue Länge = alte Länge
- ; - Anz. gelösch. Zei.
- ADD SI, AX ; Zeichen an
- INC SI ; der Startposition
- MOV DI, SI ; wird Ziel Verschiebung
- ADD SI, DX ; Zeichen hinter dem
- ; Letzten zu löschenden
- CLD ; Autoinkrement
- SHR CX, 1 ; ungerade Anzahl von
- ; Zeichen verschieben ?
- JNC Wort ; nein, alles wortweise
- MOVSB ; ja, erst ein Byte einzeln
- ; verschieben
- Wort: REP MOVSW ; Rest wortweise schieben
- Ende: POP DS ; Datensegment restaurieren
- RET 8 ; Parameter vom Stack
- Delete ENDP ; und zurück
-
- ;* ------------------------------------------------------- *
- ;* PROCEDURE Insert (Quelle : STRING; VAR Ziel : STRING; *
- ;* MaxLen, StartPos: INTEGER); *
- ;* *
- ;* Insert fügt den String Quelle in den String Ziel ab der *
- ;* Position StartPos ein, wobei die maximale Länge Maxlen *
- ;* von Ziel nicht überschritten werden darf. *
- ;* *
- ;* Algorithmus: Allgemein werden die Zeichen in Ziel hin- *
- ;* ter StartPos nach hinten verschoben und in die ent- *
- ;* stehende Lücke wird Quelle hineinkopiert. Als erstes *
- ;* wird überprüft, ob die Startposition kleiner 1 ist. In *
- ;* diesem Fall wird sie auf 1 gesetzt. Ist die Start- *
- ;* position größer als die Länge von Ziel, so wird als *
- ;* Startposition die Länge von Ziel eingetragen (Insert *
- ;* wirkt also dann wie Concat). Überschreitet die Summe *
- ;* der Startposition und der Länge von Quelle die Maximal- *
- ;* länge von Ziel, so muß keine Lücke geschaffen werden, *
- ;* da die Zeichen aus Ziel hinter der Startposition *
- ;* 'herausfallen'. Zusätzlich muß die Länge von Quelle an- *
- ;* gepaßt werden, da nicht alle Zeichen in Ziel eingefügt *
- ;* werden können. Ansonsten wird errechnet, wieviele Zei- *
- ;* chen zu verschieben sind, *
- ;* um die Lücke zu erzeugen. Anschließend wird diese er- *
- ;* zeugt. Zum Schluß wird die errechnete Anzahl von Zei- *
- ;* chen von Quelle ab der Startposition einkopiert. *
- ;* ------------------------------------------------------- *
-
- Insert PROC FAR
- PUSH BP ; Framepointer retten
- MOV BP, SP ; neuer Framepointer
- PUSH DS ; Datensegment retten
- LDS SI, [BP+14] ; Adresse von Quelle
- XOR CX, CX ; höherwertiges Byte
- ; löschen
- OR CL, [SI] ; Länge von Quelle
- JZ Ende2 ; wenn Quelle leer
- LES DX, [BP+6] ; DX=StartPos,
- ; ES=Maximallänge von Ziel
- MOV AX, ES ; Maximallänge von Ziel
- LES DI, [BP+10] ; Adresse von Ziel
- MOV BH, CH ; höherwertiges Byte der
- ; Länge löschen
- MOV BL, ES:[DI] ; Länge von Ziel
- DEC DX ; StartPos - 1
- JG GroesserNul ; StartPos - 1 > 0 ?
- XOR DX, DX ; nein, setze StartPos-1=0
- ; (StartPos = 1)
- GroesserNul:CMP DX, BX ; StartPos - 1 >=
- ; Länge von Ziel ?
- JL KeinConcat ; nein, echtes Insert
- MOV DX, BX ; StartPos - 1 =
- ; Länge von Ziel
- KeinConcat:MOV BP, AX ; Maximallänge von Ziel
- SUB BP, DX ; (Maximallänge Ziel -
- ; StartPos + 1) <= 0 ?
- JLE Ende2 ; ja, Einf. unmöglich, da
- ; Maximallänge erreicht
- CLD ; Autoinkrement
- SUB BP, CX ; Maximallänge Ziel -
- ; StartPos-Länge Quelle+1
- JG Weiter2 ; paßt Quelle komplett
- ; innerhalb der MaxLen ?
- ADD CX, BP ; Länge von Quelle anpassen
- STOSB ; neue Länge von Ziel
- ; ist Maximallänge
- ADD DI, DX ; nach diesem Zeichen wird
- ; Quelle eingefügt
- JMP Short Einkopiern ; füge Quelle ein
- Weiter2: MOV DX, CX ; Länge von Quelle retten
- ADD CX, BX ; neue Lnge Ziel = alte
- ; Länge Ziel + Länge Quelle
- SUB CX, AX ; neue Länge Ziel -
- ; Maximallänge von Ziel
- JL Luecke ; neue Länge<Maximallänge ?
- XOR CX, CX ; nein, neue Länge Ziel -
- ; Maximallänge = 0
- Luecke: ADD AX, CX ; neue Länge Ziel
- STOSB ; abspeichern
- DEC DI ; correct pointer
- ADD CX, BP ; new targetlength -
- ; objectlength - pos + 1
- ADD DI, AX ; dieses Zeichen wird das
- ; letzte in Ziel
- MOV AX, SI ; Offset der Adresse von
- ; Ziel retten
- MOV SI, DI ; berechne
- SUB SI, DX ; Ende der Lücke
- MOV BP, DS ; Segment der Adresse
- ; von Quelle retten
- MOV BX, ES ; beide Segmente
- MOV DS, BX ; adressieren Ziel
- STD ; Autodekrement
- REP MOVSB ; Lücke erzeugen
- MOV DI, SI ; Quelle wird nach diesem
- ; Zeichen eingefügt
- MOV CX, DX ; Länge von Quelle
- MOV SI, AX ; Offset der Adresse
- MOV DS, BP ; Segment der Adresse
- ; ... von Quelle
- INC DI ; Quelle wird ab hier in
- ; Ziel eingefügt
- CLD ; Autoinkrement
- Einkopiern:INC SI ; 1. Zeichen von Quelle
- SHR CX, 1 ; Anz. der zu verschieben-
- ; den Zeichen ungerade ?
- JNC Wort2 ; nein, alles wortweise
- MOVSB ; ja, ein Byte einzeln
- ; verschieben
- Wort2: REP MOVSW ; Rest wortweise schieben
- Ende2: POP DS ; Datensegment restaurieren
- POP BP ; Framepointer restaurieren
- RET 12 ; Parameter vom Stack
- Insert ENDP ; und zurück
-
- CODE ENDS
- END
- ;* ------------------------------------------------------- *
- ;* Ende von STRING1.ASM *