home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / 1989 / 11 / grdlagen / string1.asm next >
Encoding:
Assembly Source File  |  1989-07-25  |  19.8 KB  |  369 lines

  1. ;* ------------------------------------------------------- *
  2. ;*                    STRING1.ASM                          *
  3. ;* Verbesserte Stringroutinen für Turbo-Pascal 4.0 und 5.0 *
  4. ;*        (c) 1989  Norbert Juffa  &  TOOLBOX              *
  5. ;* ------------------------------------------------------- *
  6. CODE       SEGMENT BYTE PUBLIC 'CODE'
  7.            ASSUME  CS:CODE
  8.  
  9.            PUBLIC  Pos, Delete, Insert, Instr
  10.  
  11. ;* ------------------------------------------------------- *
  12. ;*  FUNCTION Pos (SuchStr, Str2: STRING): BYTE;            *
  13. ;*                                                         *
  14. ;* Pos sucht "Suchstr" in Str2 und gibt die Position des   *
  15. ;* ersten Zeichens zurück, ab dem Suchstr komplett in Str2 *
  16. ;* enthalten ist. Sonst liefert die Funktion den Wert 0.   *
  17. ;*                                                         *
  18. ;* Algorithmus: Zuerst wird überprüft, ob die Länge von    *
  19. ;* "SuchStr" größer als die von Str2 ist. In diesem Fall   *
  20. ;* kann SuchStr natürlich nicht in Str2 vorkommen und die  *
  21. ;* Funktion liefert 0. Sonst wird berechnet, wieviele Zei- *
  22. ;* chen von Str2 bei der Suche berücksichtigt werden müs-  *
  23. ;* sen. Daraufhin wird eine Schleife ausgeführt, in der    *
  24. ;* als erstes das erste Zeichen von SuchStr in Str2 gesucht*
  25. ;* wird. Wird dieses nicht gefunden, so kommt SuchStr mit  *
  26. ;* Sicherheit nicht in Str2 vor. Ansonsten müssen noch die *
  27. ;* weiteren Zeichen verglichen und bei Mißerfolg die       *
  28. ;* Schleife erneut ausgeführt werden, bis das Ende von Str2*
  29. ;* erreicht ist.                                           *
  30. ;* ------------------------------------------------------- *
  31.  
  32. Pos        PROC    FAR
  33.            CLD                   ; Autoinkrement
  34.            PUSH    BP            ; TP-Framepointer sichern
  35.            MOV     BP, SP        ; neuer Framepointer für
  36.                                  ; Zugriff auf Parameter
  37.            PUSH    DS            ; TP-Datensegment sichern
  38.            LES     DI, [BP+6]    ; Adresse von Str2
  39.            LDS     SI, [BP+10]   ; Adresse von SuchStr
  40.            LODSW                 ; AL = Länge SuchStr,
  41.                                  ; AH = 1. Zeich. v. SuchStr
  42.            XOR     CH, CH        ; initialisiere Ergebnis
  43.            DEC     AL            ; Länge SuchStr - 1
  44.            MOV     CL, ES: [DI]  ; Länge Str2
  45.            SUB     CL, AL        ; Länge Str2 <=
  46.                                  ; Länge SuchStr - 1 ?
  47.            JBE     NichtGefnd    ; ja, Str2 zu kurz
  48.            MOV     BH, CL        ; relevante Länge von
  49.                                  ; Str2 retten
  50.            INC     DI            ; zeigt auf 1.Zeich v. Str2
  51.            XCHG    AL, AH        ; AL = 1. Zeich. SuchStr,
  52.                                  ; AH = Länge SuchStr
  53.            MOV     BP, SI        ; Zeiger auf 2. Zeichen
  54.                                  ; von Suchstr sichern
  55. Suche:     REPNZ   SCASB         ; suche nach 1. Zeichen von
  56.                                  ; SuchStr in Str2
  57.            JNZ     NichtGefnd    ; SuchStr nicht in Str2
  58.            MOV     BL, CL        ; verbleibende Länge v.Str2
  59.            MOV     CL, AH        ; Anzahl der noch zu
  60.                                  ; vergleichenden Zeichen
  61.            MOV     DX, DI        ; Zeiger auf aktuelles
  62.                                  ; Zeichen von Str2
  63.            REPZ    CMPSB         ; vergleiche restl. Zeich.
  64.                                  ; v. SuchStr mit Str2
  65.            MOV     SI, BP        ; Zeiger auf 2. Zeichen
  66.                                  ; von SuchStr
  67.            MOV     DI, DX        ; Zeiger auf aktuelles
  68.                                  ; Zeichen von Str2
  69.            MOV     CL, BL        ; verbleibende Länge v.Str2
  70.            JNZ     Suche         ; weitersuchen, wenn keine
  71.                                  ; vollst. Übereinstimmung
  72.            SUB     BH, BL        ; Pos = Länge Str2 -
  73.                                  ; verbliebene Länge Str2
  74.            MOV     CH, BH        ; Pos
  75. NichtGefnd:MOV     AL, CH        ; Pos
  76.            XOR     AH, AH        ; auf Wortbreite erweitern
  77.            POP     DS            ; Datensegment restaurieren
  78.            POP     BP            ; Framepointer restaurieren
  79.            RET     8             ; Parameter vom Stack
  80. Pos        ENDP                  ; und zurück
  81.  
  82. ;* ------------------------------------------------------- *
  83. ;*  FUNCTION Instr (SuchStr, Str2 : STRING;                *
  84. ;*                       StartPos : BYTE) : BYTE;          *
  85. ;*                                                         *
  86. ;* Instr sucht Suchstr in Str2 ab der Position StartPos    *
  87. ;* und gibt die Position des ersten Zeichens zurück, ab    *
  88. ;* dem Suchstr komplett in Str2 enthalten ist. Sonst       *
  89. ;* liefert die Funktion den Wert 0.                        *
  90. ;*                                                         *
  91. ;* Algorithmus: Zuerst wird überprüft, ob SuchStr leer ist *
  92. ;* oder ob die Länge von SuchStr größer als die von Str2   *
  93. ;* ist. In diesem Fall kann SuchStr nicht in Str2 vor-     *
  94. ;* kommen. Hierauf wird ausgerechnet, wieviele Zeichen von *
  95. ;* Str2 bei der Suche berücksichtigt werden müssen.        *
  96. ;* Daraufhin wird eine Schleife ausgeführt, in der als     *
  97. ;* erstes das erste Zeichen von SuchStr in Str2 gesucht    *
  98. ;* wird. Wird dieses nicht gefunden, so kommt SuchStr mit  *
  99. ;* Sicherheit nicht in Str2 vor. Ansonsten müssen noch die *
  100. ;* weiteren Zeichen verglichen werden und bei Mißerfolg    *
  101. ;* die Schleife erneut ausgeführt werden, bis das Ende von *
  102. ;* Str2 erreicht ist. Zum Schluß wird das Ergebnis noch    *
  103. ;* einmal an die durch StartPos verurschte Verschiebung    *
  104. ;* angepaßt.                                               *
  105. ;* ------------------------------------------------------- *
  106.  
  107. Instr      PROC    FAR
  108.            CLD                   ; Autoinkrement
  109.            PUSH    BP            ; Framepointer retten
  110.            MOV     BP, SP        ; neuer Framepointer
  111.            PUSH    DS            ; Datensegment retten
  112.            LES     DI, [BP+8]    ; Adresse Str2
  113.            LDS     SI, [BP+12]   ; Adresse SuchStr
  114.            XOR     BX, BX        ; initialisieren
  115.            OR      BL, [BP+6]    ; Startposition
  116.            JZ      NoChange      ; nichts ändern, wenn 0
  117.            DEC     BX            ; Startposition
  118.                                  ; dekrementieren
  119. NoChange:  PUSH    BX            ; Startposition retten
  120.            LODSW                 ; AL = Länge SuchStr,
  121.                                  ; AH = 1. Zeichen SuchStr
  122.            XOR     CH, CH        ; Ergebnis initialisieren
  123.            SUB     AL, 1         ; Länge SuchStr - 1
  124.            JB      NotFound1     ; wenn Länge SuchStr-1 < 0,
  125.                                  ; SuchStr n. gef.
  126.            MOV     CL, ES: [DI]  ; Länge von Str2
  127.            SUB     CL, AL        ; Länge Str2 - Länge
  128.                                  ; SuchStr + 1
  129.            SUB     CL, BL        ; zu durchsuchende Länge
  130.                                  ; von Str2
  131.            JBE     NotFound1     ; wenn Str2 kürzer
  132.                                  ; als SuchStr, fertig
  133.            INC     DI            ; 1. Zeichen von Str2
  134.            ADD     DI, BX        ; Zeichen bei StartPos
  135.                                  ; in Str2
  136.            MOV     BH, CL        ; Länge Str2 retten
  137.            XCHG    AL, AH        ; AL = 1. Zeichen SuchStr,
  138.                                  ; AH = Länge SuchStr
  139.            MOV     BP, SI        ; Zeiger auf 2. Zeichen
  140.                                  ; SuchStr retten
  141. Suche1:    REPNZ   SCASB         ; Suche 1. Zeichen von
  142.                                  ; SuchStr in Str2
  143.            JNZ     NotFound1     ; nicht gefunden, also
  144.                                  ; SuchStr nicht in Str2
  145.            MOV     BL, CL        ; verbleibende Länge
  146.                                  ; von Str2 retten
  147.            MOV     CL, AH        ; Anzahl noch zu
  148.                                  ; vergleichender Zeichen
  149.            MOV     DX, DI        ; Zeiger auf aktuelles
  150.                                  ; Zeichen von Str2 retten
  151.            REPZ    CMPSB         ; vergl. restl. Zeichen
  152.                                  ; von SuchStr und Str2
  153.            MOV     SI, BP        ; Zeiger auf 2. Zeichen
  154.                                  ; von SuchStr
  155.            MOV     DI, DX        ; Zeiger auf aktuelles
  156.                                  ; Zeichen von Str 2
  157.            MOV     CL, BL        ; verbleibende Länge
  158.                                  ; von Str2
  159.            JNZ     Suche1        ; weitersuchen, wenn
  160.                                  ; SuchStr nicht gefunden
  161.            SUB     BH, BL        ; Offset = Länge Str2 -
  162.                                  ; verbliebene Länge Str2
  163.            MOV     CH, BH        ; Offset
  164.            POP     BX            ; Startposition vom Stack
  165.            SUB     SP, 2         ; Stackpointer korrigieren
  166.            ADD     CH, BL        ; Pos = Startpos + Offset
  167. NotFound1: MOV     AL, CH        ; Pos
  168.            XOR     AH, AH        ; auf Wortbreite erweitern
  169.            ADD     SP, 2         ; gerettete Startposition
  170.                                  ; vom Stack entfernen
  171.            POP     DS            ; Datensegment restaurieren
  172.            POP     BP            ; Framepointer restaurieren
  173.            RET     10            ; Parameter vom Stack
  174. Instr      ENDP                  ; und zurück
  175.  
  176. ;* ------------------------------------------------------- *
  177. ;*  PROCEDURE Delete (VAR St : STRING;                     *
  178. ;*                    Startposition, Anzahl : INTEGER)     *
  179. ;*                                                         *
  180. ;* Delete löscht ab der Startposition Anzahl Zeichen aus   *
  181. ;* dem String.                                             *
  182. ;*                                                         *
  183. ;* Algorithmus: Allgemein werden die Zeichen des Strings,  *
  184. ;* die hinter dem letzten gelöschten Zeichen stehen, auf   *
  185. ;* die Startposition verschoben. Als erstes wird überprüft,*
  186. ;* ob die Startposition < 1 ist. Ist dies der Fall, so     *
  187. ;* wird Startposition auf 1 gesetzt und die Anzahl ent-    *
  188. ;* sprechend korrigiert. Dann wird überprüft, ob die       *
  189. ;* Startposition vielleicht hinter dem Stringende liegt.   *
  190. ;* Ist dies der Fall, so bleibt der String unverändert.    *
  191. ;* Nun wird die Anzahl der Zeichen berechnet, die zwischen *
  192. ;* dem letzten gelöschten Zeichen und dem Stringende       *
  193. ;* liegen. Diese Zeichen müssen verschoben werden. Ist     *
  194. ;* diese Anzahl <= 0, weil bis zum Stringende (bzw.        *
  195. ;* darüber hinaus) gelöscht wird, so ergibt sich die neue  *
  196. ;* Länge des Strings zu Startposition-1. Ansonsten müssen  *
  197. ;* Zeichen verschoben werden und die neue Länge ergibt sich
  198. ;* aus der alten Länge abzüglich der gelöschten Zeichen.   *
  199. ;* ------------------------------------------------------- *
  200.  
  201. Delete     PROC    FAR
  202.            PUSH    DS            ; Datensegment retten
  203.            MOV     BX, SP        ; neuer Framepointer
  204.            LES     CX, SS:[BX+6] ; CX = Anzahl,
  205.                                  ; ES = Startposition
  206.            MOV     AX, ES        ; Startposition
  207.            DEC     AX            ; Startposition - 1
  208.            CWD                   ; DX = $FFFF wenn AX < 0
  209.                                  ; (sonst DX = 0)
  210.            AND     DX, AX        ; Startposition - 1
  211.            SUB     AX, DX        ; 0 (sonst Startpos. - 1)
  212.                                  ; = neue Startpos. - 1
  213.            ADD     DX, CX        ; Startpos. - 1 + Anz.
  214.                                  ; (sonst Anz.) = neu. Anz.
  215.            JLE     Ende          ; Abbruch, wenn Anzahl <= 0
  216.            LDS     SI, SS:[BX+10]; Adresse des Strings
  217.            MOV     CL, [SI]      ; Länge des Strings
  218.            XOR     CH, CH        ; Stringlänge auf Wort
  219.                                  ; erweitern
  220.            SUB     CX, AX        ; Länge - Startposition + 1
  221.            JLE     Ende          ; Abbruch, wenn <= 0
  222.                                  ; (Startposition > Länge)
  223.            SUB     CX, DX        ; Länge-Anzahl-Startpos.+1
  224.                                  ; = Anz. versch. Zeich.
  225.            JG      Weiter        ; weiter, wenn Zeichen
  226.                                  ; zu verschieben
  227.            MOV     [SI], AL      ; neue Länge des Strings
  228.                                  ; = Startposition - 1
  229.            JMP Short Ende        ; fertig
  230. Weiter:    MOV     DI, DS        ; beide Segmente
  231.            MOV     ES, DI        ; zeigen auf den String
  232.            SUB     [SI], DL      ; neue Länge = alte Länge
  233.                                  ; - Anz. gelösch. Zei.
  234.            ADD     SI, AX        ; Zeichen an
  235.            INC     SI            ;  der Startposition
  236.            MOV     DI, SI        ;   wird Ziel Verschiebung
  237.            ADD     SI, DX        ; Zeichen hinter dem
  238.                                  ; Letzten zu löschenden
  239.            CLD                   ; Autoinkrement
  240.            SHR     CX, 1         ; ungerade Anzahl von
  241.                                  ; Zeichen verschieben ?
  242.            JNC     Wort          ; nein, alles wortweise
  243.            MOVSB                 ; ja, erst ein Byte einzeln
  244.                                  ; verschieben
  245. Wort:      REP     MOVSW         ; Rest wortweise schieben
  246. Ende:      POP     DS            ; Datensegment restaurieren
  247.            RET     8             ; Parameter vom Stack
  248. Delete     ENDP                  ; und zurück
  249.  
  250. ;* ------------------------------------------------------- *
  251. ;*  PROCEDURE Insert (Quelle : STRING; VAR Ziel : STRING;  *
  252. ;*                    MaxLen, StartPos: INTEGER);          *
  253. ;*                                                         *
  254. ;* Insert fügt den String Quelle in den String Ziel ab der *
  255. ;* Position StartPos ein, wobei die maximale Länge Maxlen  *
  256. ;* von Ziel nicht überschritten werden darf.               *
  257. ;*                                                         *
  258. ;* Algorithmus: Allgemein werden die Zeichen in Ziel hin-  *
  259. ;* ter StartPos nach hinten verschoben und in die ent-     *
  260. ;* stehende Lücke wird Quelle hineinkopiert. Als erstes    *
  261. ;* wird überprüft, ob die Startposition kleiner 1 ist. In  *
  262. ;* diesem Fall wird sie auf 1 gesetzt. Ist die Start-      *
  263. ;* position größer als die Länge von Ziel, so wird als     *
  264. ;* Startposition die Länge von Ziel eingetragen (Insert    *
  265. ;* wirkt also dann wie Concat). Überschreitet die Summe    *
  266. ;* der Startposition und der Länge von Quelle die Maximal- *
  267. ;* länge von Ziel, so muß keine Lücke geschaffen werden,   *
  268. ;* da die Zeichen aus Ziel hinter der Startposition        *
  269. ;* 'herausfallen'. Zusätzlich muß die Länge von Quelle an- *
  270. ;* gepaßt werden, da nicht alle Zeichen in Ziel eingefügt  *
  271. ;* werden können. Ansonsten wird errechnet, wieviele Zei-  *
  272. ;* chen zu verschieben sind,                               *
  273. ;* um die Lücke zu erzeugen. Anschließend wird diese er-   *
  274. ;* zeugt. Zum Schluß wird die errechnete Anzahl von Zei-   *
  275. ;* chen von Quelle ab der Startposition einkopiert.        *
  276. ;* ------------------------------------------------------- *
  277.  
  278. Insert     PROC    FAR
  279.            PUSH    BP            ; Framepointer retten
  280.            MOV     BP, SP        ; neuer Framepointer
  281.            PUSH    DS            ; Datensegment retten
  282.            LDS     SI, [BP+14]   ; Adresse von Quelle
  283.            XOR     CX, CX        ; höherwertiges Byte
  284.                                  ; löschen
  285.            OR      CL, [SI]      ; Länge von Quelle
  286.            JZ      Ende2         ; wenn Quelle leer
  287.            LES     DX, [BP+6]    ; DX=StartPos,
  288.                                  ; ES=Maximallänge von Ziel
  289.            MOV     AX, ES        ; Maximallänge von Ziel
  290.            LES     DI, [BP+10]   ; Adresse von Ziel
  291.            MOV     BH, CH        ; höherwertiges Byte der
  292.                                  ; Länge löschen
  293.            MOV     BL, ES:[DI]   ; Länge von Ziel
  294.            DEC     DX            ; StartPos - 1
  295.            JG      GroesserNul   ; StartPos - 1 > 0 ?
  296.            XOR     DX, DX        ; nein, setze StartPos-1=0
  297.                                  ; (StartPos = 1)
  298. GroesserNul:CMP     DX, BX       ; StartPos - 1 >=
  299.                                  ; Länge von Ziel ?
  300.            JL      KeinConcat    ; nein, echtes Insert
  301.            MOV     DX, BX        ; StartPos - 1 =
  302.                                  ; Länge von Ziel
  303. KeinConcat:MOV     BP, AX        ; Maximallänge von Ziel
  304.            SUB     BP, DX        ; (Maximallänge Ziel -
  305.                                  ; StartPos + 1) <= 0 ?
  306.            JLE     Ende2         ; ja, Einf. unmöglich, da
  307.                                  ; Maximallänge erreicht
  308.            CLD                   ; Autoinkrement
  309.            SUB     BP, CX        ; Maximallänge Ziel -
  310.                                  ; StartPos-Länge Quelle+1
  311.            JG      Weiter2       ; paßt Quelle komplett
  312.                                  ; innerhalb der MaxLen ?
  313.            ADD     CX, BP        ; Länge von Quelle anpassen
  314.            STOSB                 ; neue Länge von Ziel
  315.                                  ; ist Maximallänge
  316.            ADD     DI, DX        ; nach diesem Zeichen wird
  317.                                  ; Quelle eingefügt
  318.            JMP Short Einkopiern  ; füge Quelle ein
  319. Weiter2:   MOV     DX, CX        ; Länge von Quelle retten
  320.            ADD     CX, BX        ; neue Lnge Ziel = alte
  321.                                  ; Länge Ziel + Länge Quelle
  322.            SUB     CX, AX        ; neue Länge Ziel -
  323.                                  ; Maximallänge von Ziel
  324.            JL      Luecke        ; neue Länge<Maximallänge ?
  325.            XOR     CX, CX        ; nein, neue Länge Ziel -
  326.                                  ; Maximallänge = 0
  327. Luecke:    ADD     AX, CX        ; neue Länge Ziel
  328.            STOSB                 ; abspeichern
  329.            DEC     DI            ; correct pointer
  330.            ADD     CX, BP        ; new targetlength -
  331.                                  ; objectlength - pos + 1
  332.            ADD     DI, AX        ; dieses Zeichen wird das
  333.                                  ; letzte in Ziel
  334.            MOV     AX, SI        ; Offset der Adresse von
  335.                                  ; Ziel retten
  336.            MOV     SI, DI        ; berechne
  337.            SUB     SI, DX        ; Ende der Lücke
  338.            MOV     BP, DS        ; Segment der Adresse
  339.                                  ; von Quelle retten
  340.            MOV     BX, ES        ; beide Segmente
  341.            MOV     DS, BX        ;  adressieren Ziel
  342.            STD                   ; Autodekrement
  343.            REP     MOVSB         ; Lücke erzeugen
  344.            MOV     DI, SI        ; Quelle wird nach diesem
  345.                                  ; Zeichen eingefügt
  346.            MOV     CX, DX        ; Länge von Quelle
  347.            MOV     SI, AX        ; Offset der Adresse
  348.            MOV     DS, BP        ; Segment der Adresse
  349.                                  ; ... von Quelle
  350.            INC     DI            ; Quelle wird ab hier in
  351.                                  ; Ziel eingefügt
  352.            CLD                   ; Autoinkrement
  353. Einkopiern:INC     SI            ; 1. Zeichen von Quelle
  354.            SHR     CX, 1         ; Anz. der zu verschieben-
  355.                                  ; den Zeichen ungerade ?
  356.            JNC     Wort2         ; nein, alles wortweise
  357.            MOVSB                 ; ja, ein Byte einzeln
  358.                                  ; verschieben
  359. Wort2:     REP     MOVSW         ; Rest wortweise schieben
  360. Ende2:     POP     DS            ; Datensegment restaurieren
  361.            POP     BP            ; Framepointer restaurieren
  362.            RET     12            ; Parameter vom Stack
  363. Insert     ENDP                  ; und zurück
  364.  
  365. CODE       ENDS
  366.            END
  367. ;* ------------------------------------------------------- *
  368. ;*                  Ende von STRING1.ASM                   *
  369.