[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]