[Back to STRINGS SWAG index] [Back to Main SWAG index] [Original]

    procedure CopySubStr( Str1: string; start, nrchars: byte; var Str2: string );
    assembler;
      { copy part of Str1 (beginning at start for nrchars) to Str2
        if start > length of Str1, Str2 will contain a empty string.
        if nrchars specifies more characters than remain starting at the
        start position, Str2 will contain just that remainder of Str1. }
    asm
            { setup }
            LDS   SI,Str1      { load in DS:SI pointer to str1 }
            CLD                { string operations forward     }
            LES   DI,Str2      { load in ES:DI pointer to str2 }
            MOV   AH,[SI]      { length str1 --> AH            }
            AND   AH,AH        { length str1 = 0?              }
            JE    @null        { yes, empty string in Str2     }
            MOV   BL,[start]   { starting position --> BL      }
            CMP   AH,BL        { start > length str1?          }
            JB    @null        { yes, empty string in Str2     }

            { start + nrchars - 1 > length str1?               }
            MOV   AL,[nrchars] { nrchars --> AL                }
            MOV   DH,AL        { nrchars --> DH                }
            ADD   DH,BL        { add start                     }
            DEC   DH
            CMP   AH,DH        { nrchars > rest of str1?       }
            JB    @rest        { yes, copy rest of str1        }
            JMP   @copy
    @null:
            MOV   AL,0         { return a empty string         }
            JMP   @done
    @rest:
            SUB   AH,BL        { length str1 - start           }
            INC   AH
            MOV   AL,AH
    @copy:
            MOV   CL,AL        { how many chars to copy        }
            XOR   CH,CH        { clear CH                      }
            XOR   BH,BH        { clear BH                      }
            ADD   SI,BX        { starting position             }
            MOV   DX,DI        { save pointer to str2          }
            INC   DI
            REP   MOVSB        { copy part str1 to str2        }
            MOV   DI,DX        { restore pointer to str2       }
    @done:
            MOV   [DI],AL      { overwrite length byte of str2 }
    @exit:
    end  { CopySubStr };

    procedure StrCopy( var Str1, Str2: string ); assembler;
      { copy str1 to str2 }
    asm
            LDS   SI,Str1    { load in DS:SI pointer to str1 }
            CLD              { string operations forward     }
            LES   DI,Str2    { load in ES:DI pointer to str2 }
            XOR   CH,CH      { clear CH                      }
            MOV   CL,[SI]    { length str1 --> CX            }
            INC   CX         { include length byte           }
            REP   MOVSB      { copy str1 to str2             }
    @exit:
    end  { StrCopy };

    function StrPos( var str1, str2: string ): byte; assembler;
      { returns position of the first occurrence of str1 in str2 }
      { return value in AX }
      { str1 - string to search for }
      { str2 - string to search in  }
    asm
            CLD              { string operations forward                 }
            LES   DI,Str2    { load in ES:DI pointer to str2             }
            XOR   CH,CH      { clear CH                                  }
            MOV   CL,[DI]    { length str2 --> CX                        }
            AND   CX,CX      { length str2 = 0?                          }
            JZ    @Negatief  { length str2 = 0, nothing to search in     }
            INC   DI         { make DI point to the 1st char of str2     }
            LDS   SI,Str1    { load in DS:SI pointer to str1             }
            LODSB            { load in AL length str1                    }
            AND   AL,AL      { length str1 = 0?                          }
            JZ    @Negatief  { length str1 = 0, nothing to search for    }
            MOV   AH,AL      { length str1 --> AH                        }
            DEC   AH         { 1st char need not be compared again       }
            LODSB            { load in AL 1st character of str1          }
    @Start:
      REPNE SCASB            { scan for next occurrence 1st char in str2 }
            JNE   @Negatief  { no success                                }
            CMP   CL,AH      { length str1 > # chars left in str2 ?      }
            JB    @Negatief  { yes, str1 not in str2                     }
            MOV   DX,SI      { pointer to 2nd char in str1 --> DX        }
            MOV   BX,CX      { number of chars in str2 to go --> BX      }
            MOV   CL,AH      { length str1 --> CL                        }
            REPE  CMPSB      { compare until characters don't match      }
            JE    @Positief  { full match                                }
            SUB   SI,DX      { current SI - prev. SI = # of chars moved  }
            SUB   DI,SI      { reconstruct DI                            }
            MOV   SI,DX      { restore pointer to 2nd char in str1       }
            MOV   CX,BX      { number of chars in str2 to go --> BX      }
            JMP   @Start     { scan for next occurrence 1st char in str2 }
    @Negatief:
            XOR   AX,AX      { str1 is not in str, result 0              }
            JMP   @Exit
    @Positief:
            XOR   AH,AH      { clear AH                                  }
            LES   DI,Str2    { load in ES:DI pointer to str2             }
            MOV   AL,[DI]    { length str2 --> AX                        }
            SUB   AX,BX      { start position of str1 in str2            }
    @Exit:                   { we are finished. }
    end  { StrPos };

    procedure Trim( var Str: string ); assembler;
      { remove leading and trailing white space from str }
    asm
            { setup }
            LDS   SI,Str     { load in DS:SI pointer to Str       }
            MOV   AX,DS      { Set ES to same segment as DS       }
            MOV   ES,AX      { Set ES to same segment as DS       }
            MOV   AL,[SI]    { length Str --> AL                  }
            AND   AL,AL      { length Str = 0?                    }
            JZ    @exit      { yes, nothing to do                 }
            MOV   DI,SI      { pointer to Str --> DI              }
            MOV   AH,AL      { length Str --> AH                  }

            { remove trailing white space }
            XOR   CH,CH      { clear CH                           }
            MOV   CL,AH      { length Str --> CX                  }
            ADD   SI,CX      { start with last character          }
    @start1:
            MOV   AL,[SI]    { character  --> AL                  }
            CMP   AL,20H     { no white space                     }
            JA    @stop1     { last non-blank character found     }
            DEC   SI         { count down SI                      }
            DEC   CL         { count down CX                      }
            AND   CL,CL      { more characters left?              }
            JZ    @stop1     { no, done                           }
            JMP   @start1    { try again                          }
    @stop1:
            AND   CL,CL      { length Str = 0?                    }
            JZ    @done      { string is empty, done              }

            { look for leading white space }
            MOV   SI,DI      { pointer to Str --> SI              }
    @start2:
            INC   SI         { next character                     }
            MOV   AL,[SI]    { character  --> AL                  }
            CMP   AL,20H     { no white space                     }
            JA    @stop2     { first non-blank character found    }
            DEC   CL         { count down                         }
            AND   CL,CL      { more characters left?              }
            JZ    @stop2     { no, done                           }
            JMP   @start2    { try again                          }
    @stop2:
            MOV   DX,SI      { difference between SI and DI gives }
            SUB   DX,DI      { position first non-blank character }
            CMP   DX,1       { first character non-blank?         }
            JE    @done      { yes, done                          }

            { remove leading white space }
            CLD              { string operations forward          }
            MOV   BX,CX      { save length Str                    }
            MOV   DX,DI      { save pointer to Str                }
            INC   DI         { don't overwrite length byte of Str }
            REP   MOVSB      { move remaining part of Str         }
            MOV   DI,DX      { restore pointer to Str             }
            MOV   CX,BX      { restore length Str                 }
    @done:
            MOV   [DI],CL    { overwrite length byte of Str       }
    @exit:
    end  { Trim };

    procedure RTrim( var Str: string ); assembler;
      { remove trailing white space from str }
    asm
            { setup }
            LDS   SI,Str     { load in DS:SI pointer to Str      }
            MOV   AL,[SI]    { length Str --> AL                 }
            AND   AL,AL      { length Str = 0?                   }
            JZ    @exit      { yes, exit                         }
            MOV   DI,SI      { pointer to Str --> DI             }
            MOV   AH,AL      { length Str --> AH                 }

            { remove trailing space }
            STD              { SeT Direction flag --> backwards  }
            XOR   CH,CH      { clear CH                          }
            MOV   CL,AH      { length Str --> CX                 }
            ADD   SI,CX      { start with last character         }
    @start:
            MOV   AL,[SI]    { character  --> AL                 }
            CMP   AL,20H     { no white space                     }
            JA    @stop      { last non-blank character found    }
            DEC   SI         { count down                        }
            DEC   CL         { count down                        }
            AND   CL,CL      { more characters left?             }
            JZ    @stop      { no, done                          }
            JMP   @start     { try again                         }
    @stop:
            MOV   [DI],CL    { overwrite length byte of Str      }
    @exit:
    end  { RTrim };

    procedure LTrim( var Str: string ); assembler;
      { remove leading white space from str }
    asm
            { setup }
            LDS   SI,Str     { load in DS:SI pointer to Str       }
            MOV   AL,[SI]    { length Str --> AL                  }
            AND   AL,AL      { length Str = 0?                    }
            JZ    @exit      { yes, nothing to do                 }
            MOV   DI,SI      { pointer to Str --> DI              }
            XOR   CH,CH      { clear CH                           }
            MOV   CL,AL      { length Str --> CX                  }

            { look for leading white space }
    @start:
            INC   SI         { next character                     }
            MOV   AL,[SI]    { character  --> AL                  }
            CMP   AL,20H     { no white space                     }
            JA    @stop      { first non-blank character found    }
            DEC   CL         { count down                         }
            AND   CL,CL      { more characters left?              }
            JZ    @nullstr   { no, done                           }
            JMP   @start     { try again                          }
    @nullstr:
            MOV   CL,0       { null string                        }
            JMP   @done      { we're done                         }
    @stop:
            MOV   DX,SI      { difference between SI and DI gives }
            SUB   DX,DI      { position first non-blank character }
            CMP   DX,1       { first character non-blank?         }
            JE    @exit      { yes, exit                          }

            { remove leading white space }
            CLD              { string operations forward          }
            MOV   DX,CX      { save length Str                    }
            MOV   BX,DI      { save pointer to Str                }
            INC   DI         { don't overwrite length byte of Str }
            REP   MOVSB      { move remaining part of Str         }
            MOV   DI,BX      { restore pointer to Str             }
            MOV   CX,DX      { restore length Str                 }
    @done:
            MOV   [DI],CL    { overwrite length byte of Str       }
    @exit:
    end  { LTrim };

[Back to STRINGS SWAG index] [Back to Main SWAG index] [Original]